diff options
author | Peter Stephenson <pws@users.sourceforge.net> | 2011-03-11 16:32:07 +0000 |
---|---|---|
committer | Peter Stephenson <pws@users.sourceforge.net> | 2011-03-11 16:32:07 +0000 |
commit | f2dca9e155f25ee57f15df7dc2dc81489e1abbae (patch) | |
tree | 7fcb3500f0c2c7d66b12fe3a50e92e2913d26cc7 /Src/utils.c | |
parent | cc69ecfb9e10fca2d8f68100ff9f2365dedb1405 (diff) | |
download | zsh-f2dca9e155f25ee57f15df7dc2dc81489e1abbae.tar.gz zsh-f2dca9e155f25ee57f15df7dc2dc81489e1abbae.tar.xz zsh-f2dca9e155f25ee57f15df7dc2dc81489e1abbae.zip |
users/15864: turn zsh_directory_name into a hook
Diffstat (limited to 'Src/utils.c')
-rw-r--r-- | Src/utils.c | 78 |
1 files changed, 62 insertions, 16 deletions
diff --git a/Src/utils.c b/Src/utils.c index 844a43e1b..9857303bb 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -890,7 +890,8 @@ finddir(char *s) { static struct nameddir homenode = { {NULL, "", 0}, NULL, 0 }; static int ffsz; - Shfunc func = getshfunc("zsh_directory_name"); + char **ares; + int len; /* Invalidate directory cache if argument is NULL. This is called * * whenever a node is added to or removed from the hash table, and * @@ -906,9 +907,16 @@ finddir(char *s) return finddir_last = NULL; } - /* It's not safe to use the cache while we have function transformations.*/ - if(!func && !strcmp(s, finddir_full) && *finddir_full) +#if 0 + /* + * It's not safe to use the cache while we have function + * transformations, and it's not clear it's worth the + * complexity of guessing here whether subst_string_by_hook + * is going to turn up the goods. + */ + if (!strcmp(s, finddir_full) && *finddir_full) return finddir_last; +#endif if ((int)strlen(s) >= ffsz) { free(finddir_full); @@ -920,18 +928,15 @@ finddir(char *s) finddir_scan(&homenode.node, 0); scanhashtable(nameddirtab, 0, 0, 0, finddir_scan, 0); - if (func) { - char **ares = subst_string_by_func(func, "d", finddir_full); - int len; - if (ares && arrlen(ares) >= 2 && - (len = (int)zstrtol(ares[1], NULL, 10)) > finddir_best) { - /* better duplicate this string since it's come from REPLY */ - finddir_last = (Nameddir)hcalloc(sizeof(struct nameddir)); - finddir_last->node.nam = zhtricat("[", dupstring(ares[0]), "]"); - finddir_last->dir = dupstrpfx(finddir_full, len); - finddir_last->diff = len - strlen(finddir_last->node.nam); - finddir_best = len; - } + ares = subst_string_by_hook("zsh_directory_name", "d", finddir_full); + if (ares && arrlen(ares) >= 2 && + (len = (int)zstrtol(ares[1], NULL, 10)) > finddir_best) { + /* better duplicate this string since it's come from REPLY */ + finddir_last = (Nameddir)hcalloc(sizeof(struct nameddir)); + finddir_last->node.nam = zhtricat("[", dupstring(ares[0]), "]"); + finddir_last->dir = dupstrpfx(finddir_full, len); + finddir_last->diff = len - strlen(finddir_last->node.nam); + finddir_best = len; } return finddir_last; @@ -3212,7 +3217,7 @@ getshfunc(char *nam) char ** subst_string_by_func(Shfunc func, char *arg1, char *orig) { - int osc = sfcontext; + int osc = sfcontext, osm = stopmsg; LinkList l = newlinklist(); char **ret; @@ -3228,6 +3233,47 @@ subst_string_by_func(Shfunc func, char *arg1, char *orig) ret = getaparam("reply"); sfcontext = osc; + stopmsg = osm; + return ret; +} + +/** + * Front end to subst_string_by_func to use hook-like logic. + * name can refer to a function, and name + "_hook" can refer + * to an array containing a list of functions. The functions + * are tried in order until one returns success. + */ +/**/ +char ** +subst_string_by_hook(char *name, char *arg1, char *orig) +{ + Shfunc func; + char **ret = NULL; + + if ((func = getshfunc(name))) { + ret = subst_string_by_func(func, arg1, orig); + } + + if (!ret) { + char **arrptr; + int namlen = strlen(name); + VARARR(char, arrnam, namlen + HOOK_SUFFIX_LEN); + memcpy(arrnam, name, namlen); + memcpy(arrnam + namlen, HOOK_SUFFIX, HOOK_SUFFIX_LEN); + + if ((arrptr = getaparam(arrnam))) { + /* Guard against internal modification of the array */ + arrptr = arrdup(arrptr); + for (; *arrptr; arrptr++) { + if ((func = getshfunc(*arrptr))) { + ret = subst_string_by_func(func, arg1, orig); + if (ret) + break; + } + } + } + } + return ret; } |