11 #include "llvm/Config/config.h"
27 return std::string(Path.str());
32 LineEditor::CompleterConcept::~CompleterConcept() =
default;
33 LineEditor::ListCompleterConcept::~ListCompleterConcept() =
default;
35 std::string LineEditor::ListCompleterConcept::getCommonPrefix(
36 const std::vector<Completion> &Comps) {
39 std::string CommonPrefix = Comps[0].TypedText;
40 for (std::vector<Completion>::const_iterator
I = Comps.begin() + 1,
43 size_t Len =
std::min(CommonPrefix.size(),
I->TypedText.size());
45 for (; CommonLen != Len; ++CommonLen) {
46 if (CommonPrefix[CommonLen] !=
I->TypedText[CommonLen])
49 CommonPrefix.resize(CommonLen);
55 LineEditor::ListCompleterConcept::complete(
StringRef Buffer,
size_t Pos)
const {
56 CompletionAction Action;
57 std::vector<Completion> Comps = getCompletions(Buffer, Pos);
59 Action.Kind = CompletionAction::AK_ShowCompletions;
63 std::string CommonPrefix = getCommonPrefix(Comps);
70 if (CommonPrefix.empty()) {
71 Action.Kind = CompletionAction::AK_ShowCompletions;
72 for (
const Completion &Comp : Comps)
73 Action.Completions.push_back(Comp.DisplayText);
75 Action.Kind = CompletionAction::AK_Insert;
76 Action.Text = CommonPrefix;
90 return Completer->complete(Buffer, Pos);
104 std::string ContinuationOutput;
111 const char *ElGetPromptFn(EditLine *EL) {
113 if (el_get(EL, EL_CLIENTDATA, &
Data) == 0)
114 return Data->LE->getPrompt().c_str();
122 unsigned char ElCompletionFn(EditLine *EL,
int ch) {
124 if (el_get(EL, EL_CLIENTDATA, &
Data) == 0) {
125 if (!
Data->ContinuationOutput.empty()) {
127 FILE *Out =
Data->Out;
130 ::fwrite(
Data->ContinuationOutput.c_str(),
131 Data->ContinuationOutput.size(), 1, Out);
135 std::string Prevs(
Data->PrevCount,
'\02');
136 ::el_push(EL,
const_cast<char *
>(Prevs.c_str()));
138 Data->ContinuationOutput.clear();
143 const LineInfo *LI = ::el_line(EL);
145 StringRef(LI->buffer, LI->lastchar - LI->buffer),
146 LI->cursor - LI->buffer);
147 switch (Action.
Kind) {
149 ::el_insertstr(EL, Action.
Text.c_str());
154 return CC_REFRESH_BEEP;
163 ::el_push(EL,
const_cast<char *
>(
"\05\t"));
172 for (std::vector<std::string>::iterator
I = Action.
Completions.begin(),
181 OS <<
Data->LE->getPrompt()
182 <<
StringRef(LI->buffer, LI->lastchar - LI->buffer);
186 Data->PrevCount = LI->lastchar - LI->cursor;
198 FILE *Out, FILE *Err)
199 : Prompt((ProgName +
"> ").str()), HistoryPath(
std::
string(HistoryPath)),
201 if (HistoryPath.
empty())
207 Data->Hist = ::history_init();
210 Data->EL = ::el_init(ProgName.
str().c_str(),
In, Out, Err);
213 ::el_set(
Data->EL, EL_PROMPT, ElGetPromptFn);
214 ::el_set(
Data->EL, EL_EDITOR,
"emacs");
215 ::el_set(
Data->EL, EL_HIST, history,
Data->Hist);
216 ::el_set(
Data->EL, EL_ADDFN,
"tab_complete",
"Tab completion function",
218 ::el_set(
Data->EL, EL_BIND,
"\t",
"tab_complete", NULL);
219 ::el_set(
Data->EL, EL_BIND,
"^r",
"em-inc-search-prev",
221 ::el_set(
Data->EL, EL_BIND,
"^w",
"ed-delete-prev-word",
223 ::el_set(
Data->EL, EL_BIND,
"\033[3~",
"ed-delete-next-char",
225 ::el_set(
Data->EL, EL_CLIENTDATA,
Data.get());
228 ::history(
Data->Hist, &HE, H_SETSIZE, 800);
229 ::history(
Data->Hist, &HE, H_SETUNIQUE, 1);
236 ::history_end(
Data->Hist);
238 ::fwrite(
"\n", 1, 1,
Data->Out);
242 if (!HistoryPath.
empty()) {
244 ::history(
Data->Hist, &HE, H_SAVE, HistoryPath.c_str());
249 if (!HistoryPath.
empty()) {
251 ::history(
Data->Hist, &HE, H_LOAD, HistoryPath.c_str());
258 const char *Line = ::el_gets(
Data->EL, &LineLen);
261 if (!Line || LineLen == 0)
265 while (LineLen > 0 &&
266 (Line[LineLen - 1] ==
'\n' || Line[LineLen - 1] ==
'\r'))
271 ::history(
Data->Hist, &HE, H_ENTER, Line);
273 return std::string(Line, LineLen);
276 #else // HAVE_LIBEDIT
286 FILE *Out, FILE *Err)
293 ::fwrite(
"\n", 1, 1,
Data->Out);
300 ::fprintf(
Data->Out,
"%s", Prompt.c_str());
305 char *Res = ::fgets(Buf,
sizeof(Buf),
Data->In);
313 }
while (Line.empty() ||
314 (Line[Line.size() - 1] !=
'\n' && Line[Line.size() - 1] !=
'\r'));
316 while (!Line.empty() &&
317 (Line[Line.size() - 1] ==
'\n' || Line[Line.size() - 1] ==
'\r'))
318 Line.resize(Line.size() - 1);
323 #endif // HAVE_LIBEDIT