From 4b9675e797c87ea363aa313854b72b5754122b79 Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Mon, 28 Dec 2015 16:32:46 +0100 Subject: tighten this up a little --- akonadish/syntax_modules/akonadi_list.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'akonadish') diff --git a/akonadish/syntax_modules/akonadi_list.cpp b/akonadish/syntax_modules/akonadi_list.cpp index 807119c..18f15e7 100644 --- a/akonadish/syntax_modules/akonadi_list.cpp +++ b/akonadish/syntax_modules/akonadi_list.cpp @@ -72,7 +72,6 @@ bool list(const QStringList &args, State &state) //qDebug() << "Listing"; int colSize = 38; //Necessary to display a complete UUID - state.print(" " + QObject::tr("Column") + " "); state.print(QObject::tr("Resource").leftJustified(colSize, ' ', true) + QObject::tr("Identifier").leftJustified(colSize, ' ', true)); for (int i = 0; i < model->columnCount(QModelIndex()); i++) { @@ -82,9 +81,8 @@ bool list(const QStringList &args, State &state) QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model, colSize, state](const QModelIndex &index, int start, int end) { for (int i = start; i <= end; i++) { - state.print(" " + QObject::tr("Row %1").arg(QString::number(model->rowCount())).rightJustified(4, ' ') + ": "); auto object = model->data(model->index(i, 0, index), Akonadi2::Store::DomainObjectBaseRole).value(); - state.print(" " + object->resourceInstanceIdentifier().leftJustified(colSize, ' ', true)); + state.print(object->resourceInstanceIdentifier().leftJustified(colSize, ' ', true)); state.print(object->identifier().leftJustified(colSize, ' ', true)); for (int col = 0; col < model->columnCount(QModelIndex()); col++) { state.print(" | " + model->data(model->index(i, col, index)).toString().leftJustified(colSize, ' ', true)); -- cgit v1.2.3 From 949609b3f19b8a8823a7c62f23617eef05b796dd Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Mon, 28 Dec 2015 20:19:42 +0100 Subject: allow access to the state member --- akonadish/syntaxtree.cpp | 5 +++++ akonadish/syntaxtree.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'akonadish') diff --git a/akonadish/syntaxtree.cpp b/akonadish/syntaxtree.cpp index 495ad22..4860582 100644 --- a/akonadish/syntaxtree.cpp +++ b/akonadish/syntaxtree.cpp @@ -168,6 +168,11 @@ Syntax::List SyntaxTree::nearestSyntax(const QStringList &words, const QString & return matches; } +State &SyntaxTree::state() +{ + return m_state; +} + QStringList SyntaxTree::tokenize(const QString &text) { //TODO: properly tokenize (e.g. "foo bar" should not become ['"foo', 'bar"']a diff --git a/akonadish/syntaxtree.h b/akonadish/syntaxtree.h index 884a10d..ee06d28 100644 --- a/akonadish/syntaxtree.h +++ b/akonadish/syntaxtree.h @@ -63,7 +63,7 @@ public: Syntax::List syntax() const; Command match(const QStringList &commands) const; Syntax::List nearestSyntax(const QStringList &words, const QString &fragment) const; - + State &state(); bool run(const QStringList &commands); static QStringList tokenize(const QString &text); -- cgit v1.2.3 From 7e48662cf11b5be7d062b082a9a1970419921a08 Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Mon, 28 Dec 2015 20:20:16 +0100 Subject: pass the state object into the completer allows completion to use an eventloop e.g. --- akonadish/repl/replStates.cpp | 2 +- akonadish/syntax_modules/core_syntax.cpp | 2 +- akonadish/syntaxtree.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'akonadish') diff --git a/akonadish/repl/replStates.cpp b/akonadish/repl/replStates.cpp index 62888d0..55fdf39 100644 --- a/akonadish/repl/replStates.cpp +++ b/akonadish/repl/replStates.cpp @@ -156,7 +156,7 @@ static char *akonadi2_cli_next_tab_complete_match(const char *text, int state) if (nearest.isEmpty()) { SyntaxTree::Command command = SyntaxTree::self()->match(tab_completion_full_state); if (command.first && command.first->completer) { - QStringList commandCompletions = command.first->completer(tab_completion_full_state, fragment); + QStringList commandCompletions = command.first->completer(tab_completion_full_state, fragment, SyntaxTree::self()->state()); if (commandCompletions.size() > state) { return qstrdup(commandCompletions[state].toUtf8()); } diff --git a/akonadish/syntax_modules/core_syntax.cpp b/akonadish/syntax_modules/core_syntax.cpp index 31b824a..b4812df 100644 --- a/akonadish/syntax_modules/core_syntax.cpp +++ b/akonadish/syntax_modules/core_syntax.cpp @@ -76,7 +76,7 @@ bool showHelp(const QStringList &commands, State &state) return true; } -QStringList showHelpCompleter(const QStringList &commands, const QString &fragment) +QStringList showHelpCompleter(const QStringList &commands, const QString &fragment, State &) { QStringList items; diff --git a/akonadish/syntaxtree.h b/akonadish/syntaxtree.h index ee06d28..468aad3 100644 --- a/akonadish/syntaxtree.h +++ b/akonadish/syntaxtree.h @@ -47,7 +47,7 @@ public: QString help; Interactivity interactivity; std::function lambda; - std::function completer; + std::function completer; QVector children; }; -- cgit v1.2.3 From 7b380e9677678c0e3bcec981a2466ccb04f4e590 Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Mon, 28 Dec 2015 20:21:02 +0100 Subject: methods to get resourceIds and a compelter built on that --- akonadish/akonadish_utils.cpp | 44 +++++++++++++++++++++++++++++++++++++++++++ akonadish/akonadish_utils.h | 4 ++++ 2 files changed, 48 insertions(+) (limited to 'akonadish') diff --git a/akonadish/akonadish_utils.cpp b/akonadish/akonadish_utils.cpp index ffbdcb3..90847f6 100644 --- a/akonadish/akonadish_utils.cpp +++ b/akonadish/akonadish_utils.cpp @@ -70,6 +70,50 @@ QSharedPointer loadModel(const QString &type, Akonadi2::Quer return model; } +QStringList resourceIds(State &state) +{ + QStringList resources; + Akonadi2::Query query; + query.syncOnDemand = false; + query.processAll = false; + query.liveQuery = false; + auto model = AkonadishUtils::loadModel("resource", query); + + QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model, &resources] (const QModelIndex &index, int start, int end) mutable { + for (int i = start; i <= end; i++) { + auto object = model->data(model->index(i, 0, index), Akonadi2::Store::DomainObjectBaseRole).value(); + resources << object->identifier(); + } + }); + + QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [model, state](const QModelIndex &, const QModelIndex &, const QVector &roles) { + if (roles.contains(Akonadi2::Store::ChildrenFetchedRole)) { + state.commandFinished(); + } + }); + + state.commandStarted(); + + return resources; +} + +QStringList resourceCompleter(const QStringList &commands, const QString &fragment, State &state) +{ + QStringList resources = resourceIds(state); + if (fragment.isEmpty()) { + return resources; + } + + QStringList filtered; + for (auto resource: resources) { + if (resource.startsWith(fragment)) { + filtered << resource; + } + } + + return filtered; +} + QMap keyValueMapFromArgs(const QStringList &args) { //TODO: this is not the most clever of algorithms. preserved during the port of commands diff --git a/akonadish/akonadish_utils.h b/akonadish/akonadish_utils.h index 17b8ec7..5671157 100644 --- a/akonadish/akonadish_utils.h +++ b/akonadish/akonadish_utils.h @@ -26,6 +26,8 @@ #include "common/query.h" #include "common/clientapi.h" +#include "state.h" + namespace AkonadishUtils { @@ -34,6 +36,8 @@ class StoreBase; bool isValidStoreType(const QString &type); StoreBase &getStore(const QString &type); QSharedPointer loadModel(const QString &type, Akonadi2::Query query); +QStringList resourceIds(); +QStringList resourceCompleter(const QStringList &, const QString &fragment, State &state); QMap keyValueMapFromArgs(const QStringList &args); /** -- cgit v1.2.3 From 67d664f6dc36e3bd85fac27d5008b84e4b1d5568 Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Mon, 28 Dec 2015 20:26:44 +0100 Subject: resource automcompletion --- akonadish/syntax_modules/akonadi_clear.cpp | 6 +++--- akonadish/syntax_modules/akonadi_count.cpp | 6 +++--- akonadish/syntax_modules/akonadi_modify.cpp | 9 ++++----- akonadish/syntax_modules/akonadi_remove.cpp | 9 ++++----- akonadish/syntax_modules/akonadi_stat.cpp | 6 +++--- akonadish/syntax_modules/akonadi_sync.cpp | 6 +++--- 6 files changed, 20 insertions(+), 22 deletions(-) (limited to 'akonadish') diff --git a/akonadish/syntax_modules/akonadi_clear.cpp b/akonadish/syntax_modules/akonadi_clear.cpp index d17fac2..d328849 100644 --- a/akonadish/syntax_modules/akonadi_clear.cpp +++ b/akonadish/syntax_modules/akonadi_clear.cpp @@ -50,10 +50,10 @@ bool clear(const QStringList &args, State &state) Syntax::List syntax() { - Syntax::List syntax; - syntax << Syntax("clear", QObject::tr("Clears the local cache of one or more resources (be careful!)"), &AkonadiClear::clear); + Syntax clear("clear", QObject::tr("Clears the local cache of one or more resources (be careful!)"), &AkonadiClear::clear); + clear.completer = &AkonadishUtils::resourceCompleter; - return syntax; + return Syntax::List() << clear; } REGISTER_SYNTAX(AkonadiClear) diff --git a/akonadish/syntax_modules/akonadi_count.cpp b/akonadish/syntax_modules/akonadi_count.cpp index cda7235..fa3f1fb 100644 --- a/akonadish/syntax_modules/akonadi_count.cpp +++ b/akonadish/syntax_modules/akonadi_count.cpp @@ -74,10 +74,10 @@ bool count(const QStringList &args, State &state) Syntax::List syntax() { - Syntax::List syntax; - syntax << Syntax("count", QObject::tr("Returns the number of items of a given type in a resource. Usage: count "), &AkonadiCount::count, Syntax::EventDriven); + Syntax count("count", QObject::tr("Returns the number of items of a given type in a resource. Usage: count "), &AkonadiCount::count, Syntax::EventDriven); + count.completer = &AkonadishUtils::resourceCompleter; - return syntax; + return Syntax::List() << count; } REGISTER_SYNTAX(AkonadiCount) diff --git a/akonadish/syntax_modules/akonadi_modify.cpp b/akonadish/syntax_modules/akonadi_modify.cpp index 8438301..8ab873a 100644 --- a/akonadish/syntax_modules/akonadi_modify.cpp +++ b/akonadish/syntax_modules/akonadi_modify.cpp @@ -107,13 +107,12 @@ bool resource(const QStringList &args, State &state) Syntax::List syntax() { - Syntax::List syntax; - Syntax modify("modify", QObject::tr("Modify items in a resource"), &AkonadiModify::modify); - modify.children << Syntax("resource", QObject::tr("Modify a resource"), &AkonadiModify::resource);//, Syntax::EventDriven); + Syntax resource("resource", QObject::tr("Modify a resource"), &AkonadiModify::resource);//, Syntax::EventDriven); + resource.completer = &AkonadishUtils::resourceCompleter; + modify.children << resource; - syntax << modify; - return syntax; + return Syntax::List() << modify; } REGISTER_SYNTAX(AkonadiModify) diff --git a/akonadish/syntax_modules/akonadi_remove.cpp b/akonadish/syntax_modules/akonadi_remove.cpp index bf09e2e..9691d78 100644 --- a/akonadish/syntax_modules/akonadi_remove.cpp +++ b/akonadish/syntax_modules/akonadi_remove.cpp @@ -97,13 +97,12 @@ bool resource(const QStringList &args, State &state) Syntax::List syntax() { - Syntax::List syntax; - Syntax remove("remove", QObject::tr("Remove items in a resource"), &AkonadiRemove::remove); - remove.children << Syntax("resource", QObject::tr("Removes a resource"), &AkonadiRemove::resource);//, Syntax::EventDriven); + Syntax resource("resource", QObject::tr("Removes a resource"), &AkonadiRemove::resource);//, Syntax::EventDriven); + resource.completer = &AkonadishUtils::resourceCompleter; + remove.children << resource; - syntax << remove; - return syntax; + return Syntax::List() << remove; } REGISTER_SYNTAX(AkonadiRemove) diff --git a/akonadish/syntax_modules/akonadi_stat.cpp b/akonadish/syntax_modules/akonadi_stat.cpp index 0ea65dd..9270f9d 100644 --- a/akonadish/syntax_modules/akonadi_stat.cpp +++ b/akonadish/syntax_modules/akonadi_stat.cpp @@ -111,10 +111,10 @@ bool stat(const QStringList &args, State &state) Syntax::List syntax() { - Syntax::List syntax; - syntax << Syntax("stat", QObject::tr("Shows database usage for the resources requested"), &AkonadiStat::stat, Syntax::EventDriven); + Syntax state("stat", QObject::tr("Shows database usage for the resources requested"), &AkonadiStat::stat, Syntax::EventDriven); + state.completer = &AkonadishUtils::resourceCompleter; - return syntax; + return Syntax::List() << state; } REGISTER_SYNTAX(AkonadiStat) diff --git a/akonadish/syntax_modules/akonadi_sync.cpp b/akonadish/syntax_modules/akonadi_sync.cpp index 1cf097d..03abbb4 100644 --- a/akonadish/syntax_modules/akonadi_sync.cpp +++ b/akonadish/syntax_modules/akonadi_sync.cpp @@ -58,10 +58,10 @@ bool sync(const QStringList &args, State &state) Syntax::List syntax() { - Syntax::List syntax; - syntax << Syntax("sync", QObject::tr("Syncronizes all resources that are listed; and empty list triggers a syncronizaton on all resources"), &AkonadiSync::sync, Syntax::EventDriven ); + Syntax sync("sync", QObject::tr("Syncronizes all resources that are listed; and empty list triggers a syncronizaton on all resources"), &AkonadiSync::sync, Syntax::EventDriven ); + sync.completer = &AkonadishUtils::resourceCompleter; - return syntax; + return Syntax::List() << sync; } REGISTER_SYNTAX(AkonadiSync) -- cgit v1.2.3 From d456572c4178390a1f539e4923023ec331d2cde3 Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Mon, 28 Dec 2015 21:59:58 +0100 Subject: consistency (and avoids warnings on redirect input) --- akonadish/main.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'akonadish') diff --git a/akonadish/main.cpp b/akonadish/main.cpp index 45bd5ea..f3cbcac 100644 --- a/akonadish/main.cpp +++ b/akonadish/main.cpp @@ -48,7 +48,8 @@ int main(int argc, char *argv[]) //qDebug() << "state at startup is" << interactive << startRepl << startJsonListener << fromScript; QCoreApplication app(argc, argv); - app.setApplicationName(argv[0]); + app.setApplicationName(fromScript ? "interactive-app-shell" : argv[0]); + //app.setApplicationName(argv[0]); if (startRepl || startJsonListener) { if (startRepl) { @@ -71,26 +72,29 @@ int main(int argc, char *argv[]) return 1; } - QString line = f.readLine().trimmed(); + QString line = f.readLine(); while (!line.isEmpty()) { - if (line.isEmpty() || line.startsWith('#')) { - line = f.readLine().trimmed(); - continue; + line = line.trimmed(); + + if (!line.isEmpty() && !line.startsWith('#')) { + SyntaxTree::self()->run(SyntaxTree::tokenize(line)); } - SyntaxTree::self()->run(SyntaxTree::tokenize(line)); - line = f.readLine().trimmed(); + + line = f.readLine(); } exit(0); } else if (!interactive) { QTextStream inputStream(stdin); - while (true) { - const QString input = inputStream.readLine(); - if (input.isEmpty()) { - ::exit(0); + + QString line = inputStream.readLine(); + while (!line.isEmpty()) { + line = line.trimmed(); + + if (!line.isEmpty() && !line.startsWith('#')) { + SyntaxTree::self()->run(SyntaxTree::tokenize(line)); } - const QStringList commands = SyntaxTree::tokenize(input); - SyntaxTree::self()->run(commands); + line = inputStream.readLine(); } } else { QStringList commands = app.arguments(); -- cgit v1.2.3 From cc5363fe4b0cd4ea95ac98d9d37f2028fe226145 Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Mon, 28 Dec 2015 22:00:19 +0100 Subject: typeCompleter and resourceOrTypeCompleter --- akonadish/akonadish_utils.cpp | 36 ++++++++++++++++++++++------- akonadish/akonadish_utils.h | 2 ++ akonadish/syntax_modules/akonadi_count.cpp | 2 +- akonadish/syntax_modules/akonadi_list.cpp | 7 +++--- akonadish/syntax_modules/akonadi_modify.cpp | 2 +- 5 files changed, 35 insertions(+), 14 deletions(-) (limited to 'akonadish') diff --git a/akonadish/akonadish_utils.cpp b/akonadish/akonadish_utils.cpp index 90847f6..070d788 100644 --- a/akonadish/akonadish_utils.cpp +++ b/akonadish/akonadish_utils.cpp @@ -25,10 +25,11 @@ namespace AkonadishUtils { +static QStringList s_types = QStringList() << "resource" << "folder" << "mail" << "event"; + bool isValidStoreType(const QString &type) { - static const QSet types = QSet() << "folder" << "mail" << "event" << "resource"; - return types.contains(type); + return s_types.contains(type); } StoreBase &getStore(const QString &type) @@ -97,23 +98,42 @@ QStringList resourceIds(State &state) return resources; } -QStringList resourceCompleter(const QStringList &commands, const QString &fragment, State &state) +QStringList filtered(const QStringList &list, const QString &fragment) { - QStringList resources = resourceIds(state); if (fragment.isEmpty()) { - return resources; + return list; } QStringList filtered; - for (auto resource: resources) { - if (resource.startsWith(fragment)) { - filtered << resource; + for (auto item: list) { + if (item.startsWith(fragment)) { + filtered << item; } } return filtered; } +QStringList resourceCompleter(const QStringList &, const QString &fragment, State &state) +{ + return filtered(resourceIds(state), fragment); +} + +QStringList resourceOrTypeCompleter(const QStringList &commands, const QString &fragment, State &state) +{ + static QStringList types = QStringList() << "resource" << "folder" << "mail" << "event"; + if (commands.count() == 1) { + return filtered(s_types, fragment); + } + + return filtered(resourceIds(state), fragment); +} + +QStringList typeCompleter(const QStringList &commands, const QString &fragment, State &state) +{ + return filtered(s_types, fragment); +} + QMap keyValueMapFromArgs(const QStringList &args) { //TODO: this is not the most clever of algorithms. preserved during the port of commands diff --git a/akonadish/akonadish_utils.h b/akonadish/akonadish_utils.h index 5671157..5dd24f1 100644 --- a/akonadish/akonadish_utils.h +++ b/akonadish/akonadish_utils.h @@ -38,6 +38,8 @@ StoreBase &getStore(const QString &type); QSharedPointer loadModel(const QString &type, Akonadi2::Query query); QStringList resourceIds(); QStringList resourceCompleter(const QStringList &, const QString &fragment, State &state); +QStringList resourceOrTypeCompleter(const QStringList &commands, const QString &fragment, State &state); +QStringList typeCompleter(const QStringList &commands, const QString &fragment, State &state); QMap keyValueMapFromArgs(const QStringList &args); /** diff --git a/akonadish/syntax_modules/akonadi_count.cpp b/akonadish/syntax_modules/akonadi_count.cpp index fa3f1fb..5acdcdd 100644 --- a/akonadish/syntax_modules/akonadi_count.cpp +++ b/akonadish/syntax_modules/akonadi_count.cpp @@ -75,7 +75,7 @@ bool count(const QStringList &args, State &state) Syntax::List syntax() { Syntax count("count", QObject::tr("Returns the number of items of a given type in a resource. Usage: count "), &AkonadiCount::count, Syntax::EventDriven); - count.completer = &AkonadishUtils::resourceCompleter; + count.completer = &AkonadishUtils::typeCompleter; return Syntax::List() << count; } diff --git a/akonadish/syntax_modules/akonadi_list.cpp b/akonadish/syntax_modules/akonadi_list.cpp index 18f15e7..82f13b5 100644 --- a/akonadish/syntax_modules/akonadi_list.cpp +++ b/akonadish/syntax_modules/akonadi_list.cpp @@ -106,10 +106,9 @@ bool list(const QStringList &args, State &state) Syntax::List syntax() { - Syntax::List syntax; - syntax << Syntax("list", QObject::tr("List all resources, or the contents of one or more resources"), &AkonadiList::list, Syntax::EventDriven); - - return syntax; + Syntax list("list", QObject::tr("List all resources, or the contents of one or more resources"), &AkonadiList::list, Syntax::EventDriven); + list.completer = &AkonadishUtils::resourceOrTypeCompleter; + return Syntax::List() << list; } REGISTER_SYNTAX(AkonadiList) diff --git a/akonadish/syntax_modules/akonadi_modify.cpp b/akonadish/syntax_modules/akonadi_modify.cpp index 8ab873a..76a7f5e 100644 --- a/akonadish/syntax_modules/akonadi_modify.cpp +++ b/akonadish/syntax_modules/akonadi_modify.cpp @@ -109,7 +109,7 @@ Syntax::List syntax() { Syntax modify("modify", QObject::tr("Modify items in a resource"), &AkonadiModify::modify); Syntax resource("resource", QObject::tr("Modify a resource"), &AkonadiModify::resource);//, Syntax::EventDriven); - resource.completer = &AkonadishUtils::resourceCompleter; + resource.completer = &AkonadishUtils::resourceOrTypeCompleter; modify.children << resource; return Syntax::List() << modify; -- cgit v1.2.3