summaryrefslogtreecommitdiffstats
path: root/akonadish/syntaxtree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'akonadish/syntaxtree.cpp')
-rw-r--r--akonadish/syntaxtree.cpp167
1 files changed, 167 insertions, 0 deletions
diff --git a/akonadish/syntaxtree.cpp b/akonadish/syntaxtree.cpp
new file mode 100644
index 0000000..0cd3e3f
--- /dev/null
+++ b/akonadish/syntaxtree.cpp
@@ -0,0 +1,167 @@
1/*
2 * Copyright (C) 2014 Aaron Seigo <aseigo@kde.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#include "syntaxtree.h"
21
22#include <QCoreApplication>
23#include <QDebug>
24
25// TODO: needs a proper registry; making "core" modules plugins is
26// almost certainly overkill, but this is not the way either
27#include "syntax_modules/core_syntax.h"
28#include "syntax_modules/akonadi_list.h"
29#include "syntax_modules/akonadi_count.h"
30
31SyntaxTree *SyntaxTree::s_module = 0;
32
33Syntax::Syntax()
34{
35}
36
37Syntax::Syntax(const QString &k, const QString &helpText, std::function<bool(const QStringList &, State &)> l, Interactivity inter)
38 : keyword(k),
39 help(helpText),
40 interactivity(inter),
41 lambda(l)
42{
43}
44
45SyntaxTree::SyntaxTree()
46{
47 QVector<std::function<Syntax::List()> > syntaxSyntaxTrees;
48 syntaxSyntaxTrees << &CoreSyntax::syntax
49 << &AkonadiList::syntax
50 << &AkonadiCount::syntax
51 ;
52 for (auto syntaxSyntaxTree: syntaxSyntaxTrees) {
53 m_syntax += syntaxSyntaxTree();
54 }
55}
56
57SyntaxTree *SyntaxTree::self()
58{
59 if (!s_module) {
60 s_module = new SyntaxTree;
61 }
62
63 return s_module;
64}
65
66Syntax::List SyntaxTree::syntax() const
67{
68 return m_syntax;
69}
70
71bool SyntaxTree::run(const QStringList &commands)
72{
73 Command command = match(commands);
74 if (command.first && command.first->lambda) {
75 bool rv = command.first->lambda(command.second, m_state);
76 if (rv && command.first->interactivity == Syntax::EventDriven) {
77 return m_state.commandStarted();
78 }
79
80 return rv;
81 }
82
83 return false;
84}
85
86SyntaxTree::Command SyntaxTree::match(const QStringList &commandLine) const
87{
88 if (commandLine.isEmpty()) {
89 return Command();
90 }
91
92 QStringListIterator commandLineIt(commandLine);
93
94 QVectorIterator<Syntax> syntaxIt(m_syntax);
95 const Syntax *lastFullSyntax = 0;
96 QStringList tailCommands;
97 while (commandLineIt.hasNext() && syntaxIt.hasNext()) {
98 const QString word = commandLineIt.next();
99 while (syntaxIt.hasNext()) {
100 const Syntax &syntax = syntaxIt.next();
101 if (word == syntax.keyword) {
102 lastFullSyntax = &syntax;
103 syntaxIt = syntax.children;
104 break;
105 }
106 }
107 }
108
109 if (lastFullSyntax) {
110 while (commandLineIt.hasNext()) {
111 tailCommands << commandLineIt.next();
112 }
113
114 return std::make_pair(lastFullSyntax, tailCommands);
115 }
116
117 return Command();
118}
119
120Syntax::List SyntaxTree::nearestSyntax(const QStringList &words, const QString &fragment) const
121{
122 Syntax::List matches;
123
124 //qDebug() << "words are" << words;
125 if (words.isEmpty()) {
126 for (const Syntax &syntax: m_syntax) {
127 if (syntax.keyword.startsWith(fragment)) {
128 matches.push_back(syntax);
129 }
130 }
131 } else {
132 QStringListIterator wordIt(words);
133 QVectorIterator<Syntax> syntaxIt(m_syntax);
134 Syntax lastFullSyntax;
135
136 while (wordIt.hasNext()) {
137 QString word = wordIt.next();
138 while (syntaxIt.hasNext()) {
139 const Syntax &syntax = syntaxIt.next();
140 if (word == syntax.keyword) {
141 lastFullSyntax = syntax;
142 syntaxIt = syntax.children;
143 }
144 }
145 }
146
147 //qDebug() << "exiting with" << lastFullSyntax.keyword << words.last();
148 if (lastFullSyntax.keyword == words.last()) {
149 syntaxIt = lastFullSyntax.children;
150 while (syntaxIt.hasNext()) {
151 Syntax syntax = syntaxIt.next();
152 if (fragment.isEmpty() || syntax.keyword.startsWith(fragment)) {
153 matches.push_back(syntax);
154 }
155 }
156 }
157 }
158
159 return matches;
160}
161
162QStringList SyntaxTree::tokenize(const QString &text)
163{
164 //TODO: properly tokenize (e.g. "foo bar" should not become ['"foo', 'bar"']
165 return text.split(" ");
166}
167