LLVM  3.7.0
LineEditor.cpp
Go to the documentation of this file.
1 //===-- LineEditor.cpp - line editor --------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/Config/config.h"
13 #include "llvm/Support/Path.h"
15 #include <stdio.h>
16 #ifdef HAVE_LIBEDIT
17 #include <histedit.h>
18 #endif
19 
20 using namespace llvm;
21 
23  SmallString<32> Path;
24  if (sys::path::home_directory(Path)) {
25  sys::path::append(Path, "." + ProgName + "-history");
26  return Path.str();
27  }
28  return std::string();
29 }
30 
31 LineEditor::CompleterConcept::~CompleterConcept() {}
32 LineEditor::ListCompleterConcept::~ListCompleterConcept() {}
33 
34 std::string LineEditor::ListCompleterConcept::getCommonPrefix(
35  const std::vector<Completion> &Comps) {
36  assert(!Comps.empty());
37 
38  std::string CommonPrefix = Comps[0].TypedText;
39  for (std::vector<Completion>::const_iterator I = Comps.begin() + 1,
40  E = Comps.end();
41  I != E; ++I) {
42  size_t Len = std::min(CommonPrefix.size(), I->TypedText.size());
43  size_t CommonLen = 0;
44  for (; CommonLen != Len; ++CommonLen) {
45  if (CommonPrefix[CommonLen] != I->TypedText[CommonLen])
46  break;
47  }
48  CommonPrefix.resize(CommonLen);
49  }
50  return CommonPrefix;
51 }
52 
54 LineEditor::ListCompleterConcept::complete(StringRef Buffer, size_t Pos) const {
55  CompletionAction Action;
56  std::vector<Completion> Comps = getCompletions(Buffer, Pos);
57  if (Comps.empty()) {
58  Action.Kind = CompletionAction::AK_ShowCompletions;
59  return Action;
60  }
61 
62  std::string CommonPrefix = getCommonPrefix(Comps);
63 
64  // If the common prefix is non-empty we can simply insert it. If there is a
65  // single completion, this will insert the full completion. If there is more
66  // than one, this might be enough information to jog the user's memory but if
67  // not the user can also hit tab again to see the completions because the
68  // common prefix will then be empty.
69  if (CommonPrefix.empty()) {
70  Action.Kind = CompletionAction::AK_ShowCompletions;
71  for (std::vector<Completion>::iterator I = Comps.begin(), E = Comps.end();
72  I != E; ++I)
73  Action.Completions.push_back(I->DisplayText);
74  } else {
75  Action.Kind = CompletionAction::AK_Insert;
76  Action.Text = CommonPrefix;
77  }
78 
79  return Action;
80 }
81 
83  size_t Pos) const {
84  if (!Completer) {
85  CompletionAction Action;
87  return Action;
88  }
89 
90  return Completer->complete(Buffer, Pos);
91 }
92 
93 #ifdef HAVE_LIBEDIT
94 
95 // libedit-based implementation.
96 
99 
100  History *Hist;
101  EditLine *EL;
102 
103  unsigned PrevCount;
104  std::string ContinuationOutput;
105 
106  FILE *Out;
107 };
108 
109 static const char *ElGetPromptFn(EditLine *EL) {
111  if (el_get(EL, EL_CLIENTDATA, &Data) == 0)
112  return Data->LE->getPrompt().c_str();
113  return "> ";
114 }
115 
116 // Handles tab completion.
117 //
118 // This function is really horrible. But since the alternative is to get into
119 // the line editor business, here we are.
120 static unsigned char ElCompletionFn(EditLine *EL, int ch) {
122  if (el_get(EL, EL_CLIENTDATA, &Data) == 0) {
123  if (!Data->ContinuationOutput.empty()) {
124  // This is the continuation of the AK_ShowCompletions branch below.
125  FILE *Out = Data->Out;
126 
127  // Print the required output (see below).
128  ::fwrite(Data->ContinuationOutput.c_str(),
129  Data->ContinuationOutput.size(), 1, Out);
130 
131  // Push a sequence of Ctrl-B characters to move the cursor back to its
132  // original position.
133  std::string Prevs(Data->PrevCount, '\02');
134  ::el_push(EL, const_cast<char *>(Prevs.c_str()));
135 
136  Data->ContinuationOutput.clear();
137 
138  return CC_REFRESH;
139  }
140 
141  const LineInfo *LI = ::el_line(EL);
143  StringRef(LI->buffer, LI->lastchar - LI->buffer),
144  LI->cursor - LI->buffer);
145  switch (Action.Kind) {
147  ::el_insertstr(EL, Action.Text.c_str());
148  return CC_REFRESH;
149 
151  if (Action.Completions.empty()) {
152  return CC_REFRESH_BEEP;
153  } else {
154  // Push a Ctrl-E and a tab. The Ctrl-E causes libedit to move the cursor
155  // to the end of the line, so that when we emit a newline we will be on
156  // a new blank line. The tab causes libedit to call this function again
157  // after moving the cursor. There doesn't seem to be anything we can do
158  // from here to cause libedit to move the cursor immediately. This will
159  // break horribly if the user has rebound their keys, so for now we do
160  // not permit user rebinding.
161  ::el_push(EL, const_cast<char *>("\05\t"));
162 
163  // This assembles the output for the continuation block above.
165 
166  // Move cursor to a blank line.
167  OS << "\n";
168 
169  // Emit the completions.
170  for (std::vector<std::string>::iterator I = Action.Completions.begin(),
171  E = Action.Completions.end();
172  I != E; ++I) {
173  OS << *I << "\n";
174  }
175 
176  // Fool libedit into thinking nothing has changed. Reprint its prompt
177  // and the user input. Note that the cursor will remain at the end of
178  // the line after this.
179  OS << Data->LE->getPrompt()
180  << StringRef(LI->buffer, LI->lastchar - LI->buffer);
181 
182  // This is the number of characters we need to tell libedit to go back:
183  // the distance between end of line and the original cursor position.
184  Data->PrevCount = LI->lastchar - LI->cursor;
185 
186  return CC_REFRESH;
187  }
188  }
189  }
190  return CC_ERROR;
191 }
192 
194  FILE *Out, FILE *Err)
195  : Prompt((ProgName + "> ").str()), HistoryPath(HistoryPath),
196  Data(new InternalData) {
197  if (HistoryPath.empty())
198  this->HistoryPath = getDefaultHistoryPath(ProgName);
199 
200  Data->LE = this;
201  Data->Out = Out;
202 
203  Data->Hist = ::history_init();
204  assert(Data->Hist);
205 
206  Data->EL = ::el_init(ProgName.str().c_str(), In, Out, Err);
207  assert(Data->EL);
208 
209  ::el_set(Data->EL, EL_PROMPT, ElGetPromptFn);
210  ::el_set(Data->EL, EL_EDITOR, "emacs");
211  ::el_set(Data->EL, EL_HIST, history, Data->Hist);
212  ::el_set(Data->EL, EL_ADDFN, "tab_complete", "Tab completion function",
214  ::el_set(Data->EL, EL_BIND, "\t", "tab_complete", NULL);
215  ::el_set(Data->EL, EL_BIND, "^r", "em-inc-search-prev",
216  NULL); // Cycle through backwards search, entering string
217  ::el_set(Data->EL, EL_BIND, "^w", "ed-delete-prev-word",
218  NULL); // Delete previous word, behave like bash does.
219  ::el_set(Data->EL, EL_BIND, "\033[3~", "ed-delete-next-char",
220  NULL); // Fix the delete key.
221  ::el_set(Data->EL, EL_CLIENTDATA, Data.get());
222 
223  HistEvent HE;
224  ::history(Data->Hist, &HE, H_SETSIZE, 800);
225  ::history(Data->Hist, &HE, H_SETUNIQUE, 1);
226  loadHistory();
227 }
228 
230  saveHistory();
231 
232  ::history_end(Data->Hist);
233  ::el_end(Data->EL);
234  ::fwrite("\n", 1, 1, Data->Out);
235 }
236 
238  if (!HistoryPath.empty()) {
239  HistEvent HE;
240  ::history(Data->Hist, &HE, H_SAVE, HistoryPath.c_str());
241  }
242 }
243 
245  if (!HistoryPath.empty()) {
246  HistEvent HE;
247  ::history(Data->Hist, &HE, H_LOAD, HistoryPath.c_str());
248  }
249 }
250 
252  // Call el_gets to prompt the user and read the user's input.
253  int LineLen = 0;
254  const char *Line = ::el_gets(Data->EL, &LineLen);
255 
256  // Either of these may mean end-of-file.
257  if (!Line || LineLen == 0)
258  return Optional<std::string>();
259 
260  // Strip any newlines off the end of the string.
261  while (LineLen > 0 &&
262  (Line[LineLen - 1] == '\n' || Line[LineLen - 1] == '\r'))
263  --LineLen;
264 
265  HistEvent HE;
266  if (LineLen > 0)
267  ::history(Data->Hist, &HE, H_ENTER, Line);
268 
269  return std::string(Line, LineLen);
270 }
271 
272 #else
273 
274 // Simple fgets-based implementation.
275 
277  FILE *In;
278  FILE *Out;
279 };
280 
282  FILE *Out, FILE *Err)
283  : Prompt((ProgName + "> ").str()), Data(new InternalData) {
284  Data->In = In;
285  Data->Out = Out;
286 }
287 
289  ::fwrite("\n", 1, 1, Data->Out);
290 }
291 
292 void LineEditor::saveHistory() {}
293 void LineEditor::loadHistory() {}
294 
296  ::fprintf(Data->Out, "%s", Prompt.c_str());
297 
298  std::string Line;
299  do {
300  char Buf[64];
301  char *Res = ::fgets(Buf, sizeof(Buf), Data->In);
302  if (!Res) {
303  if (Line.empty())
304  return Optional<std::string>();
305  else
306  return Line;
307  }
308  Line.append(Buf);
309  } while (Line.empty() ||
310  (Line[Line.size() - 1] != '\n' && Line[Line.size() - 1] != '\r'));
311 
312  while (!Line.empty() &&
313  (Line[Line.size() - 1] == '\n' || Line[Line.size() - 1] == '\r'))
314  Line.resize(Line.size() - 1);
315 
316  return Line;
317 }
318 
319 #endif
static const char * ProgName
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:188
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:443
llvm::Optional< std::string > readLine() const
Reads a line.
Definition: LineEditor.cpp:251
Number of individual test Apply this number of consecutive mutations to each input exit after the first new interesting input is found the minimized corpus is saved into the first input directory Number of jobs to run If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
static const char * ElGetPromptFn(EditLine *EL)
Definition: LineEditor.cpp:109
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:25
Insert Text at the cursor position.
Definition: LineEditor.h:51
LineEditor(StringRef ProgName, StringRef HistoryPath="", FILE *In=stdin, FILE *Out=stdout, FILE *Err=stderr)
Create a LineEditor object.
Definition: LineEditor.cpp:193
static std::string getDefaultHistoryPath(StringRef ProgName)
Definition: LineEditor.cpp:22
The action to perform upon a completion request.
Definition: LineEditor.h:48
CompletionAction getCompletionAction(StringRef Buffer, size_t Pos) const
Use the current completer to produce a CompletionAction for the given completion request.
Definition: LineEditor.cpp:82
Show Completions, or beep if the list is empty.
Definition: LineEditor.h:53
std::vector< std::string > Completions
The list of completions to show.
Definition: LineEditor.h:62
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:267
static unsigned char ElCompletionFn(EditLine *EL, int ch)
Definition: LineEditor.cpp:120
#define I(x, y, z)
Definition: MD5.cpp:54
std::string Text
The text to insert.
Definition: LineEditor.h:59
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:465
bool home_directory(SmallVectorImpl< char > &result)
Get the user's home directory.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
const std::string & getPrompt() const
Definition: LineEditor.h:105
bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:110