diff options
author | Rémi Nicole <nicole@kolabsystems.com> | 2018-08-03 16:59:16 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2018-08-03 17:10:31 +0200 |
commit | 50bed81038f10091d35c5719df8078612393ae95 (patch) | |
tree | e4a3b634118b2b1b9fd88203902e934299deac9b /sinksh/syntaxtree.cpp | |
parent | ad3dc221273100ba61828f993f1d1c8a1272d665 (diff) | |
download | sink-50bed81038f10091d35c5719df8078612393ae95.tar.gz sink-50bed81038f10091d35c5719df8078612393ae95.zip |
Improve documentation of SinkSH
Summary:
- Add support for positional arguments, options, flags in the syntax tree
- Add automatic generation of usage string
TODO:
- ~~Better document the `--reduce` option in the `list` command~~
- Get the parent command for sub-commands so we could show help for `trace on` and not just `on`
- Pass the syntax to the implementation of the command so commands can easily show help on wrong usage. Also, SyntaxTree could do automatic input validation in the future, this could also help.
- Even with the new documentation, some command could still be confusing. Should we add some usage examples?
Reviewers: cmollekopf
Reviewed By: cmollekopf
Tags: #sink
Differential Revision: https://phabricator.kde.org/D14547
Diffstat (limited to 'sinksh/syntaxtree.cpp')
-rw-r--r-- | sinksh/syntaxtree.cpp | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/sinksh/syntaxtree.cpp b/sinksh/syntaxtree.cpp index 0eb9782..fea99ef 100644 --- a/sinksh/syntaxtree.cpp +++ b/sinksh/syntaxtree.cpp | |||
@@ -33,6 +33,104 @@ Syntax::Syntax(const QString &k, const QString &helpText, std::function<bool(con | |||
33 | { | 33 | { |
34 | } | 34 | } |
35 | 35 | ||
36 | void Syntax::addPositionalArgument(const Argument &argument) | ||
37 | { | ||
38 | arguments.push_back(argument); | ||
39 | } | ||
40 | |||
41 | void Syntax::addParameter(const QString &name, const ParameterOptions &options) | ||
42 | { | ||
43 | parameters.insert(name, options); | ||
44 | } | ||
45 | |||
46 | void Syntax::addFlag(const QString &name, const QString &help) | ||
47 | { | ||
48 | flags.insert(name, help); | ||
49 | } | ||
50 | |||
51 | QString Syntax::usage() const | ||
52 | { | ||
53 | // TODO: refactor into meaningful functions? | ||
54 | bool hasArguments = !arguments.isEmpty(); | ||
55 | bool hasFlags = !flags.isEmpty(); | ||
56 | bool hasOptions = !parameters.isEmpty(); | ||
57 | bool hasSubcommand = !children.isEmpty(); | ||
58 | |||
59 | QString argumentsSummary; | ||
60 | |||
61 | QString argumentsUsage; | ||
62 | if (hasArguments) { | ||
63 | argumentsUsage += "\nARGUMENTS:\n"; | ||
64 | for (const auto &arg : arguments) { | ||
65 | if (arg.required) { | ||
66 | argumentsSummary += QString(" <%1>").arg(arg.name); | ||
67 | argumentsUsage += QString(" <%1>: %2\n").arg(arg.name).arg(arg.help); | ||
68 | } else { | ||
69 | argumentsSummary += QString(" [%1]").arg(arg.name); | ||
70 | argumentsUsage += QString(" [%1]: %2\n").arg(arg.name).arg(arg.help); | ||
71 | } | ||
72 | if (arg.variadic) { | ||
73 | argumentsSummary += "..."; | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | |||
78 | if (hasFlags) { | ||
79 | argumentsSummary += " [FLAGS]"; | ||
80 | } | ||
81 | |||
82 | if (hasOptions) { | ||
83 | argumentsSummary += " [OPTIONS]"; | ||
84 | } | ||
85 | |||
86 | if (hasSubcommand) { | ||
87 | if (hasArguments || hasFlags || hasOptions) { | ||
88 | argumentsSummary = QString(" [ <SUB-COMMAND> |%1 ]").arg(argumentsSummary); | ||
89 | } else { | ||
90 | argumentsSummary = " <SUB-COMMAND>"; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | argumentsSummary += '\n'; | ||
95 | |||
96 | QString subcommandsUsage; | ||
97 | if (hasSubcommand) { | ||
98 | subcommandsUsage += "\nSUB-COMMANDS:\n" | ||
99 | " Use the 'help' command to find out more about a sub-command.\n\n"; | ||
100 | for (const auto &command : children) { | ||
101 | subcommandsUsage += QString(" %1: %2\n").arg(command.keyword).arg(command.help); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | QString flagsUsage; | ||
106 | if (hasFlags) { | ||
107 | flagsUsage += "\nFLAGS:\n"; | ||
108 | for (auto it = flags.constBegin(); it != flags.constEnd(); ++it) { | ||
109 | flagsUsage += QString(" [--%1]: %2\n").arg(it.key()).arg(it.value()); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | QString optionsUsage; | ||
114 | if (hasOptions) { | ||
115 | optionsUsage += "\nOPTIONS:\n"; | ||
116 | for (auto it = parameters.constBegin(); it != parameters.constEnd(); ++it) { | ||
117 | optionsUsage += " "; | ||
118 | if (!it.value().required) { | ||
119 | optionsUsage += QString("[--%1 $%2]").arg(it.key()).arg(it.value().name); | ||
120 | } else { | ||
121 | optionsUsage += QString("<--%1 $%2>").arg(it.key()).arg(it.value().name); | ||
122 | } | ||
123 | |||
124 | optionsUsage += ": " + it.value().help + '\n'; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | // TODO: instead of just the keyword, we might want to have the whole | ||
129 | // command (e.g. if this is a sub-command) | ||
130 | return QString("USAGE:\n ") + keyword + argumentsSummary + subcommandsUsage + | ||
131 | argumentsUsage + flagsUsage + optionsUsage; | ||
132 | } | ||
133 | |||
36 | SyntaxTree::SyntaxTree() | 134 | SyntaxTree::SyntaxTree() |
37 | { | 135 | { |
38 | } | 136 | } |