1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2026-01-01 20:11:06 +01:00

52641: incarg: add a backward variant and make it repeatable

This commit is contained in:
midchildan 2024-02-29 22:34:33 +09:00 committed by Oliver Kiddle
parent d1ff06f991
commit 36a2d5cfa4
4 changed files with 363 additions and 104 deletions

View file

@ -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