From 2c31feef4d7fef24a19e633fbf50b846aeaccb34 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 11 Feb 2011 19:28:44 +0000 Subject: users/15738: better cursor positioning in modify-current-argument --- Functions/Zle/modify-current-argument | 44 +++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 10 deletions(-) (limited to 'Functions/Zle') diff --git a/Functions/Zle/modify-current-argument b/Functions/Zle/modify-current-argument index 92ca7bdab..92851d600 100644 --- a/Functions/Zle/modify-current-argument +++ b/Functions/Zle/modify-current-argument @@ -14,7 +14,7 @@ setopt localoptions noksharrays multibyte local -a reply -integer REPLY REPLY2 +integer REPLY REPLY2 fromend endoffset autoload -Uz split-shell-arguments split-shell-arguments @@ -30,6 +30,13 @@ if (( REPLY & 1 )); then (( REPLY2 = ${#reply[REPLY]} + 1 )) fi +# Work out offset from end of string +(( fromend = $REPLY2 - ${#reply[REPLY]} - 1 )) +if (( fromend >= -1 )); then + # Cursor is near the end of the word, we'll try to keep it there. + endoffset=1 +fi + # Length of all characters before current. # Force use of character (not index) counting and join without IFS. integer wordoff="${(cj..)#reply[1,REPLY-1]}" @@ -37,15 +44,32 @@ integer wordoff="${(cj..)#reply[1,REPLY-1]}" # Replacement for current word. This could do anything to ${reply[REPLY]}. local ARG="${reply[REPLY]}" repl eval repl=\"$1\" + +if (( !endoffset )) && [[ ${repl[fromend,-1]} = ${ARG[fromend,-1]} ]]; then + # If the part of the string from here to the end hasn't changed, + # leave the cursor this distance from the end instead of the beginning. + endoffset=1 +fi + # New line: all words before and after current word, with # no additional spaces since we've already got the whitespace # and the replacement word in the middle. -BUFFER="${(j..)reply[1,REPLY-1]}${repl}${(j..)reply[REPLY+1,-1]}" - -# Keep cursor at same position in replaced word. -# Redundant here, but useful if $repl changes the length. -# Limit to the next position after the end of the word. -integer repmax=$(( ${#repl} + 1 )) -# Remember CURSOR starts from offset 0 for some reason, so -# subtract 1 from positions. -(( CURSOR = wordoff + (REPLY2 > repmax ? repmax : REPLY2) - 1 )) +local left="${(j..)reply[1,REPLY-1]}${repl}" +local right="${(j..)reply[REPLY+1,-1]}" + +if [[ endoffset -ne 0 && ${#repl} -ne 0 ]]; then + # Place cursor relative to end. + LBUFFER="$left" + RBUFFER="$right" + (( CURSOR += fromend )) +else + BUFFER="$left$right" + + # Keep cursor at same position in replaced word. + # Redundant here, but useful if $repl changes the length. + # Limit to the next position after the end of the word. + integer repmax=$(( ${#repl} + 1 )) + # Remember CURSOR starts from offset 0 for some reason, so + # subtract 1 from positions. + (( CURSOR = wordoff + (REPLY2 > repmax ? repmax : REPLY2) - 1 )) +fi -- cgit 1.4.1