diff options
Diffstat (limited to 'sinksh/repl/replStates.cpp')
-rw-r--r-- | sinksh/repl/replStates.cpp | 68 |
1 files changed, 23 insertions, 45 deletions
diff --git a/sinksh/repl/replStates.cpp b/sinksh/repl/replStates.cpp index 18081df..c4b08b7 100644 --- a/sinksh/repl/replStates.cpp +++ b/sinksh/repl/replStates.cpp | |||
@@ -21,46 +21,54 @@ | |||
21 | 21 | ||
22 | #include <iostream> | 22 | #include <iostream> |
23 | 23 | ||
24 | #include <readline/readline.h> | ||
25 | #include <readline/history.h> | ||
26 | |||
27 | #include <QDebug> | 24 | #include <QDebug> |
28 | #include <QEvent> | 25 | #include <QEvent> |
29 | #include <QStateMachine> | 26 | #include <QStateMachine> |
27 | #include "linenoise.hpp" | ||
30 | 28 | ||
31 | #include "syntaxtree.h" | 29 | #include "syntaxtree.h" |
32 | 30 | ||
33 | static char *sink_cli_next_tab_complete_match(const char *text, int state); | ||
34 | static char ** sink_cli_tab_completion(const char *text, int start, int end); | ||
35 | |||
36 | ReadState::ReadState(QState *parent) | 31 | ReadState::ReadState(QState *parent) |
37 | : QState(parent) | 32 | : QState(parent) |
38 | { | 33 | { |
39 | rl_completion_entry_function = sink_cli_next_tab_complete_match; | 34 | linenoise::SetCompletionCallback([](const char* editBuffer, std::vector<std::string>& completions) { |
40 | rl_attempted_completion_function = sink_cli_tab_completion; | 35 | QStringList words = QString(editBuffer).split(" ", QString::SkipEmptyParts); |
36 | const QString fragment = words.takeLast(); | ||
37 | Syntax::List nearest = SyntaxTree::self()->nearestSyntax(words, fragment); | ||
38 | if (nearest.isEmpty()) { | ||
39 | SyntaxTree::Command command = SyntaxTree::self()->match(words); | ||
40 | if (command.first && command.first->completer) { | ||
41 | QStringList commandCompletions = command.first->completer(words, fragment, SyntaxTree::self()->state()); | ||
42 | for (const auto &c : commandCompletions) { | ||
43 | completions.push_back(c.toStdString()); | ||
44 | } | ||
45 | } | ||
46 | } else { | ||
47 | for (const auto &n : nearest) { | ||
48 | completions.push_back(n.keyword.toStdString()); | ||
49 | } | ||
50 | } | ||
51 | }); | ||
41 | } | 52 | } |
42 | 53 | ||
43 | void ReadState::onEntry(QEvent *event) | 54 | void ReadState::onEntry(QEvent *event) |
44 | { | 55 | { |
45 | Q_UNUSED(event) | 56 | Q_UNUSED(event) |
46 | char *line = readline(prompt()); | ||
47 | 57 | ||
48 | if (!line) { | 58 | std::string line; |
59 | if (linenoise::Readline(prompt(), line)) { | ||
49 | std::cout << std::endl; | 60 | std::cout << std::endl; |
50 | emit exitRequested(); | 61 | emit exitRequested(); |
51 | return; | 62 | return; |
52 | } | 63 | } |
53 | 64 | ||
54 | // we have actual data, so let's wait for a full line of text | 65 | // we have actual data, so let's wait for a full line of text |
55 | QByteArray input(line); | 66 | const QString text = QString::fromStdString(line).simplified(); |
56 | const QString text = QString(line).simplified(); | ||
57 | //qDebug() << "Line is ... " << text; | ||
58 | 67 | ||
59 | if (text.length() > 0) { | 68 | if (text.length() > 0) { |
60 | add_history(line); | 69 | linenoise::AddHistory(line.c_str()); |
61 | } | 70 | } |
62 | 71 | ||
63 | free(line); | ||
64 | emit command(text); | 72 | emit command(text); |
65 | } | 73 | } |
66 | 74 | ||
@@ -136,36 +144,6 @@ void PrintState::onEntry(QEvent *event) | |||
136 | emit completed(); | 144 | emit completed(); |
137 | } | 145 | } |
138 | 146 | ||
139 | static QStringList tab_completion_full_state; | ||
140 | static bool tab_completion_at_root = false; | ||
141 | |||
142 | static char **sink_cli_tab_completion(const char *text, int start, int end) | ||
143 | { | ||
144 | tab_completion_at_root = start == 0; | ||
145 | tab_completion_full_state = QString(rl_line_buffer).remove(start, end - start).split(" ", QString::SkipEmptyParts); | ||
146 | return NULL; | ||
147 | } | ||
148 | |||
149 | static char *sink_cli_next_tab_complete_match(const char *text, int state) | ||
150 | { | ||
151 | const QString fragment(text); | ||
152 | Syntax::List nearest = SyntaxTree::self()->nearestSyntax(tab_completion_full_state, fragment); | ||
153 | //for (auto syntax: nearest) { qDebug() << "Nearest: " << syntax.keyword; } | ||
154 | |||
155 | if (nearest.isEmpty()) { | ||
156 | SyntaxTree::Command command = SyntaxTree::self()->match(tab_completion_full_state); | ||
157 | if (command.first && command.first->completer) { | ||
158 | QStringList commandCompletions = command.first->completer(tab_completion_full_state, fragment, SyntaxTree::self()->state()); | ||
159 | if (commandCompletions.size() > state) { | ||
160 | return qstrdup(commandCompletions[state].toUtf8()); | ||
161 | } | ||
162 | } | ||
163 | } else if (nearest.size() > state) { | ||
164 | return qstrdup(nearest[state].keyword.toUtf8()); | ||
165 | } | ||
166 | |||
167 | return rl_filename_completion_function(text, state); | ||
168 | } | ||
169 | 147 | ||
170 | //Ignore warning I don't know how to fix in a moc file | 148 | //Ignore warning I don't know how to fix in a moc file |
171 | #pragma clang diagnostic push | 149 | #pragma clang diagnostic push |