summaryrefslogtreecommitdiffstats
path: root/akonadi2_cli/syntaxtree.cpp
diff options
context:
space:
mode:
authorAaron Seigo <aseigo@kde.org>2015-12-23 16:43:45 +0100
committerAaron Seigo <aseigo@kde.org>2015-12-23 16:43:45 +0100
commit7e96145d27329ca3870f23d5b161785d10c9faf5 (patch)
tree46c5c673b9410341c817cc7fe6f93672718ec85d /akonadi2_cli/syntaxtree.cpp
parent8c78033ca7e59c44eb2886a3f8fe89c5b22ad114 (diff)
downloadsink-7e96145d27329ca3870f23d5b161785d10c9faf5.tar.gz
sink-7e96145d27329ca3870f23d5b161785d10c9faf5.zip
Module -> SyntaxTree
Diffstat (limited to 'akonadi2_cli/syntaxtree.cpp')
-rw-r--r--akonadi2_cli/syntaxtree.cpp165
1 files changed, 165 insertions, 0 deletions
diff --git a/akonadi2_cli/syntaxtree.cpp b/akonadi2_cli/syntaxtree.cpp
new file mode 100644
index 0000000..ea017db
--- /dev/null
+++ b/akonadi2_cli/syntaxtree.cpp
@@ -0,0 +1,165 @@
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
29SyntaxTree *SyntaxTree::s_module = 0;
30
31SyntaxTree::Syntax::Syntax()
32{
33}
34
35SyntaxTree::Syntax::Syntax(const QString &k, const QString &helpText, std::function<bool(const QStringList &, State &)> l, Interactivity inter)
36 : keyword(k),
37 help(helpText),
38 interactivity(inter),
39 lambda(l)
40{
41}
42
43SyntaxTree::SyntaxTree()
44{
45 QVector<std::function<SyntaxList()> > syntaxSyntaxTrees;
46 syntaxSyntaxTrees << &CoreSyntax::syntax;
47 for (auto syntaxSyntaxTree: syntaxSyntaxTrees) {
48 m_syntax += syntaxSyntaxTree();
49 }
50}
51
52SyntaxTree *SyntaxTree::self()
53{
54 if (!s_module) {
55 s_module = new SyntaxTree;
56 }
57
58 return s_module;
59}
60
61SyntaxTree::SyntaxList SyntaxTree::syntax() const
62{
63 return m_syntax;
64}
65
66bool SyntaxTree::run(const QStringList &commands)
67{
68 Command command = match(commands);
69 if (command.first && command.first->lambda) {
70 command.first->lambda(command.second, m_state);
71 if (command.first->interactivity == Syntax::EventDriven) {
72 return QCoreApplication::instance()->exec();
73 }
74
75 return true;
76 }
77
78 return false;
79}
80
81SyntaxTree::Command SyntaxTree::match(const QStringList &commandLine) const
82{
83 if (commandLine.isEmpty()) {
84 return Command();
85 }
86
87 QStringListIterator commandLineIt(commandLine);
88
89 QVectorIterator<Syntax> syntaxIt(m_syntax);
90 const Syntax *lastFullSyntax = 0;
91 QStringList tailCommands;
92 while (commandLineIt.hasNext() && syntaxIt.hasNext()) {
93 const QString word = commandLineIt.next();
94 while (syntaxIt.hasNext()) {
95 const Syntax &syntax = syntaxIt.next();
96 if (word == syntax.keyword) {
97 lastFullSyntax = &syntax;
98 syntaxIt = syntax.children;
99 }
100 }
101
102 if (!syntaxIt.hasNext()) {
103 break;
104 }
105 }
106
107 if (lastFullSyntax && lastFullSyntax->lambda) {
108 while (commandLineIt.hasNext()) {
109 tailCommands << commandLineIt.next();
110 }
111
112 return std::make_pair(lastFullSyntax, tailCommands);
113 }
114
115 return Command();
116}
117
118SyntaxTree::SyntaxList SyntaxTree::nearestSyntax(const QStringList &words, const QString &fragment) const
119{
120 SyntaxList matches;
121
122 //qDebug() << "words are" << words;
123 if (words.isEmpty()) {
124 for (const Syntax &syntax: m_syntax) {
125 if (syntax.keyword.startsWith(fragment)) {
126 matches.push_back(syntax);
127 }
128 }
129 } else {
130 QStringListIterator wordIt(words);
131 QVectorIterator<Syntax> syntaxIt(m_syntax);
132 Syntax lastFullSyntax;
133
134 while (wordIt.hasNext()) {
135 QString word = wordIt.next();
136 while (syntaxIt.hasNext()) {
137 const Syntax &syntax = syntaxIt.next();
138 if (word == syntax.keyword) {
139 lastFullSyntax = syntax;
140 syntaxIt = syntax.children;
141 }
142 }
143 }
144
145 //qDebug() << "exiting with" << lastFullSyntax.keyword << words.last();
146 if (lastFullSyntax.keyword == words.last()) {
147 syntaxIt = lastFullSyntax.children;
148 while (syntaxIt.hasNext()) {
149 Syntax syntax = syntaxIt.next();
150 if (fragment.isEmpty() || syntax.keyword.startsWith(fragment)) {
151 matches.push_back(syntax);
152 }
153 }
154 }
155 }
156
157 return matches;
158}
159
160QStringList SyntaxTree::tokenize(const QString &text)
161{
162 //TODO: properly tokenize (e.g. "foo bar" should not become ['"foo', 'bar"']
163 return text.split(" ");
164}
165