summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--akonadish/akonadish_utils.cpp68
-rw-r--r--akonadish/akonadish_utils.h6
-rw-r--r--akonadish/main.cpp30
-rw-r--r--akonadish/repl/replStates.cpp2
-rw-r--r--akonadish/syntax_modules/akonadi_clear.cpp6
-rw-r--r--akonadish/syntax_modules/akonadi_count.cpp6
-rw-r--r--akonadish/syntax_modules/akonadi_list.cpp11
-rw-r--r--akonadish/syntax_modules/akonadi_modify.cpp9
-rw-r--r--akonadish/syntax_modules/akonadi_remove.cpp9
-rw-r--r--akonadish/syntax_modules/akonadi_stat.cpp6
-rw-r--r--akonadish/syntax_modules/akonadi_sync.cpp6
-rw-r--r--akonadish/syntax_modules/core_syntax.cpp2
-rw-r--r--akonadish/syntaxtree.cpp5
-rw-r--r--akonadish/syntaxtree.h4
14 files changed, 122 insertions, 48 deletions
diff --git a/akonadish/akonadish_utils.cpp b/akonadish/akonadish_utils.cpp
index ffbdcb3..070d788 100644
--- a/akonadish/akonadish_utils.cpp
+++ b/akonadish/akonadish_utils.cpp
@@ -25,10 +25,11 @@
25namespace AkonadishUtils 25namespace AkonadishUtils
26{ 26{
27 27
28static QStringList s_types = QStringList() << "resource" << "folder" << "mail" << "event";
29
28bool isValidStoreType(const QString &type) 30bool isValidStoreType(const QString &type)
29{ 31{
30 static const QSet<QString> types = QSet<QString>() << "folder" << "mail" << "event" << "resource"; 32 return s_types.contains(type);
31 return types.contains(type);
32} 33}
33 34
34StoreBase &getStore(const QString &type) 35StoreBase &getStore(const QString &type)
@@ -70,6 +71,69 @@ QSharedPointer<QAbstractItemModel> loadModel(const QString &type, Akonadi2::Quer
70 return model; 71 return model;
71} 72}
72 73
74QStringList resourceIds(State &state)
75{
76 QStringList resources;
77 Akonadi2::Query query;
78 query.syncOnDemand = false;
79 query.processAll = false;
80 query.liveQuery = false;
81 auto model = AkonadishUtils::loadModel("resource", query);
82
83 QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model, &resources] (const QModelIndex &index, int start, int end) mutable {
84 for (int i = start; i <= end; i++) {
85 auto object = model->data(model->index(i, 0, index), Akonadi2::Store::DomainObjectBaseRole).value<Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr>();
86 resources << object->identifier();
87 }
88 });
89
90 QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [model, state](const QModelIndex &, const QModelIndex &, const QVector<int> &roles) {
91 if (roles.contains(Akonadi2::Store::ChildrenFetchedRole)) {
92 state.commandFinished();
93 }
94 });
95
96 state.commandStarted();
97
98 return resources;
99}
100
101QStringList filtered(const QStringList &list, const QString &fragment)
102{
103 if (fragment.isEmpty()) {
104 return list;
105 }
106
107 QStringList filtered;
108 for (auto item: list) {
109 if (item.startsWith(fragment)) {
110 filtered << item;
111 }
112 }
113
114 return filtered;
115}
116
117QStringList resourceCompleter(const QStringList &, const QString &fragment, State &state)
118{
119 return filtered(resourceIds(state), fragment);
120}
121
122QStringList resourceOrTypeCompleter(const QStringList &commands, const QString &fragment, State &state)
123{
124 static QStringList types = QStringList() << "resource" << "folder" << "mail" << "event";
125 if (commands.count() == 1) {
126 return filtered(s_types, fragment);
127 }
128
129 return filtered(resourceIds(state), fragment);
130}
131
132QStringList typeCompleter(const QStringList &commands, const QString &fragment, State &state)
133{
134 return filtered(s_types, fragment);
135}
136
73QMap<QString, QString> keyValueMapFromArgs(const QStringList &args) 137QMap<QString, QString> keyValueMapFromArgs(const QStringList &args)
74{ 138{
75 //TODO: this is not the most clever of algorithms. preserved during the port of commands 139 //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..5dd24f1 100644
--- a/akonadish/akonadish_utils.h
+++ b/akonadish/akonadish_utils.h
@@ -26,6 +26,8 @@
26#include "common/query.h" 26#include "common/query.h"
27#include "common/clientapi.h" 27#include "common/clientapi.h"
28 28
29#include "state.h"
30
29namespace AkonadishUtils 31namespace AkonadishUtils
30{ 32{
31 33
@@ -34,6 +36,10 @@ class StoreBase;
34bool isValidStoreType(const QString &type); 36bool isValidStoreType(const QString &type);
35StoreBase &getStore(const QString &type); 37StoreBase &getStore(const QString &type);
36QSharedPointer<QAbstractItemModel> loadModel(const QString &type, Akonadi2::Query query); 38QSharedPointer<QAbstractItemModel> loadModel(const QString &type, Akonadi2::Query query);
39QStringList resourceIds();
40QStringList resourceCompleter(const QStringList &, const QString &fragment, State &state);
41QStringList resourceOrTypeCompleter(const QStringList &commands, const QString &fragment, State &state);
42QStringList typeCompleter(const QStringList &commands, const QString &fragment, State &state);
37QMap<QString, QString> keyValueMapFromArgs(const QStringList &args); 43QMap<QString, QString> keyValueMapFromArgs(const QStringList &args);
38 44
39/** 45/**
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[])
48 //qDebug() << "state at startup is" << interactive << startRepl << startJsonListener << fromScript; 48 //qDebug() << "state at startup is" << interactive << startRepl << startJsonListener << fromScript;
49 49
50 QCoreApplication app(argc, argv); 50 QCoreApplication app(argc, argv);
51 app.setApplicationName(argv[0]); 51 app.setApplicationName(fromScript ? "interactive-app-shell" : argv[0]);
52 //app.setApplicationName(argv[0]);
52 53
53 if (startRepl || startJsonListener) { 54 if (startRepl || startJsonListener) {
54 if (startRepl) { 55 if (startRepl) {
@@ -71,26 +72,29 @@ int main(int argc, char *argv[])
71 return 1; 72 return 1;
72 } 73 }
73 74
74 QString line = f.readLine().trimmed(); 75 QString line = f.readLine();
75 while (!line.isEmpty()) { 76 while (!line.isEmpty()) {
76 if (line.isEmpty() || line.startsWith('#')) { 77 line = line.trimmed();
77 line = f.readLine().trimmed(); 78
78 continue; 79 if (!line.isEmpty() && !line.startsWith('#')) {
80 SyntaxTree::self()->run(SyntaxTree::tokenize(line));
79 } 81 }
80 SyntaxTree::self()->run(SyntaxTree::tokenize(line)); 82
81 line = f.readLine().trimmed(); 83 line = f.readLine();
82 } 84 }
83 exit(0); 85 exit(0);
84 } else if (!interactive) { 86 } else if (!interactive) {
85 QTextStream inputStream(stdin); 87 QTextStream inputStream(stdin);
86 while (true) { 88
87 const QString input = inputStream.readLine(); 89 QString line = inputStream.readLine();
88 if (input.isEmpty()) { 90 while (!line.isEmpty()) {
89 ::exit(0); 91 line = line.trimmed();
92
93 if (!line.isEmpty() && !line.startsWith('#')) {
94 SyntaxTree::self()->run(SyntaxTree::tokenize(line));
90 } 95 }
91 96
92 const QStringList commands = SyntaxTree::tokenize(input); 97 line = inputStream.readLine();
93 SyntaxTree::self()->run(commands);
94 } 98 }
95 } else { 99 } else {
96 QStringList commands = app.arguments(); 100 QStringList commands = app.arguments();
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)
156 if (nearest.isEmpty()) { 156 if (nearest.isEmpty()) {
157 SyntaxTree::Command command = SyntaxTree::self()->match(tab_completion_full_state); 157 SyntaxTree::Command command = SyntaxTree::self()->match(tab_completion_full_state);
158 if (command.first && command.first->completer) { 158 if (command.first && command.first->completer) {
159 QStringList commandCompletions = command.first->completer(tab_completion_full_state, fragment); 159 QStringList commandCompletions = command.first->completer(tab_completion_full_state, fragment, SyntaxTree::self()->state());
160 if (commandCompletions.size() > state) { 160 if (commandCompletions.size() > state) {
161 return qstrdup(commandCompletions[state].toUtf8()); 161 return qstrdup(commandCompletions[state].toUtf8());
162 } 162 }
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)
50 50
51Syntax::List syntax() 51Syntax::List syntax()
52{ 52{
53 Syntax::List syntax; 53 Syntax clear("clear", QObject::tr("Clears the local cache of one or more resources (be careful!)"), &AkonadiClear::clear);
54 syntax << Syntax("clear", QObject::tr("Clears the local cache of one or more resources (be careful!)"), &AkonadiClear::clear); 54 clear.completer = &AkonadishUtils::resourceCompleter;
55 55
56 return syntax; 56 return Syntax::List() << clear;
57} 57}
58 58
59REGISTER_SYNTAX(AkonadiClear) 59REGISTER_SYNTAX(AkonadiClear)
diff --git a/akonadish/syntax_modules/akonadi_count.cpp b/akonadish/syntax_modules/akonadi_count.cpp
index cda7235..5acdcdd 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)
74 74
75Syntax::List syntax() 75Syntax::List syntax()
76{ 76{
77 Syntax::List syntax; 77 Syntax count("count", QObject::tr("Returns the number of items of a given type in a resource. Usage: count <type> <resource>"), &AkonadiCount::count, Syntax::EventDriven);
78 syntax << Syntax("count", QObject::tr("Returns the number of items of a given type in a resource. Usage: count <type> <resource>"), &AkonadiCount::count, Syntax::EventDriven); 78 count.completer = &AkonadishUtils::typeCompleter;
79 79
80 return syntax; 80 return Syntax::List() << count;
81} 81}
82 82
83REGISTER_SYNTAX(AkonadiCount) 83REGISTER_SYNTAX(AkonadiCount)
diff --git a/akonadish/syntax_modules/akonadi_list.cpp b/akonadish/syntax_modules/akonadi_list.cpp
index 807119c..82f13b5 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)
72 72
73 //qDebug() << "Listing"; 73 //qDebug() << "Listing";
74 int colSize = 38; //Necessary to display a complete UUID 74 int colSize = 38; //Necessary to display a complete UUID
75 state.print(" " + QObject::tr("Column") + " ");
76 state.print(QObject::tr("Resource").leftJustified(colSize, ' ', true) + 75 state.print(QObject::tr("Resource").leftJustified(colSize, ' ', true) +
77 QObject::tr("Identifier").leftJustified(colSize, ' ', true)); 76 QObject::tr("Identifier").leftJustified(colSize, ' ', true));
78 for (int i = 0; i < model->columnCount(QModelIndex()); i++) { 77 for (int i = 0; i < model->columnCount(QModelIndex()); i++) {
@@ -82,9 +81,8 @@ bool list(const QStringList &args, State &state)
82 81
83 QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model, colSize, state](const QModelIndex &index, int start, int end) { 82 QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model, colSize, state](const QModelIndex &index, int start, int end) {
84 for (int i = start; i <= end; i++) { 83 for (int i = start; i <= end; i++) {
85 state.print(" " + QObject::tr("Row %1").arg(QString::number(model->rowCount())).rightJustified(4, ' ') + ": ");
86 auto object = model->data(model->index(i, 0, index), Akonadi2::Store::DomainObjectBaseRole).value<Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr>(); 84 auto object = model->data(model->index(i, 0, index), Akonadi2::Store::DomainObjectBaseRole).value<Akonadi2::ApplicationDomain::ApplicationDomainType::Ptr>();
87 state.print(" " + object->resourceInstanceIdentifier().leftJustified(colSize, ' ', true)); 85 state.print(object->resourceInstanceIdentifier().leftJustified(colSize, ' ', true));
88 state.print(object->identifier().leftJustified(colSize, ' ', true)); 86 state.print(object->identifier().leftJustified(colSize, ' ', true));
89 for (int col = 0; col < model->columnCount(QModelIndex()); col++) { 87 for (int col = 0; col < model->columnCount(QModelIndex()); col++) {
90 state.print(" | " + model->data(model->index(i, col, index)).toString().leftJustified(colSize, ' ', true)); 88 state.print(" | " + model->data(model->index(i, col, index)).toString().leftJustified(colSize, ' ', true));
@@ -108,10 +106,9 @@ bool list(const QStringList &args, State &state)
108 106
109Syntax::List syntax() 107Syntax::List syntax()
110{ 108{
111 Syntax::List syntax; 109 Syntax list("list", QObject::tr("List all resources, or the contents of one or more resources"), &AkonadiList::list, Syntax::EventDriven);
112 syntax << Syntax("list", QObject::tr("List all resources, or the contents of one or more resources"), &AkonadiList::list, Syntax::EventDriven); 110 list.completer = &AkonadishUtils::resourceOrTypeCompleter;
113 111 return Syntax::List() << list;
114 return syntax;
115} 112}
116 113
117REGISTER_SYNTAX(AkonadiList) 114REGISTER_SYNTAX(AkonadiList)
diff --git a/akonadish/syntax_modules/akonadi_modify.cpp b/akonadish/syntax_modules/akonadi_modify.cpp
index 8438301..76a7f5e 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)
107 107
108Syntax::List syntax() 108Syntax::List syntax()
109{ 109{
110 Syntax::List syntax;
111
112 Syntax modify("modify", QObject::tr("Modify items in a resource"), &AkonadiModify::modify); 110 Syntax modify("modify", QObject::tr("Modify items in a resource"), &AkonadiModify::modify);
113 modify.children << Syntax("resource", QObject::tr("Modify a resource"), &AkonadiModify::resource);//, Syntax::EventDriven); 111 Syntax resource("resource", QObject::tr("Modify a resource"), &AkonadiModify::resource);//, Syntax::EventDriven);
112 resource.completer = &AkonadishUtils::resourceOrTypeCompleter;
113 modify.children << resource;
114 114
115 syntax << modify; 115 return Syntax::List() << modify;
116 return syntax;
117} 116}
118 117
119REGISTER_SYNTAX(AkonadiModify) 118REGISTER_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)
97 97
98Syntax::List syntax() 98Syntax::List syntax()
99{ 99{
100 Syntax::List syntax;
101
102 Syntax remove("remove", QObject::tr("Remove items in a resource"), &AkonadiRemove::remove); 100 Syntax remove("remove", QObject::tr("Remove items in a resource"), &AkonadiRemove::remove);
103 remove.children << Syntax("resource", QObject::tr("Removes a resource"), &AkonadiRemove::resource);//, Syntax::EventDriven); 101 Syntax resource("resource", QObject::tr("Removes a resource"), &AkonadiRemove::resource);//, Syntax::EventDriven);
102 resource.completer = &AkonadishUtils::resourceCompleter;
103 remove.children << resource;
104 104
105 syntax << remove; 105 return Syntax::List() << remove;
106 return syntax;
107} 106}
108 107
109REGISTER_SYNTAX(AkonadiRemove) 108REGISTER_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)
111 111
112Syntax::List syntax() 112Syntax::List syntax()
113{ 113{
114 Syntax::List syntax; 114 Syntax state("stat", QObject::tr("Shows database usage for the resources requested"), &AkonadiStat::stat, Syntax::EventDriven);
115 syntax << Syntax("stat", QObject::tr("Shows database usage for the resources requested"), &AkonadiStat::stat, Syntax::EventDriven); 115 state.completer = &AkonadishUtils::resourceCompleter;
116 116
117 return syntax; 117 return Syntax::List() << state;
118} 118}
119 119
120REGISTER_SYNTAX(AkonadiStat) 120REGISTER_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)
58 58
59Syntax::List syntax() 59Syntax::List syntax()
60{ 60{
61 Syntax::List syntax; 61 Syntax sync("sync", QObject::tr("Syncronizes all resources that are listed; and empty list triggers a syncronizaton on all resources"), &AkonadiSync::sync, Syntax::EventDriven );
62 syntax << Syntax("sync", QObject::tr("Syncronizes all resources that are listed; and empty list triggers a syncronizaton on all resources"), &AkonadiSync::sync, Syntax::EventDriven ); 62 sync.completer = &AkonadishUtils::resourceCompleter;
63 63
64 return syntax; 64 return Syntax::List() << sync;
65} 65}
66 66
67REGISTER_SYNTAX(AkonadiSync) 67REGISTER_SYNTAX(AkonadiSync)
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)
76 return true; 76 return true;
77} 77}
78 78
79QStringList showHelpCompleter(const QStringList &commands, const QString &fragment) 79QStringList showHelpCompleter(const QStringList &commands, const QString &fragment, State &)
80{ 80{
81 QStringList items; 81 QStringList items;
82 82
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 &
168 return matches; 168 return matches;
169} 169}
170 170
171State &SyntaxTree::state()
172{
173 return m_state;
174}
175
171QStringList SyntaxTree::tokenize(const QString &text) 176QStringList SyntaxTree::tokenize(const QString &text)
172{ 177{
173 //TODO: properly tokenize (e.g. "foo bar" should not become ['"foo', 'bar"']a 178 //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..468aad3 100644
--- a/akonadish/syntaxtree.h
+++ b/akonadish/syntaxtree.h
@@ -47,7 +47,7 @@ public:
47 QString help; 47 QString help;
48 Interactivity interactivity; 48 Interactivity interactivity;
49 std::function<bool(const QStringList &, State &)> lambda; 49 std::function<bool(const QStringList &, State &)> lambda;
50 std::function<QStringList(const QStringList &, const QString &)> completer; 50 std::function<QStringList(const QStringList &, const QString &, State &state)> completer;
51 51
52 QVector<Syntax> children; 52 QVector<Syntax> children;
53}; 53};
@@ -63,7 +63,7 @@ public:
63 Syntax::List syntax() const; 63 Syntax::List syntax() const;
64 Command match(const QStringList &commands) const; 64 Command match(const QStringList &commands) const;
65 Syntax::List nearestSyntax(const QStringList &words, const QString &fragment) const; 65 Syntax::List nearestSyntax(const QStringList &words, const QString &fragment) const;
66 66 State &state();
67 bool run(const QStringList &commands); 67 bool run(const QStringList &commands);
68 68
69 static QStringList tokenize(const QString &text); 69 static QStringList tokenize(const QString &text);