zsh-workers
 help / color / mirror / code / Atom feed
* Re: PATCH: suggestion for new glob modifiers
       [not found] <199901251328.OAA16371@beta.informatik.hu-berlin.de>
@ 1999-01-25 13:34 ` Peter Stephenson
  0 siblings, 0 replies; 3+ messages in thread
From: Peter Stephenson @ 1999-01-25 13:34 UTC (permalink / raw)
  To: Zsh hackers list

Sven sent me this and suggested I forwarded it to the list...


Peter Stephenson wrote:

> ...
> 
> One minor question is whether (Om) etc. should really be oldest first.
> I can see that's logical --- `time order' certainly implies oldest
> first --- but unfortunately it's the other way round from ls -t, which
> is the order I've grown to expect.  I can easily get used to using ^,
> though.

Funny, I was worrying about this, too, and for the same reason
(comparison with `ls -t'). Maybe it's better to change it.

Bye
 Sven

*** os/glob.c	Mon Jan 25 12:07:41 1999
--- Src/glob.c	Mon Jan 25 14:22:09 1999
***************
*** 1038,1050 ****
  	    r = b->size - a->size;
  	    break;
  	case GS_ATIME:
! 	    r = b->atime - a->atime;
  	    break;
  	case GS_MTIME:
! 	    r = b->mtime - a->mtime;
  	    break;
  	case GS_CTIME:
! 	    r = b->ctime - a->ctime;
  	    break;
  	case GS_LINKS:
  	    r = b->links - a->links;
--- 1038,1050 ----
  	    r = b->size - a->size;
  	    break;
  	case GS_ATIME:
! 	    r = a->atime - b->atime;
  	    break;
  	case GS_MTIME:
! 	    r = a->mtime - b->mtime;
  	    break;
  	case GS_CTIME:
! 	    r = a->ctime - b->ctime;
  	    break;
  	case GS_LINKS:
  	    r = b->links - a->links;
***************
*** 1053,1065 ****
  	    r = b->_size - a->_size;
  	    break;
  	case GS__ATIME:
! 	    r = b->_atime - a->_atime;
  	    break;
  	case GS__MTIME:
! 	    r = b->_mtime - a->_mtime;
  	    break;
  	case GS__CTIME:
! 	    r = b->_ctime - a->_ctime;
  	    break;
  	case GS__LINKS:
  	    r = b->_links - a->_links;
--- 1053,1065 ----
  	    r = b->_size - a->_size;
  	    break;
  	case GS__ATIME:
! 	    r = a->_atime - b->_atime;
  	    break;
  	case GS__MTIME:
! 	    r = a->_mtime - b->_mtime;
  	    break;
  	case GS__CTIME:
! 	    r = a->_ctime - b->_ctime;
  	    break;
  	case GS__LINKS:
  	    r = b->_links - a->_links;
*** od/Zsh/expn.yo	Mon Jan 25 12:07:48 1999
--- Doc/Zsh/expn.yo	Mon Jan 25 14:24:33 1999
***************
*** 1128,1134 ****
  are sorted depending on the size (length) of the files, tt(l) makes
  them be sorted by the number of links, and tt(a), tt(m), and tt(c)
  make them be sorted by the time of the last access, modification, and
! inode change respectively. Note that the modifiers tt(^) and tt(-) are 
  used, so `tt(*(^-OL))' gives a list of all files sorted by file size in 
  descending order working not on symbolic links but on the files they
  point to.
--- 1128,1136 ----
  are sorted depending on the size (length) of the files, tt(l) makes
  them be sorted by the number of links, and tt(a), tt(m), and tt(c)
  make them be sorted by the time of the last access, modification, and
! inode change respectively. Note that tt(a), tt(m), and tt(c) compare
! the age with to the current time, so the first name in the list is the 
! one of the youngest file. Also note that the modifiers tt(^) and tt(-) are 
  used, so `tt(*(^-OL))' gives a list of all files sorted by file size in 
  descending order working not on symbolic links but on the files they
  point to.

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

* Re: PATCH: suggestion for new glob modifiers
  1999-01-25 11:06 Sven Wischnowsky
@ 1999-01-25 12:51 ` Peter Stephenson
  0 siblings, 0 replies; 3+ messages in thread
From: Peter Stephenson @ 1999-01-25 12:51 UTC (permalink / raw)
  To: zsh-workers

Sven Wischnowsky wrote:
> 
> 1) A new glob modifier that allows to make the resulting list sorted
>    not only by name. The syntax is `Oc' where `c' is a character
>    saying how the list should be sorted:
> 
>    `n'           - by name
>    `L'           - by size (length)
>    `l'           - by number of links
>    `a', `m', ac' - by access, modification, or inode change time
> 
>    The modifiers `^' and `-' are respected, so `*(^OL^On)' gives you a 
>    list sorted largest file first, with files with the same size being 
>    sorted by name in ascending order.
> 
> 2) The second change is that you can give subscripts in modifier lists 
>    which say which matches you want to get.

This is excellent --- I've been using completion trickery for things
like this, but this is very much more flexible.

One minor question is whether (Om) etc. should really be oldest first.
I can see that's logical --- `time order' certainly implies oldest
first --- but unfortunately it's the other way round from ls -t, which
is the order I've grown to expect.  I can easily get used to using ^,
though.

-- 
Peter Stephenson <pws@ibmth.df.unipi.it>       Tel: +39 050 844536
WWW:  http://www.ifh.de/~pws/
Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy


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

* PATCH: suggestion for new glob modifiers
@ 1999-01-25 11:06 Sven Wischnowsky
  1999-01-25 12:51 ` Peter Stephenson
  0 siblings, 1 reply; 3+ messages in thread
From: Sven Wischnowsky @ 1999-01-25 11:06 UTC (permalink / raw)
  To: zsh-workers


This implements something I missed a long time...

1) A new glob modifier that allows to make the resulting list sorted
   not only by name. The syntax is `Oc' where `c' is a character
   saying how the list should be sorted:

   `n'           - by name
   `L'           - by size (length)
   `l'           - by number of links
   `a', `m', ac' - by access, modification, or inode change time

   The modifiers `^' and `-' are respected, so `*(^OL^On)' gives you a 
   list sorted largest file first, with files with the same size being 
   sorted by name in ascending order.

2) The second change is that you can give subscripts in modifier lists 
   which say which matches you want to get. The subscripts are as for
   arrays *without* the flags. If you use flags, the globbing code
   will take the modifier list as a pattern and return something you
   probably won't want. Maybe we should make this return an error.
   Example: `*(^OL[1,3])' gives you the names of the three biggest
   files.

This patch should work with all versions that have associative arrays
(due to the hunks in params.c which are needed to allow the globbing
code to easily use getindex() with a struct value which contains no
param-pointer).

Any comments?

Bye
 Sven

*** os/glob.c	Mon Jan 25 10:22:39 1999
--- Src/glob.c	Mon Jan 25 11:52:16 1999
***************
*** 31,37 ****
  #include "glob.pro"
  
  /* flag for CSHNULLGLOB */
!  
  /**/
  int badcshglob;
   
--- 31,72 ----
  #include "glob.pro"
  
  /* flag for CSHNULLGLOB */
! 
! typedef struct gmatch *Gmatch; 
! 
! struct gmatch {
!     char *name;
!     long size;
!     long atime;
!     long mtime;
!     long ctime;
!     long links;
!     long _size;
!     long _atime;
!     long _mtime;
!     long _ctime;
!     long _links;
! };
! 
! #define GS_NAME   1
! #define GS_SIZE   2
! #define GS_ATIME  4
! #define GS_MTIME  8
! #define GS_CTIME 16
! #define GS_LINKS 32
! 
! #define GS_SHIFT  5
! #define GS__SIZE  (GS_SIZE << GS_SHIFT)
! #define GS__ATIME (GS_ATIME << GS_SHIFT)
! #define GS__MTIME (GS_MTIME << GS_SHIFT)
! #define GS__CTIME (GS_CTIME << GS_SHIFT)
! #define GS__LINKS (GS_LINKS << GS_SHIFT)
! 
! #define GS_DESC  2048
! 
! #define GS_NORMAL (GS_SIZE | GS_ATIME | GS_MTIME | GS_CTIME | GS_LINKS)
! #define GS_LINKED (GS_NORMAL << GS_SHIFT)
! 
  /**/
  int badcshglob;
   
***************
*** 42,49 ****
  static char *pathbuf;		/* pathname buffer                      */
  static int pathbufsz;		/* size of pathbuf			*/
  static int pathbufcwd;		/* where did we chdir()'ed		*/
! static char **matchbuf;		/* array of matches                     */
! static char **matchptr;		/* &matchbuf[matchct]                   */
  static char *colonmod;		/* colon modifiers in qualifier list    */
  
  typedef struct stat *Statptr;	 /* This makes the Ultrix compiler happy.  Go figure. */
--- 77,84 ----
  static char *pathbuf;		/* pathname buffer                      */
  static int pathbufsz;		/* size of pathbuf			*/
  static int pathbufcwd;		/* where did we chdir()'ed		*/
! static Gmatch matchbuf;		/* array of matches                     */
! static Gmatch matchptr;		/* &matchbuf[matchct]                   */
  static char *colonmod;		/* colon modifiers in qualifier list    */
  
  typedef struct stat *Statptr;	 /* This makes the Ultrix compiler happy.  Go figure. */
***************
*** 81,86 ****
--- 116,122 ----
  static int qualct, qualorct;
  static int range, amc, units;
  static int gf_nullglob, gf_markdirs, gf_noglobdots, gf_listtypes, gf_follow;
+ static int gf_sorts, gf_nsorts, gf_sortlist[11];
  
  /* Prefix, suffix for doing zle trickery */
  
***************
*** 213,218 ****
--- 249,255 ----
  
  	if (!statted && statfullpath(s, &buf, 1))
  	    return;
+ 	statted = 1;
  	qo = quals;
  	for (qn = qo; qn && qn->func;) {
  	    range = qn->range;
***************
*** 237,255 ****
  	    }
  	    qn = qn->next;
  	}
!     } else if (!checked && statfullpath(s, NULL, 1))
! 	return;
! 
      news = dyncat(pathbuf, news);
      if (colonmod) {
  	/* Handle the remainder of the qualifer:  e.g. (:r:s/foo/bar/). */
  	s = colonmod;
  	modify(&news, &s);
      }
!     *matchptr++ = news;
      if (++matchct == matchsz) {
! 	matchbuf = (char **)realloc((char *)matchbuf,
! 				    sizeof(char **) * (matchsz *= 2));
  
  	matchptr = matchbuf + matchct;
      }
--- 274,317 ----
  	    }
  	    qn = qn->next;
  	}
!     } else if (!checked) {
! 	if (statfullpath(s, NULL, 1))
! 	    return;
! 	statted = 1;
!     }
      news = dyncat(pathbuf, news);
      if (colonmod) {
  	/* Handle the remainder of the qualifer:  e.g. (:r:s/foo/bar/). */
  	s = colonmod;
  	modify(&news, &s);
      }
!     if (!statted && (gf_sorts & GS_NORMAL)) {
! 	statfullpath(s, &buf, 1);
! 	statted = 1;
!     }
!     if (statted != 2 && (gf_sorts & GS_LINKED)) {
! 	if (statted) {
! 	    if (!S_ISLNK(buf.st_mode) || statfullpath(s, &buf2, 0))
! 		memcpy(&buf2, &buf, sizeof(buf));
! 	} else if (statfullpath(s, &buf2, 0))
! 	    statfullpath(s, &buf2, 1);
!     }
!     matchptr->name = news;
!     matchptr->size = buf.st_size;
!     matchptr->atime = buf.st_atime;
!     matchptr->mtime = buf.st_mtime;
!     matchptr->ctime = buf.st_ctime;
!     matchptr->links = buf.st_nlink;
!     matchptr->_size = buf2.st_size;
!     matchptr->_atime = buf2.st_atime;
!     matchptr->_mtime = buf2.st_mtime;
!     matchptr->_ctime = buf2.st_ctime;
!     matchptr->_links = buf2.st_nlink;
!     matchptr++;
! 
      if (++matchct == matchsz) {
! 	matchbuf = (Gmatch )realloc((char *)matchbuf,
! 				    sizeof(struct gmatch) * (matchsz *= 2));
  
  	matchptr = matchbuf + matchct;
      }
***************
*** 961,966 ****
--- 1023,1076 ----
      return v;
  }
  
+ static int
+ gmatchcmp(Gmatch a, Gmatch b)
+ {
+     int i, *s;
+     long r;
+ 
+     for (i = gf_nsorts, s = gf_sortlist; i; i--, s++) {
+ 	switch (*s & ~GS_DESC) {
+ 	case GS_NAME:
+ 	    r = notstrcmp(&a->name, &b->name);
+ 	    break;
+ 	case GS_SIZE:
+ 	    r = b->size - a->size;
+ 	    break;
+ 	case GS_ATIME:
+ 	    r = b->atime - a->atime;
+ 	    break;
+ 	case GS_MTIME:
+ 	    r = b->mtime - a->mtime;
+ 	    break;
+ 	case GS_CTIME:
+ 	    r = b->ctime - a->ctime;
+ 	    break;
+ 	case GS_LINKS:
+ 	    r = b->links - a->links;
+ 	    break;
+ 	case GS__SIZE:
+ 	    r = b->_size - a->_size;
+ 	    break;
+ 	case GS__ATIME:
+ 	    r = b->_atime - a->_atime;
+ 	    break;
+ 	case GS__MTIME:
+ 	    r = b->_mtime - a->_mtime;
+ 	    break;
+ 	case GS__CTIME:
+ 	    r = b->_ctime - a->_ctime;
+ 	    break;
+ 	case GS__LINKS:
+ 	    r = b->_links - a->_links;
+ 	    break;
+ 	}
+ 	if (r)
+ 	    return (int) ((*s & GS_DESC) ? -r : r);
+     }
+     return 0;
+ }
+ 
  /* Main entry point to the globbing code for filename globbing. *
   * np points to a node in the list list which will be expanded  *
   * into a series of nodes.                                      */
***************
*** 976,982 ****
      Complist q;				/* pattern after parsing         */
      char *ostr = (char *)getdata(np);	/* the pattern before the parser */
  					/* chops it up                   */
! 
      MUSTUSEHEAP("glob");
      if (unset(GLOBOPT) || !haswilds(ostr)) {
  	untokenize(ostr);
--- 1086,1093 ----
      Complist q;				/* pattern after parsing         */
      char *ostr = (char *)getdata(np);	/* the pattern before the parser */
  					/* chops it up                   */
!     int first = 0, last = -1;		/* index of first/last match to  */
! 				        /* return */
      MUSTUSEHEAP("glob");
      if (unset(GLOBOPT) || !haswilds(ostr)) {
  	untokenize(ostr);
***************
*** 994,999 ****
--- 1105,1111 ----
      gf_markdirs = isset(MARKDIRS);
      gf_listtypes = gf_follow = 0;
      gf_noglobdots = unset(GLOBDOTS);
+     gf_sorts = gf_nsorts = 0;
  
      /* Check for qualifiers */
      if (isset(BAREGLOBQUAL) && str[sl - 1] == Outpar) {
***************
*** 1315,1320 ****
--- 1427,1477 ----
  			data = qgetnum(&s);
  			break;
  
+ 		    case 'O':
+ 			{
+ 			    int t;
+ 
+ 			    switch (*s) {
+ 			    case 'n': t = GS_NAME; break;
+ 			    case 'L': t = GS_SIZE; break;
+ 			    case 'l': t = GS_LINKS; break;
+ 			    case 'a': t = GS_ATIME; break;
+ 			    case 'm': t = GS_MTIME; break;
+ 			    case 'c': t = GS_CTIME; break;
+ 			    default:
+ 				zerr("unknown sort specifier", NULL, 0);
+ 				return;
+ 			    }
+ 			    if ((sense & 2) && t != GS_NAME)
+ 				t <<= GS_SHIFT;
+ 			    if (gf_sorts & t) {
+ 				zerr("doubled sort specifier", NULL, 0);
+ 				return;
+ 			    }
+ 			    gf_sorts |= t;
+ 			    gf_sortlist[gf_nsorts++] = t |
+ 				((sense & 1) ? GS_DESC : 0);
+ 			    s++;
+ 			    break;
+ 			}
+ 		    case '[':
+ 		    case Inbrack:
+ 			{
+ 			    char *os = --s;
+ 			    struct value v;
+ 
+ 			    v.isarr = SCANPM_WANTVALS;
+ 			    v.pm = NULL;
+ 			    v.b = -1;
+ 			    v.inv = 0;
+ 			    if (getindex(&s, &v) || s == os) {
+ 				zerr("invalid subscript", NULL, 0);
+ 				return;
+ 			    }
+ 			    first = v.a;
+ 			    last = v.b;
+ 			    break;
+ 			}
  		    default:
  			zerr("unknown file attribute", NULL, 0);
  			return;
***************
*** 1353,1362 ****
  	zerr("bad pattern: %s", ostr, 0);
  	return;
      }
! 
      /* Initialise receptacle for matched files, *
       * expanded by insert() where necessary.    */
!     matchptr = matchbuf = (char **)zalloc((matchsz = 16) * sizeof(char *));
      matchct = 0;
  
      /* The actual processing takes place here: matches go into  *
--- 1510,1523 ----
  	zerr("bad pattern: %s", ostr, 0);
  	return;
      }
!     if (!gf_nsorts) {
! 	gf_sortlist[0] = gf_sorts = GS_NAME;
! 	gf_nsorts = 1;
!     }
      /* Initialise receptacle for matched files, *
       * expanded by insert() where necessary.    */
!     matchptr = matchbuf = (Gmatch)zalloc((matchsz = 16) *
! 					 sizeof(struct gmatch));
      matchct = 0;
  
      /* The actual processing takes place here: matches go into  *
***************
*** 1375,1392 ****
  	    return;
  	} else {
  	    /* treat as an ordinary string */
! 	    untokenize(*matchptr++ = dupstring(ostr));
  	    matchct = 1;
  	}
      }
      /* Sort arguments in to lexical (and possibly numeric) order. *
       * This is reversed to facilitate insertion into the list.    */
!     qsort((void *) & matchbuf[0], matchct, sizeof(char *),
! 	       (int (*) _((const void *, const void *)))notstrcmp);
  
!     matchptr = matchbuf;
!     while (matchct--)		/* insert matches in the arg list */
! 	insertlinknode(list, node, *matchptr++);
      free(matchbuf);
  }
  
--- 1536,1567 ----
  	    return;
  	} else {
  	    /* treat as an ordinary string */
! 	    untokenize(matchptr->name = dupstring(ostr));
! 	    matchptr++;
  	    matchct = 1;
  	}
      }
      /* Sort arguments in to lexical (and possibly numeric) order. *
       * This is reversed to facilitate insertion into the list.    */
!     qsort((void *) & matchbuf[0], matchct, sizeof(struct gmatch),
! 	       (int (*) _((const void *, const void *)))gmatchcmp);
  
!     if (first < 0)
! 	first += matchct;
!     if (last < 0)
! 	last += matchct;
!     if (first < 0)
! 	first = 0;
!     if (last >= matchct)
! 	last = matchct - 1;
!     if (first <= last) {
! 	matchptr = matchbuf + matchct - 1 - last;
! 	last -= first;
! 	while (last-- >= 0) {		/* insert matches in the arg list */
! 	    insertlinknode(list, node, matchptr->name);
! 	    matchptr++;
! 	}
!     }
      free(matchbuf);
  }
  
*** os/params.c	Mon Jan 25 10:22:41 1999
--- Src/params.c	Mon Jan 25 11:52:16 1999
***************
*** 679,685 ****
      Comp c;
  
      /* first parse any subscription flags */
!     if (*s == '(' || *s == Inpar) {
  	int escapes = 0;
  	int waste;
  	for (s++; *s != ')' && *s != Outpar && s != *str; s++) {
--- 679,685 ----
      Comp c;
  
      /* first parse any subscription flags */
!     if (v->pm && *s == '(' || *s == Inpar) {
  	int escapes = 0;
  	int waste;
  	for (s++; *s != ')' && *s != Outpar && s != *str; s++) {
***************
*** 765,771 ****
  	} else if (rev) {
  	    v->isarr |= SCANPM_WANTVALS;
  	}
! 	if (!down && PM_TYPE(v->pm->flags) == PM_HASHED)
  	    v->isarr &= ~SCANPM_MATCHMANY;
  	*inv = ind;
      }
--- 765,771 ----
  	} else if (rev) {
  	    v->isarr |= SCANPM_WANTVALS;
  	}
! 	if (!down && v->pm && PM_TYPE(v->pm->flags) == PM_HASHED)
  	    v->isarr &= ~SCANPM_MATCHMANY;
  	*inv = ind;
      }
***************
*** 785,791 ****
      singsub(&s);
  
      if (!rev) {
! 	if (PM_TYPE(v->pm->flags) == PM_HASHED) {
  	    HashTable ht = v->pm->gets.hfn(v->pm);
  	    if (!ht) {
  		ht = newparamtable(17, v->pm->nam);
--- 785,791 ----
      singsub(&s);
  
      if (!rev) {
! 	if (v->pm && PM_TYPE(v->pm->flags) == PM_HASHED) {
  	    HashTable ht = v->pm->gets.hfn(v->pm);
  	    if (!ht) {
  		ht = newparamtable(17, v->pm->nam);
*** od/Zsh/expn.yo	Mon Jan 25 10:22:13 1999
--- Doc/Zsh/expn.yo	Mon Jan 25 11:52:17 1999
***************
*** 1122,1127 ****
--- 1122,1146 ----
  sets the tt(GLOB_DOTS) option for the current pattern
  pindex(GLOB_DOTS, setting in pattern)
  )
+ item(tt(O)var(c))(
+ specifies how the names of the files should be sorted. If var(c) is
+ tt(n) they are sorted by name (the default), if var(c) is tt(L) they
+ are sorted depending on the size (length) of the files, tt(l) makes
+ them be sorted by the number of links, and tt(a), tt(m), and tt(c)
+ make them be sorted by the time of the last access, modification, and
+ inode change respectively. Note that the modifiers tt(^) and tt(-) are 
+ used, so `tt(*(^-OL))' gives a list of all files sorted by file size in 
+ descending order working not on symbolic links but on the files they
+ point to.
+ )
+ item(tt([)var(beg)[tt(,)var(end)]tt(]))(
+ specifies which of the matched filenames should be included in the
+ returned list. The syntax is the same as for array
+ subscripts. var(beg) and the optional var(end) may be mathematical
+ expressions. As in parameter subscripting they may be negative to make 
+ them count from the last match backward. E.g.: `tt(*(^-OL[1,3]))'
+ gives a list of the names of three biggest files.
+ )
  enditem()
  
  More than one of these lists can be combined, separated by commas. The

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

end of thread, other threads:[~1999-01-25 13:34 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <199901251328.OAA16371@beta.informatik.hu-berlin.de>
1999-01-25 13:34 ` PATCH: suggestion for new glob modifiers Peter Stephenson
1999-01-25 11:06 Sven Wischnowsky
1999-01-25 12:51 ` 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).