File indexing completed on 2024-05-12 05:12:40
0001 /* 0002 Copyright (C) 2012 Kevin Krammer <krammer@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 along 0015 with this program; if not, write to the Free Software Foundation, Inc., 0016 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 0017 */ 0018 0019 #include "commandfactory.h" 0020 0021 #include "abstractcommand.h" 0022 #include "errorreporter.h" 0023 #include "commandshell.h" 0024 0025 #include <QDebug> 0026 #include <QHash> 0027 0028 #include <iostream> 0029 0030 struct CommandData { 0031 KLocalizedString shortHelp; 0032 CommandFactory::creatorFunction creator; 0033 }; 0034 0035 static QHash<QString, CommandData *> *sCommands = nullptr; 0036 0037 CommandFactory::CommandFactory(const QStringList *parsedArgs) 0038 : mParsedArgs(parsedArgs) 0039 { 0040 Q_ASSERT(mParsedArgs != nullptr); 0041 0042 checkAndHandleHelp(); 0043 } 0044 0045 AbstractCommand *CommandFactory::createCommand() 0046 { 0047 const QString commandName = mParsedArgs->first(); 0048 CommandData *data = sCommands->value(commandName); 0049 if (data == nullptr) { 0050 ErrorReporter::error(i18nc("@info:shell", "Unknown command '%1'", commandName)); 0051 if (!CommandShell::isActive()) printHelpAndExit(false); 0052 return (nullptr); 0053 } 0054 0055 AbstractCommand *command = (data->creator)(nullptr); 0056 Q_ASSERT(command != nullptr); 0057 return (command); 0058 } 0059 0060 void CommandFactory::registerCommand(const QString &name, 0061 const KLocalizedString &shortHelp, 0062 CommandFactory::creatorFunction creator) 0063 { 0064 CommandData *data = new CommandData; 0065 data->shortHelp = shortHelp; 0066 data->creator = creator; 0067 0068 if (sCommands == nullptr) { 0069 sCommands = new QHash<QString, CommandData *>; 0070 } 0071 sCommands->insert(name, data); 0072 } 0073 0074 // There are 3 cases to consider here: 0075 // 0076 // 1. No arguments specified. Display an error message and the list of 0077 // available commands to stderr. 0078 // 0079 // 2. One argument specified and it is "help". Just display the list of 0080 // available commands to stdout. 0081 // 0082 // 3. More than one argument is specified and the first is "help". For 0083 // each argument, display the help for its options to stdout. 0084 // If there is no such command, display an error message. 0085 // 0086 // If none of the above apply, then do nothing. 0087 0088 void CommandFactory::checkAndHandleHelp() 0089 { 0090 if (mParsedArgs->isEmpty()) { // case 1 0091 ErrorReporter::error(i18nc("@info:shell", 0092 "No command specified (try '%1 --help')", 0093 QCoreApplication::applicationName())); 0094 std::exit(EXIT_FAILURE); 0095 } 0096 0097 if (mParsedArgs->first() == QLatin1String("help")) { 0098 if (mParsedArgs->count() == 1) { // case 2 0099 printHelpAndExit(true); 0100 } 0101 0102 for (int a = 1; a<mParsedArgs->count(); ++a) { // case 3 0103 const QString commandName = mParsedArgs->at(a); 0104 if (!sCommands->contains(commandName)) { 0105 ErrorReporter::warning(i18nc("@info:shell", "Unknown command '%1'", commandName)); 0106 continue; 0107 } 0108 0109 CommandData *data = sCommands->value(commandName); 0110 Q_ASSERT(data != nullptr); 0111 AbstractCommand *command = (data->creator)(nullptr); 0112 Q_ASSERT(command != nullptr); 0113 command->init(*mParsedArgs, true); // set up and display help 0114 } 0115 0116 if (!CommandShell::isActive()) std::exit(EXIT_SUCCESS); 0117 } 0118 } 0119 0120 void CommandFactory::printHelpAndExit(bool userRequestedHelp) 0121 { 0122 int maxNameLength = 0; 0123 QStringList commands = sCommands->keys(); 0124 std::sort(commands.begin(), commands.end()); 0125 Q_FOREACH (const QString &commandName, commands) { 0126 maxNameLength = qMax(maxNameLength, commandName.length()); 0127 } 0128 0129 // if the user requested help output to stdout, 0130 // otherwise we are missing the mandatory command argument and output to stderr 0131 std::ostream &stream = userRequestedHelp ? std::cout : std::cerr; 0132 0133 const QString linePattern = QLatin1String(" %1 %2"); 0134 const bool shellActive = CommandShell::isActive(); 0135 0136 stream << std::endl << qPrintable(i18nc("@info:shell", "Available commands are:")) << std::endl; 0137 0138 Q_FOREACH (const QString &commandName, commands) { 0139 if (commandName == "shell" && shellActive) continue; 0140 0141 stream << qPrintable(linePattern.arg(commandName.leftJustified(maxNameLength), 0142 sCommands->value(commandName)->shortHelp.toString(Kuit::TermText))) 0143 << std::endl; 0144 } 0145 0146 if (!shellActive) std::exit(userRequestedHelp ? EXIT_SUCCESS : EXIT_FAILURE); 0147 stream << std::endl; 0148 }