zsh-users
 help / color / mirror / code / Atom feed
* Resolving absolute path of named directory
@ 2013-01-22  8:50 Jesper Nygårds
  2013-01-22 10:14 ` Thomas Köhler
  0 siblings, 1 reply; 5+ messages in thread
From: Jesper Nygårds @ 2013-01-22  8:50 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 750 bytes --]

Say I have a string containing a directory name. I know I can use the :a
modifier to turn the string into the absolute path, but this does not seem
to work with named directories, and if I read the documentation correctly,
it's not supposed to. I wonder how I can go about resolving the string if
it is a named directory.

Here's an example of what I mean:
% pwd
/c/Program/Java
% ls
jdk16  jdk17  jre6  jre7
% mydir="jre6"
% print ${mydir:a}
/c/Program/Java/jre6       # Expexted
% pr=~/projects
% mydir="~pr"
% print ${mydir:a}
/c/Program/Java/~pr        # What I wanted was "/home/jesper/projects"

So, in the above example, is there a way to make $mydir resolve to the
absolute path of the named directory ~pr, without using an external program?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Resolving absolute path of named directory
  2013-01-22  8:50 Resolving absolute path of named directory Jesper Nygårds
@ 2013-01-22 10:14 ` Thomas Köhler
  2013-01-22 10:58   ` Jesper Nygårds
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas Köhler @ 2013-01-22 10:14 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 1303 bytes --]

Hi,

Jesper Nygårds wrote:
> 
> Say I have a string containing a directory name. I know I can use the :a
> modifier to turn the string into the absolute path, but this does not seem
> to work with named directories, and if I read the documentation correctly,
> it's not supposed to. I wonder how I can go about resolving the string if
> it is a named directory.
> 
> Here's an example of what I mean:
> % pwd
> /c/Program/Java
> % ls
> jdk16  jdk17  jre6  jre7
> % mydir="jre6"
> % print ${mydir:a}
> /c/Program/Java/jre6       # Expexted
> % pr=~/projects
> % mydir="~pr"
> % print ${mydir:a}
> /c/Program/Java/~pr        # What I wanted was "/home/jesper/projects"
> 
> So, in the above example, is there a way to make $mydir resolve to the
> absolute path of the named directory ~pr, without using an external program?

I expect what you want is not
  % pr=~/projects
  % mydir="~pr"
but
  % pr=~/projects
  % mydir="$pr"
instead. Or you might want
  % mydir=~/projects
  % print ${mydir:a}


Ciao,
Thomas

-- 
 Thomas Köhler       Email:       jean-luc@picard.franken.de
     <><             WWW:              http://gott-gehabt.de
                     IRC: tkoehler       Freenode: thkoehler
                     PGP public key available from Homepage!

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Resolving absolute path of named directory
  2013-01-22 10:14 ` Thomas Köhler
@ 2013-01-22 10:58   ` Jesper Nygårds
  2013-01-22 19:45     ` Peter Stephenson
  0 siblings, 1 reply; 5+ messages in thread
From: Jesper Nygårds @ 2013-01-22 10:58 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 1263 bytes --]

On Tue, Jan 22, 2013 at 11:14 AM, Thomas Köhler
<jean-luc@picard.franken.de>wrote:

> I expect what you want is not
>   % pr=~/projects
>   % mydir="~pr"
> but
>   % pr=~/projects
>   % mydir="$pr"
> instead. Or you might want
>   % mydir=~/projects
>   % print ${mydir:a}
>
>
Thank you for your help, Thomas, but I believe my example obscured what I
am trying to do, so I will try to clarify with a better example. Consider
this zle widget that I believe I have picked up from this list:

current-argument-absolute-path() {
    modify-current-argument '$ARG:a'
}
zle -N current-argument-absolute-path
bindkey '\e+' current-argument-absolute-path

As its name implies, it takes the current word on the command line, and
replaces it with its corresponding absolute path. However, it does not work
for named directories. If I write ls ~<\e+> when standing in, say,
/usr/lib, it expands the "~" to "/usr/lib/~", not "/home/jesper". And the
same for named directories that I have defined myself. So my question is,
can I rewrite this function so that if what's on the command line is a
named directory, it is expanded into its correct absolute path? And I still
want it to work for arguments that are not named directories, of course.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Resolving absolute path of named directory
  2013-01-22 10:58   ` Jesper Nygårds
@ 2013-01-22 19:45     ` Peter Stephenson
  2013-01-23 19:19       ` Peter Stephenson
  0 siblings, 1 reply; 5+ messages in thread
From: Peter Stephenson @ 2013-01-22 19:45 UTC (permalink / raw)
  To: zsh-users

On Tue, 22 Jan 2013 11:58:44 +0100
Jesper Nygårds <jesper.nygards@gmail.com> wrote:
> Thank you for your help, Thomas, but I believe my example obscured what I
> am trying to do, so I will try to clarify with a better example. Consider
> this zle widget that I believe I have picked up from this list:
> 
> current-argument-absolute-path() {
>     modify-current-argument '$ARG:a'
> }
> zle -N current-argument-absolute-path
> bindkey '\e+' current-argument-absolute-path
> 
> As its name implies, it takes the current word on the command line, and
> replaces it with its corresponding absolute path. However, it does not work
> for named directories. If I write ls ~<\e+> when standing in, say,
> /usr/lib, it expands the "~" to "/usr/lib/~", not "/home/jesper". And the
> same for named directories that I have defined myself. So my question is,
> can I rewrite this function so that if what's on the command line is a
> named directory, it is expanded into its correct absolute path? And I still
> want it to work for arguments that are not named directories, of course.

Well, you could do something like

current-argument-absolute-path() {
    modify-current-argument '${$(print -r -- ${~ARG}):a}'
}                                                      

but it seems cheating, and if ARG contains special characters for
globbing you're in trouble.  I couldn't offhand think of a direct way of
getting ~ expansion within a double-quoted expression, which is what's
happening internally.

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.

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Resolving absolute path of named directory
  2013-01-22 19:45     ` Peter Stephenson
@ 2013-01-23 19:19       ` Peter Stephenson
  0 siblings, 0 replies; 5+ messages in thread
From: Peter Stephenson @ 2013-01-23 19:19 UTC (permalink / raw)
  To: zsh-users

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/


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2013-01-23 23:05 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-22  8:50 Resolving absolute path of named directory 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

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).