diff --git a/.gitignore b/.gitignore index 4e50d82d1..c914d015e 100644 --- a/.gitignore +++ b/.gitignore @@ -21,5 +21,7 @@ picocli.iml /src/test/dejagnu.tests/testrun.log /src/test/dejagnu.tests/testrun.sum /src/test/dejagnu.tests/tmp/ +/src/test/dejagnu.fishtests/log/completion.sum +/src/test/dejagnu.fishtests/log/completion.log /picocli-legacy-tests/gradle/wrapper/dists/**/*.lck /picocli-legacy-tests/gradle/wrapper/dists/**/*.ok diff --git a/src/main/java/picocli/AutoComplete.java b/src/main/java/picocli/AutoComplete.java index 46d8588ed..ac0baa67e 100644 --- a/src/main/java/picocli/AutoComplete.java +++ b/src/main/java/picocli/AutoComplete.java @@ -554,22 +554,18 @@ public static String fish(String scriptName, CommandLine commandLine) { continue; } if (!descriptor.parentFunctionName.equals(parentFunction)) { - if (!currentLevelCommands.isEmpty()) { - processLevel(scriptName, result, currentLevel, currentLevelCommands, parentFunction, rootDescriptor); - rootDescriptor = null; + processLevel(scriptName, result, currentLevel, currentLevelCommands, parentFunction, rootDescriptor); + rootDescriptor = null; - currentLevel.clear(); - currentLevelCommands.clear(); - } + currentLevel.clear(); + currentLevelCommands.clear(); parentFunction = descriptor.parentFunctionName; } currentLevel.add(descriptor); currentLevelCommands.add(descriptor.commandName); } - if (!currentLevelCommands.isEmpty()) { - processLevel(scriptName, result, currentLevel, currentLevelCommands, parentFunction, rootDescriptor); - } + processLevel(scriptName, result, currentLevel, currentLevelCommands, parentFunction, rootDescriptor); return result.toString(); @@ -578,7 +574,10 @@ public static String fish(String scriptName, CommandLine commandLine) { private static void processLevel(String scriptName, StringBuilder result, List currentLevel, List currentLevelCommands, String levelName, CommandDescriptor rootDescriptor) { - result.append("\n# ").append(levelName).append(" completion \n"); + if (levelName.equals("")) { + levelName = "root"; + } + result.append("\n# ").append(levelName).append(" completion\n"); result.append("set -l ").append(levelName).append(" ").append(String.join(" ", currentLevelCommands)).append( "\n"); if (rootDescriptor != null) { @@ -586,9 +585,16 @@ private static void processLevel(String scriptName, StringBuilder result, List 0 ? optionSpec.description()[0] : ""); result.append(" -d '").append(optionDescription).append("'\n"); + + if (!optionSpec.shortestName().equals(optionSpec.longestName())) { result.append("complete -c ").append(scriptName); result.append(" -n \"not __fish_seen_subcommand_from $").append(levelName).append("\""); @@ -617,9 +623,15 @@ private static void processLevel(String scriptName, StringBuilder result, List 0 ? optionSpec.description()[0] : ""); result.append(" -d '").append(optionDescription).append("'\n"); + if (!optionSpec.shortestName().equals(optionSpec.longestName())) { result.append("complete -c ").append(scriptName); result.append(" -n \"__fish_seen_subcommand_from ").append(commandDescriptor.commandName).append("\""); diff --git a/src/test/dejagnu.fishtests/README.adoc b/src/test/dejagnu.fishtests/README.adoc new file mode 100644 index 000000000..28caddea8 --- /dev/null +++ b/src/test/dejagnu.fishtests/README.adoc @@ -0,0 +1,4 @@ +Run +``` +runtest --outdir log --tool completion +``` \ No newline at end of file diff --git a/src/test/dejagnu.fishtests/completion/simple.exp b/src/test/dejagnu.fishtests/completion/simple.exp new file mode 100644 index 000000000..15ab19dc5 --- /dev/null +++ b/src/test/dejagnu.fishtests/completion/simple.exp @@ -0,0 +1,30 @@ +exp_internal 1 +set timeout 1 + +proc run_completion_test {cmd test candidates} { + send "${cmd}\t" + expect { + -re "(\n${candidates}\u001b)" { pass $test } + timeout { fail $test } + } + puts "###Output" + puts "$expect_out(1,string)" + send "\x03" + expect ">" +} + +set cmd "basicExample -" +set test "Tab should show options for '$cmd'" +set candidates "-t -u --timeout --timeUnit --timeUnit=" +run_completion_test $cmd $test $candidates + +set cmd "basicExample --" +set test "Tab should show options for '$cmd'" +set candidates "--timeout --timeUnit --timeUnit=" +run_completion_test $cmd $test $candidates + +set cmd "basicExample --timeUnit=" +set test "Tab should show time unit enum values for '$cmd'" +#set candidates "1 2 3" +set candidates "\u2026timeUnit=DAYS \u2026timeUnit=MICROSECONDS \u2026timeUnit=MINUTES \u2026timeUnit=SECONDS\r\n\u2026timeUnit=HOURS \u2026timeUnit=MILLISECONDS \u2026timeUnit=NANOSECONDS " +run_completion_test $cmd $test $candidates diff --git a/src/test/dejagnu.fishtests/lib/completion.exp b/src/test/dejagnu.fishtests/lib/completion.exp new file mode 100644 index 000000000..a03281f96 --- /dev/null +++ b/src/test/dejagnu.fishtests/lib/completion.exp @@ -0,0 +1,8 @@ +exp_spawn fish --no-config +expect -re "(.+>)" + +send "source ../resources/basic.fish\r" +expect -re "(.+>)" + +send "function basicExample; echo 'do'; end\r" +expect -re "(.+>)" \ No newline at end of file diff --git a/src/test/dejagnu.tests/runCompletion b/src/test/dejagnu.tests/runCompletion old mode 100644 new mode 100755 diff --git a/src/test/java/picocli/AutoCompleteTest.java b/src/test/java/picocli/AutoCompleteTest.java index 49b37b78b..5d62a3f93 100644 --- a/src/test/java/picocli/AutoCompleteTest.java +++ b/src/test/java/picocli/AutoCompleteTest.java @@ -102,6 +102,14 @@ public void basic() throws Exception { assertEquals(expected, script); } + @Test + public void basicFish() throws Exception { + String script = AutoComplete.fish("basicExample", new CommandLine(new BasicExample())); + System.out.println(script); + String expected = loadTextFromClasspath("/basic.fish"); + assertEquals(expected, script); + } + public static class TopLevel { @Option(names = {"-V", "--version"}, help = true) boolean versionRequested; @Option(names = {"-h", "--help"}, help = true) boolean helpRequested; diff --git a/src/test/resources/basic.fish b/src/test/resources/basic.fish new file mode 100644 index 000000000..b7bfdbef4 --- /dev/null +++ b/src/test/resources/basic.fish @@ -0,0 +1,7 @@ + +# root completion +set -l root +complete -c basicExample -n "not __fish_seen_subcommand_from $root" -l timeUnit -f -a 'NANOSECONDS MICROSECONDS MILLISECONDS SECONDS MINUTES HOURS DAYS' -d '' +complete -c basicExample -n "not __fish_seen_subcommand_from $root" -s u -d '' +complete -c basicExample -n "not __fish_seen_subcommand_from $root" -l timeout -d '' +complete -c basicExample -n "not __fish_seen_subcommand_from $root" -s t -d ''