10 #include <QStringBuilder>
15 using namespace swift::misc::physical_quantities;
19 QList<CSimpleCommandParser::CommandHtmlHelp> CSimpleCommandParser::s_commands;
20 QSet<QString> CSimpleCommandParser::s_registered;
24 this->setCheckedCommandList(knownCommands);
29 m_knownCommand =
false;
30 m_originalLine = commandLine;
31 m_cleanedLine = commandLine.trimmed().simplified();
32 if (!m_cleanedLine.isEmpty())
34 m_splitParts = m_cleanedLine.split(
' ');
35 if (!m_splitParts.isEmpty())
37 const QString &first = m_splitParts.constFirst();
38 const QString formatted = formatCommand(first);
41 m_commandPart = formatted;
42 m_knownCommand = m_knownCommands.contains(formatted);
50 static const QString empty(
"");
51 if (index < 0 || index >= m_splitParts.size())
return empty;
52 return m_splitParts.at(index);
57 if (index < 0) {
return m_cleanedLine; }
58 const QString p = this->part(index);
59 const int from = index < 1 ? 0 :
nthIndexOf(m_cleanedLine,
' ', index, Qt::CaseInsensitive);
60 const int fi = m_cleanedLine.indexOf(p, from, Qt::CaseInsensitive);
61 if (fi < 0) {
return {}; }
62 return m_originalLine.mid(fi).trimmed();
72 return c > 0 ? c - 1 : 0;
77 const QString p = this->part(index);
78 if (p.isEmpty()) {
return false; }
86 const QString p = this->part(index);
87 if (p.isEmpty()) {
return false; }
95 const QString p = this->part(index);
96 if (p.isEmpty()) {
return def; }
104 const QString p = this->part(index);
105 if (p.isEmpty()) {
return def; }
112 const QString p = this->part(index);
113 if (p.isEmpty()) {
return def; }
121 if (toMatch.isEmpty()) {
return false; }
122 if (!this->hasPart(index)) {
return false; }
123 const QString p(this->part(index));
124 if (p.isEmpty()) {
return false; }
125 return (p.length() == toMatch.length() && p.startsWith(toMatch, cs));
133 if (help.command == command.
command) {
return; }
135 s_commands.append(command);
140 if (s_registered.contains(helpContext)) {
return true; }
141 s_registered.insert(helpContext);
147 if (s_commands.isEmpty()) {
return {}; }
149 static const QString html(
"<table style=\"font-size: 8pt; white-space: nowrap;\">\n%1\n</table>");
150 static const QString row(
"<td>%1</td><td>%2</td>");
151 static const QString rowHeader(
"<th>%1</th><th>%2</th><th>%3</th><th>%4</th>");
154 QList<CommandHtmlHelp> cmds(s_commands);
155 std::sort(cmds.begin(), cmds.end(), CommandHtmlHelp::less);
157 static const QString cmdCol(QString().fill(
'-', 20));
158 static const QString textCol(QString().fill(
'-', 40));
159 rows += u
"<tr>" % rowHeader.arg(
"command",
"synopsis",
"command",
"synopsis") % u
"</tr>\n" % u
"<tr>" %
160 rowHeader.arg(cmdCol, textCol, cmdCol, textCol) % u
"</tr>\n";
162 for (
int i = 0; i < cmds.size(); i++)
165 rows += u
"<tr>" % row.arg(help.
command, help.
help);
172 else { rows += row.arg(
"",
""); }
175 return html.arg(rows);
178 QString CSimpleCommandParser::removeLeadingDot(
const QString &candidate)
180 if (!candidate.startsWith(
'.')) {
return candidate; }
181 return candidate.right(candidate.length() - 1);
184 QString CSimpleCommandParser::formatCommand(
const QString &command)
186 return removeLeadingDot(command.trimmed().toLower());
189 bool CSimpleCommandParser::isCommand(
const QString &candidate) {
return candidate.startsWith(
'.'); }
193 if (m_commandPart.isEmpty()) {
return false; }
194 if (!checkCommand.isEmpty() && formatCommand(checkCommand) == m_commandPart) {
return true; }
195 if (!alias1.isEmpty() && formatCommand(alias1) == m_commandPart) {
return true; }
196 if (!alias2.isEmpty() && formatCommand(alias2) == m_commandPart) {
return true; }
202 if (m_commandPart.isEmpty()) {
return false; }
203 return m_commandPart.startsWith(formatCommand(startPattern));
208 if (m_commandPart.isEmpty()) {
return false; }
209 return m_commandPart.endsWith(endPattern);
212 void CSimpleCommandParser::setCheckedCommandList(
const QStringList &commands)
214 for (
const QString &c : commands) { m_knownCommands.append(formatCommand(c)); }
static void registerCommand(const CommandHtmlHelp &command)
Register a command.
static QString commandsHtmlHelp()
HTML commands HELP.
int countPartsWithoutCommand() const
Count parts, command excluded.
int toInt(int index, int def=-1) const
Part as integer.
bool isInt(int index) const
Is part an integer?
int countParts() const
Count parts.
bool toBool(int index, bool def=false) const
Part as bool.
bool commandStartsWith(const QString &startPattern) const
Command starting with pattern?
CSimpleCommandParser(const QStringList &knownCommands)
Constructor.
bool matchesPart(int index, const QString &toMatch, Qt::CaseSensitivity cs=Qt::CaseInsensitive) const
Matches given part.
bool isDouble(int index) const
Is part a double?
void parse(const QString &commandLine)
Parse.
QString partAndRemainingStringAfter(int index) const
Part and remaing string after.
double toDouble(int index, double def=-1.0) const
Part as double.
bool matchesCommand(const QString &checkCommand, const QString &alias1="", const QString &alias2="")
Is given command current command of command line.
const QString & part(int index) const
Get part, 0 is command itself.
bool hasPart(int index) const
Existing part.
static bool registered(const QString &helpContext)
Help already registered.
bool commandEndsWith(const QString &endPattern) const
Command ending with pattern?
@ SeparatorBestGuess
try to figure out
static double parseNumber(const QString &number, bool &success, SeparatorMode mode=SeparatorBestGuess)
Locale aware parsing.
Free functions in swift::misc.
SWIFT_MISC_EXPORT int nthIndexOf(const QString &string, QChar ch, int nth=1, Qt::CaseSensitivity cs=Qt::CaseInsensitive)
nth index of ch
SWIFT_MISC_EXPORT bool stringToBool(const QString &boolString)
Convert string to bool.