summaryrefslogtreecommitdiffstats
path: root/sinksh/repl/replStates.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2018-05-23 16:49:49 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2018-05-23 16:52:00 +0200
commit426392f71d5f45aad8c57969643fd6c365ce2362 (patch)
tree3e5b6ddfc395e26f1a931f9a97516ede9b7c68d3 /sinksh/repl/replStates.cpp
parent1ec240e3df3e9c8571c0df174b9f239b451dbf3a (diff)
downloadsink-426392f71d5f45aad8c57969643fd6c365ce2362.tar.gz
sink-426392f71d5f45aad8c57969643fd6c365ce2362.zip
Replaced readline with cpp-linenoise
... a single header readline replacement that works on all linux, osx and windows (or so they claim). Besides cleaning up the code considerably, it should help us build sinksh on windows where readline is not really (there are some ancient broken readline ports) available. cpp-readline comes from here: https://github.com/yhirose/cpp-linenoise
Diffstat (limited to 'sinksh/repl/replStates.cpp')
-rw-r--r--sinksh/repl/replStates.cpp68
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
33static char *sink_cli_next_tab_complete_match(const char *text, int state);
34static char ** sink_cli_tab_completion(const char *text, int start, int end);
35
36ReadState::ReadState(QState *parent) 31ReadState::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
43void ReadState::onEntry(QEvent *event) 54void 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
139static QStringList tab_completion_full_state;
140static bool tab_completion_at_root = false;
141
142static 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
149static 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