diff --git a/src/main/java/picocli/AutoComplete.java b/src/main/java/picocli/AutoComplete.java index 5c6b224dd..a2d22703c 100644 --- a/src/main/java/picocli/AutoComplete.java +++ b/src/main/java/picocli/AutoComplete.java @@ -560,7 +560,8 @@ private static void generateFunctionCallsToArrContains(StringBuilder buff, int count = functionCalls.size(); CommandSpec spec = descriptor.commandLine.getCommandSpec(); String full = spec.qualifiedName(" "); - String withoutTopLevelCommand = full.substring(spec.root().name().length() + 1); + String withoutTopLevelCommand = full.substring(spec.root().name().length() + 1, + full.length() - spec.name().length()) + descriptor.commandName; functionCalls.add(format(" if CompWordsContainsArray \"${cmds%2$d[@]}\"; then %1$s; return $?; fi\n", descriptor.functionName, count)); buff.append( format(" local cmds%2$d=(%1$s)\n", withoutTopLevelCommand, count)); diff --git a/src/main/java/picocli/CommandLine.java b/src/main/java/picocli/CommandLine.java index bdd5e6b9b..0f22b6499 100644 --- a/src/main/java/picocli/CommandLine.java +++ b/src/main/java/picocli/CommandLine.java @@ -6412,7 +6412,7 @@ public CommandSpec addSubcommand(String name, CommandSpec subcommand) { */ public CommandSpec addSubcommand(String name, CommandLine subCommandLine) { CommandSpec subSpec = subCommandLine.getCommandSpec(); - String actualName = validateSubcommandName(name, subSpec); + String actualName = validateSubcommandName(interpolator.interpolateCommandName(name), subSpec); Tracer t = new Tracer(); if (t.isDebug()) {t.debug("Adding subcommand '%s' to '%s'%n", actualName, this.qualifiedName());} String previousName = commands.getCaseSensitiveKey(actualName); @@ -6422,7 +6422,7 @@ public CommandSpec addSubcommand(String name, CommandLine subCommandLine) { subSpec.parent(this); for (String alias : subSpec.aliases()) { if (t.isDebug()) {t.debug("Adding alias '%s' for '%s'%n", (parent == null ? "" : parent.qualifiedName() + " ") + alias, this.qualifiedName());} - previous = commands.put(alias, subCommandLine); + previous = commands.put(interpolator.interpolate(alias), subCommandLine); if (previous != null && previous != subCommandLine) { throw new DuplicateNameException("Alias '" + alias + "' for subcommand '" + actualName + "' is already used by another subcommand of '" + this.name() + "'"); } } subSpec.initCommandHierarchyWithResourceBundle(resourceBundleBaseName(), resourceBundle()); diff --git a/src/test/java/picocli/AutoCompleteTest.java b/src/test/java/picocli/AutoCompleteTest.java index 61e3a4085..46a618289 100644 --- a/src/test/java/picocli/AutoCompleteTest.java +++ b/src/test/java/picocli/AutoCompleteTest.java @@ -1896,4 +1896,35 @@ public void testIssue1352_SubcommandNameResourceBundle() throws FileNotFoundExce } } + @CommandLine.Command(name = "aliases", aliases = {"a"}) + static class Issue1388AliasesCommand {} + + @CommandLine.Command(name = "aliases-parent", subcommands = {Issue1388AliasesCommand.class}) + static class Issue1388AliasesParentCommand {} + + @Test + public void testIssue1388_AliasesCommand() throws FileNotFoundException { + File existingScript = new File("aliases-parent_completion"); + if (existingScript.exists()) { + assertTrue(existingScript.delete()); + } + try { + AutoComplete.main(Issue1388AliasesParentCommand.class.getName()); + + assertEquals("", systemErrRule.getLog()); + assertEquals("", systemOutRule.getLog()); + + assertTrue("Expected file '" + existingScript.getAbsolutePath() + "' to exist", + existingScript.exists()); + + Scanner scanner = new Scanner(existingScript); + scanner.useDelimiter("\\Z"); // end of file + String script = scanner.next(); + scanner.close(); + assertThat(script, containsString("local cmds0=(aliases)")); + assertThat(script, containsString("local cmds1=(a)")); + } finally { + existingScript.delete(); + } + } }