about summary refs log tree commit diff
diff options
context:
space:
mode:
authormidchildan <git@midchildan.org>2024-02-29 22:34:33 +0900
committerOliver Kiddle <opk@zsh.org>2024-03-05 00:05:21 +0100
commit36a2d5cfa49a6b7d699269cb4f22d5f3d0255bc8 (patch)
tree4b0f5bec64fae4c859764deb42fe32191ce53dab
parentd1ff06f99185bb14554c6a48e0466aee6466ecac (diff)
downloadzsh-36a2d5cfa49a6b7d699269cb4f22d5f3d0255bc8.tar.gz
zsh-36a2d5cfa49a6b7d699269cb4f22d5f3d0255bc8.tar.xz
zsh-36a2d5cfa49a6b7d699269cb4f22d5f3d0255bc8.zip
52641: incarg: add a backward variant and make it repeatable
-rw-r--r--ChangeLog5
-rw-r--r--Doc/Zsh/contrib.yo8
-rw-r--r--Functions/Zle/incarg64
-rw-r--r--Test/X05zleincarg.ztst358
4 files changed, 347 insertions, 88 deletions
diff --git a/ChangeLog b/ChangeLog
index 9718d0cae..5c839cd19 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2024-03-05  Oliver Kiddle  <opk@zsh.org>
+
+	* 52641: midchildan: Doc/Zsh/contrib.yo, Functions/Zle/incarg,
+	Test/X05zleincarg.ztst: add a backward variant and make it repeatable
+
 2024-03-02  Bart Schaefer  <schaefer@zsh.org>
 
 	* 52652: Src/params.c, Test/D04parameter.ztst: fix obscure bug
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index ea00f0ccc..e682c800a 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -2635,7 +2635,8 @@ When the widget is named tt(incarg), the widget will increment an integer
 placed under the cursor placed or just to the left of it. tt(decarg), on the
 other hand, decrements the integer. When the name is prefixed with tt(vi),
 the cursor will jump to the nearest integer after the cursor before incrementing
-it.
+it. The tt(vi) prefix can also be combined with a tt(backward-) prefix to make
+the widget search backwards for numbers.
 
 There's also a tt(sync-) prefix that can be added to the widget name. This
 variant is used for creating a sequence of numbers on split terminals with
@@ -2643,8 +2644,9 @@ synchronized key input. The first pane won't increment the integer at all, but
 each pane after that will have the integer incremented once more than the
 previous pane. It currently supports tmux and iTerm2.
 
-The prefixes tt(vi) and tt(sync-) can be combined, for example, into
-tt(vim-sync-). In this case, the tt(vi) prefix should come first.
+The prefixes tt(vi), tt(backward-), and tt(sync-) can be combined, for example,
+into tt(vim-sync-) or tt(vim-backward-sync-). The tt(vi) prefix needs to be
+at the very beginning.
 
 example(bindkey '^X+' incarg)
 )
diff --git a/Functions/Zle/incarg b/Functions/Zle/incarg
index 9d56b21f6..0cfaf9ff5 100644
--- a/Functions/Zle/incarg
+++ b/Functions/Zle/incarg
@@ -41,11 +41,20 @@ emulate -L zsh
 #   This behaves like Vim's CTRL-A / CTRL-X. It moves the cursor to the nearest
 #   number after the cursor and increments or decrements it.
 #
+# - vim-backward-incarg / vim-backward-decarg
+#
+#   This behaves like vim-incarg & vim-decarg, but it searches backwards for a
+#   number.
+#
 # - vim-sync-incarg / vim-sync-decarg
 #
 #   This combines the behavior of the vim- and sync- variants. It's inspired by
 #   Vim's g_CTRL-A / g_CTRL-X.
 #
+# - vim-backward-sync-incarg / vim-backward-sync-decarg
+#
+#   This combines the behavior of the vim-backward- and sync- variants.
+#
 # Example Usage:
 #
 #   autoload -Uz incarg
@@ -58,9 +67,13 @@ emulate -L zsh
 #     'g^A' vim-sync-incarg \
 #     'g^X' vim-sync-decarg
 
+zle -f vichange
+
 setopt localoptions extended_glob
 local match mbegin mend MATCH MBEGIN MEND i
 
+[[ -z "$BUFFER" ]] && return 1
+
 # find the number and determine the base
 integer pos=$(( CURSOR + 1 )) base=0
 
@@ -104,11 +117,35 @@ fi
 
 if (( base == 0 )); then
   if [[ "$WIDGET" == vi* ]]; then
-    # jump to the nearest number after the cursor
-    while [[ "$BUFFER[pos]" == [^0-9] ]]; do
-      (( pos++ ))
-      (( pos > $#BUFFER )) && return 1
-    done
+    if [[ "$WIDGET" == *backward-* ]]; then
+      # search backwards for a number
+      while true; do
+        case "$BUFFER[1,pos]" in
+          *0[xX][0-9a-fA-F]##) base=16 ;;
+          *0[oO][0-7]##) base=8 ;;
+          *0[bB][01]##) base=2 ;;
+          *[0-9]) base=10 ;;
+          *-)
+            case "$BUFFER[pos,-1]" in
+              -0[xX][0-9a-fA-F]*) ;;
+              -0[oO][0-7]*) ;;
+              -0[bB][01]*) ;;
+              -[0-9]*) base=10 ;;
+            esac
+            ;;
+        esac
+        (( base != 0 )) && break
+
+        (( pos-- ))
+        (( pos <= 0 )) && return 1
+      done
+    else
+      # jump to the nearest number after the cursor
+      while [[ "$BUFFER[pos]" == [^0-9] ]]; do
+        (( pos++ ))
+        (( pos > $#BUFFER )) && return 1
+      done
+    fi
   fi
 
   # check for a prefix right after the cursor and jump right after it, if any
@@ -204,6 +241,12 @@ fi
 
 local old="$BUFFER[first,last]"
 integer oldlen=$#BUFFER
+integer oldnum="$base#$old" 2> /dev/null
+
+# -00 should increment to 01 instead of 001
+if [[ "$BUFFER[first]" == '-' ]] && (( oldnum == 0 )); then
+  (( ndigits-- ))
+fi
 
 local fmt1 fmt2
 case "$base" in
@@ -214,10 +257,12 @@ case "$base" in
 esac
 
 local raw_result padded
+# $(( )) outputs an error message to stderr when integer truncation occurs
 printf -v raw_result "%0$ndigits$fmt1" $(( [$fmt2] "$base#$old" + delta )) 2> /dev/null
 padded="${raw_result// /0}"
+integer newnum="$base#$padded" 2> /dev/null
 
-integer oldnum="$base#$old" newnum="$base#$padded" 2> /dev/null
+# try to detect integer truncation
 if (( base != 10 && newnum < 0
         || delta > 0 && newnum < oldnum
         || delta < 0 && newnum > oldnum  )); then
@@ -242,7 +287,12 @@ if zstyle -t ":zle:$WIDGET" debug; then
   zle -M "[$WIDGET] base: $base delta: $delta old: '$old' new: '$new'"
 fi
 
-BUFFER[first,last]="$new"
+if (( 0 < first && first <= last && last <= $#BUFFER )); then
+  BUFFER[first,last]="$new"
+else
+  zle -M "[$WIDGET] The detected location of the integer was invalid. [location=BUFFER[$first,$last]]"
+  return 1
+fi
 
 integer offset=0
 if [[ "$WIDGET" == vi* ]]; then
diff --git a/Test/X05zleincarg.ztst b/Test/X05zleincarg.ztst
index 2a6aa2d3f..cd9817c82 100644
--- a/Test/X05zleincarg.ztst
+++ b/Test/X05zleincarg.ztst
@@ -10,7 +10,7 @@
   fi
   zpty_run '
     autoload -Uz incarg
-    for name in {,vim-}{,sync-}{inc,dec}arg; do
+    for name in {,vim-,vim-backward-}{,sync-}{inc,dec}arg; do
       zle -N "$name" incarg
     done
     bindkey -v "^N" incarg
@@ -21,6 +21,8 @@
     bindkey -a "^P" vim-decarg
     bindkey -a "^F" vim-sync-incarg
     bindkey -a "^B" vim-sync-decarg
+    bindkey -a "^E" vim-backward-incarg
+    bindkey -a "^Y" vim-backward-decarg
     unset TMUX_PANE ITERM_SESSION_ID
     tmux() {
       echo "$TMUX_PANE"
@@ -29,26 +31,40 @@
 
 %test
 
+# Basic increment & decrement
+
   zletest $'0\C-n'
-0:increment an integer with incarg
+0:incarg increments an integer
 >BUFFER: 1
 >CURSOR: 1
 
   zletest $'0\C-p'
-0:decrement an integer with decarg
+0:decarg decrements an integer
 >BUFFER: -1
 >CURSOR: 2
 
   zletest $'echo 0\e0\C-n'
-0:increment an integer with vim-incarg
+0:vim-incarg increments an integer
 >BUFFER: echo 1
 >CURSOR: 5
 
   zletest $'echo 0\e0\C-p'
-0:decrement an integer with vim-decarg
+0:vim-decarg decrements an integer
 >BUFFER: echo -1
 >CURSOR: 6
 
+  zletest $'echo 0 foo\e\C-e'
+0:vim-backward-incarg increments an integer
+>BUFFER: echo 1 foo
+>CURSOR: 5
+
+  zletest $'echo 0 foo\e\C-y'
+0:vim-backward-decarg decrements an integer
+>BUFFER: echo -1 foo
+>CURSOR: 6
+
+# sync- variants
+
   zletest $'0\C-f'
 0:sync-incarg does nothing on unsupported terminals
 >BUFFER: 0
@@ -57,42 +73,42 @@
   zpty_run 'TMUX_PANE=0'
   zletest $'0\C-f'
   zpty_run 'unset TMUX_PANE'
-0:sync-incarg on tmux in pane 0
+0:sync-incarg does nothing on tmux in pane 0
 >BUFFER: 0
 >CURSOR: 1
 
   zpty_run 'TMUX_PANE=1'
   zletest $'0\C-f'
   zpty_run 'unset TMUX_PANE'
-0:sync-incarg on tmux in pane 1
+0:sync-incarg increments by 1 on tmux in pane 1
 >BUFFER: 1
 >CURSOR: 1
 
   zpty_run 'TMUX_PANE=2'
   zletest $'0\C-f'
   zpty_run 'unset TMUX_PANE'
-0:sync-incarg on tmux in pane 2
+0:sync-incarg increments by 2 on tmux in pane 2
 >BUFFER: 2
 >CURSOR: 1
 
   zpty_run 'ITERM_SESSION_ID=w0t0p0:00000000-0000-0000-0000-000000000000'
   zletest $'0\C-f'
   zpty_run 'unset ITERM_SESSION_ID'
-0:sync-incarg on tmux in pane 0
+0:sync-incarg does nothing on tmux in pane 0
 >BUFFER: 0
 >CURSOR: 1
 
   zpty_run 'ITERM_SESSION_ID=w0t0p1:00000000-0000-0000-0000-000000000000'
   zletest $'0\C-f'
   zpty_run 'unset ITERM_SESSION_ID'
-0:sync-incarg on tmux in pane 1
+0:sync-incarg increments by 1 on tmux in pane 1
 >BUFFER: 1
 >CURSOR: 1
 
   zpty_run 'ITERM_SESSION_ID=w0t0p2:00000000-0000-0000-0000-000000000000'
   zletest $'0\C-f'
   zpty_run 'unset ITERM_SESSION_ID'
-0:sync-incarg on tmux in pane 2
+0:sync-incarg increments by 2 on tmux in pane 2
 >BUFFER: 2
 >CURSOR: 1
 
@@ -100,230 +116,281 @@
   zpty_run 'ITERM_SESSION_ID=w0t0p2:00000000-0000-0000-0000-000000000000'
   zletest $'0\C-f'
   zpty_run 'unset TMUX_PANE ITERM_SESSION_ID'
-0:tmux pane number takes precedence over iTerm2's
+0:sync-incarg prioritizes tmux pane number over iTerm2's
 >BUFFER: 1
 >CURSOR: 1
 
   zletest $'0\e2\C-n'
-0:Providing a numeric argument will change the incremented amount
+0:incarg changes the incremented amount based on the numeric argument
 >BUFFER: 2
 >CURSOR: 0
 
   zpty_run 'incarg=3'
   zletest $'0\e\C-n'
   zpty_run 'unset incarg'
-0:Setting the incarg variable will change the default incremented amount
+0:incarg changes the default incremented amount based on the incarg variable
 >BUFFER: 3
 >CURSOR: 0
 
   zpty_run 'incarg=3'
   zletest $'0\e2\C-n'
   zpty_run 'unset incarg'
-0:A numeric argument will take precedence over the incarg variable
+0:incarg prioritizes the numeric argument over the incarg variable
 >BUFFER: 2
 >CURSOR: 0
 
   zpty_run 'TMUX_PANE=2'
   zletest $'0\e2\C-f'
   zpty_run 'unset TMUX_PANE'
-0:Providing a numeric argument will work for the sync- variants of incarg
+0:The sync- variants of incarg takes the numeric argument into account
 >BUFFER: 4
 >CURSOR: 0
 
+# Leading zeros
+
   zletest $'000\C-n'
-0:Incrementing a decimal integer preserves leading zeros
+0:incarg preserves leading zeros of decimal integers
 >BUFFER: 001
 >CURSOR: 3
 
   zletest $'-001\C-n\C-n'
-0:Leading zeros are preserved when the digit turns from negative to positive
+0:incarg preserves leading zeros when the digit turns from negative to positive
 >BUFFER: 001
 >CURSOR: 3
 
   zletest $'001\C-p\C-p'
-0:Leading zeros are preserved when the digit turns from positive to negative
+0:incarg preserves leading zeros when the digit turns from positive to negative
 >BUFFER: -001
 >CURSOR: 4
 
   zletest $'001\e1000\C-n'
-0:Incrementing an integer works when the result has more zeros than the original
+0:incarg works when the result has more number of digits than the original
 >BUFFER: 1001
 >CURSOR: 3
 
   zletest $'001\e2000\C-p'
-0:Decrementing an integer with leading zeros works when the result has more digits than the original
+0:decargs works on integers with leading zeros when the result has more digits than the original
 >BUFFER: -1999
 >CURSOR: 4
 
+  zletest $'-000\C-n'
+0:incarg produces the correct number of zeros when incrementing integers starting with -0
+>BUFFER: 001
+>CURSOR: 3
+
+  zletest $'-000\C-p'
+0:decarg produces the correct number of zeros when incrementing integers starting with -0
+>BUFFER: -001
+>CURSOR: 4
+
+  zpty_run 'incarg=0'
+  zletest $'-000\C-n'
+  zpty_run 'unset incarg'
+0:incarg removes the sign when the target integer starts with -0 and the increment amount is 0
+>BUFFER: 000
+>CURSOR: 3
+
+  zletest $'-0\C-n'
+0:incarg turns -0 into 1
+>BUFFER: 1
+>CURSOR: 1
+
+  zletest $'-0\C-p'
+0:decarg turns -0 into -1
+>BUFFER: -1
+>CURSOR: 2
+
+  zpty_run 'incarg=0'
+  zletest $'-0\C-n'
+  zpty_run 'unset incarg'
+0:incarg turns -0 into 0 when the increment amount is 0
+>BUFFER: 0
+>CURSOR: 1
+
+# Binaries
+
   zletest $'0b11\C-n'
-0:Increment a binary integer
+0:incarg can increment a binary integer
 >BUFFER: 0b100
 >CURSOR: 5
 
   zletest $'0B11\C-n'
-0:Increment a binary integer with an upper case prefix
+0:incarg can increment a binary integer with an upper case prefix
 >BUFFER: 0B100
 >CURSOR: 5
 
   zletest $'0b100\C-p'
-0:Decrement a binary integer
+0:decarg can decrement a binary integer
 >BUFFER: 0b11
 >CURSOR: 4
 
   zletest $'0b0011\C-n'
-0:Increment a binary integer preserves leading zeros
+0:incarg can preserve leading zeros of binaries
 >BUFFER: 0b0100
 >CURSOR: 6
 
   zletest $'0b001\e8\C-n'
-0:Incrementing a binary integer work when the result has more zeros than the original
+0:incarg works on binaries when the result has more zeros than the original
 >BUFFER: 0b1001
 >CURSOR: 5
 
   zletest $'0b0\C-p'
-0:Decrementing a binary integer to a negative value will fail
+0:decarg fails to produce a negative binary value
 >BUFFER: 0b0
 >CURSOR: 3
 
+# Octals
+
   zletest $'0o7\C-n'
-0:Increment an octal integer
+0:incarg can increment an octal integer
 >BUFFER: 0o10
 >CURSOR: 4
 
   zletest $'0O7\C-n'
-0:Increment an octal integer with an upper case prefix
+0:incarg can increment an octal integer with an upper case prefix
 >BUFFER: 0O10
 >CURSOR: 4
 
   zletest $'0o10\C-p'
-0:Decrement an octal integer
+0:decarg can decrement an octal integer
 >BUFFER: 0o7
 >CURSOR: 3
 
   zletest $'0o0\C-p'
-0:Decrementing an octal integer to a negative value will fail
+0:decarg fails to produce a negative octal value
 >BUFFER: 0o0
 >CURSOR: 3
 
+# Hexadecimals
+
   zletest $'0x9\C-n'
-0:Increment a hexadecimal integer
+0:incarg can increment a hexadecimal integer
 >BUFFER: 0xa
 >CURSOR: 3
 
   zletest $'0X9\C-n'
-0:Increment a hexadecimal integer with an upper case prefix
+0:incarg can increment a hexadecimal integer with an upper case prefix
 >BUFFER: 0XA
 >CURSOR: 3
 
   zletest $'0xf\C-n'
-0:Increment a hexadecimal integer with no numeric digit
+0:incarg can increment a hexadecimal integer with no numeric digit
 >BUFFER: 0x10
 >CURSOR: 4
 
   zletest $'0x10\C-p'
-0:Decrement a hexadecimal integer
+0:decarg can decrement a hexadecimal integer
 >BUFFER: 0xf
 >CURSOR: 3
 
   zletest $'0x0\C-p'
-0:Decrementing an octal integer to a negative value will fail
+0:decarg fails to produce a negative hexadecimal value
 >BUFFER: 0x0
 >CURSOR: 3
 
   zletest $'0x0b1\C-n'
-0:a number that starts with 0x0b is interpreted as a hexadecimal integer
+0:incarg interprets integers starting with 0x0b as a hexadecimal
 >BUFFER: 0x0b2
 >CURSOR: 5
 
+  zletest $'0x0b1\e\C-e'
+0:vim-backward-incarg interprets integers starting with 0x0b as a hexadecimal
+>BUFFER: 0x0b2
+>CURSOR: 4
+
+# Cursor position - incarg
+
+  zletest $'echo 012ab\eF i\C-n'
+0:incarg does nothing when the cursor is placed just to the left of an integer
+>BUFFER: echo 012ab
+>CURSOR: 4
+
+  zletest $'echo 012ab\eF0i\C-n'
+0:incarg works when the cursor is placed at the leftmost digit of an integer
+>BUFFER: echo 013ab
+>CURSOR: 8
+
+  zletest $'echo 012ab\eF1i\C-n'
+0:incarg works when the cursor is placed at the inner digit of an integer
+>BUFFER: echo 013ab
+>CURSOR: 8
+
+  zletest $'echo 012ab\eF2i\C-n'
+0:incarg works when the cursor is placed at the rightmost digit of an integer
+>BUFFER: echo 013ab
+>CURSOR: 8
+
+  zletest $'echo 012ab\eFai\C-n'
+0:incarg works when the cursor is placed just to the right of an integer
+>BUFFER: echo 013ab
+>CURSOR: 8
+
+  zletest $'echo 012ab\ei\C-n'
+0:incarg does nothing when the cursor is placed more than a single letter away to the right
+>BUFFER: echo 012ab
+>CURSOR: 9
+
   zletest $'10x9\e0\C-n'
-0:[0-9]0x[0-9a-f] will become [0-9]1x[0-9a-f] when incremented from the left of x
+0:incarg turns [0-9]0x[0-9a-f] into [0-9]1x[0-9a-f] when the cursor is at the left of x
 >BUFFER: 11x9
 >CURSOR: 1
 
   zletest $'10x9\eFx\C-n'
-0:[0-9]0x[0-9a-f] will increment the hexadecimal 0x[0-9a-f] when the cursor is on x
+0:incarg takes [0-9]0x[0-9a-f] and increments the hexadecimal part when the cursor is on x
 >BUFFER: 10xa
 >CURSOR: 3
 
   zletest $'10x9\e\C-n'
-0:[0-9]0x[0-9a-f] will increment the hexadecimal 0x[0-9a-f] when the cursor is on the right of x
+0:incarg takes [0-9]0x[0-9a-f] and increments the hexadecimal part when the cursor is at the right of x
 >BUFFER: 10xa
 >CURSOR: 3
 
   zletest $'10b1\e0\C-n'
-0:[0-9]0b[01] will become [0-9]1b[01] when incremented from the left of b
+0:incarg turns [0-9]0b[01] into [0-9]1b[01] when the cursor is at the left of b
 >BUFFER: 11b1
 >CURSOR: 1
 
   zletest $'10b1\eFb\C-n'
-0:[0-9]0b[01] will increment the binary 0b[01] when the cursor is on b
+0:incarg takes [0-9]0b[01] and increments the binary part when the cursor is on b
 >BUFFER: 10b10
 >CURSOR: 4
 
   zletest $'10b1\e\C-n'
-0:[0-9]0b[01] will increment the binary 0b[01] when the cursor is on the right of b
+0:incarg takes [0-9]0b[01] and increments binary part when the cursor is at the right of b
 >BUFFER: 10b10
 >CURSOR: 4
 
   zletest $'10o7\e0\C-n'
-0:[0-9]0o[0-7] will become [0-9]1o[0-7] when incremented from the left of o
+0:incarg turns [0-9]0o[0-7] into [0-9]1o[0-7] when the cursor is at the left of o
 >BUFFER: 11o7
 >CURSOR: 1
 
   zletest $'10o7\eFo\C-n'
-0:[0-9]0o[0-7] will increment the octal 0o[0-7] when the cursor is on o
+0:incarg takes [0-9]0o[0-7] and increments the octal part when the cursor is on o
 >BUFFER: 10o10
 >CURSOR: 4
 
   zletest $'10o7\e\C-n'
-0:[0-9]0o[0-7] will increment the octal 0o[0-7] when the cursor is on the right of o
+0:incarg takes [0-9]0o[0-7] and increments the octal part when the cursor is at the right of o
 >BUFFER: 10o10
 >CURSOR: 4
 
   zletest $'0b0x9\eF0\C-n'
-0:0b0x[0-9a-f] will increment the binary 0b0 when the cursor is on the left of x
+0:incarg takes 0b0x[0-9a-f] and increments the binary part when the cursor is at the left of x
 >BUFFER: 0b1x9
 >CURSOR: 2
 
   zletest $'0b0x9\eFx\C-n'
-0:0b0x[0-9a-f] will increment the hexadecimal 0x[0-9a-f] when the cursor is on top of x
+0:incarg takes 0b0x[0-9a-f] and increments the hexadecimal part when the cursor is on x
 >BUFFER: 0b0xa
 >CURSOR: 4
 
   zletest $'0b0x9\e\C-n'
-0:0b0x[0-9a-f] will increment the hexadecimal 0x[0-9a-f] when the cursor is on the right of x
+0:incarg takes 0b0x[0-9a-f] and increments the hexadecimal part when the cursor is at the right of x
 >BUFFER: 0b0xa
 >CURSOR: 4
 
-  zletest $'echo 012ab\eF i\C-n'
-0:incarg does nothing when the cursor is placed just to the left of an integer
->BUFFER: echo 012ab
->CURSOR: 4
-
-  zletest $'echo 012ab\eF0i\C-n'
-0:incarg works when the cursor is placed at the leftmost digit of an integer
->BUFFER: echo 013ab
->CURSOR: 8
-
-  zletest $'echo 012ab\eF1i\C-n'
-0:incarg works when the cursor is placed at the inner digit of an integer
->BUFFER: echo 013ab
->CURSOR: 8
-
-  zletest $'echo 012ab\eF2i\C-n'
-0:incarg works when the cursor is placed at the rightmost digit of an integer
->BUFFER: echo 013ab
->CURSOR: 8
-
-  zletest $'echo 012ab\eFai\C-n'
-0:incarg works when the cursor is placed just to the right of an integer
->BUFFER: echo 013ab
->CURSOR: 8
-
-  zletest $'echo 012ab\ei\C-n'
-0:incarg does nothing when the cursor is placed more than a single letter away to the right
->BUFFER: echo 012ab
->CURSOR: 9
+# Cursor position - vim-incarg
 
   zletest $'echo 012ab\eF \C-n'
 0:vim-incarg works when the cursor is placed to the left of an integer
@@ -355,6 +422,141 @@
 >BUFFER: echo 012ab
 >CURSOR: 9
 
+# Cursor position - vim-backward-incarg
+
+  zletest $'echo 012ab\eF \C-e'
+0:vim-backward-incarg does nothing when the cursor is placed just to the left of an integer
+>BUFFER: echo 012ab
+>CURSOR: 4
+
+  zletest $'echo 012ab\eF0\C-e'
+0:vim-backward-incarg works when the cursor is placed at the leftmost digit of an integer
+>BUFFER: echo 013ab
+>CURSOR: 7
+
+  zletest $'echo 012ab\eF1\C-e'
+0:vim-backward-incarg works when the cursor is placed at the inner digit of an integer
+>BUFFER: echo 013ab
+>CURSOR: 7
+
+  zletest $'echo 012ab\eF2\C-e'
+0:vim-backward-incarg works when the cursor is placed at the rightmost digit of an integer
+>BUFFER: echo 013ab
+>CURSOR: 7
+
+  zletest $'echo 012ab\eFa\C-e'
+0:vim-backward-incarg works when the cursor is placed just to the right of an integer
+>BUFFER: echo 013ab
+>CURSOR: 7
+
+  zletest $'echo 012ab\e\C-e'
+0:vim-backward-incarg works when the cursor is placed more than a single letter away to the right
+>BUFFER: echo 013ab
+>CURSOR: 7
+
+  zletest $'10x9\eFx\C-e'
+0:vim-backward-incarg will take [0-9]0x[0-9a-f] and increment the hexadecimal part when the cursor is on x
+>BUFFER: 10xa
+>CURSOR: 3
+
+  zletest $'10x9\e\C-e'
+0:vim-backward-incarg will take [0-9]0x[0-9a-f] and increment the hexadecimal part when the cursor is on the right of x
+>BUFFER: 10xa
+>CURSOR: 3
+
+  zletest $'10b1\e0\C-e'
+0:vim-backward-incarg will turn [0-9]0b[01] into [0-9]1b[01] when the cursor is at the left of b
+>BUFFER: 11b1
+>CURSOR: 1
+
+  zletest $'10b1\eFb\C-e'
+0:vim-backward-incarg will take [0-9]0b[01] and increment the binary part when the cursor is on b
+>BUFFER: 10b10
+>CURSOR: 4
+
+  zletest $'10b1\e\C-e'
+0:vim-backward-incarg will take [0-9]0b[01] and increment the binary part when the cursor is on the right of b
+>BUFFER: 10b10
+>CURSOR: 4
+
+  zletest $'10o7\e0\C-e'
+0:vim-backward-incarg will turn [0-9]0o[0-7] into [0-9]1o[0-7] when the cursor is at the left of o
+>BUFFER: 11o7
+>CURSOR: 1
+
+  zletest $'10o7\eFo\C-e'
+0:vim-backward-incarg will take [0-9]0o[0-7] and increment the octal part when the cursor is on o
+>BUFFER: 10o10
+>CURSOR: 4
+
+  zletest $'10o7\e\C-e'
+0:vim-backward-incarg will take [0-9]0o[0-7] and increment the octal part when the cursor is at the right of o
+>BUFFER: 10o10
+>CURSOR: 4
+
+  zletest $'0b0x9\eF0\C-e'
+0:vim-backward-incarg will take 0b0x[0-9a-f] and increment the binary 0b0 when the cursor is on the left of x
+>BUFFER: 0b1x9
+>CURSOR: 2
+
+  zletest $'0b0x9\eFx\C-e'
+0:vim-backward-incarg will take 0b0x[0-9a-f] and increment the hexadecimal part when the cursor is on x
+>BUFFER: 0b0xa
+>CURSOR: 4
+
+  zletest $'0b0x9\e\C-e'
+0:vim-backward-incarg will take 0b0x[0-9a-f] and increment the hexadecimal part when the cursor is at the right of x
+>BUFFER: 0b0xa
+>CURSOR: 4
+
+# Repeats
+
+  zletest $'echo 0\e0\C-n.'
+0:vim-incarg is compatible with the repeat command
+>BUFFER: echo 2
+>CURSOR: 5
+
+  zletest $'echo 0\e0\C-p.'
+0:vim-decarg is compatible with the repeat command
+>BUFFER: echo -2
+>CURSOR: 6
+
+  zletest $'echo 0 foo\e\C-e.'
+0:vim-backward-incarg is compatible with the repeat command
+>BUFFER: echo 2 foo
+>CURSOR: 5
+
+  zletest $'echo 0\e010\C-n.'
+0:Repeats of vim-incarg takes the numeric argument into account
+>BUFFER: echo 20
+>CURSOR: 6
+
+  zletest $'echo 0 foo\e10\C-e.'
+0:Repeats of vim-backward-incarg takes the numeric argument into account
+>BUFFER: echo 20 foo
+>CURSOR: 6
+
+  zpty_run 'TMUX_PANE=0'
+  zletest $'echo 0\e0\C-f.'
+  zpty_run 'unset TMUX_PANE'
+0:Repeats of vim-sync-incarg work in pane 0
+>BUFFER: echo 0
+>CURSOR: 5
+
+  zpty_run 'TMUX_PANE=1'
+  zletest $'echo 0\e0\C-f.'
+  zpty_run 'unset TMUX_PANE'
+0:Repeats of vim-sync-incarg work in pane 1
+>BUFFER: echo 2
+>CURSOR: 5
+
+  zpty_run 'TMUX_PANE=2'
+  zletest $'echo 0\e0\C-f.'
+  zpty_run 'unset TMUX_PANE'
+0:Repeats of vim-sync-incarg work in pane 2
+>BUFFER: echo 4
+>CURSOR: 5
+
 %clean
 
   zmodload -ui zsh/zpty