[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [akonadi-next/feature/new_cli] akonadi2_cli: vastly simplify by getting rid of Module as a base clas
From: Aaron Seigo <aseigo () kde ! org>
Date: 2015-12-23 11:09:12
Message-ID: E1aBhI8-0008IN-AY () scm ! kde ! org
[Download RAW message or body]
Git commit 071f4ef0122a8bfceeda9a10b41e85ad9a34a28d by Aaron Seigo.
Committed on 23/12/2015 at 10:43.
Pushed by aseigo into branch 'feature/new_cli'.
vastly simplify by getting rid of Module as a base class
just a move slightly more towards functional
M +7 -4 akonadi2_cli/CMakeLists.txt
M +1 -4 akonadi2_cli/main.cpp
M +41 -75 akonadi2_cli/module.cpp
M +25 -16 akonadi2_cli/module.h
R +19 -14 akonadi2_cli/modules/core_syntax.cpp [from: \
akonadi2_cli/modules/help/help.cpp - 070% similarity] R +5 -12 \
akonadi2_cli/modules/core_syntax.h [from: akonadi2_cli/modules/exit/exit.h - 083% \
similarity] D +0 -39 akonadi2_cli/modules/exit/exit.cpp
D +0 -37 akonadi2_cli/modules/help/help.h
M +2 -2 akonadi2_cli/repl/replStates.cpp
http://commits.kde.org/akonadi-next/071f4ef0122a8bfceeda9a10b41e85ad9a34a28d
diff --git a/akonadi2_cli/CMakeLists.txt b/akonadi2_cli/CMakeLists.txt
index b5bdb46..a07140e 100644
--- a/akonadi2_cli/CMakeLists.txt
+++ b/akonadi2_cli/CMakeLists.txt
@@ -3,14 +3,17 @@ project(akonadi2_cli)
find_package(Readline REQUIRED)
-set(akonadi2_SRCS
+set(akonadi2_cli_SRCS
main.cpp
module.cpp
- modules/exit/exit.cpp
- modules/help/help.cpp
+ modules/core_syntax.cpp
repl/repl.cpp
repl/replStates.cpp
state.cpp)
-add_executable(${PROJECT_NAME} ${akonadi2_SRCS})
+include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
+
+add_executable(${PROJECT_NAME} ${akonadi2_cli_SRCS})
+target_link_libraries(${PROJECT_NAME} Qt5::Core ${Readline_LIBRARY})
+install(TARGETS ${PROJECT_NAME} ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
diff --git a/akonadi2_cli/main.cpp b/akonadi2_cli/main.cpp
index 1a036d0..d23e070 100644
--- a/akonadi2_cli/main.cpp
+++ b/akonadi2_cli/main.cpp
@@ -36,9 +36,6 @@
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
@@ -67,5 +64,5 @@ int main(int argc, char *argv[])
QStringList commands = app.arguments();
commands.removeFirst();
- return Module::run(commands);
+ return Module::self()->run(commands);
}
diff --git a/akonadi2_cli/module.cpp b/akonadi2_cli/module.cpp
index 0b83d98..dfc58c8 100644
--- a/akonadi2_cli/module.cpp
+++ b/akonadi2_cli/module.cpp
@@ -24,83 +24,61 @@
// 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"
+#include "modules/core_syntax.h"
-QList<Module> Module::s_modules;
-State Module::s_state;
+Module *Module::s_module = 0;
Module::Syntax::Syntax()
{
}
-Module::Syntax::Syntax(const QString &k, std::function<bool(const QStringList &, \
State &)> l, const QString &helpText, bool e) +Module::Syntax::Syntax(const QString \
&k, const QString &helpText, std::function<bool(const QStringList &, State &)> l, \
Interactivity inter) : keyword(k),
- lambda(l),
help(helpText),
- eventDriven(e)
+ interactivity(inter),
+ lambda(l)
{
}
Module::Module()
{
+ QVector<std::function<SyntaxList()> > syntaxModules;
+ syntaxModules << &CoreSyntax::syntax;
+ for (auto syntaxModule: syntaxModules) {
+ m_syntax += syntaxModule();
+ }
}
-void Module::loadModules()
-{
- addModule(CLI::Exit());
- addModule(CLI::Help());
-}
-
-void Module::addModule(const Module &module)
-{
- s_modules.append(module);
-}
-
-QList<Module> Module::modules()
-{
- return s_modules;
-}
-
-Module::Command Module::match(const QStringList &commands)
+Module *Module::self()
{
- Command command;
- for (const Module &module: s_modules) {
- command = module.matches(commands);
- if (command.first) {
- break;
- }
+ if (!s_module) {
+ s_module = new Module;
}
- return command;
+ return s_module;
}
-Module::Syntax Module::syntax() const
+Module::SyntaxList 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) {
+ command.first->lambda(command.second, m_state);
+ if (command.first->interactivity == Syntax::EventDriven) {
return QCoreApplication::instance()->exec();
}
- return rv;
+ return true;
}
return false;
}
-Module::Command Module::matches(const QStringList &commandLine) const
+Module::Command Module::match(const QStringList &commandLine) const
{
if (commandLine.isEmpty()) {
return Command();
@@ -108,20 +86,16 @@ Module::Command Module::matches(const QStringList &commandLine) \
const
QStringListIterator commandLineIt(commandLine);
- if (commandLineIt.next() != m_syntax.keyword) {
- return Command();
- }
-
- QListIterator<Syntax> syntaxIt(m_syntax.children);
- const Syntax *syntax = &m_syntax;
+ QVectorIterator<Syntax> syntaxIt(m_syntax);
+ const Syntax *lastFullSyntax = 0;
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;
+ const Syntax &syntax = syntaxIt.next();
+ if (word == syntax.keyword) {
+ lastFullSyntax = &syntax;
+ syntaxIt = syntax.children;
}
}
@@ -131,55 +105,47 @@ Module::Command Module::matches(const QStringList &commandLine) \
const }
}
- if (syntax && syntax->lambda) {
+ if (lastFullSyntax && lastFullSyntax->lambda) {
while (commandLineIt.hasNext()) {
tailCommands << commandLineIt.next();
}
- return std::make_pair(syntax, tailCommands);
+ return std::make_pair(lastFullSyntax, tailCommands);
}
return Command();
}
-QVector<Module::Syntax> Module::nearestSyntax(const QStringList &words, const \
QString &fragment) +Module::SyntaxList Module::nearestSyntax(const QStringList \
&words, const QString &fragment) const {
- QVector<Module::Syntax> matches;
+ SyntaxList 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());
+ for (const Syntax &syntax: m_syntax) {
+ if (syntax.keyword.startsWith(fragment)) {
+ matches.push_back(syntax);
}
}
} else {
QStringListIterator wordIt(words);
- QString word = wordIt.next();
+ QVectorIterator<Syntax> syntaxIt(m_syntax);
Syntax lastFullSyntax;
- for (const Module &module: s_modules) {
- if (module.syntax().keyword == word) {
- lastFullSyntax = module.syntax();
- QListIterator<Syntax> 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;
- }
- }
+ while (wordIt.hasNext()) {
+ QString word = wordIt.next();
+ while (syntaxIt.hasNext()) {
+ const Syntax &syntax = syntaxIt.next();
+ if (word == syntax.keyword) {
+ lastFullSyntax = syntax;
+ syntaxIt = syntax.children;
}
-
- break;
}
}
//qDebug() << "exiting with" << lastFullSyntax.keyword << words.last();
if (lastFullSyntax.keyword == words.last()) {
- QListIterator<Syntax> syntaxIt(lastFullSyntax.children);
+ syntaxIt = lastFullSyntax.children;
while (syntaxIt.hasNext()) {
Syntax syntax = syntaxIt.next();
if (fragment.isEmpty() || syntax.keyword.startsWith(fragment)) {
diff --git a/akonadi2_cli/module.h b/akonadi2_cli/module.h
index 4f426b8..d2745d0 100644
--- a/akonadi2_cli/module.h
+++ b/akonadi2_cli/module.h
@@ -29,33 +29,42 @@ class Module
public:
struct Syntax
{
+ enum Interactivity {
+ NotInteractive = 0,
+ EventDriven
+ };
+
Syntax();
- Syntax(const QString &keyword, std::function<bool(const QStringList &, State \
&)> lambda = std::function<bool(const QStringList &, State &)>(), const QString \
&helpText = QString(), bool eventDriven = false); + Syntax(const QString \
&keyword, + const QString &helpText = QString(),
+ std::function<bool(const QStringList &, State &)> lambda = \
std::function<bool(const QStringList &, State &)>(), + Interactivity \
interactivity = NotInteractive); +
QString keyword;
- std::function<bool(const QStringList &, State &)> lambda;
- QList<Syntax> children;
QString help;
- bool eventDriven;
+ Interactivity interactivity;
+ std::function<bool(const QStringList &, State &)> lambda;
+
+ QVector<Syntax> children;
};
typedef std::pair<const Syntax *, QStringList> Command;
+ typedef QVector<Module::Syntax> SyntaxList;
- static void addModule(const Module &module);
- static QList<Module> modules();
- static Command match(const QStringList &commands);
- static bool run(const QStringList &commands);
- static void loadModules();
- static QVector<Syntax>nearestSyntax(const QStringList &words, const QString \
&fragment); + static Module *self();
- Module();
- Module::Syntax syntax() const;
- void setSyntax(const Syntax &syntax);
+ SyntaxList syntax() const;
+ Command match(const QStringList &commands) const;
+ SyntaxList nearestSyntax(const QStringList &words, const QString &fragment) \
const; +
+ bool run(const QStringList &commands);
private:
+ Module();
Command matches(const QStringList &commands) const;
- Syntax m_syntax;
- static QList<Module> s_modules;
- static State s_state;
+ SyntaxList m_syntax;
+ State m_state;
+ static Module *s_module;
};
diff --git a/akonadi2_cli/modules/help/help.cpp \
b/akonadi2_cli/modules/core_syntax.cpp similarity index 70%
rename from akonadi2_cli/modules/help/help.cpp
rename to akonadi2_cli/modules/core_syntax.cpp
index aaff6fb..8324c31 100644
--- a/akonadi2_cli/modules/help/help.cpp
+++ b/akonadi2_cli/modules/core_syntax.cpp
@@ -17,39 +17,45 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "help.h"
+#include "core_syntax.h"
-#include <QObject>
+#include <QObject> // tr()
#include <QSet>
#include <QTextStream>
-#include "module.h"
+namespace CoreSyntax
+{
-namespace CLI
+Module::SyntaxList syntax()
{
+ Module::SyntaxList syntax;
+ syntax << Module::Syntax("exit", QObject::tr("Exits the application. Ctrl-d also \
works!"), &CoreSyntax::exit); + syntax << Module::Syntax(QObject::tr("help"), \
QObject::tr("Print command information: help [command]"), &CoreSyntax::showHelp); + \
return syntax; +}
-Help::Help()
+bool exit(const QStringList &, State &)
{
- Syntax topLevel = Syntax(QObject::tr("help"), &Help::showHelp, \
QObject::tr("Print command information: help [command]"));
- setSyntax(topLevel);
+ ::exit(0);
+ return true;
}
-bool Help::showHelp(const QStringList &commands, State &)
+bool showHelp(const QStringList &commands, State &)
{
- Module::Command command = Module::match(commands);
+ Module::Command command = Module::self()->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<QString> sorted;
- for (auto module: Module::modules()) {
- sorted.insert(module.syntax().keyword);
+ for (auto syntax: Module::self()->syntax()) {
+ sorted.insert(syntax.keyword);
}
for (auto keyword: sorted) {
stream << "\t" << keyword << "\n";
}
- } else if (const Syntax *syntax = command.first) {
+ } else if (const Module::Syntax *syntax = command.first) {
//TODO: get parent!
stream << QObject::tr("Command `%1`").arg(syntax->keyword);
@@ -72,9 +78,8 @@ bool Help::showHelp(const QStringList &commands, State &)
} else {
stream << "Unknown command: " << commands.join(" ") << "\n";
}
-
return true;
}
-} // namespace CLI
+} // namespace CoreSyntax
diff --git a/akonadi2_cli/modules/exit/exit.h b/akonadi2_cli/modules/core_syntax.h
similarity index 83%
rename from akonadi2_cli/modules/exit/exit.h
rename to akonadi2_cli/modules/core_syntax.h
index 5ed4174..beb8528 100644
--- a/akonadi2_cli/modules/exit/exit.h
+++ b/akonadi2_cli/modules/core_syntax.h
@@ -21,17 +21,10 @@
#include "module.h"
-namespace CLI
+namespace CoreSyntax
{
-
-class Exit : public Module
-{
-public:
- Exit();
-
-private:
- static bool exit(const QStringList &commands, State &state);
-};
-
-} // namespace CLI
+ Module::SyntaxList syntax();
+ bool exit(const QStringList &commands, State &state);
+ bool showHelp(const QStringList &commands, State &);
+}
diff --git a/akonadi2_cli/modules/exit/exit.cpp b/akonadi2_cli/modules/exit/exit.cpp
deleted file mode 100644
index 64828be..0000000
--- a/akonadi2_cli/modules/exit/exit.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 Aaron Seigo <aseigo@kde.org>
- *
- * 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 <QObject>
-
-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/help/help.h b/akonadi2_cli/modules/help/help.h
deleted file mode 100644
index df1cfc2..0000000
--- a/akonadi2_cli/modules/help/help.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2014 Aaron Seigo <aseigo@kde.org>
- *
- * 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/replStates.cpp b/akonadi2_cli/repl/replStates.cpp
index e87dd5f..efa1353 100644
--- a/akonadi2_cli/repl/replStates.cpp
+++ b/akonadi2_cli/repl/replStates.cpp
@@ -107,7 +107,7 @@ void EvalState::onEntry(QEvent *event)
if (m_complete) {
//emit output("Processing ... " + command);
const QStringList commands = command.split(" ");
- Module::run(commands);
+ Module::self()->run(commands);
emit completed();
}
}
@@ -143,7 +143,7 @@ static char **akonadi2_cli_tab_completion(const char *text, int \
start, int end)
static char *akonadi2_cli_next_tab_complete_match(const char *text, int state)
{
- QVector<Module::Syntax> nearest = \
Module::nearestSyntax(tab_completion_full_state, QString(text)); + \
QVector<Module::Syntax> nearest = \
Module::self()->nearestSyntax(tab_completion_full_state, QString(text));
if (nearest.size() > state) {
return qstrdup(nearest[state].keyword.toUtf8());
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic