From 3ffb3ad2f2f733fbee58e21dc6aab23827ab8d49 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 3 Sep 2003 10:15:32 +0000 Subject: 19014: add alias -s suf=handler --- ChangeLog | 11 ++ Completion/Zsh/Command/_alias | 2 +- Completion/Zsh/Type/.distfiles | 1 + Completion/Zsh/Type/_aliases | 4 +- Completion/Zsh/Type/_command_names | 1 + Completion/Zsh/Type/_suffix_alias_files | 21 +++ Doc/Zsh/builtins.yo | 53 +++++--- Doc/Zsh/mod_parameter.yo | 12 +- Src/Modules/parameter.c | 231 ++++++++++++++++++++++---------- Src/builtin.c | 72 +++++++--- Src/hashtable.c | 74 +++++++--- Src/init.c | 2 +- Src/lex.c | 40 ++++-- Src/zsh.h | 5 +- 14 files changed, 383 insertions(+), 146 deletions(-) create mode 100644 Completion/Zsh/Type/_suffix_alias_files diff --git a/ChangeLog b/ChangeLog index 52800c31b..fc7a3cedf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2003-09-03 Peter Stephenson + + * 19014: Completion/Zsh/Command/_alias, + Completion/Zsh/Type/.distfiles, Completion/Zsh/Type/_aliases, + Completion/Zsh/Type/_command_names, + Completion/Zsh/Type/_suffix_alias_files, Doc/Zsh/builtins.yo, + Doc/Zsh/mod_parameter.yo, Src/builtin.c, Src/hashtable.c, + Src/init.c, Src/lex.c, Src/zsh.h, Src/Modules/parameter.c: + add `alias -s suf=cmd' capability to expand `anything.suf' + to `cmd anything.suf'. + 2003-08-30 Peter Stephenson * c.f. somewhat terse reference in zsh-users/6493: diff --git a/Completion/Zsh/Command/_alias b/Completion/Zsh/Command/_alias index ecc298c73..8feb14a07 100644 --- a/Completion/Zsh/Command/_alias +++ b/Completion/Zsh/Command/_alias @@ -5,6 +5,7 @@ local curcontext="$curcontext" state line suf _arguments -C -s -A "-*" -S \ '-+g[list or define global aliases]' \ '-+r[list or define regular aliases]' \ + '-+s[list or define suffix aliases]' \ '-+m[print aliases matching specified pattern]' \ '-L[print each alias in the form of calls to alias]' \ '*::alias definition:->defn' @@ -18,4 +19,3 @@ if [[ -n "$state" ]]; then _wanted alias expl 'alias definition' _aliases -S "$suf" fi fi - diff --git a/Completion/Zsh/Type/.distfiles b/Completion/Zsh/Type/.distfiles index 652148b61..f8f7cc905 100644 --- a/Completion/Zsh/Type/.distfiles +++ b/Completion/Zsh/Type/.distfiles @@ -4,4 +4,5 @@ _aliases _file_descriptors _jobs_fg _options_unset _arrays _functions _limits _parameters _command_names _jobs _options _vars _directory_stack _jobs_bg _options_set +_suffix_alias_files ' diff --git a/Completion/Zsh/Type/_aliases b/Completion/Zsh/Type/_aliases index 30e091d98..6506ece13 100644 --- a/Completion/Zsh/Type/_aliases +++ b/Completion/Zsh/Type/_aliases @@ -4,14 +4,16 @@ local expl sel args opts zparseopts -E -D s:=sel -[[ -z $sel ]] && sel=rg +[[ -z $sel ]] && sel=rgs opts=( "$@" ) args=() [[ $sel = *r* ]] && args=( $args 'aliases:regular alias:compadd -k aliases' ) [[ $sel = *g* ]] && args=( $args 'global-aliases:global alias:compadd -k galiases' ) +[[ $sel = *s* ]] && args=( $args 'suffix-aliases:suffix alias:compadd -k saliases' ) [[ $sel = *R* ]] && args=( $args 'disabled-aliases:disabled regular alias:compadd -k dis_aliases' ) [[ $sel = *G* ]] && args=( $args 'disabled-global-aliases:disabled global alias:compadd -k dis_galiases' ) +[[ $sel = *S* ]] && args=( $args 'disabled-suffix-aliases:disabled suffix alias:compadd -k dis_saliases' ) _alternative -O opts $args diff --git a/Completion/Zsh/Type/_command_names b/Completion/Zsh/Type/_command_names index 613f1fe59..a8bf7b481 100644 --- a/Completion/Zsh/Type/_command_names +++ b/Completion/Zsh/Type/_command_names @@ -24,6 +24,7 @@ else 'builtins:builtin command:compadd -k builtins' 'functions:shell function:compadd -k functions' 'aliases:alias:compadd -k aliases' + 'suffix-aliases:suffix alias:_suffix_alias_files' 'reserved-words:reserved word:compadd -k reswords' 'jobs:: _jobs -t' 'parameters:: _parameters -g "^*readonly*" -qS= -r "\n\t\- =["' diff --git a/Completion/Zsh/Type/_suffix_alias_files b/Completion/Zsh/Type/_suffix_alias_files new file mode 100644 index 000000000..1c2c8ebb5 --- /dev/null +++ b/Completion/Zsh/Type/_suffix_alias_files @@ -0,0 +1,21 @@ +#autoload + +# Complete files for which a suffix alias exists. + +local expl pat + +(( ${#saliases} )) || return 1 + +if (( ${#saliases} == 1 )); then + pat="*.${(kq)saliases}" +else + local -a tmpa + # This is so we can quote the alias names against expansion + # without quoting the `|' which needs to be active in the pattern + # --- remember that an alias name can be pretty much anything. + tmpa=(${(kq)saliases}) + pat="*.(${(kj.|.)tmpa})" +fi + +# _wanted is called for us by _command_names +_path_files "$@" -g $pat diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index d7f4625e4..731474555 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -60,23 +60,40 @@ which may have effects on shell parameters. A zero exit code is returned. findex(alias) cindex(aliases, defining) cindex(aliases, listing) -item(tt(alias) [ {tt(PLUS()|tt(-))}tt(gmrL) ] [ var(name)[tt(=)var(value)] ... ])( +item(tt(alias) [ {tt(PLUS()|tt(-))}tt(gmrsL) ] [ var(name)[tt(=)var(value)] ... ])( For each var(name) with a corresponding var(value), define an alias with that value. A trailing space in var(value) causes the next word to be checked for alias expansion. If the tt(-g) flag is present, define a global alias; global aliases are expanded even if they do not occur in command position. +If the tt(-s) flags is present, define a suffix alias: if the command +word on a command line is in the form `var(text)tt(.)var(name)', where +var(text) is any non-empty string, it is replaced by the text +`var(value) var(text)tt(.)var(name)'. Note that var(name) is treated as +a literal string, not a pattern. A trailing space in var(value) is not +special in this case. For example, + +example(alias -s ps=gv) + +will cause the command `tt(*.ps)' to be expanded to `tt(gv *.ps)'. As +alias expansion is carried out earlier than globbing, the `tt(*.ps)' will +then be expanded. Suffix aliases constitute a different name space from +other aliases (so in the above example it is still possible +to create an alias for the command tt(ps)) and the two sets are never +listed together. + For each var(name) with no var(value), print the value of var(name), if any. With no arguments, print all -currently defined aliases. If the tt(-m) flag is given the arguments -are taken as patterns (they should be quoted to preserve them from being -interpreted as glob patterns), and the aliases matching these patterns -are printed. When printing aliases and the tt(-g) or tt(-r) flags -are present, then restrict the printing to global or regular -aliases, respectively. Using `tt(PLUS())' instead of `tt(-)', or ending -the option list with a single `tt(PLUS())', prevents the values of the -aliases from being printed. +currently defined aliases other than suffix aliases. If the tt(-m) flag +is given the arguments are taken as patterns (they should be quoted to +preserve them from being interpreted as glob patterns), and the aliases +matching these patterns are printed. When printing aliases and one of +the tt(-g), tt(-r) or tt(-s) flags is present, restrict the printing to +global, regular or suffix aliases, respectively; a regular alias is one +which is neither a global nor a suffix alias. Using `tt(PLUS())' +instead of `tt(-)', or ending the option list with a single +`tt(PLUS())', prevents the values of the aliases from being printed. If the tt(-L) flag is present, then print each alias in a manner suitable for putting in a startup script. The exit @@ -228,11 +245,12 @@ enditem() findex(disable) cindex(disabling commands) cindex(commands, disabling) -item(tt(disable) [ tt(-afmr) ] var(name) ...)( +item(tt(disable) [ tt(-afmrs) ] var(name) ...)( Temporarily disable the var(name)d hash table elements. The default is to disable builtin commands. This allows you to use an external command with the same name as a builtin command. The tt(-a) option -causes tt(disable) to act on aliases. The tt(-f) option causes +causes tt(disable) to act on regular or global aliases. The tt(-s) +option causes tt(disable) to act on suffix aliases. The tt(-f) option causes tt(disable) to act on shell functions. The tt(-r) options causes tt(disable) to act on reserved words. Without arguments all disabled hash table elements from the corresponding hash table are printed. @@ -323,11 +341,12 @@ modes except tt(ksh). findex(enable) cindex(enabling commands) cindex(commands, enabling) -item(tt(enable) [ tt(-afmr) ] var(name) ...)( +item(tt(enable) [ tt(-afmrs) ] var(name) ...)( Enable the var(name)d hash table elements, presumably disabled earlier with tt(disable). The default is to enable builtin commands. -The tt(-a) option causes tt(enable) to act on aliases. The tt(-f) -option causes tt(enable) to act on shell functions. The tt(-r) +The tt(-a) option causes tt(enable) to act on regular or global aliases. +The tt(-s) option causes tt(enable) to act on suffix aliases. +The tt(-f) option causes tt(enable) to act on shell functions. The tt(-r) option causes tt(enable) to act on reserved words. Without arguments all enabled hash table elements from the corresponding hash table are printed. With the tt(-m) flag the arguments are taken as patterns @@ -1380,10 +1399,12 @@ alias(unalias)(unhash -a) cindex(functions, removing) alias(unfunction)(unhash -f) findex(unhash) -item(tt(unhash) [ tt(-adfm) ] var(name) ...)( +item(tt(unhash) [ tt(-adfms) ] var(name) ...)( Remove the element named var(name) from an internal hash table. The default is remove elements from the command hash table. The tt(-a) -option causes tt(unhash) to remove aliases. The tt(-f) option causes +option causes tt(unhash) to remove regular or global aliases. +The tt(-s) option causes tt(unhash) to remove suffix aliases. +The tt(-f) option causes tt(unhash) to remove shell functions. The tt(-d) options causes tt(unhash) to remove named directories. If the tt(-m) flag is given the arguments are taken as patterns (should be quoted) and all elements diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo index 2d2847af2..04a998f83 100644 --- a/Doc/Zsh/mod_parameter.yo +++ b/Doc/Zsh/mod_parameter.yo @@ -64,16 +64,24 @@ expansions. ) vindex(dis_aliases) item(tt(dis_aliases))( -Like tt(raliases) but for disabled regular aliases. +Like tt(aliases) but for disabled regular aliases. ) vindex(galiases) item(tt(galiases))( -Like tt(raliases), but for global aliases. +Like tt(aliases), but for global aliases. ) vindex(dis_galiases) item(tt(dis_galiases))( Like tt(galiases) but for disabled global aliases. ) +vindex(saliases) +item(tt(saliases))( +Like tt(raliases), but for suffix aliases. +) +vindex(dis_saliases) +item(tt(dis_saliases))( +Like tt(saliases) but for disabled suffix aliases. +) vindex(parameters) item(tt(parameters))( The keys in this associative array are the names of the parameters diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index 6960dceb0..dc92aaaf8 100644 --- a/Src/Modules/parameter.c +++ b/Src/Modules/parameter.c @@ -1611,49 +1611,56 @@ scanpmuserdirs(HashTable ht, ScanFunc func, int flags) } } -/* Functions for the regularaliases and globalaliases special parameters. */ +/* Functions for the raliases, galiases and saliases special parameters. */ /**/ static void -setralias(Param pm, char *value, int dis) +setalias(HashTable ht, Param pm, char *value, int flags) { - aliastab->addnode(aliastab, ztrdup(pm->nam), createaliasnode(value, dis)); + ht->addnode(aliastab, ztrdup(pm->nam), + createaliasnode(value, flags)); } /**/ static void setpmralias(Param pm, char *value) { - setralias(pm, value, 0); + setalias(aliastab, pm, value, 0); } /**/ static void setpmdisralias(Param pm, char *value) { - setralias(pm, value, DISABLED); + setalias(aliastab, pm, value, DISABLED); } /**/ static void -setgalias(Param pm, char *value, int dis) +setpmgalias(Param pm, char *value) { - aliastab->addnode(aliastab, ztrdup(pm->nam), - createaliasnode(value, dis | ALIAS_GLOBAL)); + setalias(aliastab, pm, value, ALIAS_GLOBAL); } /**/ static void -setpmgalias(Param pm, char *value) +setpmdisgalias(Param pm, char *value) { - setgalias(pm, value, 0); + setgalias(aliastab, pm, value, ALIAS_GLOBAL|DISABLED); } /**/ static void -setpmdisgalias(Param pm, char *value) +setpmsalias(Param pm, char *value) { - setgalias(pm, value, DISABLED); + setgalias(sufaliastab, pm, value, 0); +} + +/**/ +static void +setpmdissalias(Param pm, char *value) +{ + setgalias(sufaliastab, pm, value, DISABLED); } /**/ @@ -1668,7 +1675,17 @@ unsetpmalias(Param pm, int exp) /**/ static void -setaliases(Param pm, HashTable ht, int global, int dis) +unsetpmsalias(Param pm, int exp) +{ + HashNode hd = sufaliastab->removenode(sufaliastab, pm->nam); + + if (hd) + sufaliastab->freenode(hd); +} + +/**/ +static void +setaliases(HashTable alht, Param pm, HashTable ht, int flags) { int i; HashNode hn, next, hd; @@ -1676,13 +1693,18 @@ setaliases(Param pm, HashTable ht, int global, int dis) if (!ht) return; - for (i = 0; i < aliastab->hsize; i++) - for (hn = aliastab->nodes[i]; hn; hn = next) { + for (i = 0; i < alht->hsize; i++) + for (hn = alht->nodes[i]; hn; hn = next) { next = hn->next; - if (((global && (((Alias) hn)->flags & ALIAS_GLOBAL)) || - (!global && !(((Alias) hn)->flags & ALIAS_GLOBAL))) && - (hd = aliastab->removenode(aliastab, hn->nam))) - aliastab->freenode(hd); + /* + * The following respects the DISABLED flag, e.g. + * we get a different behaviour for raliases and dis_raliases. + * The predecessor to this code didn't do that; presumably + * that was a bug. + */ + if (flags == ((Alias)hn)->flags && + (hd = alht->removenode(alht, hn->nam))) + alht->freenode(hd); } for (i = 0; i < ht->hsize; i++) @@ -1696,10 +1718,8 @@ setaliases(Param pm, HashTable ht, int global, int dis) v.pm = (Param) hn; if ((val = getstrvalue(&v))) - aliastab->addnode(aliastab, ztrdup(hn->nam), - createaliasnode(ztrdup(val), - (global ? ALIAS_GLOBAL : 0) | - (dis ? DISABLED : 0))); + alht->addnode(alht, ztrdup(hn->nam), + createaliasnode(ztrdup(val), flags)); } deleteparamtable(ht); } @@ -1708,53 +1728,103 @@ setaliases(Param pm, HashTable ht, int global, int dis) static void setpmraliases(Param pm, HashTable ht) { - setaliases(pm, ht, 0, 0); + setaliases(aliastab, pm, ht, 0); } /**/ static void setpmdisraliases(Param pm, HashTable ht) { - setaliases(pm, ht, 0, DISABLED); + setaliases(aliastab, pm, ht, DISABLED); } /**/ static void setpmgaliases(Param pm, HashTable ht) { - setaliases(pm, ht, 1, 0); + setaliases(aliastab, pm, ht, ALIAS_GLOBAL); } /**/ static void setpmdisgaliases(Param pm, HashTable ht) { - setaliases(pm, ht, 1, DISABLED); + setaliases(aliastab, pm, ht, ALIAS_GLOBAL|DISABLED); } /**/ -static HashNode -getalias(HashTable ht, char *name, int global, int dis) +static void +setpmsaliases(Param pm, HashTable ht) { - Param pm = NULL; - Alias al; + setaliases(sufaliastab, pm, ht, ALIAS_SUFFIX); +} - pm = (Param) zhalloc(sizeof(struct param)); - pm->nam = dupstring(name); +/**/ +static void +setpmdissaliases(Param pm, HashTable ht) +{ + setaliases(sufaliastab, pm, ht, ALIAS_SUFFIX|DISABLED); +} + +/**/ +static void +assignaliasdefs(Param pm, int flags) +{ pm->flags = PM_SCALAR; - pm->sets.cfn = (global ? (dis ? setpmdisgalias : setpmgalias) : - (dis ? setpmdisralias : setpmralias)); + + /* we really need to squirrel the flags away somewhere... */ + switch (flags) { + case 0: + pm->sets.cfn = setpmralias; + break; + + case ALIAS_GLOBAL: + pm->sets.cfn = setpmgalias; + break; + + case ALIAS_SUFFIX: + pm->sets.cfn = setpmsalias; + break; + + case DISABLED: + pm->sets.cfn = setpmdisralias; + break; + + case ALIAS_GLOBAL|DISABLED: + pm->sets.cfn = setpmdisgalias; + break; + + case ALIAS_SUFFIX|DISABLED: + pm->sets.cfn = setpmdissalias; + break; + } + pm->gets.cfn = strgetfn; - pm->unsetfn = unsetpmalias; + if (flags & ALIAS_SUFFIX) + pm->unsetfn = unsetpmsalias; + else + pm->unsetfn = unsetpmalias; pm->ct = 0; pm->env = NULL; pm->ename = NULL; pm->old = NULL; pm->level = 0; - if ((al = (Alias) aliastab->getnode2(aliastab, name)) && - ((global && (al->flags & ALIAS_GLOBAL)) || - (!global && !(al->flags & ALIAS_GLOBAL))) && - (dis ? (al->flags & DISABLED) : !(al->flags & DISABLED))) +} + +/**/ +static HashNode +getalias(HashTable alht, HashTable ht, char *name, int flags) +{ + Param pm = NULL; + Alias al; + + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + + assignaliasdefs(pm, flags); + + if ((al = (Alias) alht->getnode2(alht, name)) && + flags == al->flags) pm->u.str = dupstring(al->text); else { pm->u.str = dupstring(""); @@ -1767,61 +1837,64 @@ getalias(HashTable ht, char *name, int global, int dis) static HashNode getpmralias(HashTable ht, char *name) { - return getalias(ht, name, 0, 0); + return getalias(aliastab, ht, name, 0); } /**/ static HashNode getpmdisralias(HashTable ht, char *name) { - return getalias(ht, name, 0, 0); + return getalias(aliastab, ht, name, DISABLED); } /**/ static HashNode getpmgalias(HashTable ht, char *name) { - return getalias(ht, name, 1, 0); + return getalias(aliastab, ht, name, ALIAS_GLOBAL); } /**/ static HashNode getpmdisgalias(HashTable ht, char *name) { - return getalias(ht, name, 1, DISABLED); + return getalias(aliastab, ht, name, ALIAS_GLOBAL|DISABLED); +} + +/**/ +static HashNode +getpmsalias(HashTable ht, char *name) +{ + return getalias(sufaliastab, ht, name, ALIAS_SUFFIX); +} + +/**/ +static HashNode +getpmdissalias(HashTable ht, char *name) +{ + return getalias(sufaliastab, ht, name, ALIAS_SUFFIX|DISABLED); } /**/ static void -scanaliases(HashTable ht, ScanFunc func, int flags, int global, int dis) +scanaliases(HashTable alht, HashTable ht, ScanFunc func, + int pmflags, int alflags) { struct param pm; int i; - HashNode hn; Alias al; - pm.flags = PM_SCALAR; - pm.sets.cfn = (global ? (dis ? setpmdisgalias : setpmgalias) : - (dis ? setpmdisralias : setpmralias)); - pm.gets.cfn = strgetfn; - pm.unsetfn = unsetpmalias; - pm.ct = 0; - pm.env = NULL; - pm.ename = NULL; - pm.old = NULL; - pm.level = 0; + assignaliasdefs(&pm, alflags); - for (i = 0; i < aliastab->hsize; i++) - for (hn = aliastab->nodes[i]; hn; hn = hn->next) { - if (((global && ((al = (Alias) hn)->flags & ALIAS_GLOBAL)) || - (!global && !((al = (Alias) hn)->flags & ALIAS_GLOBAL))) && - (dis ? (al->flags & DISABLED) : !(al->flags & DISABLED))) { - pm.nam = hn->nam; + for (i = 0; i < alht->hsize; i++) + for (al = (Alias) alht->nodes[i]; al; al = (Alias) al->next) { + if (alflags == al->flags) { + pm.nam = al->nam; if (func != scancountparams && - ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) || - !(flags & SCANPM_WANTKEYS))) + ((pmflags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) || + !(pmflags & SCANPM_WANTKEYS))) pm.u.str = dupstring(al->text); - func((HashNode) &pm, flags); + func((HashNode) &pm, pmflags); } } } @@ -1830,28 +1903,42 @@ scanaliases(HashTable ht, ScanFunc func, int flags, int global, int dis) static void scanpmraliases(HashTable ht, ScanFunc func, int flags) { - scanaliases(ht, func, flags, 0, 0); + scanaliases(aliastab, ht, func, flags, 0); } /**/ static void scanpmdisraliases(HashTable ht, ScanFunc func, int flags) { - scanaliases(ht, func, flags, 0, DISABLED); + scanaliases(aliastab, ht, func, flags, DISABLED); } /**/ static void scanpmgaliases(HashTable ht, ScanFunc func, int flags) { - scanaliases(ht, func, flags, 1, 0); + scanaliases(aliastab, ht, func, flags, ALIAS_GLOBAL); } /**/ static void scanpmdisgaliases(HashTable ht, ScanFunc func, int flags) { - scanaliases(ht, func, flags, 1, DISABLED); + scanaliases(aliastab, ht, func, flags, ALIAS_GLOBAL|DISABLED); +} + +/**/ +static void +scanpmsaliases(HashTable ht, ScanFunc func, int flags) +{ + scanaliases(sufaliastab, ht, func, flags, ALIAS_SUFFIX); +} + +/**/ +static void +scanpmdissaliases(HashTable ht, ScanFunc func, int flags) +{ + scanaliases(sufaliastab, ht, func, flags, ALIAS_SUFFIX|DISABLED); } /* Table for defined parameters. */ @@ -1932,12 +2019,18 @@ static struct pardef partab[] = { { "galiases", 0, getpmgalias, scanpmgaliases, setpmgaliases, NULL, NULL, stdunsetfn, NULL }, + { "saliases", 0, + getpmsalias, scanpmsaliases, setpmsaliases, + NULL, NULL, stdunsetfn, NULL }, { "dis_aliases", 0, getpmdisralias, scanpmdisraliases, setpmdisraliases, NULL, NULL, stdunsetfn, NULL }, { "dis_galiases", 0, getpmdisgalias, scanpmdisgaliases, setpmdisgaliases, NULL, NULL, stdunsetfn, NULL }, + { "dis_saliases", 0, + getpmdissalias, scanpmdissaliases, setpmdissaliases, + NULL, NULL, stdunsetfn, NULL }, { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL } }; diff --git a/Src/builtin.c b/Src/builtin.c index bdb7c72d8..057800df6 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -45,7 +45,7 @@ static struct builtin builtins[] = BUILTIN("[", 0, bin_test, 0, -1, BIN_BRACKET, NULL, NULL), BUILTIN(".", BINF_PSPECIAL, bin_dot, 1, -1, 0, NULL, NULL), BUILTIN(":", BINF_PSPECIAL, bin_true, 0, -1, 0, NULL, NULL), - BUILTIN("alias", BINF_MAGICEQUALS | BINF_PLUSOPTS, bin_alias, 0, -1, 0, "Lgmr", NULL), + BUILTIN("alias", BINF_MAGICEQUALS | BINF_PLUSOPTS, bin_alias, 0, -1, 0, "Lgmrs", NULL), BUILTIN("autoload", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "tUXwkz", "u"), BUILTIN("bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL), BUILTIN("break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL), @@ -55,11 +55,11 @@ static struct builtin builtins[] = BUILTIN("continue", BINF_PSPECIAL, bin_break, 0, 1, BIN_CONTINUE, NULL, NULL), BUILTIN("declare", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%lprtux", NULL), BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "clpv", NULL), - BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmr", NULL), + BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmrs", NULL), BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL), BUILTIN("echo", BINF_PRINTOPTS | BINF_SKIPINVALID, bin_print, 0, -1, BIN_ECHO, "neE", "-"), BUILTIN("emulate", 0, bin_emulate, 1, 1, 0, "LR", NULL), - BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmr", NULL), + BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmrs", NULL), BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL), BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL), BUILTIN("export", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "E:%F:%HL:%R:%TUZ:%afhi:%lprtu", "xg"), @@ -123,9 +123,9 @@ static struct builtin builtins[] = BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsw", "v"), BUILTIN("typeset", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%lprtuxm", NULL), BUILTIN("umask", 0, bin_umask, 0, 1, 0, "S", NULL), - BUILTIN("unalias", 0, bin_unhash, 1, -1, 0, "m", "a"), + BUILTIN("unalias", 0, bin_unhash, 1, -1, 0, "ms", "a"), BUILTIN("unfunction", 0, bin_unhash, 1, -1, 0, "m", "f"), - BUILTIN("unhash", 0, bin_unhash, 1, -1, 0, "adfm", NULL), + BUILTIN("unhash", 0, bin_unhash, 1, -1, 0, "adfms", NULL), BUILTIN("unset", BINF_PSPECIAL, bin_unset, 1, -1, 0, "fmv", NULL), BUILTIN("unsetopt", 0, bin_setopt, 0, -1, BIN_UNSETOPT, NULL, NULL), BUILTIN("wait", 0, bin_fg, 0, -1, BIN_WAIT, NULL, NULL), @@ -461,6 +461,8 @@ bin_enable(char *name, char **argv, Options ops, int func) ht = shfunctab; else if (OPT_ISSET(ops,'r')) ht = reswdtab; + else if (OPT_ISSET(ops,'s')) + ht = sufaliastab; else if (OPT_ISSET(ops,'a')) ht = aliastab; else @@ -2671,6 +2673,8 @@ bin_whence(char *nam, char **argv, Options ops, int func) informed = 0; if (!OPT_ISSET(ops,'p')) { + char *suf; + /* Look for alias */ if ((hn = aliastab->getnode(aliastab, *argv))) { aliastab->printnode(hn, printflags); @@ -2678,6 +2682,15 @@ bin_whence(char *nam, char **argv, Options ops, int func) continue; informed = 1; } + /* Look for suffix alias */ + if ((suf = strrchr(*argv, '.')) && suf[1] && + suf > *argv && suf[-1] != Meta && + (hn = sufaliastab->getnode(sufaliastab, suf+1))) { + sufaliastab->printnode(hn, printflags); + if (!all) + continue; + informed = 1; + } /* Look for reserved word */ if ((hn = reswdtab->getnode(reswdtab, *argv))) { reswdtab->printnode(hn, printflags); @@ -2901,6 +2914,8 @@ bin_unhash(char *name, char **argv, Options ops, int func) ht = nameddirtab; /* named directories */ else if (OPT_ISSET(ops,'f')) ht = shfunctab; /* shell functions */ + else if (OPT_ISSET(ops,'s')) + ht = sufaliastab; /* suffix aliases, must precede aliases */ else if (OPT_ISSET(ops,'a')) ht = aliastab; /* aliases */ else @@ -2963,34 +2978,48 @@ bin_alias(char *name, char **argv, Options ops, int func) Alias a; Patprog pprog; Asgment asg; - int haveflags = 0, returnval = 0; + int returnval = 0; int flags1 = 0, flags2 = DISABLED; int printflags = 0; + int type_opts; + HashTable ht = aliastab; /* Did we specify the type of alias? */ - if (OPT_ISSET(ops,'r') || OPT_ISSET(ops,'g')) { - if (OPT_ISSET(ops,'r') && OPT_ISSET(ops,'g')) { + type_opts = OPT_ISSET(ops, 'r') + OPT_ISSET(ops, 'g') + + OPT_ISSET(ops, 's'); + if (type_opts) { + if (type_opts > 1) { zwarnnam(name, "illegal combination of options", NULL, 0); return 1; } - haveflags = 1; if (OPT_ISSET(ops,'g')) flags1 |= ALIAS_GLOBAL; else flags2 |= ALIAS_GLOBAL; + if (OPT_ISSET(ops, 's')) { + /* + * Although we keep suffix aliases in a different table, + * it is useful to be able to distinguish Alias structures + * without reference to the table, so we have a separate + * flag, too. + */ + flags1 |= ALIAS_SUFFIX; + ht = sufaliastab; + } else + flags2 |= ALIAS_SUFFIX; } if (OPT_ISSET(ops,'L')) printflags |= PRINT_LIST; - else if (OPT_PLUS(ops,'r') || OPT_PLUS(ops,'g')|| OPT_PLUS(ops,'m') || - OPT_ISSET(ops,'+')) + else if (OPT_PLUS(ops,'g') || OPT_PLUS(ops,'r') || OPT_PLUS(ops,'s') || + OPT_PLUS(ops,'m') || OPT_ISSET(ops,'+')) printflags |= PRINT_NAMEONLY; /* In the absence of arguments, list all aliases. If a command * * line flag is specified, list only those of that type. */ if (!*argv) { queue_signals(); - scanhashtable(aliastab, 1, flags1, flags2, aliastab->printnode, printflags); + scanhashtable(ht, 1, flags1, flags2, ht->printnode, printflags); unqueue_signals(); return 0; } @@ -3003,8 +3032,8 @@ bin_alias(char *name, char **argv, Options ops, int func) if ((pprog = patcompile(*argv, PAT_STATIC, NULL))) { /* display the matching aliases */ queue_signals(); - scanmatchtable(aliastab, pprog, flags1, flags2, - aliastab->printnode, printflags); + scanmatchtable(ht, pprog, flags1, flags2, + ht->printnode, printflags); unqueue_signals(); } else { untokenize(*argv); @@ -3021,14 +3050,15 @@ bin_alias(char *name, char **argv, Options ops, int func) if (asg->value && !OPT_ISSET(ops,'L')) { /* The argument is of the form foo=bar and we are not * * forcing a listing with -L, so define an alias */ - aliastab->addnode(aliastab, ztrdup(asg->name), - createaliasnode(ztrdup(asg->value), flags1)); - } else if ((a = (Alias) aliastab->getnode(aliastab, asg->name))) { + ht->addnode(ht, ztrdup(asg->name), + createaliasnode(ztrdup(asg->value), flags1)); + } else if ((a = (Alias) ht->getnode(ht, asg->name))) { /* display alias if appropriate */ - if (!haveflags || - (OPT_ISSET(ops,'r') && !(a->flags & ALIAS_GLOBAL)) || - (OPT_ISSET(ops,'g') && (a->flags & ALIAS_GLOBAL))) - aliastab->printnode((HashNode) a, printflags); + if (!type_opts || ht == sufaliastab || + (OPT_ISSET(ops,'r') && + !(a->flags & (ALIAS_GLOBAL|ALIAS_SUFFIX))) || + (OPT_ISSET(ops,'g') && (a->flags & ALIAS_GLOBAL))) + ht->printnode((HashNode) a, printflags); } else returnval = 1; } diff --git a/Src/hashtable.c b/Src/hashtable.c index 9fc7a3232..faa858532 100644 --- a/Src/hashtable.c +++ b/Src/hashtable.c @@ -1014,30 +1014,51 @@ printreswdnode(HashNode hn, int printflags) /**/ mod_export HashTable aliastab; -/* Create new hash table for aliases */ +/* has table containing suffix aliases */ + +/**/ +mod_export HashTable sufaliastab; + +/* Create new hash tables for aliases */ + +/**/ +void +createaliastable(HashTable ht) +{ + ht->hash = hasher; + ht->emptytable = NULL; + ht->filltable = NULL; + ht->cmpnodes = strcmp; + ht->addnode = addhashnode; + ht->getnode = gethashnode; + ht->getnode2 = gethashnode2; + ht->removenode = removehashnode; + ht->disablenode = disablehashnode; + ht->enablenode = enablehashnode; + ht->freenode = freealiasnode; + ht->printnode = printaliasnode; +} /**/ void -createaliastable(void) +createaliastables(void) { + /* Table for regular and global aliases */ + aliastab = newhashtable(23, "aliastab", NULL); - aliastab->hash = hasher; - aliastab->emptytable = NULL; - aliastab->filltable = NULL; - aliastab->cmpnodes = strcmp; - aliastab->addnode = addhashnode; - aliastab->getnode = gethashnode; - aliastab->getnode2 = gethashnode2; - aliastab->removenode = removehashnode; - aliastab->disablenode = disablehashnode; - aliastab->enablenode = enablehashnode; - aliastab->freenode = freealiasnode; - aliastab->printnode = printaliasnode; + createaliastable(aliastab); /* add the default aliases */ aliastab->addnode(aliastab, ztrdup("run-help"), createaliasnode(ztrdup("man"), 0)); aliastab->addnode(aliastab, ztrdup("which-command"), createaliasnode(ztrdup("whence"), 0)); + + + /* Table for suffix aliases --- make this smaller */ + + sufaliastab = newhashtable(11, "sufaliastab", NULL); + + createaliastable(sufaliastab); } /* Create a new alias node */ @@ -1093,10 +1114,12 @@ printaliasnode(HashNode hn, int printflags) if (printflags & PRINT_WHENCE_CSH) { nicezputs(a->nam, stdout); - if (a->flags & ALIAS_GLOBAL) - printf(": globally aliased to "); - else - printf(": aliased to "); + printf(": "); + if (a->flags & ALIAS_SUFFIX) + printf("suffix "); + else if (a->flags & ALIAS_GLOBAL) + printf("globally "); + printf (" aliased to "); nicezputs(a->text, stdout); putchar('\n'); return; @@ -1104,10 +1127,14 @@ printaliasnode(HashNode hn, int printflags) if (printflags & PRINT_WHENCE_VERBOSE) { nicezputs(a->nam, stdout); - if (a->flags & ALIAS_GLOBAL) - printf(" is a global alias for "); + printf(" is a"); + if (a->flags & ALIAS_SUFFIX) + printf(" suffix"); + else if (a->flags & ALIAS_GLOBAL) + printf(" global"); else - printf(" is an alias for "); + printf("n"); + printf(" alias for"); nicezputs(a->text, stdout); putchar('\n'); return; @@ -1115,7 +1142,9 @@ printaliasnode(HashNode hn, int printflags) if (printflags & PRINT_LIST) { printf("alias "); - if (a->flags & ALIAS_GLOBAL) + if (a->flags & ALIAS_SUFFIX) + printf("-s "); + else if (a->flags & ALIAS_GLOBAL) printf("-g "); /* If an alias begins with `-', then we must output `-- ' * @@ -1127,6 +1156,7 @@ printaliasnode(HashNode hn, int printflags) quotedzputs(a->nam, stdout); putchar('='); quotedzputs(a->text, stdout); + putchar('\n'); } diff --git a/Src/init.c b/Src/init.c index 96558f84b..5c395afe2 100644 --- a/Src/init.c +++ b/Src/init.c @@ -792,7 +792,7 @@ setupvals(void) initlextabs(); /* initialize lexing tables */ createreswdtable(); /* create hash table for reserved words */ - createaliastable(); /* create hash table for aliases */ + createaliastables(); /* create hash tables for aliases */ createcmdnamtable(); /* create hash table for external commands */ createshfunctable(); /* create hash table for shell functions */ createbuiltintable(); /* create hash table for builtin commands */ diff --git a/Src/lex.c b/Src/lex.c index 40e42e857..a852de369 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -1510,7 +1510,7 @@ parse_subscript(char *s, int sub) mod_export int parse_subst_string(char *s) { - int c, l = strlen(s), err, olen; + int c, l = strlen(s), err, olen, lexstop_ret; if (!*s || !strcmp(s, nulstring)) return 0; @@ -1522,6 +1522,7 @@ parse_subst_string(char *s) bptr = tokstr = s; bsiz = l + 1; c = hgetc(); + lexstop_ret = lexstop; c = gettokstr(c, 1); err = errflag; strinend(); @@ -1603,17 +1604,32 @@ exalias(void) if (tok == STRING) { /* Check for an alias */ - an = (noaliases || unset(ALIASESOPT)) ? NULL : - (Alias) aliastab->getnode(aliastab, yytext); - if (an && !an->inuse && ((an->flags & ALIAS_GLOBAL) || incmdpos || - inalmore)) { - inpush(an->text, INP_ALIAS, an); - if (an->text[0] == ' ') - aliasspaceflag = 1; - lexstop = 0; - if (yytext == copy) - yytext = tokstr; - return 1; + if (!noaliases && isset(ALIASESOPT)) { + char *suf; + + an = (Alias) aliastab->getnode(aliastab, yytext); + if (an && !an->inuse && + ((an->flags & ALIAS_GLOBAL) || incmdpos || inalmore)) { + inpush(an->text, INP_ALIAS, an); + if (an->text[0] == ' ') + aliasspaceflag = 1; + lexstop = 0; + if (yytext == copy) + yytext = tokstr; + return 1; + } + if ((suf = strrchr(yytext, '.')) && suf[1] && + suf > yytext && suf[-1] != Meta && + (an = (Alias)sufaliastab->getnode(sufaliastab, suf+1)) && + !an->inuse && incmdpos) { + inpush(dupstring(yytext), INP_ALIAS, NULL); + inpush(" ", INP_ALIAS, NULL); + inpush(an->text, INP_ALIAS, an); + lexstop = 0; + if (yytext == copy) + yytext = tokstr; + return 1; + } } /* Then check for a reserved word */ diff --git a/Src/zsh.h b/Src/zsh.h index 16558c3d3..2dca01722 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -872,8 +872,11 @@ struct alias { int inuse; /* alias is being expanded */ }; -/* is this alias global */ +/* bit 0 of flags is the DISABLED flag */ +/* is this alias global? */ #define ALIAS_GLOBAL (1<<1) +/* is this an alias for suffix handling? */ +#define ALIAS_SUFFIX (1<<2) /* node in command path hash table (cmdnamtab) */ -- cgit 1.4.1