about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorBart Schaefer <schaefer@ipost.com>2021-05-15 13:40:37 -0700
committerBart Schaefer <schaefer@ipost.com>2021-05-15 13:40:37 -0700
commitd0e071c5f0bf6a879756f72e1f0d0ae6952a4b49 (patch)
tree1f2f6ebf7615002c1e2d068787a46d722d387004 /Src
parentacd20254b58ea689d8046ff127bc320d5fa91cf6 (diff)
downloadzsh-d0e071c5f0bf6a879756f72e1f0d0ae6952a4b49.tar.gz
zsh-d0e071c5f0bf6a879756f72e1f0d0ae6952a4b49.tar.xz
zsh-d0e071c5f0bf6a879756f72e1f0d0ae6952a4b49.zip
48790: COMPLETE_IN_WORD inside brace-param
Diffstat (limited to 'Src')
-rw-r--r--Src/Zle/compcore.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index 5162d97dc..131e86825 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -1125,6 +1125,18 @@ check_param(char *s, int set, int test)
      *
      * TODO: passing s as a parameter while we get some mysterious
      * offset "offs" into it via a global sucks badly.
+     *
+     * From ../lex.c we know:
+     * wb is the beginning position of the current word in the line
+     * we is the position of the end of the current word in the line
+     * From zle_tricky.c we know:
+     * offs is position within the word where we are completing
+     *
+     * So wb + offs is the current cursor position if COMPLETE_IN_WORD
+     * is set, otherwise it is the end of the word (same as we).
+     * 
+     * Note below we are thus stepping backward from our completion
+     * position to find a '$' in the current word (if any).
      */ 
     for (p = s + offs; ; p--) {
 	if (*p == String || *p == Qstring) {
@@ -1171,13 +1183,13 @@ check_param(char *s, int set, int test)
 	    char *tb = b;
 
 	    /* If this is a ${...}, see if we are before the '}'. */
-	    if (!skipparens(Inbrace, Outbrace, &tb))
+	    if (!skipparens(Inbrace, Outbrace, &tb) && tb - s <= offs)
 		return NULL;
 
 	    /* Ignore the possible (...) flags. */
-	    b++, br++;
-	    if ((qstring ? skipparens('(', ')', &b) :
-		 skipparens(Inpar, Outpar, &b)) > 0) {
+	    tb = ++b, br++;
+	    if ((qstring ? skipparens('(', ')', &tb) :
+		 skipparens(Inpar, Outpar, &tb)) > 0 || tb - s >= offs) {
 		/*
 		 * We are still within the parameter flags.  There's no
 		 * point trying to do anything clever here with
@@ -1188,6 +1200,14 @@ check_param(char *s, int set, int test)
 		ispar = 2;
 		return NULL;
 	    }
+	    if ((qstring ? '(' : Inpar) == *b) {
+		/*
+		 * We are inside the braces but on the opening paren.
+		 * There is nothing useful to complete here?
+		 */
+		return NULL;
+	    } else
+		b = tb;	/* Skip over the flags */
 
 	    for (tb = p - 1; tb > s && *tb != Outbrace && *tb != Inbrace; tb--);
 	    if (tb > s && *tb == Inbrace && (tb[-1] == String || *tb == Qstring))