From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-3.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,T_SCC_BODY_TEXT_LINE,URIBL_SBL_A autolearn=ham autolearn_force=no version=3.4.4 Received: from zero.zsh.org (zero.zsh.org [IPv6:2a02:898:31:0:48:4558:7a:7368]) by inbox.vuxu.org (Postfix) with ESMTP id 02C2A23D0E for ; Sun, 4 Feb 2024 20:37:41 +0100 (CET) ARC-Seal: i=1; cv=none; a=rsa-sha256; d=zsh.org; s=rsa-20210803; t=1707075461; b=BQcuNonro8Sc/ujAAgg5CjWENGv41Y01noy5wYcR/XxmBZbPH1qctjg2mhk15wiTTd5oHKO5Xl OPOkQdPenJGX9B01/U/AgP1w41xLR9Ef4pC1iyDS2OJFHhRV6nUFbzMpAVWEdNOB6w2d9nk7+B XBRSbQ9QGgwOLxB/qqIL9oZNdlEijYNUH6LIQgQ3gSboQfVimohdLebsysSuCEkzEmNDp/0K9e VTNOyxeri3r7SDB1JvKLKIAmaZHpkxVNv6t76SDbq3V3fCmy3VpuwcXN2yH+a/2J7bnR27anuB xFPM30kbMZ7Y9rBHmz0GRzp2RdkeYMgaP5zRZJW3cs2/kA==; ARC-Authentication-Results: i=1; zsh.org; iprev=pass (out3-smtp.messagingengine.com) smtp.remote-ip=66.111.4.27; dkim=pass header.d=midchildan.org header.s=fm2 header.a=rsa-sha256; dkim=pass header.d=messagingengine.com header.s=fm3 header.a=rsa-sha256; dmarc=none header.from=midchildan.org; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=zsh.org; s=rsa-20210803; t=1707075461; bh=fvg+9Q5XaVGhrVpF0Hss4hXVLmnN8PQFT4XV2W2DI9E=; h=List-Archive:List-Owner:List-Post:List-Unsubscribe:List-Subscribe:List-Help: List-Id:Sender:Content-Transfer-Encoding:MIME-Version:Message-ID:Date: Subject:Cc:To:From:DKIM-Signature:DKIM-Signature:DKIM-Signature; b=jdqtAGx2ENYlQhR/aV/Y/UIHVgW5YKhST6VXRzNesGsE5+YaWs7WwfQfpdW9Wk1iaGzvv0g7FC EOjmCL03e+dm068NJLpL4SHSxzJEaUL3A4IyTkD/4jLrjL85q1zEU0IYGL6BibCC96nvaXbh4R JV6ak6jUJeBXJLHQ2sg2vTnHh2SXzkYtJB35CAW5pvuxkmBKccuAgkSgPmKN4ZMkGVEQkIm0Eb j1Mwq0Tmo22ng6FMRgVdhZ8N8gvVJi4Xi7kPyUMs27Zj2s+advz+LgqvNTzpTbgqIS7N7+rNa+ NdunWYM7YEbjwX1kTRWnHGU/W87ZooJOJqoBIMH1e6ZINw==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zsh.org; s=rsa-20210803; h=List-Archive:List-Owner:List-Post:List-Unsubscribe: List-Subscribe:List-Help:List-Id:Sender:Content-Transfer-Encoding: MIME-Version:Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References; bh=Jik3Z7AB6MwpqTkoAFfvIPQXKh3L2ckVg1iG9YB8JMQ=; b=IIaNejs83r9sat54+vAMQvvc06 bnaL8F3m9m+QZ8LFa8ALV8sAXKoxyRf+saBy/TSK+ytBhdpxb2JkpkXbguiQ840XOmjjOxZEWqzgG KCuFKpvw61Jev/VREpFn4MlBkmmnL76c9iEDH+G8X2dUuLf/US+haYm0kjnMMTq4LyVQO342rgaQN ByJzlfxXGdM2uQhlsBeAA2tyQZTALeBMSyFbaCIeaAdO9Kuzy0GjMAoeONO85QStOGayV9z3HhF95 AXhyehdSpX2NLhMWknCadUrmei6uRh76CTwGGlCmHsAnFbhKlvWRraB+ZjxFhTfdEKfmJ7JkaQclB yjE8+0Ug==; Received: by zero.zsh.org with local id 1rWiJA-0000ZX-JA; Sun, 04 Feb 2024 19:37:40 +0000 Authentication-Results: zsh.org; iprev=pass (out3-smtp.messagingengine.com) smtp.remote-ip=66.111.4.27; dkim=pass header.d=midchildan.org header.s=fm2 header.a=rsa-sha256; dkim=pass header.d=messagingengine.com header.s=fm3 header.a=rsa-sha256; dmarc=none header.from=midchildan.org; arc=none Received: from out3-smtp.messagingengine.com ([66.111.4.27]:47807) by zero.zsh.org with esmtps (TLS1.3:TLS_AES_256_GCM_SHA384:256) id 1rWiIo-0000F4-Ac; Sun, 04 Feb 2024 19:37:19 +0000 Received: from compute7.internal (compute7.nyi.internal [10.202.2.48]) by mailout.nyi.internal (Postfix) with ESMTP id C80245C0053; Sun, 4 Feb 2024 14:37:15 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute7.internal (MEProxy); Sun, 04 Feb 2024 14:37:15 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=midchildan.org; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:message-id:mime-version:reply-to:subject :subject:to:to; s=fm2; t=1707075435; x=1707161835; bh=Jik3Z7AB6M wpqTkoAFfvIPQXKh3L2ckVg1iG9YB8JMQ=; b=Jyy7JE9MzAD9LAkl7iZ5f7T7JW wT3xsskNaZ8VBD74Aeg+s5I7Is1cif1ljF54Fc4j6qqMGMUvYSbnf8K//UdPE+B8 +szJqqNRlqyOx4p/I5YWjzBNUYL59VuHAD7q0EG/Y/VOv7vHk7JbbhkV+wpnuw1x efuT+Lu90HC1h11a1n5GJNCeiO7+wvXeBHnMd53hl0g50W17v8Axu2psfpjaKZ12 aHlzZ7aWdboMOwWb9+2eY8H+XB+hQdeAIHXDEs/Ln1oD3AHHSUM30+hMNZ2jqY5s zoUJ1P3BAEH35omGLoZkDO7IA4Mwfg4bJvahZHlhcodjwLCZT3QlD0qU5ehA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:message-id:mime-version:reply-to:subject:subject:to :to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; t=1707075435; x=1707161835; bh=Jik3Z7AB6MwpqTkoAFfvIPQXKh3L 2ckVg1iG9YB8JMQ=; b=SkY94QDxAk4B8i5/N2h6SFgBQ7yHkUW5OZtXV3N/tTnq b8XsqSsObpvdPTJSlrZakhlk3a2mtmnlVX6bKv7Gm3FW/Fr+KSigD6dRqh3Zdf3N fzM08J8+GbNgIBXVur1dzuyKozQuXBoeqwzDx9SzpevRJHLdWwOGEBsL4ZYEZ6al PdBKb+MpSkkQj5uX0KW6MjD8T7dUg2FfM7Swsx4zCHn+r+QKVzktBDbA2MZE0H7r 0g6rb9uayVfqqv2CL/JchHyjQ1gSHtVXqTW56G0N1SU39HfcM9Jiov7X75sAFoAN bHv3jUJTdt6q333LAqo6Tx/svr0xqwtTQZ2b68N43g== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvkedrfedukedguddviecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecunecujfgurhephffvvefufffkofgggfestdekre dtredttdenucfhrhhomhepmhhiuggthhhilhgurghnuceoghhithesmhhiuggthhhilhgu rghnrdhorhhgqeenucggtffrrghtthgvrhhnpefgfeffgeefheejhfefiedtjeduteefvd fhtdffudegvedvgeejffeuieegudegjeenucffohhmrghinheprghstghiihhnvghmrgdr ohhrghenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpe hgihhtsehmihgutghhihhluggrnhdrohhrgh X-ME-Proxy: Feedback-ID: i970949fb:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 4 Feb 2024 14:37:14 -0500 (EST) From: midchildan To: zsh-workers@zsh.org Cc: midchildan Subject: [PATCH] add new features and improvements to the "incarg" ZLE widget Date: Mon, 5 Feb 2024 04:19:39 +0900 Message-Id: <20240204191938.42759-1-git@midchildan.org> X-Mailer: git-send-email 2.39.3 (Apple Git-145) MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Seq: 52520 Archived-At: X-Loop: zsh-workers@zsh.org Errors-To: zsh-workers-owner@zsh.org Precedence: list Precedence: bulk Sender: zsh-workers-request@zsh.org X-no-archive: yes List-Id: List-Help: , List-Subscribe: , List-Unsubscribe: , List-Post: List-Owner: List-Archive: This brings numerous improvements to the incarg ZLE widget that's used to increment an integer under the cursor. I find myself incrementing numbers very often when editing commands from shell history. I originally used incarg for this, but I missed a couple of features from Vim's increment command. The contents of this PR is what I've eventually settled on. Here are the list of features: * Decrement integers without defining a new widget Previously, the user had to define their own widget if they wanted to decrement instead of increment. decarg() { autoload -Uz incarg (( NUMERIC = -${NUMERIC:-${incarg:-1}} )) incarg } zle -N decarg After this change, it's simply: zle -N decarg incarg * Preserve the number of leading zeros Previously, incarg omitted leading zeros. Before: 001 After: 2 After this change, leading zeros are preserved. Before: 001 After: 002 * Increment binaries, octals, and hexadecimals Previously, incarg only recognized decimals. After this change, it'll recognize 0b, 0o, and 0x prefixes. Both lower case and upper case prefixes are recognized. * Move the cursor to the end of the incremented integer Previously the cursor position didn't change after incrementing. This lead to annoyances when the number of digits increased: Before: 99 ^ cursor After: 100 ^ cursor After this change, the cursor will be moved to the immediate right of the integer. Before: 99 ^ cursor After: 100 ^ cursor This is probably a nice property even when the number of digits don't change. If I want to keep on editing the current line right after incrementing, I typically want to change something on the right of the integer. * Create a sequence of integers across terminal panes This adds a variation of the incarg widget that can be used by prefixing the widget name with sync-. It's intended to be used on multi-pane terminals with the keyboard input broadcast to all panes. It increments the integer in each pane by a different amount, with the next pane having its integer incremented once more than the previous one. Supported terminals are tmux and iTerm2. zle -N sync-incarg incarg zle -N sync-decarg incarg I often use this to interactively run the same commands on multiple sequentially numbered servers all at once. It's shown in the demo down below. * Add a Vim variant Vim's increment command jumps to the nearest integer after the cursor and increments it. I find this behavior very useful when combined with history-beginning-search-backward. So I made it possible to get this behavior by prefixing vi to the widget name. zle -N vim-incarg incarg zle -N vim-decarg decarg bindkey -a \ '^A' vim-incarg \ '^X' vim-decarg It can also be combined with the sync- prefix. zle -N vim-sync-incarg incarg zle -N vim-sync-decarg incarg bindkey -a \ 'g^A' vim-sync-incarg \ 'g^X' vim-sync-decarg I also created a short demo showing how it can be used: https://asciinema.org/a/ijvvGnXnqsgQn476JIplUxlp8 --- Doc/Zsh/contrib.yo | 30 +++- Functions/Zle/incarg | 279 ++++++++++++++++++++++++++++---- Test/X05zleincarg.ztst | 360 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 629 insertions(+), 40 deletions(-) create mode 100644 Test/X05zleincarg.ztst diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index e1781a5e1..6f13a9ebb 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2620,12 +2620,30 @@ zle -N history-pattern-search-forward history-pattern-search) tindex(incarg) vindex(incarg, use of) item(tt(incarg))( -Typing the keystrokes for this widget with the cursor placed on or to the -left of an integer causes that integer to be incremented by one. With a -numeric argument, the number is incremented by the amount of the -argument (decremented if the numeric argument is negative). The shell -parameter tt(incarg) may be set to change the default increment to -something other than one. +This widget allows you to increment integers on the current line. In addition +to decimals, it can handle hexadecimals prefixed with tt(0x), binaries with +tt(0b), and octals with tt(0o). + +By default, the target integer will be incremented by one. With a numberic +argument, the integer is incremented by the amount of the argument. The shell +parameter tt(incarg) may be set to change the default increment to something +other than one. + +The behavior of this widget changes depending on the widget name. + +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(vim-), +the cursor will jump to the nearest integer after the cursor before incrementing +it. + +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 +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(vim-) and tt(sync-) can be combined into tt(vim-sync-). example(bindkey '^X+' incarg) ) diff --git a/Functions/Zle/incarg b/Functions/Zle/incarg index cff0cfe4c..1131b148b 100644 --- a/Functions/Zle/incarg +++ b/Functions/Zle/incarg @@ -1,43 +1,254 @@ -# Shell function to increment an integer either under the cursor or just -# to the left of it. Use -# autoload -Uz incarg -# zle -N incarg -# bindkey "..." incarg -# to define it. For example, -# echo 41 -# ^^^ cursor anywhere here -# with incarg gives -# echo 42 -# with the cursor in the same place. -# -# A numeric argument gives a number other than 1 to add (may be negative). -# If you're going to do it a lot with one particular number, you can set -# the parameter incarg to that number (a numeric argument still takes -# precedence). - emulate -L zsh -setopt extendedglob -local rrest lrest num +# A ZLE widget to increment an integer. +# +# In addition to decimals, it can handle hexadecimals prefixed with "0x", +# binaries with "0b", and octals with "0o". +# +# By default, the target integer will be incremented by one. With a numeric +# argument, the integer is incremented by the amount of the argument. The shell +# parameter "incarg" may be set to change the default increment to something +# other than one. +# +# The behavior of this widget changes depending on how it is named. +# +# - incarg / decarg +# +# incarg will increment an integer either under the cursor or just to the left +# of it. decarg, on the other hand, will decrement it. +# +# For example, +# +# echo 41 +# ^^^ cursor anywhere here +# +# with incarg gives +# +# echo 42 +# ^ cursor will move here +# +# - sync-incarg / sync-decarg +# +# The sync- variant is used for creating a sequence of numbers on split +# terminals with synchronized key input. The first pane won't be incremented +# at all, but each pane after that will have the number incremented once more +# than the previous pane. +# +# Currently supports tmux and iTerm2. +# +# - vim-incarg / vim-decarg +# +# 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-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. +# +# Example Usage: +# +# autoload -Uz incarg +# for widget in vim-{,sync-}{inc,dec}arg; do +# zle -N "$widget" incarg +# done +# bindkey -a \ +# '^A' vim-incarg \ +# '^X' vim-decarg \ +# 'g^A' vim-sync-incarg \ +# 'g^X' vim-sync-decarg -rrest=${RBUFFER##[0-9]#} -if [[ $RBUFFER = [0-9]* ]]; then - if [[ -z $rrest ]]; then - num=$RBUFFER - else - num=${RBUFFER[1,-$#rrest-1]} +setopt localoptions extended_glob +local match mbegin mend MATCH MBEGIN MEND i + +# find the number and determine the base +integer pos=$(( CURSOR + 1 )) base=0 + +# avoid miscalculating positions when cursor is at the end of the line +while (( pos > 0 )) && [[ "$BUFFER[pos]" == '' ]]; do + (( pos-- )) +done + +# check for a prefix (e.g., 0x) before the cursor +for (( i = 0; i < 2; i++ )); 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 ;; + *[1-9]) base=10 ;; + *0) ;; # there may be a prefix right after the cursor + *) + # the non-Vim variant looks right before the cursor too, but not after it + if [[ "$WIDGET" != vi* ]]; then + if (( i == 0 )); then + (( pos-- )) + continue + else + return 1 + fi + fi + ;; + esac + + break +done + +# check for a prefix on the cursor +if (( base == 0 && pos < $#BUFFER )); then + case "$BUFFER[1,pos+1]" in + *0[xX][0-9a-fA-F]) base=16; (( pos++ )) ;; + *0[oO][0-7]) base=8; (( pos++ )) ;; + *0[bB][01]) base=2; (( pos++ )) ;; + esac +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 + fi + + # check for a prefix right after the cursor and jump right after it, if any + if (( pos <= 1 )) || [[ "$BUFFER[pos-1]" == [^0-9] ]]; then + case "$BUFFER[pos,-1]" in + 0[xX][0-9a-fA-F]*) base=16; (( pos += 2 )) ;; + 0[oO][0-7]*) base=8; (( pos += 2 )) ;; + 0[bB][01]*) base=2; (( pos += 2 )) ;; + esac fi fi -lrest=${LBUFFER%%[0-9]#} -if [[ $LBUFFER = *[0-9] ]]; then - if [[ -z $lrest ]]; then - num="$LBUFFER$num" - else - num="${LBUFFER[$#lrest+1,-1]}$num" - fi +if (( base == 0 )); then + base=10 fi -[[ -n $num ]] && (( num += ${NUMERIC:-${incarg:-1}} )) +# find the start of the number +integer first="$pos" +case "$base" in + 10) + while [[ "$BUFFER[first-1]" == [0-9] ]]; do + (( first-- )) + done + if [[ $BUFFER[first-1] = - ]]; then + (( first-- )) + fi + ;; + 2) + while [[ "$BUFFER[first-1]" == [01] ]]; do + (( first-- )) + done + ;; + 8) + while [[ "$BUFFER[first-1]" == [0-7] ]]; do + (( first-- )) + done + ;; + 16) + while [[ "$BUFFER[first-1]" == [0-9a-fA-F] ]]; do + (( first-- )) + done + ;; +esac -BUFFER="$lrest$num$rrest" +# find the end of the number +integer last="$pos" +case "$base" in + 10) + while [[ "$BUFFER[last+1]" == [0-9] ]]; do + (( last++ )) + done + ;; + 2) + while [[ "$BUFFER[last+1]" == [01] ]]; do + (( last++ )) + done + ;; + 8) + while [[ "$BUFFER[last+1]" == [0-7] ]]; do + (( last++ )) + done + ;; + 16) + while [[ "$BUFFER[last+1]" == [0-9a-fA-F] ]]; do + (( last++ )) + done + ;; +esac + +# calculate the number of digits +integer ndigits=0 +case "$BUFFER[first,first+1]" in + 0*|-0) ndigits=$(( last - first + 1 )) ;; +esac + +# determine the amount to increment +integer delta=${NUMERIC:-${incarg:-1}} +if [[ "$WIDGET" = *decarg ]]; then + (( delta = -delta )) +fi +if [[ "$WIDGET" = *sync-* ]]; then + integer pane_index=0 + if [[ -n "$TMUX_PANE" ]]; then + pane_index="$(tmux display-message -pt "$TMUX_PANE" '#{pane_index}')" + elif [[ "$ITERM_SESSION_ID" =~ '^w[0-9]+t[0-9]+p([0-9]+)' ]]; then + pane_index="$match[1]" + else + zle -M "[$WIDGET] unsupported terminal" + return 1 + fi + (( delta *= pane_index )) +fi + +local old="$BUFFER[first,last]" +integer oldlen=$#BUFFER + +local fmt1 fmt2 +case "$base" in + 10) fmt1=d; fmt2='#10' ;; + 2) fmt1=s; fmt2='##2' ;; + 8) fmt1=s; fmt2='##8' ;; + 16) fmt1="$BUFFER[first-1]"; fmt2='#16' ;; +esac + +local raw_result padded +raw_result="$( \ + printf "%0$ndigits$fmt1" $(( [$fmt2] "$base#$old" + delta )) 2> /dev/null)" +padded="${raw_result// /0}" + +integer oldnum="$base#$old" newnum="$base#$padded" 2> /dev/null +if (( base != 10 && newnum < 0 + || delta > 0 && newnum < oldnum + || delta < 0 && newnum > oldnum )); then + zle -M "[$WIDGET] The resulting number is either too big or too small." + return 1 +fi + +# adjust the number of leading zeros if the sign of the integer changed +local new +if (( base == 10 && ndigits == $#padded )); then + if (( oldnum < 0 && newnum >= 0 )); then + new="${padded#0}" + elif (( oldnum >= 0 && newnum < 0 )); then + new="-0${padded#-}" + fi +fi +if [[ -z "$new" ]]; then + new="$padded" +fi + +if zstyle -t ":zle:$WIDGET" debug; then + zle -M "[$WIDGET] base: $base delta: $delta old: '$old' new: '$new'" +fi + +BUFFER[first,last]="$new" + +integer offset=0 +if [[ "$WIDGET" == vi* ]]; then + offset=-1 +fi +(( CURSOR = last + $#BUFFER - oldlen + offset )) + +return 0 diff --git a/Test/X05zleincarg.ztst b/Test/X05zleincarg.ztst new file mode 100644 index 000000000..73191278f --- /dev/null +++ b/Test/X05zleincarg.ztst @@ -0,0 +1,360 @@ +# Tests the incarg ZLE widget + +%prep + ZSH_TEST_LANG=$(ZTST_find_UTF8) + if ( zmodload zsh/zpty 2>/dev/null ); then + . $ZTST_srcdir/comptest + comptestinit -v -z $ZTST_testdir/../Src/zsh + else + ZTST_unimplemented="the zsh/zpty module is not available" + fi + zpty_run ' + autoload -Uz incarg + for name in {,vim-}{,sync-}{inc,dec}arg; do + zle -N "$name" incarg + done + bindkey -v "^N" incarg + bindkey -v "^P" decarg + bindkey -v "^F" sync-incarg + bindkey -v "^B" sync-decarg + bindkey -a "^N" vim-incarg + bindkey -a "^P" vim-decarg + bindkey -a "^F" vim-sync-incarg + bindkey -a "^B" vim-sync-decarg + unset TMUX_PANE ITERM_SESSION_ID + tmux() { + echo "$TMUX_PANE" + } + ' + +%test + + zletest $'0\C-n' +0:increment an integer with incarg +>BUFFER: 1 +>CURSOR: 1 + + zletest $'0\C-p' +0:decrement an integer with decarg +>BUFFER: -1 +>CURSOR: 2 + + zletest $'echo 0\e0\C-n' +0:increment an integer with vim-incarg +>BUFFER: echo 1 +>CURSOR: 5 + + zletest $'echo 0\e0\C-p' +0:decrement an integer with vim-decarg +>BUFFER: echo -1 +>CURSOR: 6 + + zletest $'0\C-f' +0:sync-incarg does nothing on unsupported terminals +>BUFFER: 0 +>CURSOR: 1 + + zpty_run 'TMUX_PANE=0' + zletest $'0\C-f' + zpty_run 'unset TMUX_PANE' +0:sync-incarg 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 +>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 +>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 +>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 +>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 +>BUFFER: 2 +>CURSOR: 1 + + zpty_run 'TMUX_PANE=1' + 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 +>BUFFER: 1 +>CURSOR: 1 + + zletest $'0\e2\C-n' +0:Providing a numberic argument will change the incremented amount +>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 +>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 +>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 +>BUFFER: 4 +>CURSOR: 0 + + zletest $'000\C-n' +0:Incrementing a decimal integer preserves leading zeros +>BUFFER: 001 +>CURSOR: 3 + + zletest $'-001\C-n\C-n' +0:Leading zeros are preserved 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 +>BUFFER: -001 +>CURSOR: 4 + + zletest $'001\e1000\C-n' +0:Incrementing an integer works when the result has more zeros 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 +>BUFFER: -1999 +>CURSOR: 4 + + zletest $'0b11\C-n' +0:Increment a binary integer +>BUFFER: 0b100 +>CURSOR: 5 + + zletest $'0B11\C-n' +0:Increment a binary integer with an upper case prefix +>BUFFER: 0B100 +>CURSOR: 5 + + zletest $'0b100\C-p' +0:Decrement a binary integer +>BUFFER: 0b11 +>CURSOR: 4 + + zletest $'0b0011\C-n' +0:Increment a binary integer preserves leading zeros +>BUFFER: 0b0100 +>CURSOR: 6 + + zletest $'0b001\e8\C-n' +0:Incrementing a binary integer work 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 +>BUFFER: 0b0 +>CURSOR: 3 + + zletest $'0o7\C-n' +0:Increment an octal integer +>BUFFER: 0o10 +>CURSOR: 4 + + zletest $'0O7\C-n' +0:Increment an octal integer with an upper case prefix +>BUFFER: 0O10 +>CURSOR: 4 + + zletest $'0o10\C-p' +0:Decrement an octal integer +>BUFFER: 0o7 +>CURSOR: 3 + + zletest $'0o0\C-p' +0:Decrementing an octal integer to a negative value will fail +>BUFFER: 0o0 +>CURSOR: 3 + + zletest $'0x9\C-n' +0:Increment a hexadecimal integer +>BUFFER: 0xa +>CURSOR: 3 + + zletest $'0X9\C-n' +0: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 +>BUFFER: 0x10 +>CURSOR: 4 + + zletest $'0x10\C-p' +0:Decrement a hexadecimal integer +>BUFFER: 0xf +>CURSOR: 3 + + zletest $'0x0\C-p' +0:Decrementing an octal integer to a negative value will fail +>BUFFER: 0x0 +>CURSOR: 3 + + zletest $'0x0b1\C-n' +0:a number that starts with 0x0b is interpreted as a hexadecimal integer +>BUFFER: 0x0b2 +>CURSOR: 5 + + 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 +>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 +>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 +>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 +>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 +>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 +>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 +>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 +>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 +>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 +>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 +>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 +>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 + + zletest $'echo 012ab\eF \C-n' +0:vim-incarg works when the cursor is placed to the left of an integer +>BUFFER: echo 013ab +>CURSOR: 7 + + zletest $'echo 012ab\eF0\C-n' +0:vim-incarg works when the cursor is placed at the leftmost digit of an integer +>BUFFER: echo 013ab +>CURSOR: 7 + + zletest $'echo 012ab\eF1\C-n' +0:vim-incarg works when the cursor is placed at the inner digit of an integer +>BUFFER: echo 013ab +>CURSOR: 7 + + zletest $'echo 012ab\eF2\C-n' +0:incarg works when the cursor is placed at the rightmost digit of an integer +>BUFFER: echo 013ab +>CURSOR: 7 + + zletest $'echo 012ab\eFa\C-n' +0:vim-incarg does nothing when the cursor is placed to the right of an integer +>BUFFER: echo 012ab +>CURSOR: 8 + + zletest $'echo 012ab\ei\C-n' +0:vim-incarg does nothing when the cursor is placed more than a single letter away to the right +>BUFFER: echo 012ab +>CURSOR: 9 + +%clean + + zmodload -ui zsh/zpty -- 2.39.3 (Apple Git-145)