From 7154052ebe3d810390164a05c39ff83f98a1d858 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 30 Jul 2016 16:16:22 +0000 Subject: 39046 + 39061: New :P history modifier. --- ChangeLog | 10 ++++++++++ Completion/Base/Completer/_external_pwds | 2 +- Completion/Zsh/Type/_history_modifiers | 5 +++-- Doc/Zsh/contrib.yo | 2 +- Doc/Zsh/expn.yo | 9 +++++++++ Functions/MIME/zsh-mime-handler | 2 +- Functions/VCS_Info/VCS_INFO_quilt | 2 +- Functions/Zle/expand-absolute-path | 2 +- NEWS | 11 +++++++++++ Src/params.c | 2 +- Src/subst.c | 13 +++++++++++++ Src/utils.c | 14 ++++++++------ Test/D02glob.ztst | 8 ++++++++ 13 files changed, 68 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 65263033a..d3a7d3356 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2016-08-22 Daniel Shahaf + + * 39046 + 39061: Completion/Base/Completer/_external_pwds, + Completion/Zsh/Type/_history_modifiers, Doc/Zsh/contrib.yo, + Doc/Zsh/expn.yo, Functions/MIME/zsh-mime-handler, + Functions/VCS_Info/VCS_INFO_quilt, + Functions/Zle/expand-absolute-path, NEWS, Src/params.c, + Src/subst.c, Src/utils.c, Test/D02glob.ztst: New :P history + modifier. + 2016-08-20 Jun-ichi Takimoto * 39064: configure.ac, Src/Modules/mathfuc.c: use scalbn() instead diff --git a/Completion/Base/Completer/_external_pwds b/Completion/Base/Completer/_external_pwds index 4ad50f02b..79e3ba0eb 100644 --- a/Completion/Base/Completer/_external_pwds +++ b/Completion/Base/Completer/_external_pwds @@ -22,7 +22,7 @@ case $OSTYPE in ) ;; linux*) - dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:A) ) + dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:P) ) dirs=( $^dirs(N^@) ) ;; *) diff --git a/Completion/Zsh/Type/_history_modifiers b/Completion/Zsh/Type/_history_modifiers index 658f9f346..1a049d6cb 100644 --- a/Completion/Zsh/Type/_history_modifiers +++ b/Completion/Zsh/Type/_history_modifiers @@ -64,8 +64,8 @@ while true; do ) if (( ! global )); then list+=( - "a:absolute path" - "A:absolute path resolving symbolic links" + "a:absolute path, resolve '..' lexically" + "A:as ':a', then resolve symlinks" "c:PATH search for command" "g:globally apply s or &" "h:head - strip trailing path element" @@ -73,6 +73,7 @@ while true; do "r:root - strip suffix" "e:leave only extension" "Q:strip quotes" + "P:realpath, resolve '..' physically" "l:lower case all words" "u:upper case all words" ) diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 00ed08029..63df292ac 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -3477,7 +3477,7 @@ will ensure that any files found in that area will be executed as MIME types even if they are executable. As this example shows, the complete file name is matched against the pattern, regardless of how the file was passed to the handler. The file is resolved to a full path using -the tt(:A) modifier described in +the tt(:P) modifier described in ifzman(the subsection Modifiers in zmanref(zshexpn))\ ifnzman(noderef(Modifiers)); this means that symbolic links are resolved where possible, so that diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index ca4b94f5e..ecb1877a2 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -240,6 +240,7 @@ function, symbolic links are not resolved, so on those systems `tt(a)' and `tt(A)' are equivalent. Note: tt(foo:A) and tt(realpath+LPAR()foo+RPAR()) are different on some inputs. +For tt(realpath+LPAR()foo+RPAR()) semantics, see the `tt(P)` modifier. ) item(tt(c))( Resolve a command name into an absolute path by searching the command @@ -265,6 +266,14 @@ item(tt(p))( Print the new command but do not execute it. Only works with history expansion. ) +item(tt(P))( +Turn a file name into an absolute path, like tt(realpath+LPAR()3+RPAR()). +The resulting path will be absolute, have neither `tt(.)' nor `tt(..)' components, +and refer to the same directory entry as the input filename. + +Unlike tt(realpath+LPAR()3+RPAR()), non-existent trailing components are +permitted and preserved. +) item(tt(q))( Quote the substituted words, escaping further substitutions. Works with history expansion and parameter expansion, though for parameters diff --git a/Functions/MIME/zsh-mime-handler b/Functions/MIME/zsh-mime-handler index 24e5184fc..288a0796d 100644 --- a/Functions/MIME/zsh-mime-handler +++ b/Functions/MIME/zsh-mime-handler @@ -127,7 +127,7 @@ for pattern in $exec_asis; do files=(${dirpref}${~pattern}) if [[ -n ${files[(r)$1]} ]]; then for pattern in $exec_never; do - [[ ${1:A} = ${~pattern} ]] && break 2 + [[ ${1:P} = ${~pattern} ]] && break 2 done if (( list )); then for (( i = 1; i <= $#; i++ )); do diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index e7cd89f78..6adf0a358 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -170,7 +170,7 @@ function VCS_INFO_quilt() { applied=() fi patches=$(<$pc/.quilt_patches) - patches=`builtin cd -q "${pc:h}" && print -r - ${patches:A}` + patches=`builtin cd -q "${pc:h}" && print -r - ${patches:P}` fi if zstyle -t "${context}" get-unapplied; then # This zstyle call needs to be moved further up if `quilt' needs diff --git a/Functions/Zle/expand-absolute-path b/Functions/Zle/expand-absolute-path index b85757600..4887f3c60 100644 --- a/Functions/Zle/expand-absolute-path +++ b/Functions/Zle/expand-absolute-path @@ -10,7 +10,7 @@ autoload -Uz modify-current-argument if (( ! ${+functions[glob-expand-absolute-path]} )); then glob-expand-absolute-path() { local -a files - files=(${~1}(N:A)) + files=(${~1}(N:P)) (( ${#files} )) || return REPLY=${(D)files[1]} } diff --git a/NEWS b/NEWS index 15822ad34..65b246d33 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,17 @@ CHANGES FROM PREVIOUS VERSIONS OF ZSH Note also the list of incompatibilities in the README file. +Changes from 5.2 to 5.3 +----------------------- + +The new word modifier ':P' computes the physical path of the argument. +It is different from the existing ':a' modifier which always resolves +'/before/here/../after' to '/before/after', and differs from the +existing ':A' modifier which resolves symlinks only after 'here/..' is +removed, even when /before/here is itself a symbolic link. It is +recommended to review uses of ':A' and, if appropriate, convert them +to ':P' as soon as compatibility with 5.2 is no longer a requirement. + Changes from 5.1.1 to 5.2 ------------------------- diff --git a/Src/params.c b/Src/params.c index 0eda7848f..842b2f0d1 100644 --- a/Src/params.c +++ b/Src/params.c @@ -4336,7 +4336,7 @@ void homesetfn(UNUSED(Param pm), char *x) { zsfree(home); - if (x && isset(CHASELINKS) && (home = xsymlink(x))) + if (x && isset(CHASELINKS) && (home = xsymlink(x, 0))) zsfree(x); else home = x ? x : ztrdup(""); diff --git a/Src/subst.c b/Src/subst.c index c61551bf6..15eb59b64 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -4081,6 +4081,7 @@ modify(char **str, char **ptr) case 'u': case 'q': case 'Q': + case 'P': c = **ptr; break; @@ -4287,6 +4288,12 @@ modify(char **str, char **ptr) untokenize(copy); } break; + case 'P': + if (*copy != '/') { + copy = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP), "/", copy); + } + copy = xsymlink(copy, 1); + break; } tc = *tt; *tt = '\0'; @@ -4363,6 +4370,12 @@ modify(char **str, char **ptr) untokenize(*str); } break; + case 'P': + if (**str != '/') { + *str = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP), "/", *str); + } + *str = xsymlink(*str, 1); + break; } } if (rec < 0) { diff --git a/Src/utils.c b/Src/utils.c index 0a5954f65..45fd19286 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -801,9 +801,9 @@ findpwd(char *s) char *t; if (*s == '/') - return xsymlink(s); + return xsymlink(s, 0); s = tricat((pwd[1]) ? pwd : "", "/", s); - t = xsymlink(s); + t = xsymlink(s, 0); zsfree(s); return t; } @@ -969,11 +969,13 @@ xsymlinks(char *s, int full) /* * expand symlinks in s, and remove other weird things: * note that this always expands symlinks. + * + * 'heap' indicates whether to malloc() or allocate on the heap. */ /**/ char * -xsymlink(char *s) +xsymlink(char *s, int heap) { if (*s != '/') return NULL; @@ -981,8 +983,8 @@ xsymlink(char *s) if (xsymlinks(s + 1, 1) < 0) zwarn("path expansion failed, using root directory"); if (!*xbuf) - return ztrdup("/"); - return ztrdup(xbuf); + return heap ? dupstring("/") : ztrdup("/"); + return heap ? dupstring(xbuf) : ztrdup(xbuf); } /**/ @@ -1260,7 +1262,7 @@ getnameddir(char *name) /* Retrieve an entry from the password table/database for this user. */ struct passwd *pw; if ((pw = getpwnam(name))) { - char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir) + char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir, 0) : ztrdup(pw->pw_dir); if (dir) { adduserdir(name, dir, ND_USERNAME, 1); diff --git a/Test/D02glob.ztst b/Test/D02glob.ztst index 7befbc21f..1385d57d9 100644 --- a/Test/D02glob.ztst +++ b/Test/D02glob.ztst @@ -678,3 +678,11 @@ rm glob.tmp/link 0:modifier ':A' resolves '..' components before symlinks # There should be no output + + ln -s dir3/subdir glob.tmp/link + () { + print ${1:P} + } glob.tmp/link/../../hello/world + rm glob.tmp/link +0:modifier ':P' resolves symlinks before '..' components +*>*glob.tmp/hello/world -- cgit 1.4.1