summaryrefslogtreecommitdiffstats
path: root/sinksh/syntaxtree.cpp
diff options
context:
space:
mode:
authorRémi Nicole <nicole@kolabsystems.com>2018-08-03 16:59:16 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2018-08-03 17:10:31 +0200
commit50bed81038f10091d35c5719df8078612393ae95 (patch)
treee4a3b634118b2b1b9fd88203902e934299deac9b /sinksh/syntaxtree.cpp
parentad3dc221273100ba61828f993f1d1c8a1272d665 (diff)
downloadsink-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.cpp98
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
36void Syntax::addPositionalArgument(const Argument &argument)
37{
38 arguments.push_back(argument);
39}
40
41void Syntax::addParameter(const QString &name, const ParameterOptions &options)
42{
43 parameters.insert(name, options);
44}
45
46void Syntax::addFlag(const QString &name, const QString &help)
47{
48 flags.insert(name, help);
49}
50
51QString 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
36SyntaxTree::SyntaxTree() 134SyntaxTree::SyntaxTree()
37{ 135{
38} 136}