From 5b39efc96d0b6ed1b1c03735c524c62c605165ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Sat, 8 Jan 2022 17:02:56 -0800 Subject: [PATCH] Support incrementing/decrementing the number below the cursor Vim supports incrementing & decrementing the number below the cursor (or after it) via Ctrl-a and Ctrl-x, respectively. Given fish's Vi mode support, it makes sense to provide similar functionality when working on the command line, to provide a more natural environment for Vim users. With this change we add the necessary functionality. Closes: #8320 Closes #11570 --- CHANGELOG.rst | 1 + po/de.po | 3 + po/en.po | 3 + po/fr.po | 3 + po/pl.po | 3 + po/pt_BR.po | 3 + po/sv.po | 3 + po/zh_CN.po | 3 + share/functions/fish_vi_key_bindings.fish | 83 ++++++++++++++++ tests/checks/vi.fish | 115 ++++++++++++++++++++++ 10 files changed, 220 insertions(+) create mode 100644 tests/checks/vi.fish diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8f82ff009..166dfc1af 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -64,6 +64,7 @@ New or improved bindings this is only enabled by default if the terminal advertises support for the ``indn`` capability via XTGETTCAP. - Bindings using shift with non-ASCII letters (such as :kbd:`ctrl-shift-ä`) are now supported. If there is any modifier other than shift, this is the recommended notation (as opposed to :kbd:`ctrl-Ä`). +- Vi mode has learned :kbd:`ctrl-a` (increment) and :kbd:`ctrl-x` (decrement) (:issue:`11570`). Completions ^^^^^^^^^^^ diff --git a/po/de.po b/po/de.po index 4b223c320..2464578fc 100644 --- a/po/de.po +++ b/po/de.po @@ -74706,6 +74706,9 @@ msgstr "" msgid "increase verbosity level by one" msgstr "" +msgid "increment or decrement the number below the cursor" +msgstr "" + msgid "incremental mode" msgstr "" diff --git a/po/en.po b/po/en.po index e65048bc0..19263de6a 100644 --- a/po/en.po +++ b/po/en.po @@ -74702,6 +74702,9 @@ msgstr "" msgid "increase verbosity level by one" msgstr "" +msgid "increment or decrement the number below the cursor" +msgstr "" + msgid "incremental mode" msgstr "" diff --git a/po/fr.po b/po/fr.po index 13dc5aa5e..cb30febe5 100644 --- a/po/fr.po +++ b/po/fr.po @@ -74803,6 +74803,9 @@ msgstr "" msgid "increase verbosity level by one" msgstr "Incrémenter le niveau de verbosité" +msgid "increment or decrement the number below the cursor" +msgstr "" + msgid "incremental mode" msgstr "" diff --git a/po/pl.po b/po/pl.po index 7537d6694..944d2ee2a 100644 --- a/po/pl.po +++ b/po/pl.po @@ -74698,6 +74698,9 @@ msgstr "" msgid "increase verbosity level by one" msgstr "" +msgid "increment or decrement the number below the cursor" +msgstr "" + msgid "incremental mode" msgstr "" diff --git a/po/pt_BR.po b/po/pt_BR.po index 1a725ceeb..b9c1b4c78 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -74725,6 +74725,9 @@ msgstr "" msgid "increase verbosity level by one" msgstr "" +msgid "increment or decrement the number below the cursor" +msgstr "" + msgid "incremental mode" msgstr "" diff --git a/po/sv.po b/po/sv.po index 6c1fed40d..1872eeb1c 100644 --- a/po/sv.po +++ b/po/sv.po @@ -74701,6 +74701,9 @@ msgstr "" msgid "increase verbosity level by one" msgstr "" +msgid "increment or decrement the number below the cursor" +msgstr "" + msgid "incremental mode" msgstr "" diff --git a/po/zh_CN.po b/po/zh_CN.po index 7681923af..c644e53be 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -74701,6 +74701,9 @@ msgstr "增加动词" msgid "increase verbosity level by one" msgstr "将动词水平增加一个" +msgid "increment or decrement the number below the cursor" +msgstr "" + msgid "incremental mode" msgstr "递增模式" diff --git a/share/functions/fish_vi_key_bindings.fish b/share/functions/fish_vi_key_bindings.fish index 83242aafb..a25bcaa1c 100644 --- a/share/functions/fish_vi_key_bindings.fish +++ b/share/functions/fish_vi_key_bindings.fish @@ -1,3 +1,80 @@ +alias fish_vi_dec 'fish_vi_inc_dec dec' +alias fish_vi_inc 'fish_vi_inc_dec inc' + +# TODO: Currently we do not support hexadecimal and octal values. +function fish_vi_inc_dec --description 'increment or decrement the number below the cursor' + # The cursor is zero based, but all string functions assume 1 to be + # the lowest index. Adjust accordingly. + set --local cursor (math -- (commandline --cursor) + 1) + set --local line (commandline --current-buffer | string collect) + + set --local candidate (string sub --start $cursor -- $line | string collect) + if set --local just_found (string match --regex '^-?[0-9]+' -- $candidate) + # Search from the current cursor position backwards for as long as we + # can identify a valid number. + set --function found $just_found + set --function found_at $cursor + set --local end (math -- $cursor + (string length -- $found) - 1) + + set i (math -- $cursor - 1) + while [ $i -ge 1 ] + set candidate (string sub --start $i --end $end -- $line) + if set just_found (string match --regex '^-?[0-9]+$' -- $candidate) + set found $just_found + set found_at $i + # We found a candidate, but continue to make sure that we captured + # the complete number and not just part of it. + else + # We have already found a number earlier. Work with that. + break + end + + set i (math -- $i - 1) + end + else + # We didn't find a match below the cursor. Mirror Vim behavior by + # checking ahead as well. + for i in (seq (math -- $cursor + 1) (math -- (string length -- $line) - 1)) + set candidate (string sub --start $i -- $line | string collect) + + if set just_found (string match --regex '^-?[0-9]+' -- $candidate) + set found $just_found + set found_at $i + break + end + end + + if [ -z "$found" ] + return + end + end + + if [ $argv = inc ] + set number (math -- $found + 1) + else if [ $argv = dec ] + set number (math -- $found - 1) + end + + set --local number_abs (string trim --left --chars=- -- $number) + set --local signed $status + set --local found_abs (string trim --left --chars=- -- $found) + set number (string pad --char 0 --width (string length -- $found_abs) -- $number_abs) + if test $signed -eq 0 + set number "-$number" + end + + # `string sub` may bitch about `--end` being zero if `found_at` is 1. + # So ignore errors here... + set --local before (string sub --end (math -- $found_at - 1) -- $line 2> /dev/null | string collect) + set --local after (string sub --start (math -- $found_at + (string length -- $found)) -- $line | string collect) + commandline --replace -- "$before$number$after" + # Need to subtract two here because 1) cursor is zero based 2) + # `found_at` is the index of the first character of the match, but we + # want the one before that. + commandline --cursor -- (math -- $found_at + (string length -- $number) - 2) + commandline --function -- repaint +end + function fish_vi_key_bindings --description 'vi-like key bindings for fish' if contains -- -h $argv or contains -- --help $argv @@ -271,6 +348,12 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish' bind -s --preset -M replace backspace backward-char bind -s --preset -M replace shift-backspace backward-char + # + # Increment or decrement number under the cursor with ctrl+x ctrl+a + # + bind -s --preset -M default ctrl-a fish_vi_inc + bind -s --preset -M default ctrl-x fish_vi_dec + # # visual mode # diff --git a/tests/checks/vi.fish b/tests/checks/vi.fish new file mode 100644 index 000000000..1fe7d403b --- /dev/null +++ b/tests/checks/vi.fish @@ -0,0 +1,115 @@ +# RUN: %fish --interactive %s + +fish_vi_key_bindings + +commandline '1'; commandline --cursor 0; fish_vi_dec +commandline --current-buffer +# CHECK: 0 + +commandline '0'; commandline --cursor 0; fish_vi_dec +commandline --current-buffer +# CHECK: -1 + +commandline -- '-1'; commandline --cursor 0; fish_vi_dec +commandline --current-buffer +# CHECK: -2 + +commandline -- '-1'; commandline --cursor 0; fish_vi_inc +commandline --current-buffer +# CHECK: 0 + +commandline '0'; commandline --cursor 0; fish_vi_inc +commandline --current-buffer +# CHECK: 1 + +commandline '123'; commandline --cursor 0; fish_vi_inc +commandline --current-buffer +# CHECK: 124 + +commandline '123'; commandline --cursor 0; fish_vi_dec +commandline --current-buffer +# CHECK: 122 + +commandline '123'; commandline --cursor 1; fish_vi_inc +commandline --current-buffer +# CHECK: 124 + +commandline '123'; commandline --cursor 1; fish_vi_dec +commandline --current-buffer +# CHECK: 122 + +commandline '123'; commandline --cursor 2; fish_vi_inc +commandline --current-buffer +# CHECK: 124 + +commandline '123'; commandline --cursor 2; fish_vi_dec +commandline --current-buffer +# CHECK: 122 + +commandline 'abc123'; commandline --cursor 1; fish_vi_inc +commandline --current-buffer +# CHECK: abc124 + +commandline 'abc123'; commandline --cursor 1; fish_vi_dec +commandline --current-buffer +# CHECK: abc122 + +commandline 'abc123def'; commandline --cursor 1; fish_vi_inc +commandline --current-buffer +# CHECK: abc124def + +commandline 'abc123def'; commandline --cursor 1; fish_vi_dec +commandline --current-buffer +# CHECK: abc122def + +commandline 'abc123def'; commandline --cursor 5; fish_vi_inc +commandline --current-buffer +# CHECK: abc124def + +commandline 'abc123def'; commandline --cursor 5; fish_vi_dec +commandline --current-buffer +# CHECK: abc122def + +commandline 'abc123def'; commandline --cursor 6; fish_vi_inc +commandline --current-buffer +# CHECK: abc123def + +commandline 'abc123def'; commandline --cursor 6; fish_vi_dec +commandline --current-buffer +# CHECK: abc123def + +commandline 'abc99def'; commandline --cursor 1; fish_vi_inc +commandline --current-buffer +# CHECK: abc100def + +commandline 'abc99def'; commandline --cursor 1; fish_vi_dec +commandline --current-buffer +# CHECK: abc98def + +commandline 'abc-99def'; commandline --cursor 1; fish_vi_inc +commandline --current-buffer +# CHECK: abc-98def + +commandline 'abc-99def'; commandline --cursor 1; fish_vi_dec +commandline --current-buffer +# CHECK: abc-100def + +commandline '2022-04-09'; commandline --cursor 7; fish_vi_inc +commandline --current-buffer +# CHECK: 2022-04-08 + +commandline 'to 2022-04-09'; commandline --cursor 4; fish_vi_inc +commandline --current-buffer +# CHECK: to 2023-04-09 + +commandline 'to 2022-04-09'; commandline --cursor 4; fish_vi_dec +commandline --current-buffer +# CHECK: to 2021-04-09 + +commandline 'to 2022-04-09'; commandline --cursor 11; fish_vi_dec +commandline --current-buffer +# CHECK: to 2022-04-10 + +commandline 'to 2022-04-09'; commandline --cursor 11; fish_vi_inc +commandline --current-buffer +# CHECK: to 2022-04-08