From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21217 invoked from network); 14 Dec 2000 18:16:46 -0000 Received: from sunsite.dk (HELO sunsite.auc.dk) (130.225.51.30) by ns1.primenet.com.au with SMTP; 14 Dec 2000 18:16:46 -0000 Received: (qmail 26639 invoked by alias); 14 Dec 2000 18:16:40 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 13275 Received: (qmail 26631 invoked from network); 14 Dec 2000 18:16:39 -0000 To: "Andrej Borsenkow" Cc: Subject: PATCH: Re: :r modifier References: <000a01c065dc$2ea4d9e0$21c9ca95@mow.siemens.ru> From: Alexandre Duret-Lutz X-Home-Page: http://www.epita.fr/~duret_g/ X-Attribution: adl Organization: LRDE/EPITA http://www.lrde.epita.fr/ Date: 14 Dec 2000 19:18:59 +0100 In-Reply-To: "Andrej Borsenkow"'s message of "Thu, 14 Dec 2000 17:43:11 +0300" Message-ID: User-Agent: Gnus/5.0807 (Gnus v5.8.7) Emacs/20.7 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Sender: Alexandre Duret-Lutz >>> "Andrej" == Andrej Borsenkow writes: [...] Andrej> I checked bash and it behaves the same as zsh. >> >> Huh? You aren't speaking about :h here, are you? >> Andrej> I am speaking about :r and :e. What so special about Andrej> :h? Nothing, please dismiss my question... [...] Here is my proposal. The following patch modifies :r, :e, :h, and :t to behave as I expect them to. My point for doing so is that 1) this seems natural and more useful (from the user point of view) 2) that should not break anything because these modifiers are usually used in places where you won't have any surprise with the old behavior (e.g. you use :r when you *know* that there is an extenstion to delete) and the behavior is not changed in those places. I don't know if you consider the compatibility with other shells important on this point. I must confess I don't really do :), the overall semantic is still the same, but at least there is no surprises in the results. Leading double-slashes are handled, and backslashes too (under Cygwin only). remtpath() is also assuming that leading `//', `/\\', `\\/', and `\\\\' are equivalent under Cygwin, is this true? Index: Doc/Zsh/expn.yo =================================================================== RCS file: /cvsroot/zsh/zsh/Doc/Zsh/expn.yo,v retrieving revision 1.24 diff -u -r1.24 expn.yo --- Doc/Zsh/expn.yo 2000/10/05 08:41:37 1.24 +++ Doc/Zsh/expn.yo 2000/12/14 17:38:40 @@ -202,13 +202,15 @@ startitem() item(tt(h))( -Remove a trailing pathname component, leaving the head. +Remove a trailing pathname component, leaving the head. This works +like `tt(dirname)'. ) item(tt(r))( -Remove a trailing suffix of the form `tt(.)var(xxx)', leaving the basename. +Remove a filename extension of the form `tt(.)var(xxx)', leaving +the root name. ) item(tt(e))( -Remove all but the suffix. +Remove all but the extension. ) item(tt(t))( Remove all leading pathname components, leaving the tail. Index: Src/hist.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/hist.c,v retrieving revision 1.20 diff -u -r1.20 hist.c --- Src/hist.c 2000/10/21 03:15:36 1.20 +++ Src/hist.c 2000/12/14 17:38:40 @@ -1334,28 +1334,43 @@ int remtpath(char **junkptr) { - char *str = *junkptr, *remcut; + char *str = strend(*junkptr); - if ((remcut = strrchr(str, '/'))) { - if (str != remcut) - *remcut = '\0'; - else - str[1] = '\0'; - return 1; + /* ignore trailing slashes */ + while (str >= *junkptr && IS_DIRSEP(*str)) + --str; + /* skip filename */ + while (str >= *junkptr && !IS_DIRSEP(*str)) + --str; + if (str < *junkptr) + return 0; + /* repeated slashes are considered like a single slash */ + while (str > *junkptr && IS_DIRSEP(str[-1])) + --str; + /* never erase the root slash */ + if (str == *junkptr) { + ++str; + /* Leading doubled slashes (`//') have a special meaning on cygwin + and some old flavor of UNIX, so we do not assimilate them to + a single slashes. However a greater number is ok to squeeze. */ + if (IS_DIRSEP(*str) && !IS_DIRSEP(str[1])) + ++str; } - return 0; + *str = '\0'; + return 1; } /**/ int remtext(char **junkptr) { - char *str = *junkptr, *remcut; + char *str; - if ((remcut = strrchr(str, '.')) && remcut != str) { - *remcut = '\0'; - return 1; - } + for (str = strend(*junkptr); str >= *junkptr && !IS_DIRSEP(*str); --str) + if (*str == '.') { + *str = '\0'; + return 1; + } return 0; } @@ -1363,12 +1378,13 @@ int rembutext(char **junkptr) { - char *str = *junkptr, *remcut; + char *str; - if ((remcut = strrchr(str, '.')) && remcut != str) { - *junkptr = dupstring(remcut + 1); /* .xx or xx? */ - return 1; - } + for (str = strend(*junkptr); str >= *junkptr && !IS_DIRSEP(*str); --str) + if (*str == '.') { + *junkptr = dupstring(str + 1); /* .xx or xx? */ + return 1; + } return 0; } @@ -1376,13 +1392,14 @@ mod_export int remlpaths(char **junkptr) { - char *str = *junkptr, *remcut; + char *str = *junkptr + strlen (*junkptr) - 1; - if ((remcut = strrchr(str, '/'))) { - *remcut = '\0'; - *junkptr = dupstring(remcut + 1); - return 1; - } + for (str = strend(*junkptr); str >= *junkptr; --str) + if (IS_DIRSEP(*str)) { + *str = '\0'; + *junkptr = dupstring(str + 1); + return 1; + } return 0; } Index: Src/string.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/string.c,v retrieving revision 1.3 diff -u -r1.3 string.c --- Src/string.c 2000/09/27 19:31:48 1.3 +++ Src/string.c 2000/12/14 17:38:40 @@ -79,7 +79,7 @@ char *ptr; size_t l1 = strlen(s1); size_t l2 = strlen(s2); - + ptr = (char *)zhalloc(l1 + l2 + strlen(s3) + 1); strcpy(ptr, s1); strcpy(ptr + l1, s2); @@ -132,4 +132,16 @@ appstr(char *base, char const *append) { return strcat(realloc(base, strlen(base) + strlen(append) + 1), append); +} + +/* Return a pointer to the last character of a string, + unless the string is empty. */ + +/**/ +mod_export char * +strend(char *str) +{ + if (*str == '\0') + return str; + return str + strlen (str) - 1; } Index: Src/system.h =================================================================== RCS file: /cvsroot/zsh/zsh/Src/system.h,v retrieving revision 1.11 diff -u -r1.11 system.h --- Src/system.h 2000/09/18 14:22:48 1.11 +++ Src/system.h 2000/12/14 17:38:41 @@ -657,3 +657,9 @@ #ifndef MAILDIR_SUPPORT #define mailstat(X,Y) stat(X,Y) #endif + +#ifdef __CYGWIN__ +# define IS_DIRSEP(c) ((c) == '/' || (c) == '\\') +#else +# define IS_DIRSEP(c) ((c) == '/') +#endif -- Alexandre Duret-Lutz