From 1be8c010cbe8d3d4ae9cba5d7ad3da5112005e77 Mon Sep 17 00:00:00 2001 From: Tomas Stupka <tomas.stupka@oracle.com> Date: Mon, 28 Aug 2017 16:29:30 +0200 Subject: [PATCH] various fixes in cli completion --- .../r/launcher/JLineConsoleCompleter.java | 39 +++++++++++++++-- .../shell/TestJLineConsoleCompleter.java | 43 ++++++++++++++++++- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java index dc79ee71d2..99777055f9 100644 --- a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java +++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java @@ -73,7 +73,7 @@ public class JLineConsoleCompleter implements Completer { setFunction.execute(completionEnv, "start", start); setFunction.execute(completionEnv, "end", cursor); setFunction.execute(completionEnv, "linebuffer", buffer); - setFunction.execute(completionEnv, "token", buffer.substring(start, cursor)); + setFunction.execute(completionEnv, "token", start > -1 && start < buffer.length() && cursor > -1 && cursor <= buffer.length() ? buffer.substring(start, cursor).trim() : ""); completionFunction.execute(); @@ -98,13 +98,33 @@ public class JLineConsoleCompleter implements Completer { private static int getStart(String buffer, Value env, int cursor) { int start = 0; + + // are we in quotes? + int lastQuoteIdx = isInQuotes(buffer, cursor); + if (lastQuoteIdx != -1) { + return lastQuoteIdx; + } + Value opt = env.getMember("options"); if (opt.hasMembers()) { start = lastIdxOf(buffer, opt, "funarg.suffix", start, cursor); start = lastIdxOf(buffer, opt, "function.suffix", start, cursor); } - start = lastIdxOf(buffer, "\"", start, cursor); - start = lastIdxOf(buffer, "'", start, cursor); + + // are we just after a ',' or ' ' + if (cursor > 0 && cursor <= buffer.length() && (buffer.charAt(cursor - 1) == ',' || buffer.charAt(cursor - 1) == ' ')) { + return cursor; + } + + // is there any next closest ',' or ' '? + int idx = cursor >= buffer.length() ? buffer.length() - 1 : cursor; + while (idx >= start && (buffer.charAt(idx) != ',' && buffer.charAt(idx) != ' ')) { + --idx; + } + if (idx > -1) { + return ++idx; + } + return start; } @@ -120,6 +140,19 @@ public class JLineConsoleCompleter implements Completer { return start; } + private static int isInQuotes(String buffer, int cursor) { + int idx = -1; + int qidx = -1; + int c = 0; + while (++idx <= cursor && idx < buffer.length()) { + if (buffer.charAt(idx) == '\'' || buffer.charAt(idx) == '\"') { + qidx = idx; + c++; + } + } + return c % 2 == 0 ? -1 : qidx; + } + private static int lastIdxOf(String buffer, String subs, int start, int cursor) { if (!subs.isEmpty()) { int idx = buffer.lastIndexOf(subs, cursor); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java index eaabb32efe..d42b412385 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java @@ -32,10 +32,10 @@ import org.graalvm.polyglot.Context; import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import com.oracle.truffle.r.launcher.JLineConsoleCompleter; +import org.junit.Ignore; public class TestJLineConsoleCompleter { @@ -70,10 +70,27 @@ public class TestJLineConsoleCompleter { assertCompl("$", 1); assertCompl("strt", 4, "strtoi", "strtrim"); + assertCompl("strt", 5); + assertCompl("strt", 6); + assertCompl("strto", 5, "strtoi"); assertCompl("strtoi", 5, "strtoi"); assertCompl("strtoi", 4, "strtoi", "strtrim"); assertCompl("strto ", 6); + assertCompl("strto,", 6); + assertCompl("blabla,strt", 11, "strtoi", "strtrim"); + assertCompl("blabla strt", 11, "strtoi", "strtrim"); + assertCompl("blabla,,strt", 12, "strtoi", "strtrim"); + assertCompl("blabla strt", 12, "strtoi", "strtrim"); + assertCompl("blabla, strt", 12, "strtoi", "strtrim"); + // Checkstyle: stop + assertCompl("blabla ,strt", 12, "strtoi", "strtrim"); + // Checkstyle: resume + + assertCompl("source('a')", 10); + assertCompl("source('a')", 11); + assertCompl("source('a') ", 12); + assertCompl("source('a') ", 13); assertCompl("base::strt", 10, "base::strtoi", "base::strtrim"); assertCompl("base:::strt", 11, "base:::strtoi", "base:::strtrim"); @@ -88,6 +105,30 @@ public class TestJLineConsoleCompleter { assertCompl("f(strt(strto", 11, "strtoi", "strtrim"); assertCompl("f(strt(strto", 12, "strtoi"); + assertCompl("grep(", 5, "fixed=", "ignore.case=", "invert=", "pattern=", "perl=", "useBytes=", "value=", "x="); + assertCompl("grep(pattern=\"a\",", 17, "fixed=", "ignore.case=", "invert=", "pattern=", "perl=", "useBytes=", "value=", "x="); + assertCompl("grep(pattern=\"a\"", 16); + assertCompl("grep(pattern=\"a\", fixe", 22, "fixed="); + + assertCompl("grep (patt", 10, "pattern="); + assertCompl("grep,(patt", 10, "pattern="); + assertCompl("grep (patt", 11, "pattern="); + assertCompl("grep,,(patt", 11, "pattern="); + // Checkstyle: stop + assertCompl("grep ,(patt", 11, "pattern="); + // Checkstyle: resume + assertCompl("grep, (patt", 11, "pattern="); + + assertCompl("grep(patt ", 10, "fixed=", "ignore.case=", "invert=", "pattern=", "perl=", "useBytes=", "value=", "x="); + assertCompl("grep (patt ", 11, "fixed=", "ignore.case=", "invert=", "pattern=", "perl=", "useBytes=", "value=", "x="); + assertCompl("grep (patt ", 12, "fixed=", "ignore.case=", "invert=", "pattern=", "perl=", "useBytes=", "value=", "x="); + + // show only arguments for 'cor', and not also those for 'cor.test', 'cor.test.name' etc. + assertCompl("cor(", 3, "cor", "cor.test"); + assertCompl("cor(", 4, "method=", "use=", "x=", "y="); + assertCompl("cor(", 5, "method=", "use=", "x=", "y="); + assertCompl("cor( ", 5, "method=", "use=", "x=", "y="); + String noName = "_f_f_f_"; assertCompl(noName + ".", 7); assertCompl(noName + ".", 8); -- GitLab