Greetings and felicitations! Two things about auto-completion annoyed me in ksh for almost 4 years: ( `|' shows the position of cursor after auto-completion)
1) tilde bug: $ ls ~/nonexist<TAB> $ ls ~/nonexist\* | (i.e. it expands to something insensible, instead of doing nothing like in /home/<your_user_name>/nonexist case) 2) square bracket bug: $ touch 'so[me]_file' $ ls so\[<TAB> $ ls so\[| (i.e. nothing happens) behavior after the patch: 1) $ ls ~/nonexist<TAB> $ ls ~/nonexist| 2) $ ls so[<TAB> $ ls so\[me\]_file | (it should work for all kinds of auto-completions, and both in vi and emacs mode) While I was testing to see if I broke something by fixing these two, I also discovered that auto-completions now work in much more sensible and useful way for strings with variables: before patch: $ ls -d tmp $ tmp $ ls $HOME/tm<TAB> $ ls /home/s/tm | after patch: $ ls $HOME/tm<TAB> $ ls /home/s/tmp/| make test -- shows no errors. Patch: Index: edit.c =================================================================== RCS file: /OpenBSD/src/bin/ksh/edit.c,v retrieving revision 1.33 diff -r1.33 edit.c 414c414 < expand(yylval.cp, &w, DOGLOB|DOTILDE|DOMARKDIRS); --- > expand(yylval.cp, &w, DOCOMPLETION|DOGLOB|DOTILDE|DOMARKDIRS); 487c487 < pat = evalstr(toglob, DOPAT|DOTILDE); --- > pat = evalstr(toglob, DOCOMPLETION|DOPAT|DOTILDE); 650c650 < /* Given a string, copy it and possibly add a '*' to the end. The --- > /* Given a string, copy it and add a '*' to the end. The 657,658d656 < char *s; < bool saw_slash = false; 663,684c661,663 < toglob = str_nsave(str, slen + 1, ATEMP); /* + 1 for "*" */ < toglob[slen] = '\0'; < < /* < * If the pathname contains a wildcard (an unquoted '*', < * '?', or '[') or parameter expansion ('$'), or a ~username < * with no trailing slash, then it is globbed based on that < * value (i.e., without the appended '*'). < */ < for (s = toglob; *s; s++) { < if (*s == '\\' && s[1]) < s++; < else if (*s == '*' || *s == '[' || *s == '?' || *s == '$' < || (s[1] == '(' /*)*/ && strchr("*...@!", *s))) < break; < else if (*s == '/') < saw_slash = true; < } < if (!*s && (*toglob != '~' || saw_slash)) { < toglob[slen] = '*'; < toglob[slen + 1] = '\0'; < } --- > toglob = str_nsave(str, slen + 1, ATEMP); > toglob[slen] = '*'; > toglob[slen + 1] = '\0'; Index: eval.c =================================================================== RCS file: /OpenBSD/src/bin/ksh/eval.c,v retrieving revision 1.34 diff -r1.34 eval.c 557c557 < glob(p, wp, f & DOMARKDIRS); --- > glob(p, wp, f & (DOCOMPLETION | > DOMARKDIRS)); 599c599 < if (f & (DOPAT | DOGLOB)) { --- > if (!(f & DOCOMPLETION) && f & (DOPAT | > DOGLOB)) { 606d605 < case '*': 607a607,610 > if (f & DOCOMPLETION) > break; > /* fall through */ > case '*': 617,620c620,624 < if ((f & DOBRACE_) && (c == OBRACE || < (fdo & DOBRACE_))) { < fdo |= DOBRACE_|DOMAGIC_; < *dp++ = MAGIC; --- > if (!(f & DOCOMPLETION) && > (f & DOBRACE_) && > (c == OBRACE || (fdo & > DOBRACE_))) { > fdo |= > DOBRACE_|DOMAGIC_; > *dp++ = MAGIC; 936c940 < glob(char *cp, XPtrV *wp, int markdirs) --- > glob(char *cp, XPtrV *wp, int flags) 940,942c944,947 < if (glob_str(cp, wp, markdirs) == 0) < XPput(*wp, debunk(cp, cp, strlen(cp) + 1)); < else --- > if (glob_str(cp, wp, flags & DOMARKDIRS) == 0) { > if (!(flags & DOCOMPLETION)) > XPput(*wp, debunk(cp, cp, strlen(cp) + 1)); > } else 1144,1145c1149,1150 < return dp; < memcpy(dp, sp, s - sp); --- > return dp; > memmove(dp, sp, s - sp); Index: tree.h =================================================================== RCS file: /OpenBSD/src/bin/ksh/tree.h,v retrieving revision 1.10 diff -r1.10 tree.h 128a129 > #define DOCOMPLETION BIT(11) /* hint that we are doing an auto-completion */