File indexing completed on 2024-06-16 05:01:12
0001 /* 0002 * Copyright (C) 2014 Aaron Seigo <aseigo@kde.org> 0003 * 0004 * This program is free software; you can redistribute it and/or modify 0005 * it under the terms of the GNU General Public License as published by 0006 * the Free Software Foundation; either version 2 of the License, or 0007 * (at your option) any later version. 0008 * 0009 * This program is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 * GNU General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU General Public License 0015 * along with this program; if not, write to the 0016 * Free Software Foundation, Inc., 0017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 0018 */ 0019 0020 #include <QDebug> 0021 #include <QObject> // tr() 0022 #include <QSet> 0023 #include <QTextStream> 0024 0025 #include "state.h" 0026 #include "syntaxtree.h" 0027 #include "utils.h" 0028 #include "common/log.h" 0029 0030 namespace CoreSyntax 0031 { 0032 0033 bool exit(const QStringList &, State &) 0034 { 0035 ::exit(0); 0036 } 0037 0038 bool showHelp(const QStringList &commands, State &state) 0039 { 0040 SyntaxTree::Command command = SyntaxTree::self()->match(commands); 0041 if (commands.isEmpty()) { 0042 state.printLine(QObject::tr("Welcome to the Sink command line tool!")); 0043 state.printLine(QObject::tr("Top-level commands:")); 0044 0045 QSet<QString> sorted; 0046 for (auto syntax: SyntaxTree::self()->syntax()) { 0047 sorted.insert(syntax.keyword); 0048 } 0049 0050 for (auto keyword: sorted) { 0051 state.printLine(keyword, 1); 0052 } 0053 } else if (const Syntax *syntax = command.first) { 0054 //TODO: get parent! 0055 state.print(QObject::tr("Command `%1`").arg(syntax->keyword)); 0056 0057 if (!syntax->help.isEmpty()) { 0058 state.print(": " + syntax->help); 0059 } 0060 state.printLine(QString("\n\n") + syntax->usage()); 0061 } else { 0062 state.printError("Unknown command: " + commands.join(" ")); 0063 } 0064 0065 return true; 0066 } 0067 0068 QStringList showHelpCompleter(const QStringList &commands, const QString &fragment, State &) 0069 { 0070 QStringList items; 0071 0072 for (auto syntax: SyntaxTree::self()->syntax()) { 0073 if (syntax.keyword != QObject::tr("help") && 0074 (fragment.isEmpty() || syntax.keyword.startsWith(fragment))) { 0075 items << syntax.keyword; 0076 } 0077 } 0078 0079 qSort(items); 0080 return items; 0081 } 0082 0083 bool setDebugLevel(const QStringList &commands, State &state) 0084 { 0085 if (commands.count() != 1) { 0086 state.printError(QObject::tr("Wrong number of arguments; expected 1 got %1").arg(commands.count())); 0087 return false; 0088 } 0089 0090 bool ok = false; 0091 int level = commands[0].toUInt(&ok); 0092 0093 if (!ok) { 0094 state.printError(QObject::tr("Expected a number between 0 and 6, got %1").arg(commands[0])); 0095 return false; 0096 } 0097 0098 state.setDebugLevel(level); 0099 return true; 0100 } 0101 0102 bool printDebugLevel(const QStringList &, State &state) 0103 { 0104 state.printLine(QString::number(state.debugLevel())); 0105 return true; 0106 } 0107 0108 bool printCommandTiming(const QStringList &, State &state) 0109 { 0110 state.printLine(state.commandTiming() ? QObject::tr("on") : QObject::tr("off")); 0111 return true; 0112 } 0113 0114 void printSyntaxBranch(State &state, const Syntax::List &list, int depth) 0115 { 0116 if (list.isEmpty()) { 0117 return; 0118 } 0119 0120 if (depth > 0) { 0121 state.printLine("\\", depth); 0122 } 0123 0124 for (auto syntax: list) { 0125 state.print("|-", depth); 0126 state.printLine(syntax.keyword); 0127 printSyntaxBranch(state, syntax.children, depth + 1); 0128 } 0129 } 0130 0131 bool printSyntaxTree(const QStringList &, State &state) 0132 { 0133 printSyntaxBranch(state, SyntaxTree::self()->syntax(), 0); 0134 return true; 0135 } 0136 0137 bool setLoggingLevel(const QStringList &commands, State &state) 0138 { 0139 if (commands.count() != 1) { 0140 state.printError(QObject::tr("Wrong number of arguments; expected 1 got %1").arg(commands.count())); 0141 return false; 0142 } 0143 0144 state.setLoggingLevel(commands.at(0)); 0145 return true; 0146 } 0147 0148 bool printLoggingLevel(const QStringList &commands, State &state) 0149 { 0150 const QString level = state.loggingLevel(); 0151 state.printLine(level); 0152 return true; 0153 } 0154 0155 bool setLoggingAreas(const QStringList &commands, State &state) 0156 { 0157 if (commands.isEmpty()) { 0158 state.printError(QObject::tr("Wrong number of arguments; expected logging areas.")); 0159 return false; 0160 } 0161 0162 QByteArrayList areas; 0163 for (const auto &c : commands) { 0164 areas << c.toLatin1(); 0165 } 0166 0167 Sink::Log::setDebugOutputFilter(Sink::Log::Area, areas); 0168 return true; 0169 } 0170 0171 bool setLoggingFilter(const QStringList &commands, State &state) 0172 { 0173 if (commands.isEmpty()) { 0174 state.printError(QObject::tr("Wrong number of arguments; expected resource identifier or application names.")); 0175 return false; 0176 } 0177 0178 QByteArrayList filter; 0179 for (const auto &c : commands) { 0180 filter << c.toLatin1(); 0181 } 0182 0183 Sink::Log::setDebugOutputFilter(Sink::Log::ApplicationName, filter); 0184 return true; 0185 } 0186 0187 bool setLoggingFields(const QStringList &commands, State &state) 0188 { 0189 QByteArrayList output; 0190 for (const auto &c : commands) { 0191 output << c.toLatin1(); 0192 } 0193 0194 Sink::Log::setDebugOutputFields(output); 0195 return true; 0196 } 0197 0198 Syntax::List syntax() 0199 { 0200 Syntax::List syntax; 0201 syntax << Syntax("exit", QObject::tr("Exits the application. Ctrl-d also works!"), &CoreSyntax::exit); 0202 0203 Syntax help("help", QObject::tr("Print command information: help [command]"), &CoreSyntax::showHelp); 0204 help.completer = &CoreSyntax::showHelpCompleter; 0205 syntax << help; 0206 0207 syntax << Syntax("syntaxtree", QString(), &printSyntaxTree); 0208 0209 Syntax set("set", QObject::tr("Sets settings for the session")); 0210 set.children << Syntax("debug", QObject::tr("Set the debug level from 0 to 6"), &CoreSyntax::setDebugLevel); 0211 0212 Syntax setTiming = Syntax("timing", QObject::tr("Whether or not to print the time commands take to complete")); 0213 setTiming.children << Syntax("on", QString(), [](const QStringList &, State &state) -> bool { state.setCommandTiming(true); return true; }); 0214 setTiming.children << Syntax("off", QString(), [](const QStringList &, State &state) -> bool { state.setCommandTiming(false); return true; }); 0215 set.children << setTiming; 0216 0217 Syntax logging("logging", QObject::tr("Set the logging level to one of Trace, Log, Warning or Error"), &CoreSyntax::setLoggingLevel); 0218 logging.completer = [](const QStringList &, const QString &fragment, State &state) -> QStringList { return Utils::filteredCompletions(QStringList() << "trace" << "log" << "warning" << "error", fragment, Qt::CaseInsensitive); }; 0219 set.children << logging; 0220 0221 Syntax loggingAreas("loggingAreas", QObject::tr("Set logging areas."), &CoreSyntax::setLoggingAreas); 0222 set.children << loggingAreas; 0223 0224 Syntax loggingFilter("loggingFilter", QObject::tr("Set logging filter."), &CoreSyntax::setLoggingFilter); 0225 set.children << loggingFilter; 0226 0227 Syntax loggingFields("loggingFields", QObject::tr("Set logging fields."), &CoreSyntax::setLoggingFields); 0228 loggingFields.completer = [](const QStringList &, const QString &fragment, State &state) -> QStringList { return Utils::filteredCompletions(QStringList() << "time" << "name" << "function" << "location" << "", fragment, Qt::CaseInsensitive); }; 0229 set.children << loggingFields; 0230 0231 syntax << set; 0232 0233 Syntax get("get", QObject::tr("Gets settings for the session")); 0234 get.children << Syntax("debug", QObject::tr("The current debug level from 0 to 6"), &CoreSyntax::printDebugLevel); 0235 get.children << Syntax("timing", QObject::tr("Whether or not to print the time commands take to complete"), &CoreSyntax::printCommandTiming); 0236 get.children << Syntax("logging", QObject::tr("The current logging level"), &CoreSyntax::printLoggingLevel); 0237 syntax << get; 0238 0239 return syntax; 0240 } 0241 0242 REGISTER_SYNTAX(CoreSyntax) 0243 0244 } // namespace CoreSyntax 0245