From 255d73af197faf8437343abc10bd98cca2057a1e Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Wed, 23 Dec 2015 10:47:32 +0100 Subject: initial import of the new cli app --- akonadi2_cli/CMakeLists.txt | 16 +++ akonadi2_cli/main.cpp | 71 ++++++++++++++ akonadi2_cli/module.cpp | 195 +++++++++++++++++++++++++++++++++++++ akonadi2_cli/module.h | 61 ++++++++++++ akonadi2_cli/modules/exit/exit.cpp | 39 ++++++++ akonadi2_cli/modules/exit/exit.h | 37 +++++++ akonadi2_cli/modules/help/help.cpp | 80 +++++++++++++++ akonadi2_cli/modules/help/help.h | 37 +++++++ akonadi2_cli/repl/repl.cpp | 78 +++++++++++++++ akonadi2_cli/repl/repl.h | 34 +++++++ akonadi2_cli/repl/replStates.cpp | 155 +++++++++++++++++++++++++++++ akonadi2_cli/repl/replStates.h | 85 ++++++++++++++++ akonadi2_cli/state.cpp | 28 ++++++ akonadi2_cli/state.h | 29 ++++++ 14 files changed, 945 insertions(+) create mode 100644 akonadi2_cli/CMakeLists.txt create mode 100644 akonadi2_cli/main.cpp create mode 100644 akonadi2_cli/module.cpp create mode 100644 akonadi2_cli/module.h create mode 100644 akonadi2_cli/modules/exit/exit.cpp create mode 100644 akonadi2_cli/modules/exit/exit.h create mode 100644 akonadi2_cli/modules/help/help.cpp create mode 100644 akonadi2_cli/modules/help/help.h create mode 100644 akonadi2_cli/repl/repl.cpp create mode 100644 akonadi2_cli/repl/repl.h create mode 100644 akonadi2_cli/repl/replStates.cpp create mode 100644 akonadi2_cli/repl/replStates.h create mode 100644 akonadi2_cli/state.cpp create mode 100644 akonadi2_cli/state.h (limited to 'akonadi2_cli') diff --git a/akonadi2_cli/CMakeLists.txt b/akonadi2_cli/CMakeLists.txt new file mode 100644 index 0000000..b5bdb46 --- /dev/null +++ b/akonadi2_cli/CMakeLists.txt @@ -0,0 +1,16 @@ +project(akonadi2_cli) + +find_package(Readline REQUIRED) + + +set(akonadi2_SRCS + main.cpp + module.cpp + modules/exit/exit.cpp + modules/help/help.cpp + repl/repl.cpp + repl/replStates.cpp + state.cpp) + +add_executable(${PROJECT_NAME} ${akonadi2_SRCS}) + diff --git a/akonadi2_cli/main.cpp b/akonadi2_cli/main.cpp new file mode 100644 index 0000000..1a036d0 --- /dev/null +++ b/akonadi2_cli/main.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include +#include + +#include "module.h" +// #include "jsonlistener.h" +#include "repl/repl.h" + +/* + * modes of operation: + * + * 1. called with no commands: start the REPL and listen for JSON on stin + * 2. called with -: listen for JSON on stdin + * 3. called with commands: try to match to syntx + */ + +int main(int argc, char *argv[]) +{ + // load all modules + Module::loadModules(); + + const bool interactive = isatty(fileno(stdin)); + const bool startRepl = (argc == 1) && interactive; + //TODO: make a json command parse cause that would be awesomesauce + const bool startJsonListener = !startRepl && + (argc == 2 && qstrcmp(argv[1], "-") == 0); + qDebug() << "state at startup is" << interactive << startRepl << startJsonListener; + + QCoreApplication app(argc, argv); + app.setApplicationName("funq"); + + if (startRepl || startJsonListener) { + if (startRepl) { + Repl *repl = new Repl; + QObject::connect(repl, &QStateMachine::finished, + repl, &QObject::deleteLater); + QObject::connect(repl, &QStateMachine::finished, + &app, &QCoreApplication::quit); + } + + if (startJsonListener) { +// JsonListener listener(syntax); + } + + return app.exec(); + } + + QStringList commands = app.arguments(); + commands.removeFirst(); + return Module::run(commands); +} diff --git a/akonadi2_cli/module.cpp b/akonadi2_cli/module.cpp new file mode 100644 index 0000000..0b83d98 --- /dev/null +++ b/akonadi2_cli/module.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "module.h" + +#include +#include + +// TODO: needs a proper registry; making "core" modules plugins is +// almost certainly overkill, but this is not the way either +#include "modules/exit/exit.h" +#include "modules/help/help.h" + +QList Module::s_modules; +State Module::s_state; + +Module::Syntax::Syntax() +{ +} + +Module::Syntax::Syntax(const QString &k, std::function l, const QString &helpText, bool e) + : keyword(k), + lambda(l), + help(helpText), + eventDriven(e) +{ +} + +Module::Module() +{ +} + +void Module::loadModules() +{ + addModule(CLI::Exit()); + addModule(CLI::Help()); +} + +void Module::addModule(const Module &module) +{ + s_modules.append(module); +} + +QList Module::modules() +{ + return s_modules; +} + +Module::Command Module::match(const QStringList &commands) +{ + Command command; + for (const Module &module: s_modules) { + command = module.matches(commands); + if (command.first) { + break; + } + } + + return command; +} + +Module::Syntax Module::syntax() const +{ + return m_syntax; +} + +void Module::setSyntax(const Syntax &syntax) +{ + m_syntax = syntax; +} + +bool Module::run(const QStringList &commands) +{ + Command command = match(commands); + if (command.first && command.first->lambda) { + bool rv = command.first->lambda(command.second, s_state); + if (rv && command.first->eventDriven) { + return QCoreApplication::instance()->exec(); + } + + return rv; + } + + return false; +} + +Module::Command Module::matches(const QStringList &commandLine) const +{ + if (commandLine.isEmpty()) { + return Command(); + } + + QStringListIterator commandLineIt(commandLine); + + if (commandLineIt.next() != m_syntax.keyword) { + return Command(); + } + + QListIterator syntaxIt(m_syntax.children); + const Syntax *syntax = &m_syntax; + QStringList tailCommands; + while (commandLineIt.hasNext() && syntaxIt.hasNext()) { + const QString word = commandLineIt.next(); + while (syntaxIt.hasNext()) { + const Syntax &child = syntaxIt.next(); + if (word == child.keyword) { + syntax = &child; + syntaxIt = child.children; + } + } + + if (!syntaxIt.hasNext()) { + tailCommands << word; + break; + } + } + + if (syntax && syntax->lambda) { + while (commandLineIt.hasNext()) { + tailCommands << commandLineIt.next(); + } + + return std::make_pair(syntax, tailCommands); + } + + return Command(); +} + +QVector Module::nearestSyntax(const QStringList &words, const QString &fragment) +{ + QVector matches; + + //qDebug() << "words are" << words; + if (words.isEmpty()) { + for (const Module &module: s_modules) { + if (module.syntax().keyword.startsWith(fragment)) { + matches.push_back(module.syntax()); + } + } + } else { + QStringListIterator wordIt(words); + QString word = wordIt.next(); + Syntax lastFullSyntax; + + for (const Module &module: s_modules) { + if (module.syntax().keyword == word) { + lastFullSyntax = module.syntax(); + QListIterator syntaxIt(module.syntax().children); + while (wordIt.hasNext()) { + word = wordIt.next(); + while (syntaxIt.hasNext()) { + const Syntax &child = syntaxIt.next(); + if (word == child.keyword) { + lastFullSyntax = child; + syntaxIt = child.children; + } + } + } + + break; + } + } + + //qDebug() << "exiting with" << lastFullSyntax.keyword << words.last(); + if (lastFullSyntax.keyword == words.last()) { + QListIterator syntaxIt(lastFullSyntax.children); + while (syntaxIt.hasNext()) { + Syntax syntax = syntaxIt.next(); + if (fragment.isEmpty() || syntax.keyword.startsWith(fragment)) { + matches.push_back(syntax); + } + } + } + } + + return matches; +} + + diff --git a/akonadi2_cli/module.h b/akonadi2_cli/module.h new file mode 100644 index 0000000..4f426b8 --- /dev/null +++ b/akonadi2_cli/module.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include "state.h" + +#include +#include + +class Module +{ +public: + struct Syntax + { + Syntax(); + Syntax(const QString &keyword, std::function lambda = std::function(), const QString &helpText = QString(), bool eventDriven = false); + QString keyword; + std::function lambda; + QList children; + QString help; + bool eventDriven; + }; + + typedef std::pair Command; + + static void addModule(const Module &module); + static QList modules(); + static Command match(const QStringList &commands); + static bool run(const QStringList &commands); + static void loadModules(); + static QVectornearestSyntax(const QStringList &words, const QString &fragment); + + Module(); + Module::Syntax syntax() const; + void setSyntax(const Syntax &syntax); + +private: + Command matches(const QStringList &commands) const; + + Syntax m_syntax; + static QList s_modules; + static State s_state; +}; + diff --git a/akonadi2_cli/modules/exit/exit.cpp b/akonadi2_cli/modules/exit/exit.cpp new file mode 100644 index 0000000..64828be --- /dev/null +++ b/akonadi2_cli/modules/exit/exit.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "exit.h" + +#include + +namespace CLI +{ + +Exit::Exit() +{ + setSyntax(Syntax("exit", &Exit::exit, QObject::tr("Exits the application. Ctrl-d also works!"))); +} + +bool Exit::exit(const QStringList &, State &) +{ + ::exit(0); + return true; +} + +} // namespace CLI + diff --git a/akonadi2_cli/modules/exit/exit.h b/akonadi2_cli/modules/exit/exit.h new file mode 100644 index 0000000..5ed4174 --- /dev/null +++ b/akonadi2_cli/modules/exit/exit.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include "module.h" + +namespace CLI +{ + +class Exit : public Module +{ +public: + Exit(); + +private: + static bool exit(const QStringList &commands, State &state); +}; + +} // namespace CLI + diff --git a/akonadi2_cli/modules/help/help.cpp b/akonadi2_cli/modules/help/help.cpp new file mode 100644 index 0000000..aaff6fb --- /dev/null +++ b/akonadi2_cli/modules/help/help.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "help.h" + +#include +#include +#include + +#include "module.h" + +namespace CLI +{ + +Help::Help() +{ + Syntax topLevel = Syntax(QObject::tr("help"), &Help::showHelp, QObject::tr("Print command information: help [command]")); + setSyntax(topLevel); +} + +bool Help::showHelp(const QStringList &commands, State &) +{ + Module::Command command = Module::match(commands); + QTextStream stream(stdout); + if (commands.isEmpty()) { + stream << QObject::tr("Welcome to the Akonadi2 command line tool!") << "\n"; + stream << QObject::tr("Top-level commands:") << "\n"; + QSet sorted; + for (auto module: Module::modules()) { + sorted.insert(module.syntax().keyword); + } + + for (auto keyword: sorted) { + stream << "\t" << keyword << "\n"; + } + } else if (const Syntax *syntax = command.first) { + //TODO: get parent! + stream << QObject::tr("Command `%1`").arg(syntax->keyword); + + if (!syntax->help.isEmpty()) { + stream << ": " << syntax->help; + } + stream << "\n"; + + if (!syntax->children.isEmpty()) { + stream << "\tSub-commands:\n"; + QSet sorted; + for (auto childSyntax: syntax->children) { + sorted.insert(childSyntax.keyword); + } + + for (auto keyword: sorted) { + stream << "\t" << keyword << "\n"; + } + } + } else { + stream << "Unknown command: " << commands.join(" ") << "\n"; + } + + return true; +} + +} // namespace CLI + diff --git a/akonadi2_cli/modules/help/help.h b/akonadi2_cli/modules/help/help.h new file mode 100644 index 0000000..df1cfc2 --- /dev/null +++ b/akonadi2_cli/modules/help/help.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include "module.h" + +namespace CLI +{ + +class Help : public Module +{ +public: + Help(); + +private: + static bool showHelp(const QStringList &commands, State &state); +}; + +} // namespace CLI + diff --git a/akonadi2_cli/repl/repl.cpp b/akonadi2_cli/repl/repl.cpp new file mode 100644 index 0000000..395661e --- /dev/null +++ b/akonadi2_cli/repl/repl.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "repl.h" + +#include + +#include +#include +#include +#include + +#include "replStates.h" + +Repl::Repl(QObject *parent) + : QStateMachine(parent) +{ + // readline history setup + using_history(); + read_history(commandHistoryPath().toLocal8Bit()); + + // create all states + ReadState *read = new ReadState(this); + UnfinishedReadState *unfinishedRead = new UnfinishedReadState(this); + EvalState *eval = new EvalState(this); + PrintState *print = new PrintState(this); + QFinalState *final = new QFinalState(this); + + // connect the transitions + read->addTransition(read, SIGNAL(command(QString)), eval); + read->addTransition(read, SIGNAL(exitRequested()), final); + + unfinishedRead->addTransition(unfinishedRead, SIGNAL(command(QString)), eval); + unfinishedRead->addTransition(unfinishedRead, SIGNAL(exitRequested()), final); + + eval->addTransition(eval, SIGNAL(completed()), read); + eval->addTransition(eval, SIGNAL(continueInput()), unfinishedRead); + eval->addTransition(eval, SIGNAL(output(QString)), print); + + print->addTransition(print, SIGNAL(completed()), eval); + + setInitialState(read); + start(); +} + +Repl::~Repl() +{ + // readline history writing + write_history(commandHistoryPath().toLocal8Bit()); +} + +QString Repl::commandHistoryPath() +{ + const QString path = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + if (!QFile::exists(path)) { + QDir dir; + dir.mkpath(path); + } + return path + "/repl_history"; +} + +#include "moc_repl.cpp" diff --git a/akonadi2_cli/repl/repl.h b/akonadi2_cli/repl/repl.h new file mode 100644 index 0000000..b76c66b --- /dev/null +++ b/akonadi2_cli/repl/repl.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include + +class Repl : public QStateMachine +{ + Q_OBJECT + +public: + Repl(QObject *parent = 0); + ~Repl(); + +private: + static QString commandHistoryPath(); +}; diff --git a/akonadi2_cli/repl/replStates.cpp b/akonadi2_cli/repl/replStates.cpp new file mode 100644 index 0000000..e87dd5f --- /dev/null +++ b/akonadi2_cli/repl/replStates.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "replStates.h" + +#include +#include + +#include +#include + +#include +#include +#include + +#include "module.h" + +static char *akonadi2_cli_next_tab_complete_match(const char *text, int state); +static char ** akonadi2_cli_tab_completion(const char *text, int start, int end); + +ReadState::ReadState(QState *parent) + : QState(parent) +{ + rl_completion_entry_function = akonadi2_cli_next_tab_complete_match; + rl_attempted_completion_function = akonadi2_cli_tab_completion; +} + +void ReadState::onEntry(QEvent *event) +{ + Q_UNUSED(event) + char *line = readline(prompt()); + + if (!line) { + std::cout << std::endl; + emit exitRequested(); + return; + } + + // we have actual data, so let's wait for a full line of text + QByteArray input(line); + const QString text = QString(line).simplified(); + //qDebug() << "Line is ... " << text; + + if (text.length() > 0) { + add_history(line); + } + + free(line); + emit command(text); +} + +const char *ReadState::prompt() const +{ + return "> "; +} + +UnfinishedReadState::UnfinishedReadState(QState *parent) + : ReadState(parent) +{ +} + +const char *UnfinishedReadState::prompt() const +{ + return " "; +} + +EvalState::EvalState(QState *parent) + : QState(parent), + m_complete(false) +{ +} + +void EvalState::onEntry(QEvent *event) +{ + QStateMachine::SignalEvent *e = dynamic_cast(event); + + if (!e || e->arguments().isEmpty()) { + if (m_complete) { + emit completed(); + } else { + emit continueInput(); + } + return; + } + + //TODO: properly tokenize (e.g. "foo bar" should not become ['"foo', 'bar"'] + const QString command = e->arguments()[0].toString(); + + if (!command.isEmpty()) { + m_complete = command.right(1) != "\\"; + if (m_complete) { + //emit output("Processing ... " + command); + const QStringList commands = command.split(" "); + Module::run(commands); + emit completed(); + } + } +} + +PrintState::PrintState(QState *parent) + : QState(parent) +{ +} + +void PrintState::onEntry(QEvent *event) +{ + QStateMachine::SignalEvent *e = dynamic_cast(event); + + if (e && !e->arguments().isEmpty()) { + const QString command = e->arguments()[0].toString(); + QTextStream stream(stdout); + stream << command << "\n"; + } + + emit completed(); +} + +static QStringList tab_completion_full_state; +static bool tab_completion_at_root = false; + +static char **akonadi2_cli_tab_completion(const char *text, int start, int end) +{ + tab_completion_at_root = start == 0; + tab_completion_full_state = QString(rl_line_buffer).remove(start, end - start).split(" ", QString::SkipEmptyParts); + return NULL; +} + +static char *akonadi2_cli_next_tab_complete_match(const char *text, int state) +{ + QVector nearest = Module::nearestSyntax(tab_completion_full_state, QString(text)); + + if (nearest.size() > state) { + return qstrdup(nearest[state].keyword.toUtf8()); + } + + return rl_filename_completion_function(text, state); +} + +#include "moc_replStates.cpp" diff --git a/akonadi2_cli/repl/replStates.h b/akonadi2_cli/repl/replStates.h new file mode 100644 index 0000000..a019a37 --- /dev/null +++ b/akonadi2_cli/repl/replStates.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include + +class QSocketNotifier; + +class ReadState : public QState +{ + Q_OBJECT + +public: + ReadState(QState *parent = 0); + +Q_SIGNALS: + void command(const QString &command); + void exitRequested(); + +protected: + void onEntry(QEvent *event); + virtual const char *prompt() const; +}; + +class UnfinishedReadState : public ReadState +{ + Q_OBJECT + +public: + UnfinishedReadState(QState *parent = 0); + +protected: + const char *prompt() const; +}; + +class EvalState : public QState +{ + Q_OBJECT + +public: + EvalState(QState *parent = 0); + +Q_SIGNALS: + void completed(); + void continueInput(); + void output(const QString &output); + +protected: + void onEntry(QEvent *event); + +private: + bool m_complete; +}; + +class PrintState : public QState +{ + Q_OBJECT + +public: + PrintState(QState *parent = 0); + +Q_SIGNALS: + void completed(); + +protected: + void onEntry(QEvent *event); +}; + diff --git a/akonadi2_cli/state.cpp b/akonadi2_cli/state.cpp new file mode 100644 index 0000000..bb21e0e --- /dev/null +++ b/akonadi2_cli/state.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "state.h" + +#include +#include + +State::State() +{ +} + diff --git a/akonadi2_cli/state.h b/akonadi2_cli/state.h new file mode 100644 index 0000000..10b2318 --- /dev/null +++ b/akonadi2_cli/state.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 Aaron Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include + +class State +{ +public: + State(); +}; + -- cgit v1.2.3