function for editing command line in ext editor

This implements a standard function and bindings for editing the command
line in an external editor. This feature has been requested multiple
times in the past year with various solutions cut and pasted into those
issues. This change combines the best aspects of those solutions.

Fixes #1215
This commit is contained in:
Kurtis Rader 2016-12-06 19:24:08 -08:00
parent 0019c12af3
commit 59fa04bd91
3 changed files with 52 additions and 0 deletions

View file

@ -1001,6 +1001,10 @@ Some bindings are shared between emacs- and vi-mode because they aren't text edi
- @key{Alt,w} prints a short description of the command under the cursor. - @key{Alt,w} prints a short description of the command under the cursor.
- @key{Alt,e} edit the current command line in an external editor. The editor is chosen from the first available of the `$VISUAL` or `$EDITOR` variables.
- @key{Alt,v} Same as @key{Alt,e}.
\subsection emacs-mode Emacs mode commands \subsection emacs-mode Emacs mode commands
- @key{Home} or @key{Control,A} moves the cursor to the beginning of the line. - @key{Home} or @key{Control,A} moves the cursor to the beginning of the line.

View file

@ -96,4 +96,8 @@ function __fish_shared_key_bindings -d "Bindings shared between emacs and vi mod
# Make it easy to turn an unexecuted command into a comment in the shell history. Also, # Make it easy to turn an unexecuted command into a comment in the shell history. Also,
# remove the commenting chars so the command can be further edited then executed. # remove the commenting chars so the command can be further edited then executed.
bind $argv \e\# __fish_toggle_comment_commandline bind $argv \e\# __fish_toggle_comment_commandline
# The [meta-e] and [meta-v] keystrokes invoke an external editor on the command buffer.
bind \ee edit_command_buffer
bind \ev edit_command_buffer
end end

View file

@ -0,0 +1,44 @@
function edit_command_buffer --description 'Edit the command buffer in an external editor'
set -l f (mktemp)
if set -q f[1]
mv $f $f.fish
set f $f.fish
else
# We should never execute this block but better to be paranoid.
if set -q TMPDIR
set f $TMPDIR/fish.(echo %self).fish
else
set f /tmp/fish.(echo %self).fish
end
touch $f
or return 1
end
# Edit the command line with the users preferred editor or vim or emacs.
commandline -b >$f
if set -q VISUAL
eval $VISUAL $f
else if set -q EDITOR
eval $EDITOR $f
else
echo
echo (_ 'External editor requested but $VISUAL or $EDITOR not set.')
echo (_ 'Please set VISUAL or EDITOR to your preferred editor.')
commandline -f repaint
command rm $f
return 1
end
# Here we're checking the exit status of the editor.
if test $status -eq 0 -a -s $f
# Set the command to the output of the edited command and move the cursor to the
# end of the edited command.
commandline -r (cat $f)
commandline -C 999999
else
echo
echo (_ "Ignoring the output of your editor since its exit status was non-zero")
echo (_ "or the file was empty")
end
command rm $f
end