From d0e071c5f0bf6a879756f72e1f0d0ae6952a4b49 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sat, 15 May 2021 13:40:37 -0700 Subject: [PATCH] 48790: COMPLETE_IN_WORD inside brace-param --- ChangeLog | 2 ++ Src/Zle/compcore.c | 28 ++++++++++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 973455232..e7a602e68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2021-05-15 Bart Schaefer + * 48790: Src/Zle/compcore.c: COMPLETE_IN_WORD inside brace-param + * 48710: Completion/Zsh/Command/_zed, Doc/Zsh/contrib.yo, Functions/Misc/zed: add "zed -h" aka "histed", update doc and completion; improve compatibility with SH_WORD_SPLIT 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))