@@ -305,17 +305,6 @@ private static class CommandDescriptor {
305305 this .commandName = commandName ;
306306 this .commandLine = commandLine ;
307307 }
308-
309- @ Override
310- public String toString () {
311- return "CommandDescriptor{" +
312- "functionName='" + functionName + '\'' +
313- ", parentFunctionName='" + parentFunctionName + '\'' +
314- ", parentWithoutTopLevelCommand='" + parentWithoutTopLevelCommand + '\'' +
315- ", commandName='" + commandName + '\'' +
316- ", commandLine=" + commandLine +
317- '}' ;
318- }
319308 }
320309
321310 private static final String SCRIPT_HEADER = "" +
@@ -551,18 +540,105 @@ public static String fish(String scriptName, CommandLine commandLine) {
551540 if (commandLine == null ) { throw new NullPointerException ("commandLine" ); }
552541 List <CommandDescriptor > hierarchy = createHierarchy (scriptName , commandLine );
553542 //print hierarchy
543+ StringBuilder result = new StringBuilder ();
544+ //result.append("complete --command ").append(scriptName).append(" --no-files").append("\n");
545+
546+ String parentFunction = "" ;
547+ List <CommandDescriptor > currentLevel = new ArrayList <>();
548+ List <String > currentLevelCommands = new ArrayList <>();
549+
550+ CommandDescriptor rootDescriptor = null ;
554551 for (CommandDescriptor descriptor : hierarchy ) {
555- System .out .println (descriptor .functionName + " " + descriptor .commandName );
556- }
552+ if (descriptor .parentFunctionName .equals ("" )) {
553+ rootDescriptor = descriptor ;
554+ continue ;
555+ }
556+ if (!descriptor .parentFunctionName .equals (parentFunction )) {
557+ if (!currentLevelCommands .isEmpty ()) {
558+ processLevel (scriptName , result , currentLevel , currentLevelCommands , parentFunction , rootDescriptor );
559+ rootDescriptor = null ;
557560
558- StringBuilder result = new StringBuilder ();
559- result .append ("Hello from fish!" ).append ("\n " );
560- for (CommandDescriptor commandDescriptor : hierarchy ) {
561- result .append (commandDescriptor .toString ()).append ("\n " );
561+ currentLevel .clear ();
562+ currentLevelCommands .clear ();
563+ }
564+ parentFunction = descriptor .parentFunctionName ;
565+ }
566+
567+ currentLevel .add (descriptor );
568+ currentLevelCommands .add (descriptor .commandName );
562569 }
570+ if (!currentLevelCommands .isEmpty ()) {
571+ processLevel (scriptName , result , currentLevel , currentLevelCommands , parentFunction , rootDescriptor );
572+ }
573+
574+
563575 return result .toString ();
564576 }
565577
578+ private static void processLevel (String scriptName , StringBuilder result , List <CommandDescriptor > currentLevel ,
579+ List <String > currentLevelCommands , String levelName ,
580+ CommandDescriptor rootDescriptor ) {
581+ result .append ("\n # " ).append (levelName ).append (" completion \n " );
582+ result .append ("set -l " ).append (levelName ).append (" " ).append (String .join (" " , currentLevelCommands )).append (
583+ "\n " );
584+ if (rootDescriptor != null ) {
585+ for (OptionSpec optionSpec : rootDescriptor .commandLine .getCommandSpec ().options ()) {
586+ result .append ("complete -c " ).append (scriptName );
587+ result .append (" -n \" not __fish_seen_subcommand_from $" ).append (levelName ).append ("\" " );
588+ result .append (" -l " ).append (optionSpec .longestName ().replace ("--" , "" ));
589+ String optionDescription = sanitizeDescription (optionSpec .description ().length > 0 ? optionSpec .description ()[0 ] : "" );
590+ result .append (" -d '" ).append (optionDescription ).append ("'\n " );
591+
592+ if (!optionSpec .shortestName ().equals (optionSpec .longestName ())) {
593+ result .append ("complete -c " ).append (scriptName );
594+ result .append (" -n \" not __fish_seen_subcommand_from $" ).append (levelName ).append ("\" " );
595+ result .append (" -s " ).append (optionSpec .shortestName ().replace ("-" , "" ));
596+ result .append (" -d '" ).append (optionDescription ).append ("'\n " );
597+ }
598+ }
599+ }
600+ for (CommandDescriptor commandDescriptor : currentLevel ) {
601+ String [] descriptions = commandDescriptor .commandLine .getCommandSpec ().usageMessage ().description ();
602+ String description = descriptions .length > 0 ? descriptions [0 ] : "" ;
603+ result .append ("complete -c " ).append (scriptName );
604+ result .append (" -f" ); // do not show files
605+ result .append (" -n \" not __fish_seen_subcommand_from $" ).append (levelName ).append ("\" " );
606+ if (!commandDescriptor .parentWithoutTopLevelCommand .equals ("" )) {
607+ result .append (" -n '__fish_seen_subcommand_from " ).append (
608+ commandDescriptor .parentWithoutTopLevelCommand ).append ("'" );
609+ }
610+ result .append (" -a " ).append (commandDescriptor .commandName ).append (" -d '" ).append (description ).append ("'\n " );
611+
612+ for (OptionSpec optionSpec : commandDescriptor .commandLine .getCommandSpec ().options ()) {
613+ result .append ("complete -c " ).append (scriptName );
614+ result .append (" -n \" __fish_seen_subcommand_from " ).append (commandDescriptor .commandName ).append ("\" " );
615+ if (!commandDescriptor .parentWithoutTopLevelCommand .equals ("" )) {
616+ result .append (" -n '__fish_seen_subcommand_from " ).append (
617+ commandDescriptor .parentWithoutTopLevelCommand ).append ("'" );
618+ }
619+ result .append (" -l " ).append (optionSpec .longestName ().replace ("--" , "" ));
620+ String optionDescription = sanitizeDescription (optionSpec .description ().length > 0 ? optionSpec .description ()[0 ] : "" );
621+ result .append (" -d '" ).append (optionDescription ).append ("'\n " );
622+
623+ if (!optionSpec .shortestName ().equals (optionSpec .longestName ())) {
624+ result .append ("complete -c " ).append (scriptName );
625+ result .append (" -n \" __fish_seen_subcommand_from " ).append (commandDescriptor .commandName ).append ("\" " );
626+ if (!commandDescriptor .parentWithoutTopLevelCommand .equals ("" )) {
627+ result .append (" -n '__fish_seen_subcommand_from " ).append (
628+ commandDescriptor .parentWithoutTopLevelCommand ).append ("'" );
629+ }
630+ result .append (" -s " ).append (optionSpec .shortestName ().replace ("-" , "" ));
631+ result .append (" -d '" ).append (optionDescription ).append ("'\n " );
632+ }
633+ }
634+ }
635+
636+ }
637+
638+ private static String sanitizeDescription (String description ) {
639+ return description .replace ("'" , "\\ '" );
640+ }
641+
566642 private static List <CommandDescriptor > createHierarchy (String scriptName , CommandLine commandLine ) {
567643 List <CommandDescriptor > result = new ArrayList <CommandDescriptor >();
568644 result .add (new CommandDescriptor ("_picocli_" + scriptName , "" , "" , scriptName , commandLine ));
0 commit comments