Dear zsh workers, I thought it is time to have globbing size specifiers at hand also for gigabytes, and while at it for terabytes, too. As that seemed pretty straight forward, I tried to do the modification myself. So please find attached my patch to allow e.g. *(Lg+10) as well as *(Lt+1). On second thought I was not so straight forward as expected, so I hope I've done it correct; here are my thoughts: (1, glob.c) I included a check if ZSH_64_BIT_TYPE or LONG_IS_64 is defined, hence a 64-bit long type is available. If long is 32-bit the code isn't effectively changed at all. Although 1GB is small enough to fit in a 32-bit long, I included this case in the #if block, too -- just in case I have overlooked some logic and to prevent an overrun in case of a file size slightly larger than 3GB. (2, expn.yo) In the documentation I first mentioned the term ,,size specifiers'' which is used in the completion but is not showing up in the doc so far. I included the G and T specifiers of course, but introduced this sentence with ,,on some systems''. I wanted to keep it simple, hence I didn't mention the 64-bit condition. (3, _globquals) With the patch to the completion function I'm not satisfied completely, but I don't know how to do it better. First thing, the G and T madifiers are shown also with a 32-bit zsh executable. I tried to figure out a possibility to check if zsh is a 64-bit executable during runtime, but failed. Second, the items are ordered alphabetical in the completion list, resulting in an ugly arrangement: GB - KB - MB - blocks (p) - TB So far the list is -- either by change or by a very clever design decision -- ordered in a sensible way, first with increasing size the common unit prefixes and then blocks: KB - MB - blocks (p). Regarding these weak points, I'd appreciate your feedback. And of course if there are other problems I don't think of so far. Best regards, Manuel. --- Completion/Zsh/Type/_globquals | 6 +++--- Doc/Zsh/expn.yo | 10 ++++++---- Src/glob.c | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/Completion/Zsh/Type/_globquals b/Completion/Zsh/Type/_globquals index 9de7742..c98bd0c 100644 --- a/Completion/Zsh/Type/_globquals +++ b/Completion/Zsh/Type/_globquals @@ -132,13 +132,13 @@ while [[ -n $PREFIX ]]; do (L) # complete/skip file size - if ! compset -P '([kKmMpP]|)([-+]|)<->'; then + if ! compset -P '([kKmMgGtTpP]|)([-+]|)<->'; then # complete/skip size spec alts=() - if ! compset -P '[kKmMpP]' && [[ -z $PREFIX ]]; then + if ! compset -P '[kKmMgGtTpP]' && [[ -z $PREFIX ]]; then alts+=( "size-specifiers:size specifier:\ -((k\:kb m\:mb p\:512-byte\ blocks))") +((k\:kb m\:mb g\:gb t\:tb p\:512-byte\ blocks))") fi if ! compset -P '[-+]' && [[ -z $PREFIX ]]; then alts+=("senses:sense:((-\:less\ than +\:more\ than))") diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 6459c6f..de0f454 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -2521,10 +2521,12 @@ item(tt(L)[tt(PLUS())|tt(-)]var(n))( files less than var(n) bytes (tt(-)), more than var(n) bytes (tt(PLUS())), or exactly var(n) bytes in length. -If this flag is directly followed by a `tt(k)' (`tt(K)'), `tt(m)' -(`tt(M)'), or `tt(p)' (`tt(P)') (e.g. `tt(Lk-50)') the check is performed -with kilobytes, megabytes, or blocks (of 512 bytes) instead. In this -case a file is regarded as "exactly" the size if the file size rounded up +If this flag is directly followed by a em(size specifier) `tt(k)' (`tt(K)'), +`tt(m)' (`tt(M)'), or `tt(p)' (`tt(P)') (e.g. `tt(Lk-50)') the check is +performed with kilobytes, megabytes, or blocks (of 512 bytes) instead. +(On some systems additional specifiers are available for gigabytes, +`tt(g)' or `tt(G)', and terabytes, `tt(t)' or `tt(T)'.) If a size specifier +is used a file is regarded as "exactly" the size if the file size rounded up to the next unit is equal to the test size. Hence `tt(*LPAR()Lm1+RPAR())' matches files from 1 byte up to 1 Megabyte inclusive. Note also that the set of files "less than" the test size only includes files that would diff --git a/Src/glob.c b/Src/glob.c index 9a34a7f..c4227e0 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -120,6 +120,8 @@ typedef struct stat *Statptr; /* This makes the Ultrix compiler happy. Go figu #define TT_POSIX_BLOCKS 1 #define TT_KILOBYTES 2 #define TT_MEGABYTES 3 +#define TT_GIGABYTES 4 +#define TT_TERABYTES 5 typedef int (*TestMatchFunc) _((char *, struct stat *, off_t, char *)); @@ -1486,6 +1488,12 @@ zglob(LinkList list, LinkNode np, int nountok) g_units = TT_KILOBYTES, ++s; else if (*s == 'm' || *s == 'M') g_units = TT_MEGABYTES, ++s; +#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT) + else if (*s == 'g' || *s == 'G') + g_units = TT_GIGABYTES, ++s; + else if (*s == 't' || *s == 'T') + g_units = TT_TERABYTES, ++s; +#endif getrange: /* Get time multiplier */ if (g_amc >= 0) { @@ -3559,6 +3567,16 @@ qualsize(UNUSED(char *name), struct stat *buf, off_t size, UNUSED(char *dummy)) scaled += 1048575l; scaled /= 1048576l; break; +#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT) + case TT_GIGABYTES: + scaled += 1073741823l; + scaled /= 1073741824l; + break; + case TT_TERABYTES: + scaled += 1099511627775l; + scaled /= 1099511627776l; + break; +#endif } return (g_range < 0 ? scaled < QS_CAST_SIZE() size :
Attachment:
completion.patch
Description: Binary data
Attachment:
sizespec.patch
Description: Binary data