1212#include " cling/Interpreter/Exception.h"
1313#include " cling/MetaProcessor/MetaProcessor.h"
1414#include " cling/Utils/Output.h"
15- #include " textinput/Callbacks.h"
16- #include " textinput/History.h"
17- #include " textinput/StreamReader.h"
18- #include " textinput/TerminalDisplay.h"
19- #include " textinput/TextInput.h"
2015
2116#include " llvm/ADT/SmallString.h"
17+ #include " llvm/LineEditor/LineEditor.h"
2218#include " llvm/Support/ErrorHandling.h"
2319#include " llvm/Support/Path.h"
2420
@@ -30,44 +26,40 @@ namespace {
3026 // / to code complete through its own textinput mechanism which is part of the
3127 // / UserInterface.
3228 // /
33- class UITabCompletion : public textinput ::TabCompletion {
34- const cling::Interpreter& m_ParentInterpreter;
35-
36- public:
37- UITabCompletion (const cling::Interpreter& Parent) :
38- m_ParentInterpreter (Parent) {}
39- ~UITabCompletion () {}
40-
41- bool Complete (textinput::Text& Line /* in+out*/ ,
42- size_t & Cursor /* in+out*/ ,
43- textinput::EditorRange& R /* out*/ ,
44- std::vector<std::string>& Completions /* out*/ ) override {
45- m_ParentInterpreter.codeComplete (Line.GetText (), Cursor, Completions);
46- return true ;
47- }
48- };
4929
50- // /\brief Delays ~TextInput until after ~StreamReader and ~TerminalDisplay
51- // /
52- class TextInputHolder {
53- textinput::StreamReader* m_Reader;
54- textinput::TerminalDisplay* m_Display;
55- textinput::TextInput m_Input;
56-
57- public:
58- TextInputHolder (llvm::SmallString<512 >& Hist)
59- : m_Reader(textinput::StreamReader::Create()),
60- m_Display (textinput::TerminalDisplay::Create()),
61- m_Input(*m_Reader, *m_Display, Hist.empty() ? 0 : Hist.c_str()) {}
62-
63- ~TextInputHolder () {
64- delete m_Reader;
65- delete m_Display;
66- }
30+ struct ClingListCompleter {
31+ const cling::Interpreter& MainInterp;
32+
33+ ClingListCompleter (const cling::Interpreter& Interp) : MainInterp(Interp) {}
6734
68- textinput::TextInput* operator -> () { return &m_Input; }
35+ std::vector<llvm::LineEditor::Completion> operator ()(llvm::StringRef Buffer,
36+ size_t Pos) const ;
37+ std::vector<llvm::LineEditor::Completion>
38+ operator ()(llvm::StringRef Buffer, size_t Pos, llvm::Error& ErrRes) const ;
6939 };
7040
41+ std::vector<llvm::LineEditor::Completion>
42+ ClingListCompleter::operator ()(llvm::StringRef Buffer, size_t Pos) const {
43+ auto Err = llvm::Error::success ();
44+ auto res = (*this )(Buffer, Pos, Err);
45+ if (Err)
46+ llvm::logAllUnhandledErrors (std::move (Err), llvm::errs (), " error: " );
47+ return res;
48+ }
49+
50+ std::vector<llvm::LineEditor::Completion>
51+ ClingListCompleter::operator ()(llvm::StringRef Buffer, size_t Pos,
52+ llvm::Error& ErrRes) const {
53+ std::vector<llvm::LineEditor::Completion> Comps;
54+ std::vector<std::string> Results;
55+
56+ MainInterp.codeComplete (Buffer.str (), Pos, Results);
57+ for (auto c : Results) {
58+ Comps.push_back (llvm::LineEditor::Completion (c, c));
59+ }
60+ return Comps;
61+ }
62+
7163 llvm::SmallString<512 > GetHistoryFilePath () {
7264 if (std::getenv (" CLING_NOHISTORY" )) {
7365 return {};
@@ -123,42 +115,27 @@ namespace cling {
123115 }
124116
125117 auto histfilePath{GetHistoryFilePath ()};
126-
127- const auto Completion =
128- std::make_unique<UITabCompletion>(m_MetaProcessor->getInterpreter ());
129- TextInputHolder TI (histfilePath);
130-
131- TI->SetCompletion (Completion.get ());
118+ llvm::LineEditor LE (" cling" , histfilePath);
119+ std::string Input;
120+ std::string Prompt (" [cling]$ " );
132121
133122 if (const char * HistSizeEnvvar = std::getenv (" CLING_HISTSIZE" )) {
134123 const size_t HistSize = std::strtoull (HistSizeEnvvar, nullptr , 0 );
135124
136125 // std::strtoull() returns 0 if the parsing fails.
137126 // zero HistSize will disable history logging to file.
138- // refer to textinput::History::AppendToFile()
139- TI->SetHistoryMaxDepth (HistSize);
140- TI->SetHistoryPruneLength (
141- static_cast <size_t >(textinput::History::kPruneLengthDefault ));
127+ LE.setHistorySize (HistSize);
142128 }
143129
144- bool Done = false ;
145- std::string Line;
146- std::string Prompt (" [cling]$ " );
130+ LE.setPrompt (Prompt);
147131
148- while (!Done) {
132+ LE.setListCompleter (ClingListCompleter (m_MetaProcessor->getInterpreter ()));
133+ while (std::optional<std::string> Line = LE.readLine ()) {
149134 try {
150- m_MetaProcessor->getOuts ().flush ();
151- {
152- MetaProcessor::MaybeRedirectOutputRAII RAII (*m_MetaProcessor);
153- TI->SetPrompt (Prompt.c_str ());
154- Done = TI->ReadInput () == textinput::TextInput::kRREOF ;
155- TI->TakeInput (Line);
156- if (Done && Line.empty ())
157- break ;
158- }
135+ m_MetaProcessor->getOuts ().flush (); // Do we need this now?
159136
160137 cling::Interpreter::CompilationResult compRes;
161- const int indent = m_MetaProcessor->process (Line, compRes);
138+ const int indent = m_MetaProcessor->process (* Line, compRes);
162139
163140 // Quit requested?
164141 if (indent < 0 )
@@ -186,8 +163,10 @@ namespace cling {
186163 catch (...) {
187164 cling::errs () << " Exception occurred. Recovering...\n " ;
188165 }
166+
167+ LE.setPrompt (Prompt);
189168 }
190- m_MetaProcessor->getOuts ().flush ();
169+ m_MetaProcessor->getOuts ().flush (); // Do we need this now?
191170 }
192171
193172 void UserInterface::PrintLogo () {
0 commit comments