Ping, looking for OKs.
On Sun, Jul 02, 2017 at 10:46:20PM +0200, Anton Lindqvist wrote:
> Hi,
>
> On Fri, Jun 30, 2017 at 09:50:12PM -0700, Ilya Kaliman wrote:
> > Hi!
> >
> > The tab-autocomplete does not seem to work for some strings in ksh.
> > How to reproduce:
> >
> > mkdir "a a" "(bbb)" "(c c)"
> > cd a\ a && mkdir abc{1,2,3} && cd ..
> > cd \(bbb\) && mkdir abc{1,2,3} && cd ..
> > cd \(c\ c\) && mkdir abc{1,2,3} && cd ..
> >
> > type "cd a\ a/" hit tab -> auto-completes to abc, offers abc1 abc2 abc3
> > type "cd \(bbb\)/" hit tab -> auto-completes to abc, offers abc1 abc2 abc3
> > type "cd \(c\ c\)/" hit tab -> does not autocomplete; expected - same
> > as previous.
>
> Nice catch. As I see it, the bug you're seeing happens inside
> do_complete() while comparing the length of the input buffer and the
> results from the completion. Since the completions are passed through
> expand() causing escaped characters to be unescaped to their literal
> form while the input buffer remains escaped. You managed to find the
> perfect set of input causing the condition to when a completion
> succeeded to be invalidated:
>
> olen = strlen("\(c\ c\)/") = 9;
> nlen = strlen("(c c)/abc") = 9;
>
> Since `olen == nlen` no completion is performed. Please try out the diff
> below in which slashes are discarded when comparing the length. I don't
> know if any other character should be discarded as well, if true then it
> might be worth passing the input buffer through ksh's own lexer and
> parser in order to properly handle special characters, just like in
> x_file_glob().
>
> Comments? OK?
>
> Index: emacs.c
> ===================================================================
> RCS file: /cvs/src/bin/ksh/emacs.c,v
> retrieving revision 1.70
> diff -u -p -r1.70 emacs.c
> --- emacs.c 25 Jun 2017 17:28:39 -0000 1.70
> +++ emacs.c 2 Jul 2017 20:43:00 -0000
> @@ -1754,6 +1754,7 @@ do_complete(int flags, /* XCF_{COMMAND,F
> char **words;
> int nwords;
> int start, end, nlen, olen;
> + int i, ndiscard;
> int is_command;
> int completed = 0;
>
> @@ -1773,9 +1774,13 @@ do_complete(int flags, /* XCF_{COMMAND,F
> }
>
> olen = end - start;
> + ndiscard = 0;
> + for (i = start; i < end; i++)
> + if (xbuf[i] == '\\')
> + ndiscard++;
> nlen = x_longest_prefix(nwords, words);
> /* complete */
> - if (nwords == 1 || nlen > olen) {
> + if (nwords == 1 || nlen > olen - ndiscard) {
> x_goto(xbuf + start);
> x_delete(olen, false);
> x_escape(words[0], nlen, x_do_ins);