mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-27 19:53:36 +08:00
129 lines
4.0 KiB
Fish
129 lines
4.0 KiB
Fish
function __funced_md5
|
|
if type -q md5sum
|
|
# GNU systems
|
|
echo (md5sum $argv[1] | string split ' ')[1]
|
|
return 0
|
|
else if type -q md5
|
|
# BSD systems
|
|
md5 -q $argv[1]
|
|
return 0
|
|
end
|
|
return 1
|
|
end
|
|
|
|
function funced --description 'Edit function definition'
|
|
set -l options 'h/help' 'e/editor=' 'i/interactive'
|
|
argparse -n funced --min-args=1 --max-args=1 $options -- $argv
|
|
or return
|
|
|
|
if set -q _flag_help
|
|
__fish_print_help funced
|
|
return 0
|
|
end
|
|
|
|
set funcname $argv[1]
|
|
|
|
# Check VISUAL first since theoretically EDITOR could be ed.
|
|
set -l editor
|
|
if set -q _flag_interactive
|
|
set editor fish
|
|
else if set -q _flag_editor
|
|
set editor $_flag_editor
|
|
else if set -q VISUAL
|
|
set editor $VISUAL
|
|
else if set -q EDITOR
|
|
set editor $EDITOR
|
|
else
|
|
set editor fish
|
|
end
|
|
|
|
set -l init
|
|
switch $funcname
|
|
case '-*'
|
|
set init function -- $funcname\n\nend
|
|
case '*'
|
|
set init function $funcname\n\nend
|
|
end
|
|
|
|
# Break editor up to get its first command (i.e. discard flags)
|
|
if test -n "$editor"
|
|
set -l editor_cmd
|
|
eval set editor_cmd $editor
|
|
if not type -q -f "$editor_cmd[1]"
|
|
echo (_ "funced: The value for \$EDITOR '$editor' could not be used because the command '$editor_cmd[1]' could not be found")
|
|
set editor fish
|
|
end
|
|
end
|
|
|
|
if test "$editor" = fish
|
|
set -l IFS
|
|
if functions -q -- $funcname
|
|
# Shadow IFS here to avoid array splitting in command substitution
|
|
set init (functions -- $funcname | fish_indent --no-indent)
|
|
end
|
|
|
|
set -l prompt 'printf "%s%s%s> " (set_color green) '$funcname' (set_color normal)'
|
|
# Unshadow IFS since the fish_title breaks otherwise
|
|
set -e IFS
|
|
if read -p $prompt -c "$init" -s cmd
|
|
# Shadow IFS _again_ to avoid array splitting in command substitution
|
|
set -l IFS
|
|
eval (echo -n $cmd | fish_indent)
|
|
end
|
|
return 0
|
|
end
|
|
|
|
# OSX mktemp is rather restricted - no suffix, no way to automatically use TMPDIR
|
|
# Create a directory so we can use a ".fish" suffix for the file - makes editors pick up that it's a fish file
|
|
set -q TMPDIR
|
|
or set -l TMPDIR /tmp
|
|
set -l tmpdir (mktemp -d $TMPDIR/fish.XXXXXX)
|
|
set -l tmpname $tmpdir/$funcname.fish
|
|
|
|
if functions -q -- $funcname
|
|
functions -- $funcname >$tmpname
|
|
else
|
|
echo $init >$tmpname
|
|
end
|
|
|
|
# Repeatedly edit until it either parses successfully, or the user cancels
|
|
# If the editor command itself fails, we assume the user cancelled or the file
|
|
# could not be edited, and we do not try again
|
|
while true
|
|
set -l checksum (__funced_md5 "$tmpname")
|
|
|
|
if not eval $editor $tmpname
|
|
echo (_ "Editing failed or was cancelled")
|
|
else
|
|
# Verify the checksum (if present) to detect potential problems
|
|
# with the editor command
|
|
if set -q checksum[1]
|
|
set -l new_checksum (__funced_md5 "$tmpname")
|
|
if test "$new_checksum" = "$checksum"
|
|
echo (_ "Editor exited but the function was not modified")
|
|
end
|
|
end
|
|
|
|
if not source $tmpname
|
|
# Failed to source the function file. Prompt to try again.
|
|
echo # add a line between the parse error and the prompt
|
|
set -l repeat
|
|
set -l prompt (_ 'Edit the file again\? [Y/n]')
|
|
while test -z "$repeat"
|
|
read -p "echo $prompt\ " repeat
|
|
end
|
|
if not contains $repeat n N no NO No nO
|
|
continue
|
|
end
|
|
echo (_ "Cancelled function editing")
|
|
end
|
|
end
|
|
break
|
|
end
|
|
|
|
set -l stat $status
|
|
rm $tmpname >/dev/null
|
|
and rmdir $tmpdir >/dev/null
|
|
return $stat
|
|
end
|