From 3af1c4b4411491a4ce68aa9e7ff93b375e7a1867 Mon Sep 17 00:00:00 2001 From: serg-v Date: Sun, 15 Jan 2023 17:50:22 +0300 Subject: [PATCH] picocli fish completion --- src/main/java/picocli/AutoComplete.java | 89 +++++++++++++++++---- src/test/java/picocli/AutoCompleteTest.java | 16 ---- 2 files changed, 72 insertions(+), 33 deletions(-) diff --git a/src/main/java/picocli/AutoComplete.java b/src/main/java/picocli/AutoComplete.java index 72d34d86e..7d3cabd1b 100644 --- a/src/main/java/picocli/AutoComplete.java +++ b/src/main/java/picocli/AutoComplete.java @@ -305,17 +305,6 @@ private static class CommandDescriptor { this.commandName = commandName; this.commandLine = commandLine; } - - @Override - public String toString() { - return "CommandDescriptor{" + - "functionName='" + functionName + '\'' + - ", parentFunctionName='" + parentFunctionName + '\'' + - ", parentWithoutTopLevelCommand='" + parentWithoutTopLevelCommand + '\'' + - ", commandName='" + commandName + '\'' + - ", commandLine=" + commandLine + - '}'; - } } private static final String SCRIPT_HEADER = "" + @@ -551,18 +540,84 @@ public static String fish(String scriptName, CommandLine commandLine) { if (commandLine == null) { throw new NullPointerException("commandLine"); } List hierarchy = createHierarchy(scriptName, commandLine); //print hierarchy + StringBuilder result = new StringBuilder(); + //result.append("complete --command ").append(scriptName).append(" --no-files").append("\n"); + + String parentFunction = ""; + List currentLevel = new ArrayList<>(); + List currentLevelCommands = new ArrayList<>(); for (CommandDescriptor descriptor : hierarchy) { - System.out.println(descriptor.functionName + " " + descriptor.commandName); - } + if (descriptor.parentFunctionName.equals("")) { + continue; + } + if (!descriptor.parentFunctionName.equals(parentFunction)) { + if (!currentLevelCommands.isEmpty()) { + processLevel(scriptName, result, currentLevel, currentLevelCommands, parentFunction); - StringBuilder result = new StringBuilder(); - result.append("Hello from fish!").append("\n"); - for (CommandDescriptor commandDescriptor : hierarchy) { - result.append(commandDescriptor.toString()).append("\n"); + currentLevel.clear(); + currentLevelCommands.clear(); + } + parentFunction = descriptor.parentFunctionName; + } + + currentLevel.add(descriptor); + currentLevelCommands.add(descriptor.commandName); + } + if (!currentLevelCommands.isEmpty()) { + processLevel(scriptName, result, currentLevel, currentLevelCommands, parentFunction); } + + return result.toString(); } + private static void processLevel(String scriptName, StringBuilder result, List currentLevel, + List currentLevelCommands, String levelName) { + result.append("\n# ").append(levelName).append(" completion \n"); + result.append("set -l ").append(levelName).append(" ").append(String.join(" ", currentLevelCommands)).append( + "\n"); + for (CommandDescriptor commandDescriptor : currentLevel) { + String[] descriptions = commandDescriptor.commandLine.getCommandSpec().usageMessage().description(); + String description = descriptions.length > 0 ? descriptions[0] : ""; + result.append("complete -c ").append(scriptName); + result.append(" -f"); // do not show files + result.append(" -n \"not __fish_seen_subcommand_from $").append(levelName).append("\""); + if (!commandDescriptor.parentWithoutTopLevelCommand.equals("")) { + result.append(" -n '__fish_seen_subcommand_from ").append( + commandDescriptor.parentWithoutTopLevelCommand).append("'"); + } + result.append(" -a ").append(commandDescriptor.commandName).append(" -d '").append(description).append("'\n"); + + for (OptionSpec optionSpec : commandDescriptor.commandLine.getCommandSpec().options()) { + result.append("complete -c ").append(scriptName); + result.append(" -n \"__fish_seen_subcommand_from ").append(commandDescriptor.commandName).append("\""); + if (!commandDescriptor.parentWithoutTopLevelCommand.equals("")) { + result.append(" -n '__fish_seen_subcommand_from ").append( + commandDescriptor.parentWithoutTopLevelCommand).append("'"); + } + result.append(" -l ").append(optionSpec.longestName().replace("--", "")); + String optionDescription = sanitizeDescription(optionSpec.description().length > 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("\""); + if (!commandDescriptor.parentWithoutTopLevelCommand.equals("")) { + result.append(" -n '__fish_seen_subcommand_from ").append( + commandDescriptor.parentWithoutTopLevelCommand).append("'"); + } + result.append(" -s ").append(optionSpec.shortestName().replace("-", "")); + result.append(" -d '").append(optionDescription).append("'\n"); + } + } + } + + } + + private static String sanitizeDescription(String description) { + return description.replace("'", "\\'"); + } + private static List createHierarchy(String scriptName, CommandLine commandLine) { List result = new ArrayList(); result.add(new CommandDescriptor("_picocli_" + scriptName, "", "", scriptName, commandLine)); diff --git a/src/test/java/picocli/AutoCompleteTest.java b/src/test/java/picocli/AutoCompleteTest.java index d62e16dc3..49b37b78b 100644 --- a/src/test/java/picocli/AutoCompleteTest.java +++ b/src/test/java/picocli/AutoCompleteTest.java @@ -2117,20 +2117,4 @@ public void testIssue1388_AliasesCommand() throws FileNotFoundException { existingScript.delete(); } } - - @Test - public void testFish() { - String expected = String.format("hello from fish%n"); - - assertEquals( - expected, - AutoComplete.fish("myapp", new CommandLine(new Issue1352CommandWithResourceBundle())) - ); - - assertEquals( - expected, - AutoComplete.fish("myapp", new CommandLine(new Issue1352ParentCommand())) - ); - - } }