1 /*
2  * hunt-console eases the creation of beautiful and testable command line interfaces.
3  *
4  * Copyright (C) 2018-2019, HuntLabs
5  *
6  * Website: https://www.huntlabs.net
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11  
12 module hunt.console.descriptor.MarkdownDescriptor;
13 
14 import std.string;
15 
16 import hunt.console.Console;
17 import hunt.console.command.Command;
18 import hunt.console.input.InputArgument;
19 import hunt.console.input.InputDefinition;
20 import hunt.console.input.InputOption;
21 import hunt.console.util.StringUtils;
22 
23 import hunt.collection.List;
24 import hunt.collection.Map;
25 import hunt.console.descriptor.AbstractDescriptor;
26 import hunt.console.descriptor.DescriptorOptions;
27 import hunt.console.descriptor.ConsoleDescription;
28 
29 class MarkdownDescriptor : AbstractDescriptor
30 {
31     override protected void describeInputArgument(InputArgument argument, DescriptorOptions options)
32     {
33         write(
34             "**" ~ argument.getName() ~ ":**\n\n" ~
35             "* Name: " ~ (argument.getName() is null ? "<none>" : argument.getName()) ~ "\n" ~
36             "* Is required: " ~ (argument.isRequired() ? "yes" : "no") ~ "\n" ~
37             "* Is array: " ~ (argument.isArray() ? "yes" : "no") ~ "\n" ~
38             "* Description: " ~ (argument.getDescription() is null ? "<none>" : argument.getDescription()) ~ "\n" ~
39             "* Default: `" ~ (argument.getDefaultValue() is null ? "" : argument.getDefaultValue().replace("\\n", " ")) ~ "`"
40         );
41     }
42 
43     override protected void describeInputOption(InputOption option, DescriptorOptions options)
44     {
45         write(
46             "**" ~ option.getName() ~ ":**\n\n" ~
47             "* Name: `--" ~ option.getName() ~ "`\n" ~
48             "* Shortcut: " ~ (option.getShortcut() is null ? "<none>" : "`-" ~ StringUtils.join(StringUtils.split(option.getShortcut(), '|'), "|")) ~ "\n" ~
49             "* Accept value: " ~ (option.acceptValue() ? "yes" : "no") ~ "\n" ~
50             "* Is value required: " ~ (option.isValueRequired() ? "yes" : "no") ~ "\n" ~
51             "* Is multiple: " ~ (option.isArray() ? "yes" : "no") ~ "\n" ~
52             "* Description: " ~ (option.getDescription() is null ? "<none>" : option.getDescription()) ~ "\n" ~
53             "* Default: `" ~ (option.getDefaultValue() is null ? "" : option.getDefaultValue().replace("\\n", " ")) ~ "`"
54         );
55     }
56 
57     override protected void describeInputDefinition(InputDefinition definition, DescriptorOptions options)
58     {
59         bool showArguments = definition.getArguments().size() > 0;
60         if (showArguments) {
61             write("### Arguments:");
62             foreach (InputArgument argument ; definition.getArguments()) {
63                 write("\n\n");
64                 describeInputArgument(argument, options);
65             }
66         }
67 
68         if (definition.getOptions().size() > 0) {
69             if (showArguments) {
70                 write("\n\n");
71             }
72             write("### Options:");
73             foreach (InputOption option ; definition.getOptions()) {
74                 write("\n\n");
75                 describeInputOption(option, options);
76             }
77         }
78     }
79 
80     override protected void describeCommand(Command command, DescriptorOptions options)
81     {
82         command.getSynopsis();
83         command.mergeConsoleDefinition(false);
84 
85         write(
86                 command.getName() ~ "\n" ~
87                 StringUtils.repeat("-", command.getName().length) ~ "\n\n" ~
88                 "* Description: " ~ (command.getDescription() is null ? "<none>" : command.getDescription()) ~ "\n" ~
89                 "* Usage: `" ~ command.getSynopsis() ~ "`\n" ~
90                 "* Aliases: " ~ (command.getAliases().length > 0 ? "`" ~ StringUtils.join(command.getAliases(), "`, `") ~ "`" : "<none>")
91         );
92 
93         string help = command.getProcessedHelp();
94         if (help !is null) {
95             write("\n\n");
96             write(help);
97         }
98 
99         InputDefinition definition = command.getNativeDefinition();
100         if (definition !is null) {
101             write("\n\n");
102             describeInputDefinition(definition, options);
103         }
104     }
105 
106     override protected void describeConsole(Console application, DescriptorOptions options)
107     {
108         string describedNamespace = options.has("namespace") ? options.get("namespace") : null;
109         ConsoleDescription description = new ConsoleDescription(application, describedNamespace);
110 
111         write(application.getName() ~ "\n" ~ StringUtils.repeat("=", application.getName().length));
112 
113         foreach (string k ,List!(string) v ; description.getNamespaces()) {
114             string namespace = k;
115             if (!(namespace == ConsoleDescription.GLOBAL_NAMESPACE)) {
116                 write("\n\n");
117                 write("**" ~ namespace ~ ":**");
118             }
119 
120             write("\n\n");
121             foreach (string commandName ; v) {
122                 write("* " ~ commandName ~ "\n");
123             }
124         }
125 
126         foreach (Command command ; description.getCommands().values()) {
127             write("\n\n");
128             describeCommand(command, options);
129         }
130     }
131 }