1 package org
.argeo
.api
.cli
;
3 import java
.io
.PrintWriter
;
4 import java
.io
.StringWriter
;
6 import java
.util
.function
.Function
;
8 import org
.apache
.commons
.cli
.HelpFormatter
;
9 import org
.apache
.commons
.cli
.Option
;
10 import org
.apache
.commons
.cli
.Options
;
12 /** A special command that can describe {@link DescribedCommand}. */
13 public class HelpCommand
implements DescribedCommand
<String
> {
15 * System property forcing the root command to this value (typically the name of
18 public final static String ROOT_COMMAND_PROPERTY
= "org.argeo.api.cli.rootCommand";
20 final static String HELP
= "help";
21 final static Option HELP_OPTION
= Option
.builder().longOpt(HELP
).desc("print this help").build();
23 private CommandsCli commandsCli
;
24 private CommandsCli parentCommandsCli
;
27 private static int helpWidth
= 80;
28 private static int helpLeftPad
= 4;
29 private static int helpDescPad
= 20;
31 public HelpCommand(CommandsCli parentCommandsCli
, CommandsCli commandsCli
) {
33 this.parentCommandsCli
= parentCommandsCli
;
34 this.commandsCli
= commandsCli
;
38 public String
apply(List
<String
> args
) {
39 StringWriter out
= new StringWriter();
41 if (args
.size() == 0) {// overview
42 printHelp(commandsCli
, out
);
44 String cmd
= args
.get(0);
45 Function
<List
<String
>, ?
> function
= commandsCli
.getCommand(cmd
);
47 return "Command " + cmd
+ " not found.";
50 DescribedCommand
<?
> command
= null;
51 if (function
instanceof DescribedCommand
) {
52 command
= (DescribedCommand
<?
>) function
;
53 options
= command
.getOptions();
54 examples
= command
.getExamples();
56 options
= new Options();
59 String description
= getShortDescription(function
);
60 String commandCall
= getCommandUsage(cmd
, command
);
61 HelpFormatter formatter
= new HelpFormatter();
62 formatter
.printHelp(new PrintWriter(out
), helpWidth
, commandCall
, description
, options
, helpLeftPad
,
63 helpDescPad
, examples
, false);
65 return out
.toString();
68 private static String
getShortDescription(Function
<List
<String
>, ?
> function
) {
69 if (function
instanceof DescribedCommand
) {
70 return ((DescribedCommand
<?
>) function
).getDescription();
72 return function
.toString();
76 public String
getCommandUsage(String cmd
, DescribedCommand
<?
> command
) {
77 String commandCall
= getCommandCall(commandsCli
) + " " + cmd
;
78 assert command
!= null;
79 if (command
!= null && command
.getUsage() != null) {
80 commandCall
= commandCall
+ " " + command
.getUsage();
86 public String
getDescription() {
87 return "Shows this help or describes a command";
91 public String
getUsage() {
95 public CommandsCli
getParentCommandsCli() {
96 return parentCommandsCli
;
99 protected String
getCommandCall(CommandsCli commandsCli
) {
100 HelpCommand hc
= commandsCli
.getHelpCommand();
101 if (hc
.getParentCommandsCli() != null) {
102 return getCommandCall(hc
.getParentCommandsCli()) + " " + commandsCli
.getCommandName();
104 String rootCommand
= System
.getProperty(ROOT_COMMAND_PROPERTY
);
105 if (rootCommand
!= null)
107 return commandsCli
.getCommandName();
111 public static void printHelp(DescribedCommand
<?
> command
, StringWriter out
) {
112 String usage
= "java " + command
.getClass().getName()
113 + (command
.getUsage() != null ?
" " + command
.getUsage() : "");
114 HelpFormatter formatter
= new HelpFormatter();
115 Options options
= command
.getOptions();
116 options
.addOption(HelpCommand
.HELP_OPTION
);
117 formatter
.printHelp(new PrintWriter(out
), helpWidth
, usage
, command
.getDescription(), options
, helpLeftPad
,
118 helpDescPad
, command
.getExamples(), false);
122 public static void printHelp(CommandsCli commandsCli
, String commandName
, StringWriter out
) {
123 if (commandName
== null) {
124 printHelp(commandsCli
, out
);
127 DescribedCommand
<?
> command
= (DescribedCommand
<?
>) commandsCli
.getCommand(commandName
);
128 String usage
= commandsCli
.getHelpCommand().getCommandUsage(commandName
, command
);
129 HelpFormatter formatter
= new HelpFormatter();
130 Options options
= command
.getOptions();
131 options
.addOption(HelpCommand
.HELP_OPTION
);
132 formatter
.printHelp(new PrintWriter(out
), helpWidth
, usage
, command
.getDescription(), options
, helpLeftPad
,
133 helpDescPad
, command
.getExamples(), false);
137 public static void printHelp(CommandsCli commandsCli
, StringWriter out
) {
138 out
.append(commandsCli
.getDescription()).append('\n');
139 String leftPad
= spaces(helpLeftPad
);
140 for (String cmd
: commandsCli
.getSubCommands()) {
141 Function
<List
<String
>, ?
> function
= commandsCli
.getCommand(cmd
);
142 assert function
!= null;
145 // TODO deal with long commands
146 out
.append(spaces(helpDescPad
- cmd
.length()));
147 out
.append(getShortDescription(function
));
152 private static String
spaces(int count
) {
154 // return " ".repeat(count);
158 StringBuilder sb
= new StringBuilder(count
);
159 for (int i
= 0; i
< count
; i
++)
161 return sb
.toString();