edit_command_buffer: preserve external editor's cursor position

Unless the editor changed to a different file for some reason.

Note that the Kakoune integration uses -always to export the cursor even if
the user temporarily suppressed hooks - possibly a "fish_indent" hook.
This commit is contained in:
Johannes Altmanninger
2024-03-10 10:16:35 +01:00
parent 5fa743337c
commit d8d491741b
2 changed files with 42 additions and 3 deletions

View File

@@ -51,7 +51,8 @@ Interactive improvements
- Command-specific tab completions may now offer results whose first character is a period. For example, it is now possible to tab-complete ``git add`` for files with leading periods. The default file completions hide these files, unless the token itself has a leading period (:issue:`3707`).
- The :kbd:`Control-R` history search now uses glob syntax (:issue:`10131`).
- When the cursor is on a command that resolves to a script, :kbd:`Alt-O` will now open that script in your editor.
- :kbd:`Alt-E` now passes the cursor position to the external editor also if the editor aliases a supported editor (via ``complete --wraps``).
- After using :kbd:`Alt-E` to edit the commandline in an external editor, the editor's cursor position will be copied over to fish. This is currently supported for Vim and Kakoune.
- When deciding how to pass the cursor position to and from the external editor, :kbd:`Alt-E` now resolves aliases. For example use ``complete --wraps my-vim vim`` to synchronize cursors when `EDITOR=my-vim`.
- Option completion now uses fuzzy subsequence filtering as well. This means that ``--fb`` may be completed to ``--foobar`` if there is no better match.
- ASCII control characters are now rendered using symbols from Unicode's Control Pictures block.

View File

@@ -38,12 +38,34 @@ function edit_command_buffer --description 'Edit the command buffer in an extern
set -a wrapped_commands $tmp[1]
end
set -l found false
set -l cursor_from_editor
for editor_command in $editor_basename $wrapped_commands
switch $editor_command
case vi vim nvim
set -a editor +$line +"norm! $col|" $f
case emacs emacsclient gedit kak
if test $editor_command = vi && not set -l vi_version "$(vi --version 2>/dev/null)"
if printf %s $vi_version | grep -q BusyBox
break
end
set -a editor +{$line} $f
set found true
break
end
set cursor_from_editor (mktemp)
set -a editor +$line "+norm! $col|" $f \
'+autocmd VimLeave * ++once call writefile(
[printf("%s %s %s", shellescape(bufname()), line("."), col("."))],
"'$cursor_from_editor'"
)'
case emacs emacsclient gedit
set -a editor +$line:$col $f
case kak
set cursor_from_editor (mktemp)
set -a editor +$line:$col $f -e "
hook -always -once global ClientClose %val{client} %{
echo -to-file $cursor_from_editor -quoting shell \
%val{buffile} %val{cursor_line} %val{cursor_column}
}
"
case nano
set -a editor +$line,$col $f
case joe ee
@@ -80,6 +102,22 @@ function edit_command_buffer --description 'Edit the command buffer in an extern
echo (_ "Ignoring the output of your editor since its exit status was non-zero")
echo (_ "or the file was empty")
end
if set -q cursor_from_editor[1]
eval set -l pos "$(cat $cursor_from_editor)"
if set -q pos[1] && test $pos[1] = $f
set -l line $pos[2]
set -l column $pos[3]
commandline -C 0
for _line in (seq $line)[2..]
commandline -f down-line
end
commandline -f beginning-of-line
for _column in (seq $column)[2..]
commandline -f forward-single-char
end
end
command rm $cursor_from_editor
end
command rm $f
# We've probably opened something that messed with the screen.
# A repaint seems in order.