File indexing completed on 2024-05-12 05:12:40
0001 /* 0002 * Copyright (C) 2014 Bhaskar Kandiyal <bkandiyal@gmail.com> 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 0020 #include "commandshell.h" 0021 0022 #include "commandfactory.h" 0023 #include "errorreporter.h" 0024 0025 #include <kshell.h> 0026 0027 #include <QTextStream> 0028 #include <QCoreApplication> 0029 #include <QTextCodec> 0030 0031 DEFINE_COMMAND("shell", CommandShell, I18N_NOOP("Enter commands in an interactive shell")); 0032 0033 bool CommandShell::sIsActive = false; 0034 0035 CommandShell::CommandShell(QObject *parent) 0036 : AbstractCommand(parent) 0037 { 0038 mTextStream = new QTextStream(stdin); 0039 mTextStream->setCodec(QTextCodec::codecForLocale()); 0040 } 0041 0042 CommandShell::~CommandShell() 0043 { 0044 delete mTextStream; 0045 } 0046 0047 void CommandShell::setupCommandOptions(QCommandLineParser *parser) 0048 { 0049 } 0050 0051 int CommandShell::initCommand(QCommandLineParser *parser) 0052 { 0053 return (AbstractCommand::NoError); 0054 } 0055 0056 void CommandShell::start() 0057 { 0058 sIsActive = true; 0059 while (enterCommandLoop()) {} 0060 sIsActive = false; 0061 QCoreApplication::quit(); 0062 } 0063 0064 bool CommandShell::enterCommandLoop() 0065 { 0066 const QString input = mTextStream->readLine(); 0067 if (mTextStream->atEnd()) { 0068 return (false); 0069 } 0070 0071 AbstractCommand *toInvoke = nullptr; 0072 0073 KShell::Errors err; 0074 const QStringList args = KShell::splitArgs(input, KShell::AbortOnMeta, &err); 0075 if (err != KShell::NoError) { // error splitting line 0076 ErrorReporter::error(i18nc("@info:shell", "Invalid command")); 0077 } // but continue command loop 0078 else if (!args.isEmpty()) { // non-empty input line 0079 const QString cmd = args.first(); // look at command name 0080 if (cmd == "quit" || cmd == "exit") { // exit shell on these 0081 return (false); 0082 } 0083 0084 CommandFactory factory(&args); 0085 if (cmd == "help") return (true); // handled above by CommandFactory 0086 0087 toInvoke = factory.createCommand(); 0088 if (toInvoke != nullptr) { 0089 connect(toInvoke, &AbstractCommand::error, this, &CommandShell::onCommandError); 0090 if (toInvoke->init(args) == AbstractCommand::NoError) { 0091 QEventLoop loop; // hopefully safe, because not a child of us 0092 connect(toInvoke, &AbstractCommand::finished, &loop, &QEventLoop::quit); 0093 QMetaObject::invokeMethod(toInvoke, "start", Qt::QueuedConnection); 0094 loop.exec(); 0095 } 0096 0097 toInvoke->deleteLater(); 0098 } 0099 } 0100 0101 return (true); 0102 } 0103 0104 void CommandShell::onCommandError(const QString &error) 0105 { 0106 ErrorReporter::error(error); 0107 }