From 67793793e8dadd3fc015114f0080bab7c73061bc Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Mon, 2 Mar 2020 05:29:31 +0100 Subject: [PATCH] bistromathic: properly compute the lcp, as expected by readline Currently completion on "at" proposes only "atan", but does not actually complete "at" into "atan". * examples/c/bistromathic/parse.y (completion): Install the lcp in matches[0]. * examples/c/bistromathic/bistromathic.test: Check that case. --- examples/c/bistromathic/bistromathic.test | 8 ++++++++ examples/c/bistromathic/parse.y | 17 +++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/examples/c/bistromathic/bistromathic.test b/examples/c/bistromathic/bistromathic.test index 0bec1cb3..a877bea3 100755 --- a/examples/c/bistromathic/bistromathic.test +++ b/examples/c/bistromathic/bistromathic.test @@ -85,6 +85,7 @@ run 0 '> 1 / 0 ## Completion. ## ## ------------ ## +# Check completion after an operator. sed -e 's/\\t/ /g' >input < (1+ atan exp sqrt > (1+ > err: 1.4: syntax error: expected - or ( or double precision number or function or variable before end of file' + +# Check the completion of a word. +sed -e 's/\\t/ /g' >input < (atan ( '' +> err: 1.9: syntax error: expected - or ( or double precision number or function or variable before end of file' diff --git a/examples/c/bistromathic/parse.y b/examples/c/bistromathic/parse.y index d424cdfe..e1315ee5 100644 --- a/examples/c/bistromathic/parse.y +++ b/examples/c/bistromathic/parse.y @@ -384,8 +384,7 @@ completion (const char *text, int start, int end) const int len = strlen (text); // Need initial prefix and final NULL. char **matches = calloc (ntokens + symbol_count () + 2, sizeof *matches); - int match = 0; - matches[match++] = strdup (text); + int match = 1; for (int i = 0; i < ntokens; ++i) if (tokens[i] == YYTRANSLATE (TOK_VAR)) { @@ -406,6 +405,20 @@ completion (const char *text, int start, int end) matches[match++] = strdup (token); } + // Find the longest common prefix, and install it in matches[0], as + // required by readline. + if (match == 1) + matches[0] = strdup (text); + else + { + int lcplen = strlen (matches[1]); + for (int i = 2; i < match && lcplen; ++i) + for (int j = 0; j < lcplen; ++j) + if (matches[1][j] != matches[i][j]) + lcplen = j; + matches[0] = strndup (matches[1], lcplen); + } + if (yydebug) { fprintf (stderr, "completion(\"%.*s[%.*s]%s\") = ",