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);

Reply via email to