diff --git a/doc_src/index.hdr.in b/doc_src/index.hdr.in index b0f534a4b..c1f7178ea 100644 --- a/doc_src/index.hdr.in +++ b/doc_src/index.hdr.in @@ -953,33 +953,34 @@ For a list of all builtins, functions and commands shipped with fish, see the completes the current token. @key{Shift, Tab} completes the current token and starts the pager's search mode. -- @key{Home} or @key{Control,A} moves the cursor to the beginning of the line. - -- @key{End} or @key{Control,E} moves to the end of line. If the cursor is already at the end of the line, and an autosuggestion is available, @key{End} or @key{Control,E} accepts the autosuggestion. - -- @cursor_key{←,Left} (or @key{Control,B}) and @cursor_key{→,Right} (or @key{Control,F}) move the cursor left or right by one character. If the cursor is already at the end of the line, and an autosuggestion is available, the @cursor_key{→,Right} key and the @key{Control,F} combination accept the suggestion. - - @key{Alt,←,Left} and @key{Alt,→,Right} move the cursor one word left or right, or moves forward/backward in the directory history if the command line is empty. If the cursor is already at the end of the line, and an autosuggestion is available, @key{Alt,→,Right} (or @key{Alt,F}) accepts the first word in the suggestion. - @cursor_key{↑,Up} and @cursor_key{↓,Down} search the command history for the previous/next command containing the string that was specified on the commandline before the search was started. If the commandline was empty when the search started, all commands match. See the history section for more information on history searching. - @key{Alt,↑,Up} and @key{Alt,↓,Down} search the command history for the previous/next token containing the token under the cursor before the search was started. If the commandline was not on a token when the search started, all tokens match. See the history section for more information on history searching. -- @key{Delete} and @key{Backspace} removes one character forwards or backwards respectively. - - @key{Control,C} deletes the entire line. - @key{Control,D} delete one character to the right of the cursor. If the command line is empty, @key{Control,D} will exit fish. -- @key{Control,K} moves contents from the cursor to the end of line to the killring. - - @key{Control,U} moves contents from the beginning of line to the cursor to the killring. - @key{Control,L} clears and repaints the screen. @@ -988,18 +989,30 @@ Similar to bash, fish has Emacs and Vi editing modes. The default editing mode i - @key{Alt,D} moves the next word to the killring. -- @key{Alt,W} prints a short description of the command under the cursor. +- @key{Alt,H} (or @key{F1}) shows the manual page for the current command, if one exists. - @key{Alt,L} lists the contents of the current directory, unless the cursor is over a directory argument, in which case the contents of that directory will be listed. - @key{Alt,P} adds the string '`| less;`' to the end of the job under the cursor. The result is that the output of the command will be paged. +- @key{Alt,W} prints a short description of the command under the cursor. + +\subsection emacs-mode Emacs mode commands + +- @key{Home} or @key{Control,A} moves the cursor to the beginning of the line. + +- @key{End} or @key{Control,E} moves to the end of line. If the cursor is already at the end of the line, and an autosuggestion is available, @key{End} or @key{Control,E} accepts the autosuggestion. + +- @cursor_key{←,Left} (or @key{Control,B}) and @cursor_key{→,Right} (or @key{Control,F}) move the cursor left or right by one character. If the cursor is already at the end of the line, and an autosuggestion is available, the @cursor_key{→,Right} key and the @key{Control,F} combination accept the suggestion. + +- @key{Delete} and @key{Backspace} removes one character forwards or backwards respectively. + +- @key{Control,K} moves contents from the cursor to the end of line to the killring. + - @key{Alt,C} capitalizes the current word. - @key{Alt,U} makes the current word uppercase. -- @key{Alt,H} (or @key{F1}) shows the manual page for the current command, if one exists. - - @key{Control, t} transposes the last two characters - @key{Alt,t} transposes the last two words @@ -1010,7 +1023,7 @@ You can change these key bindings using the bindinsert mode is active. @key{Escape} enters command mode. The commands available in command, insert and visual mode are described below. Vi mode builds on top of Emacs mode, so all keybindings mentioned there that do not contradict the ones mentioned here also work. +Vi mode allows for the use of Vi-like commands at the prompt. Initially, insert mode is active. @key{Escape} enters command mode. The commands available in command, insert and visual mode are described below. Vi mode shares some bindings with Emacs mode. When in vi-mode, the `fish_mode_prompt` function will display a mode indicator to the left of the prompt. The `fish_vi_cursor` function is available to change the cursor's shape depending on the mode in supported terminals. @@ -1047,16 +1060,8 @@ Command mode is also known as normal mode. \subsubsection vi-mode-insert Insert mode -- @key{Tab} completes the current token. - - @key{Escape} or @key{Control,C} enters command mode. -- @cursor_key{↑,Up} and @cursor_key{↓,Down} search the command history. See the history section for more information on history searching. - -- @key{Control,W} moves the previous word to the killring. - -- @key{Control,U} moves contents from the beginning of line to the cursor to the killring. - - @key{Control,x} moves the cursor to the end of the line. If an autosuggestion is available, it will be accepted completely. \subsubsection vi-mode-visual Visual mode diff --git a/share/functions/__fish_shared_key_bindings.fish b/share/functions/__fish_shared_key_bindings.fish new file mode 100644 index 000000000..49b7db51c --- /dev/null +++ b/share/functions/__fish_shared_key_bindings.fish @@ -0,0 +1,91 @@ +function __fish_shared_key_bindings -d "Bindings shared between emacs and vi mode" + # These are some bindings that are supposed to be shared between vi mode and default mode. + # They are supposed to be unrelated to text-editing (or movement). + # This takes $argv so the vi-bindings can pass the mode they are valid in. + + bind $argv \cy yank + bind $argv \ey yank-pop + + # Left/Right arrow + bind $argv -k right forward-char + bind $argv -k left backward-char + bind $argv \e\[C forward-char + bind $argv \e\[D backward-char + # Some terminals output these when they're in in keypad mode. + bind $argv \eOC forward-char + bind $argv \eOD backward-char + + # Interaction with the system clipboard. + bind $argv \cx fish_clipboard_copy + bind $argv \cv fish_clipboard_paste + + bind $argv \e cancel + bind $argv \cy yank + bind $argv \ey yank-pop + + bind $argv \t complete + # shift-tab does a tab complete followed by a search. + bind $argv --key btab complete-and-search + + bind $argv \e\n "commandline -i \n" + bind $argv \e\r "commandline -i \n" + + bind $argv -k down down-or-search + bind $argv -k up up-or-search + bind $argv \e\[A up-or-search + bind $argv \e\[B down-or-search + bind $argv \eOA up-or-search + bind $argv \eOB down-or-search + + # Alt-left/Alt-right + bind $argv \e\eOC nextd-or-forward-word + bind $argv \e\eOD prevd-or-backward-word + bind $argv \e\e\[C nextd-or-forward-word + bind $argv \e\e\[D prevd-or-backward-word + bind $argv \eO3C nextd-or-forward-word + bind $argv \eO3D prevd-or-backward-word + bind $argv \e\[3C nextd-or-forward-word + bind $argv \e\[3D prevd-or-backward-word + bind $argv \e\[1\;3C nextd-or-forward-word + bind $argv \e\[1\;3D prevd-or-backward-word + bind $argv \e\[1\;9C nextd-or-forward-word #iTerm2 + bind $argv \e\[1\;9D prevd-or-backward-word #iTerm2 + + # Alt-up/Alt-down + bind $argv \e\eOA history-token-search-backward + bind $argv \e\eOB history-token-search-forward + bind $argv \e\e\[A history-token-search-backward + bind $argv \e\e\[B history-token-search-forward + bind $argv \eO3A history-token-search-backward + bind $argv \eO3B history-token-search-forward + bind $argv \e\[3A history-token-search-backward + bind $argv \e\[3B history-token-search-forward + bind $argv \e\[1\;3A history-token-search-backward + bind $argv \e\[1\;3B history-token-search-forward + bind $argv \e\[1\;9A history-token-search-backward # iTerm2 + bind $argv \e\[1\;9B history-token-search-forward # iTerm2 + # Bash compatibility + # https://github.com/fish-shell/fish-shell/issues/89 + bind $argv \e. history-token-search-backward + + bind $argv \el __fish_list_current_token + bind $argv \ew 'set tok (commandline -pt); if test $tok[1]; echo; whatis $tok[1]; commandline -f repaint; end' + bind $argv \cl 'clear; commandline -f repaint' + bind $argv \cc __fish_cancel_commandline + bind $argv \cu backward-kill-line + bind $argv \cw backward-kill-path-component + bind $argv \ed 'set -l cmd (commandline); if test -z "$cmd"; echo; dirh; commandline -f repaint; else; commandline -f kill-word; end' + bind $argv \cd delete-or-exit + + # Allow reading manpages by pressing F1 (many GUI applications) or Alt+h (like in zsh). + bind $argv -k f1 __fish_man_page + bind $argv \eh __fish_man_page + + # This will make sure the output of the current command is paged using the default pager when you press Meta-p. + # If none is set, less will be used. + bind $argv \ep '__fish_paginate' + + # 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. + bind $argv \e\# __fish_toggle_comment_commandline +end diff --git a/share/functions/fish_default_key_bindings.fish b/share/functions/fish_default_key_bindings.fish index 64bbbe2e4..6d1e4bb19 100644 --- a/share/functions/fish_default_key_bindings.fish +++ b/share/functions/fish_default_key_bindings.fish @@ -1,160 +1,92 @@ function fish_default_key_bindings -d "Default (Emacs-like) key bindings for fish" - if not set -q argv[1] - if test "$fish_key_bindings" != "fish_default_key_bindings" - # Allow the user to set the variable universally - set -q fish_key_bindings - or set -g fish_key_bindings - set fish_key_bindings fish_default_key_bindings # This triggers the handler, which calls us again and ensures the user_key_bindings are executed - return - end - # Clear earlier bindings, if any - bind --erase --all - end + if not set -q argv[1] + if test "$fish_key_bindings" != "fish_default_key_bindings" + # Allow the user to set the variable universally + set -q fish_key_bindings; or set -g fish_key_bindings + set fish_key_bindings fish_default_key_bindings # This triggers the handler, which calls us again and ensures the user_key_bindings are executed + return + end + # Clear earlier bindings, if any + bind --erase --all + end - # This is the default binding, i.e. the one used if no other binding matches - bind $argv "" self-insert + # These are shell-specific bindings that we share with vi mode. + __fish_shared_key_bindings - bind $argv \n execute - bind $argv \r execute + # This is the default binding, i.e. the one used if no other binding matches + bind $argv "" self-insert - bind $argv \ck kill-line - bind $argv \cy yank - bind $argv \cx fish_clipboard_copy - bind $argv \cv fish_clipboard_paste - bind $argv \t complete + bind $argv \n execute + bind $argv \r execute - bind $argv \e\n "commandline -i \n" - bind $argv \e\r "commandline -i \n" + bind $argv \ck kill-line - bind $argv \e\[A up-or-search - bind $argv \e\[B down-or-search - bind $argv -k down down-or-search - bind $argv -k up up-or-search + bind $argv \eOC forward-char + bind $argv \eOD backward-char + bind $argv \e\[C forward-char + bind $argv \e\[D backward-char + bind $argv -k right forward-char + bind $argv -k left backward-char - # Some linux VTs output these (why?) - bind $argv \eOA up-or-search - bind $argv \eOB down-or-search - bind $argv \eOC forward-char - bind $argv \eOD backward-char + bind $argv -k dc delete-char + bind $argv -k backspace backward-delete-char + bind $argv \x7f backward-delete-char - bind $argv \e\[C forward-char - bind $argv \e\[D backward-char - bind $argv -k right forward-char - bind $argv -k left backward-char + bind $argv \e\[H beginning-of-line + bind $argv \e\[F end-of-line - bind $argv -k dc delete-char - bind $argv -k backspace backward-delete-char - bind $argv \x7f backward-delete-char + # for PuTTY + # https://github.com/fish-shell/fish-shell/issues/180 + bind $argv \e\[1~ beginning-of-line + bind $argv \e\[3~ delete-char + bind $argv \e\[4~ end-of-line - bind $argv \e\[H beginning-of-line - bind $argv \e\[F end-of-line + # OS X SnowLeopard doesn't have these keys. Don't show an annoying error message. + bind $argv -k home beginning-of-line 2> /dev/null + bind $argv -k end end-of-line 2> /dev/null + bind $argv \e\[3\;2~ backward-delete-char # Mavericks Terminal.app shift-delete - # for PuTTY - # https://github.com/fish-shell/fish-shell/issues/180 - bind $argv \e\[1~ beginning-of-line - bind $argv \e\[3~ delete-char - bind $argv \e\[4~ end-of-line + bind $argv \ca beginning-of-line + bind $argv \ce end-of-line + bind $argv \ch backward-delete-char + bind $argv \cp up-or-search + bind $argv \cn down-or-search + bind $argv \cf forward-char + bind $argv \cb backward-char + bind $argv \ct transpose-chars + bind $argv \et transpose-words + bind $argv \eu upcase-word - # OS X SnowLeopard doesn't have these keys. Don't show an annoying error message. - bind $argv -k home beginning-of-line 2>/dev/null - bind $argv -k end end-of-line 2>/dev/null - bind $argv \e\[3\;2~ backward-delete-char # Mavericks Terminal.app shift-delete + # This clashes with __fish_list_current_token + # bind $argv \el downcase-word + bind $argv \ec capitalize-word + bind $argv \e\x7f backward-kill-word + bind $argv \eb backward-word + bind $argv \ef forward-word + bind $argv \e\[1\;5C forward-word + bind $argv \e\[1\;5D backward-word + bind $argv -k ppage beginning-of-history + bind $argv -k npage end-of-history + bind $argv \e\< beginning-of-buffer + bind $argv \e\> end-of-buffer - bind $argv \e\eOC nextd-or-forward-word - bind $argv \e\eOD prevd-or-backward-word - bind $argv \e\e\[C nextd-or-forward-word - bind $argv \e\e\[D prevd-or-backward-word - bind $argv \eO3C nextd-or-forward-word - bind $argv \eO3D prevd-or-backward-word - bind $argv \e\[3C nextd-or-forward-word - bind $argv \e\[3D prevd-or-backward-word - bind $argv \e\[1\;3C nextd-or-forward-word - bind $argv \e\[1\;3D prevd-or-backward-word + bind \ed forward-kill-word + bind \ed kill-word - bind $argv \e\eOA history-token-search-backward - bind $argv \e\eOB history-token-search-forward - bind $argv \e\e\[A history-token-search-backward - bind $argv \e\e\[B history-token-search-forward - bind $argv \eO3A history-token-search-backward - bind $argv \eO3B history-token-search-forward - bind $argv \e\[3A history-token-search-backward - bind $argv \e\[3B history-token-search-forward - bind $argv \e\[1\;3A history-token-search-backward - bind $argv \e\[1\;3B history-token-search-forward + # escape cancels stuff + bind \e cancel - bind $argv \ca beginning-of-line - bind $argv \ce end-of-line - bind $argv \ey yank-pop - bind $argv \ch backward-delete-char - bind $argv \cp up-or-search - bind $argv \cn down-or-search - bind $argv \cf forward-char - bind $argv \cb backward-char - bind $argv \ct transpose-chars - bind $argv \et transpose-words - bind $argv \eu upcase-word + # Ignore some known-bad control sequences + # https://github.com/fish-shell/fish-shell/issues/1917 + bind \e\[I 'begin;end' + bind \e\[O 'begin;end' - # This clashes with __fish_list_current_token - # bind $argv \el downcase-word - bind $argv \ec capitalize-word - bind $argv \e\x7f backward-kill-word - bind $argv \eb backward-word - bind $argv \ef forward-word - bind $argv \e\[1\;5C forward-word - bind $argv \e\[1\;5D backward-word - bind $argv \e\[1\;9A history-token-search-backward # iTerm2 - bind $argv \e\[1\;9B history-token-search-forward # iTerm2 - bind $argv \e\[1\;9C nextd-or-forward-word #iTerm2 - bind $argv \e\[1\;9D prevd-or-backward-word #iTerm2 - # Bash compatibility - # https://github.com/fish-shell/fish-shell/issues/89 - bind $argv \e. history-token-search-backward - bind $argv -k ppage beginning-of-history - bind $argv -k npage end-of-history - bind $argv \e\< beginning-of-buffer - bind $argv \e\> end-of-buffer - - bind $argv \el __fish_list_current_token - bind $argv \ew 'set tok (commandline -pt); if test $tok[1]; echo; whatis $tok[1]; commandline -f repaint; end' - bind $argv \cl 'clear; commandline -f repaint' - bind $argv \cc __fish_cancel_commandline - bind $argv \cu backward-kill-line - bind $argv \cw backward-kill-path-component - bind $argv \ed 'set -l cmd (commandline); if test -z "$cmd"; echo; dirh; commandline -f repaint; else; commandline -f kill-word; end' - bind $argv \cd delete-or-exit - - bind \ed forward-kill-word - bind \ed kill-word - - # Allow reading manpages by pressing F1 (many GUI applications) or Alt+h (like in zsh) - bind $argv -k f1 __fish_man_page - bind $argv \eh __fish_man_page - - # This will make sure the output of the current command is paged using the default pager when you press Meta-p - # If none is set, less will be used - bind $argv \ep '__fish_paginate' - - # shift-tab does a tab complete followed by a search - bind $argv --key btab complete-and-search - - # escape cancels stuff - bind \e cancel - - # Ignore some known-bad control sequences - # https://github.com/fish-shell/fish-shell/issues/1917 - bind \e\[I 'begin;end' - bind \e\[O 'begin;end' - - # term-specific special bindings - switch "$TERM" - case 'rxvt*' - bind $argv \e\[8~ end-of-line - bind $argv \eOc forward-word - bind $argv \eOd backward-word - end - - # 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. - bind \e\# __fish_toggle_comment_commandline + # term-specific special bindings + switch "$TERM" + case 'rxvt*' + bind $argv \e\[8~ end-of-line + bind $argv \eOc forward-word + bind $argv \eOd backward-word + end end diff --git a/share/functions/fish_vi_key_bindings.fish b/share/functions/fish_vi_key_bindings.fish index b6b7494e6..fa77c3609 100644 --- a/share/functions/fish_vi_key_bindings.fish +++ b/share/functions/fish_vi_key_bindings.fish @@ -1,10 +1,17 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' - if test "$fish_key_bindings" != "fish_vi_key_bindings" - # Allow the user to set the variable universally - set -q fish_key_bindings; or set -g fish_key_bindings - set fish_key_bindings fish_vi_key_bindings # This triggers the handler, which calls us again and ensures the user_key_bindings are executed - return - end + # Allow any argument to skip setting the variable. + if not set -q argv[1] + # Allow just calling this function to correctly set the bindings. + # Because it's a rather discoverable name, users will execute it + # and without this would then have subtly broken bindings. + if test "$fish_key_bindings" != "fish_vi_key_bindings" + # Allow the user to set the variable universally + set -q fish_key_bindings + or set -g fish_key_bindings + set fish_key_bindings fish_vi_key_bindings # This triggers the handler, which calls us again and ensures the user_key_bindings are executed + return + end + end # The default escape timeout is 300ms. But for users of Vi bindings that can be slightly # annoying when trying to switch to Vi "normal" mode. So set a shorter timeout in this case # unless the user has explicitly set the delay. @@ -17,14 +24,18 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' set init_mode $argv[1] end - # Inherit default key bindings. + # Inherit shared key bindings. # Do this first so vi-bindings win over default. bind --erase --all - fish_default_key_bindings -M insert - fish_default_key_bindings -M default + for mode in insert default visual + __fish_shared_key_bindings -M $mode + end + + bind -M insert \r execute + bind -M insert \n execute + + bind -M insert "" self-insert - # Remove the default self-insert bindings in default mode - bind -e "" -M default # Add way to kill current command line while in insert mode. bind -M insert \cc __fish_cancel_commandline # Add a way to switch from insert to normal (command) mode. @@ -34,17 +45,8 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' bind :q exit bind \cd exit bind -m insert \cc __fish_cancel_commandline - bind h backward-char - bind l forward-char - bind \e\[C forward-char - bind \e\[D backward-char - - # Some terminals output these when they're in in keypad mode. - bind \eOC forward-char - bind \eOD backward-char - - bind -k right forward-char - bind -k left backward-char + bind -M default h backward-char + bind -M default l forward-char bind -m insert \n execute bind -m insert \r execute bind -m insert i force-repaint @@ -169,10 +171,6 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' bind P backward-char yank bind gp yank-pop - ### Overrides - # This is complete in vim - bind -M insert \cx end-of-line - bind '"*p' "commandline -i ( xsel -p; echo )[1]" bind '"*P' backward-char "commandline -i ( xsel -p; echo )[1]" @@ -186,12 +184,6 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' # # visual mode # - bind -M visual \e\[C forward-char - bind -M visual \e\[D backward-char - bind -M visual -k right forward-char - bind -M visual -k left backward-char - bind -M insert \eOC forward-char - bind -M insert \eOD backward-char bind -M visual h backward-char bind -M visual l forward-char @@ -231,7 +223,4 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' # the commenting chars so the command can be further edited then executed. bind -M default \# __fish_toggle_comment_commandline bind -M visual \# __fish_toggle_comment_commandline - bind -M default \e\# __fish_toggle_comment_commandline - bind -M insert \e\# __fish_toggle_comment_commandline - bind -M visual \e\# __fish_toggle_comment_commandline end diff --git a/tests/bind.expect b/tests/bind.expect index 7c5942410..00da321c6 100644 --- a/tests/bind.expect +++ b/tests/bind.expect @@ -80,18 +80,6 @@ expect_prompt -re {\r\nsuccess: default escape timeout\r\n} { puts stderr "vi replace line, default timeout: long delay" } -# Verify that a human can transpose words using \et (which is an emacs default -# binding but should be valid while in vi insert or normal mode). -send "echo abc def" -send "\033" -sleep 0.010 -send "t\r" -expect_prompt -re {\r\ndef abc\r\n} { - puts "vi transpose words, default timeout: short delay" -} unmatched { - puts stderr "vi transpose words, default timeout: short delay" -} - # Test replacing a single character. send "echo TEXT" send "\033" diff --git a/tests/bind.expect.out b/tests/bind.expect.out index 07f09fdec..b9ff26444 100644 --- a/tests/bind.expect.out +++ b/tests/bind.expect.out @@ -4,7 +4,6 @@ emacs transpose words, default timeout: long delay prime vi mode, default timeout vi-mode default timeout set correctly vi replace line, default timeout: long delay -vi transpose words, default timeout: short delay vi mode replace char, default timeout: long delay vi replace line, 100ms timeout: long delay vi replace line, 100ms timeout: short delay