2012-06-27 11:37:48 +08:00
|
|
|
function funced --description 'Edit function definition'
|
2020-03-10 02:36:12 +08:00
|
|
|
set -l options h/help 'e/editor=' i/interactive s/save
|
2018-11-22 19:43:35 +08:00
|
|
|
argparse -n funced --max-args=1 $options -- $argv
|
2017-07-14 04:29:35 +08:00
|
|
|
or return
|
|
|
|
|
|
|
|
if set -q _flag_help
|
|
|
|
__fish_print_help funced
|
|
|
|
return 0
|
|
|
|
end
|
|
|
|
|
2018-11-22 19:43:35 +08:00
|
|
|
if not set -q argv[1]
|
|
|
|
printf (_ "%ls: Expected at least %d args, got only %d\n") funced 1 0
|
|
|
|
return 1
|
|
|
|
end
|
|
|
|
|
2020-05-15 13:56:06 +08:00
|
|
|
set -l funcname $argv[1]
|
2017-07-14 04:29:35 +08:00
|
|
|
|
|
|
|
# Check VISUAL first since theoretically EDITOR could be ed.
|
2015-09-02 19:55:59 +08:00
|
|
|
set -l editor
|
2017-07-14 04:29:35 +08:00
|
|
|
if set -q _flag_interactive
|
|
|
|
set editor fish
|
|
|
|
else if set -q _flag_editor
|
|
|
|
set editor $_flag_editor
|
|
|
|
else if set -q VISUAL
|
2024-01-27 14:41:52 +08:00
|
|
|
echo $VISUAL | read -at editor
|
2015-09-02 19:55:59 +08:00
|
|
|
else if set -q EDITOR
|
2024-01-27 14:41:52 +08:00
|
|
|
echo $EDITOR | read -at editor
|
2017-07-14 04:29:35 +08:00
|
|
|
else
|
|
|
|
set editor fish
|
2012-06-30 10:22:41 +08:00
|
|
|
end
|
2012-06-27 11:37:48 +08:00
|
|
|
|
2012-06-30 10:22:41 +08:00
|
|
|
set -l init
|
|
|
|
switch $funcname
|
|
|
|
case '-*'
|
2016-11-28 13:27:22 +08:00
|
|
|
set init function -- $funcname\n\nend
|
2012-06-30 10:22:41 +08:00
|
|
|
case '*'
|
2016-11-28 13:27:22 +08:00
|
|
|
set init function $funcname\n\nend
|
2012-06-30 10:22:41 +08:00
|
|
|
end
|
2012-06-27 11:37:48 +08:00
|
|
|
|
2013-01-24 10:24:49 +08:00
|
|
|
# Break editor up to get its first command (i.e. discard flags)
|
2018-10-15 16:13:19 +08:00
|
|
|
set -l editor_cmd
|
2019-12-03 19:18:39 +08:00
|
|
|
echo $editor | read -ta editor_cmd
|
2018-10-15 16:13:19 +08:00
|
|
|
if not type -q -f "$editor_cmd[1]"
|
2022-04-04 11:57:55 +08:00
|
|
|
echo (_ "funced: The value for \$EDITOR '$editor' could not be used because the command '$editor_cmd[1]' could not be found") >&2
|
2018-10-15 16:13:19 +08:00
|
|
|
set editor fish
|
2013-01-28 05:14:24 +08:00
|
|
|
end
|
2016-11-28 13:27:22 +08:00
|
|
|
|
2017-07-14 04:29:35 +08:00
|
|
|
if test "$editor" = fish
|
2012-06-30 10:22:41 +08:00
|
|
|
if functions -q -- $funcname
|
2024-10-10 11:12:10 +08:00
|
|
|
functions --no-details -- $funcname | __fish_indent --only-unindent | __fish_indent --no-indent | read -z init
|
2012-06-30 10:22:41 +08:00
|
|
|
end
|
2007-04-23 02:55:39 +08:00
|
|
|
|
2012-06-30 10:22:41 +08:00
|
|
|
set -l prompt 'printf "%s%s%s> " (set_color green) '$funcname' (set_color normal)'
|
2018-03-10 01:55:12 +08:00
|
|
|
if read -p $prompt -c "$init" --shell cmd
|
2024-10-10 11:12:10 +08:00
|
|
|
echo -n $cmd | __fish_indent --only-unindent | read -lz cmd
|
2018-10-28 08:19:00 +08:00
|
|
|
eval "$cmd"
|
2012-06-30 10:22:41 +08:00
|
|
|
end
|
2017-12-22 00:54:29 +08:00
|
|
|
if set -q _flag_save
|
|
|
|
funcsave $funcname
|
|
|
|
end
|
2012-06-30 10:22:41 +08:00
|
|
|
return 0
|
|
|
|
end
|
|
|
|
|
2017-07-25 11:45:43 +08:00
|
|
|
# OS X (macOS) `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.
|
2016-11-28 13:27:22 +08:00
|
|
|
set -q TMPDIR
|
|
|
|
or set -l TMPDIR /tmp
|
2016-05-23 06:49:09 +08:00
|
|
|
set -l tmpdir (mktemp -d $TMPDIR/fish.XXXXXX)
|
2020-11-13 23:58:45 +08:00
|
|
|
or return 1
|
2016-05-23 06:49:09 +08:00
|
|
|
set -l tmpname $tmpdir/$funcname.fish
|
2012-06-30 10:22:41 +08:00
|
|
|
|
2021-08-10 21:46:00 +08:00
|
|
|
set -l writepath
|
|
|
|
|
|
|
|
if not functions -q -- $funcname
|
2016-11-28 13:27:22 +08:00
|
|
|
echo $init >$tmpname
|
2021-08-10 21:46:00 +08:00
|
|
|
else if functions --details -- $funcname | string match --invert --quiet --regex '^(?:-|stdin)$'
|
|
|
|
set writepath (functions --details -- $funcname)
|
|
|
|
# Use cat here rather than cp to avoid copying permissions
|
|
|
|
cat "$writepath" >$tmpname
|
|
|
|
else
|
|
|
|
functions -- $funcname >$tmpname
|
2012-06-30 10:22:41 +08:00
|
|
|
end
|
2017-04-17 23:18:02 +08:00
|
|
|
|
2016-11-28 13:27:22 +08:00
|
|
|
# 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
|
2024-04-04 22:22:58 +08:00
|
|
|
set -l checksum (__fish_md5 "$tmpname")
|
2017-04-17 23:18:02 +08:00
|
|
|
|
2021-09-14 00:57:18 +08:00
|
|
|
if not $editor_cmd $tmpname
|
2017-04-17 23:18:02 +08:00
|
|
|
echo (_ "Editing failed or was cancelled")
|
2016-11-28 13:27:22 +08:00
|
|
|
else
|
2017-04-17 23:18:02 +08:00
|
|
|
# Verify the checksum (if present) to detect potential problems
|
|
|
|
# with the editor command
|
|
|
|
if set -q checksum[1]
|
2024-04-04 22:22:58 +08:00
|
|
|
set -l new_checksum (__fish_md5 "$tmpname")
|
2017-04-17 23:18:02 +08:00
|
|
|
if test "$new_checksum" = "$checksum"
|
|
|
|
echo (_ "Editor exited but the function was not modified")
|
2023-09-05 15:16:03 +08:00
|
|
|
echo (_ "If the editor is still running, check if it waits for completion, maybe a '--wait' option?")
|
2024-02-23 02:45:20 +08:00
|
|
|
# Source but don't save an unmodified file.
|
|
|
|
# (Source in case the file changed externally since we first loaded it.)
|
2024-04-12 17:16:00 +08:00
|
|
|
if set -q writepath[1]
|
|
|
|
source "$writepath"
|
|
|
|
end
|
2021-07-10 22:07:54 +08:00
|
|
|
break
|
2017-04-17 23:18:02 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-07-10 21:30:31 +08:00
|
|
|
if not source <$tmpname
|
2016-11-28 13:27:22 +08:00
|
|
|
# Failed to source the function file. Prompt to try again.
|
|
|
|
echo # add a line between the parse error and the prompt
|
|
|
|
set -l repeat
|
2021-08-10 21:46:00 +08:00
|
|
|
set -l prompt (_ 'Edit the file again? [Y/n]')
|
2022-09-10 23:42:16 +08:00
|
|
|
read -P "$prompt " response
|
2017-08-12 07:09:13 +08:00
|
|
|
if test -z "$response"
|
|
|
|
or contains $response {Y,y}{E,e,}{S,s,}
|
|
|
|
continue
|
|
|
|
else if not contains $response {N,n}{O,o,}
|
|
|
|
echo "I don't understand '$response', assuming 'Yes'"
|
|
|
|
sleep 2
|
2016-11-28 13:27:22 +08:00
|
|
|
continue
|
|
|
|
end
|
2017-04-17 23:18:02 +08:00
|
|
|
echo (_ "Cancelled function editing")
|
2021-08-10 21:46:00 +08:00
|
|
|
else if test -n "$writepath"
|
|
|
|
if not set -q _flag_save
|
|
|
|
echo (_ "Warning: the file containing this function has not been saved. Changes may be lost when fish is closed.")
|
|
|
|
set -l prompt (printf (_ 'Save function to %s? [Y/n]') "$writepath")
|
|
|
|
read --prompt-str "$prompt " response
|
|
|
|
if test -z "$response"
|
|
|
|
or contains $response {Y,y}{E,e,}{S,s,}
|
|
|
|
set _flag_save 1
|
|
|
|
else if not contains $response {N,n}{O,o,}
|
|
|
|
echo "I don't understand '$response', assuming 'Yes'"
|
|
|
|
set _flag_save 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if set -q _flag_save
|
|
|
|
# try to write the file back
|
|
|
|
# cp preserves existing permissions, though it might overwrite the owner
|
|
|
|
if cp $tmpname "$writepath" 2>&1
|
|
|
|
printf (_ "Function saved to %s") "$writepath"
|
|
|
|
echo
|
|
|
|
# read it back again - this ensures that the output of `functions --details` is correct
|
|
|
|
source "$writepath"
|
|
|
|
else
|
|
|
|
echo (_ "Saving to original location failed; saving to user configuration instead.")
|
2023-01-26 03:04:57 +08:00
|
|
|
set writepath $__fish_config_dir/functions/(path basename "$writepath")
|
2021-08-10 21:46:00 +08:00
|
|
|
if cp $tmpname "$writepath"
|
|
|
|
printf (_ "Function saved to %s") "$writepath"
|
|
|
|
echo
|
|
|
|
# read it back again - this ensures that the output of `functions --details` is correct
|
|
|
|
source "$writepath"
|
|
|
|
else
|
|
|
|
echo (_ "Saving to user configuration failed. Changes may be lost when fish is closed.")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2017-12-22 00:54:29 +08:00
|
|
|
else if set -q _flag_save
|
|
|
|
funcsave $funcname
|
2021-08-10 21:47:15 +08:00
|
|
|
else
|
|
|
|
printf (_ "Run funcsave %s to save this function to the configuration directory.") $funcname
|
|
|
|
echo
|
2016-11-28 13:27:22 +08:00
|
|
|
end
|
2014-10-18 02:49:26 +08:00
|
|
|
end
|
2016-11-28 13:27:22 +08:00
|
|
|
break
|
|
|
|
end
|
2017-04-17 23:18:02 +08:00
|
|
|
|
2012-11-18 18:23:22 +08:00
|
|
|
set -l stat $status
|
2021-03-16 03:38:35 +08:00
|
|
|
command rm $tmpname >/dev/null
|
2016-05-28 18:34:04 +08:00
|
|
|
and rmdir $tmpdir >/dev/null
|
2012-06-30 10:22:41 +08:00
|
|
|
return $stat
|
|
|
|
end
|