From: Peter Stephenson <p.w.stephenson@ntlworld.com>
To: zsh-users@zsh.org
Subject: Re: Resolving absolute path of named directory
Date: Wed, 23 Jan 2013 19:19:01 +0000 [thread overview]
Message-ID: <20130123191901.76a2b366@pws-pc.ntlworld.com> (raw)
In-Reply-To: <20130122194559.0d59be6e@pws-pc.ntlworld.com>
On Tue, 22 Jan 2013 19:45:59 +0000
Peter Stephenson <p.w.stephenson@ntlworld.com> wrote:
> Actually, the key chunk of modify-current-argument that does this,
>
> local ARG="${reply[REPLY]}" repl
> eval repl=\"$1\"
>
> is a real hack that's crying out for something a bit more sophisticated.
How about this? You can now use a function to modify the argument and
return the new value in REPLY. The documentation has code for this
example.
Index: Doc/Zsh/contrib.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/contrib.yo,v
retrieving revision 1.145
diff -p -u -r1.145 contrib.yo
--- Doc/Zsh/contrib.yo 28 Sep 2012 22:07:29 -0000 1.145
+++ Doc/Zsh/contrib.yo 23 Jan 2013 19:16:40 -0000
@@ -2477,15 +2477,22 @@ See the function tt(modify-current-argum
an example of how to call this function.
)
tindex(modify-current-argument)
-item(tt(modify-current-argument) var(expr-using-)tt($ARG))(
+item(tt(modify-current-argument) [ var(expr-using-)tt($ARG) | var(func) ])(
This function provides a simple method of allowing user-defined widgets
to modify the command line argument under the cursor (or immediately to the
-left of the cursor if the cursor is between arguments). The argument
-should be an expression which when evaluated operates on the shell
+left of the cursor if the cursor is between arguments).
+
+The argument can be an expression which when evaluated operates on the shell
parameter tt(ARG), which will have been set to the command line argument
under the cursor. The expression should be suitably quoted to prevent
it being evaluated too early.
+Alternatively, if the argument does not contain the string tt(ARG), it
+is assumed to be a shell function, to which the current command line
+argument is passed as the only argument. The function should set the
+variable tt(REPLY) to the new value for the command line argument.
+If the function returns non-zero status, so does the calling function.
+
For example, a user-defined widget containing the following code
converts the characters in the argument under the cursor into all upper
case:
@@ -2497,6 +2504,18 @@ or one of the styles of quotes), and rep
throughout:
example(modify-current-argument '${(qq)${(Q)ARG}}')
+
+The following performs directory expansion on the command line
+argument and replaces it by the absolute path:
+
+example(expand-dir() {
+ REPLY=${~1}
+ REPLY=${REPLY:a}
+}
+modify-current-argument expand-dir)
+
+In practice the function tt(expand-dir) would probably not be defined
+within the widget where tt(modify-current-argument) is called.
)
enditem()
Index: Functions/Zle/modify-current-argument
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Zle/modify-current-argument,v
retrieving revision 1.4
diff -p -u -r1.4 modify-current-argument
--- Functions/Zle/modify-current-argument 11 Feb 2011 19:28:44 -0000 1.4
+++ Functions/Zle/modify-current-argument 23 Jan 2013 19:16:40 -0000
@@ -14,24 +14,27 @@
setopt localoptions noksharrays multibyte
local -a reply
-integer REPLY REPLY2 fromend endoffset
+integer posword poschar fromend endoffset
+local REPLY REPLY2
autoload -Uz split-shell-arguments
split-shell-arguments
+(( posword = REPLY, poschar = REPLY2 ))
+
# Can't do this unless there's some text under or left of us.
-(( REPLY < 2 )) && return 1
+(( posword < 2 )) && return 1
# Get the index of the word we want.
-if (( REPLY & 1 )); then
+if (( posword & 1 )); then
# Odd position; need previous word.
- (( REPLY-- ))
+ (( posword-- ))
# Pretend position was just after the end of it.
- (( REPLY2 = ${#reply[REPLY]} + 1 ))
+ (( poschar = ${#reply[posword]} + 1 ))
fi
# Work out offset from end of string
-(( fromend = $REPLY2 - ${#reply[REPLY]} - 1 ))
+(( fromend = $poschar - ${#reply[posword]} - 1 ))
if (( fromend >= -1 )); then
# Cursor is near the end of the word, we'll try to keep it there.
endoffset=1
@@ -39,11 +42,17 @@ 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]}"
+integer wordoff="${(cj..)#reply[1,posword-1]}"
-# Replacement for current word. This could do anything to ${reply[REPLY]}.
-local ARG="${reply[REPLY]}" repl
-eval repl=\"$1\"
+# Replacement for current word. This could do anything to ${reply[posword]}.
+local ARG="${reply[posword]}" repl
+if [[ $1 != *ARG* ]]; then
+ REPLY=
+ $1 $ARG || return 1
+ repl=$REPLY
+else
+ eval repl=\"$1\"
+fi
if (( !endoffset )) && [[ ${repl[fromend,-1]} = ${ARG[fromend,-1]} ]]; then
# If the part of the string from here to the end hasn't changed,
@@ -54,8 +63,8 @@ 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.
-local left="${(j..)reply[1,REPLY-1]}${repl}"
-local right="${(j..)reply[REPLY+1,-1]}"
+local left="${(j..)reply[1,posword-1]}${repl}"
+local right="${(j..)reply[posword+1,-1]}"
if [[ endoffset -ne 0 && ${#repl} -ne 0 ]]; then
# Place cursor relative to end.
@@ -71,5 +80,5 @@ else
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 ))
+ (( CURSOR = wordoff + (poschar > repmax ? repmax : poschar) - 1 ))
fi
--
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/
prev parent reply other threads:[~2013-01-23 23:05 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-01-22 8:50 Jesper Nygårds
2013-01-22 10:14 ` Thomas Köhler
2013-01-22 10:58 ` Jesper Nygårds
2013-01-22 19:45 ` Peter Stephenson
2013-01-23 19:19 ` Peter Stephenson [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130123191901.76a2b366@pws-pc.ntlworld.com \
--to=p.w.stephenson@ntlworld.com \
--cc=zsh-users@zsh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).