summaryrefslogtreecommitdiff
path: root/Src/utils.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2011-03-11 16:32:07 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2011-03-11 16:32:07 +0000
commitf2dca9e155f25ee57f15df7dc2dc81489e1abbae (patch)
tree7fcb3500f0c2c7d66b12fe3a50e92e2913d26cc7 /Src/utils.c
parentcc69ecfb9e10fca2d8f68100ff9f2365dedb1405 (diff)
downloadzsh-f2dca9e155f25ee57f15df7dc2dc81489e1abbae.tar.gz
zsh-f2dca9e155f25ee57f15df7dc2dc81489e1abbae.zip
users/15864: turn zsh_directory_name into a hook
Diffstat (limited to 'Src/utils.c')
-rw-r--r--Src/utils.c78
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;
}