diff options
Diffstat (limited to 'Functions/Zle/modify-current-argument')
-rw-r--r-- | Functions/Zle/modify-current-argument | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/Functions/Zle/modify-current-argument b/Functions/Zle/modify-current-argument new file mode 100644 index 000000000..be244ccc1 --- /dev/null +++ b/Functions/Zle/modify-current-argument @@ -0,0 +1,51 @@ +# Take an expression suitable for interpolation in double quotes that +# performs a replacement on the parameter "ARG". Replaces the +# shell argument (which may be a quoted string) under or before the +# cursor with that. Ensure the expression is suitable quoted. +# +# For example, to uppercase the entire shell argument: +# modify-current-word '${(U)ARG}' +# To strip the current quoting from the word (whether backslashes or +# single, double or dollar quotes) and use single quotes instead: +# modify-current-word '${(qq)${(Q)ARG}}' + +# Retain most options from the calling function for the eval. +# Reset some that might confuse things. +setopt localoptions noksharrays multibyte + +local -a reply +integer REPLY REPLY2 + +autoload -U split-shell-arguments +split-shell-arguments + +# Can't do this unless there's some text under or left of us. +(( REPLY < 2 )) && return 1 + +# Get the index of the word we want. +if (( REPLY & 1 )); then + # Odd position; need previous word. + (( REPLY-- )) + # Pretend position was just after the end of it. + (( REPLY2 = ${#reply[REPLY]} + 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]}" + +# Replacement for current word. This could do anything to ${reply[REPLY]}. +local ARG="${reply[REPLY]}" repl +eval repl=\"$1\" +# 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 )) |