LLVM  14.0.0git
LineEditor.cpp
Go to the documentation of this file.
1 //===-- LineEditor.cpp - line editor --------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "llvm/ADT/SmallString.h"
11 #include "llvm/Config/config.h"
12 #include "llvm/Support/Path.h"
14 #include <algorithm>
15 #include <cassert>
16 #include <cstdio>
17 #ifdef HAVE_LIBEDIT
18 #include <histedit.h>
19 #endif
20 
21 using namespace llvm;
22 
24  SmallString<32> Path;
25  if (sys::path::home_directory(Path)) {
26  sys::path::append(Path, "." + ProgName + "-history");
27  return std::string(Path.str());
28  }
29  return std::string();
30 }
31 
32 LineEditor::CompleterConcept::~CompleterConcept() {}
33 LineEditor::ListCompleterConcept::~ListCompleterConcept() {}
34 
35 std::string LineEditor::ListCompleterConcept::getCommonPrefix(
36  const std::vector<Completion> &Comps) {
37  assert(!Comps.empty());
38 
39  std::string CommonPrefix = Comps[0].TypedText;
40  for (std::vector<Completion>::const_iterator I = Comps.begin() + 1,
41  E = Comps.end();
42  I != E; ++I) {
43  size_t Len = std::min(CommonPrefix.size(), I->TypedText.size());
44  size_t CommonLen = 0;
45  for (; CommonLen != Len; ++CommonLen) {
46  if (CommonPrefix[CommonLen] != I->TypedText[CommonLen])
47  break;
48  }
49  CommonPrefix.resize(CommonLen);
50  }
51  return CommonPrefix;
52 }
53 
55 LineEditor::ListCompleterConcept::complete(StringRef Buffer, size_t Pos) const {
56  CompletionAction Action;
57  std::vector<Completion> Comps = getCompletions(Buffer, Pos);
58  if (Comps.empty()) {
59  Action.Kind = CompletionAction::AK_ShowCompletions;
60  return Action;
61  }
62 
63  std::string CommonPrefix = getCommonPrefix(Comps);
64 
65  // If the common prefix is non-empty we can simply insert it. If there is a
66  // single completion, this will insert the full completion. If there is more
67  // than one, this might be enough information to jog the user's memory but if
68  // not the user can also hit tab again to see the completions because the
69  // common prefix will then be empty.
70  if (CommonPrefix.empty()) {
71  Action.Kind = CompletionAction::AK_ShowCompletions;
72  for (std::vector<Completion>::iterator I = Comps.begin(), E = Comps.end();
73  I != E; ++I)
74  Action.Completions.push_back(I->DisplayText);
75  } else {
76  Action.Kind = CompletionAction::AK_Insert;
77  Action.Text = CommonPrefix;
78  }
79 
80  return Action;
81 }
82 
84  size_t Pos) const {
85  if (!Completer) {
86  CompletionAction Action;
88  return Action;
89  }
90 
91  return Completer->complete(Buffer, Pos);
92 }
93 
94 #ifdef HAVE_LIBEDIT
95 
96 // libedit-based implementation.
97 
99  LineEditor *LE;
100 
101  History *Hist;
102  EditLine *EL;
103 
104  unsigned PrevCount;
105  std::string ContinuationOutput;
106 
107  FILE *Out;
108 };
109 
110 namespace {
111 
112 const char *ElGetPromptFn(EditLine *EL) {
114  if (el_get(EL, EL_CLIENTDATA, &Data) == 0)
115  return Data->LE->getPrompt().c_str();
116  return "> ";
117 }
118 
119 // Handles tab completion.
120 //
121 // This function is really horrible. But since the alternative is to get into
122 // the line editor business, here we are.
123 unsigned char ElCompletionFn(EditLine *EL, int ch) {
125  if (el_get(EL, EL_CLIENTDATA, &Data) == 0) {
126  if (!Data->ContinuationOutput.empty()) {
127  // This is the continuation of the AK_ShowCompletions branch below.
128  FILE *Out = Data->Out;
129 
130  // Print the required output (see below).
131  ::fwrite(Data->ContinuationOutput.c_str(),
132  Data->ContinuationOutput.size(), 1, Out);
133 
134  // Push a sequence of Ctrl-B characters to move the cursor back to its
135  // original position.
136  std::string Prevs(Data->PrevCount, '\02');
137  ::el_push(EL, const_cast<char *>(Prevs.c_str()));
138 
139  Data->ContinuationOutput.clear();
140 
141  return CC_REFRESH;
142  }
143 
144  const LineInfo *LI = ::el_line(EL);
145  LineEditor::CompletionAction Action = Data->LE->getCompletionAction(
146  StringRef(LI->buffer, LI->lastchar - LI->buffer),
147  LI->cursor - LI->buffer);
148  switch (Action.Kind) {
150  ::el_insertstr(EL, Action.Text.c_str());
151  return CC_REFRESH;
152 
154  if (Action.Completions.empty()) {
155  return CC_REFRESH_BEEP;
156  } else {
157  // Push a Ctrl-E and a tab. The Ctrl-E causes libedit to move the cursor
158  // to the end of the line, so that when we emit a newline we will be on
159  // a new blank line. The tab causes libedit to call this function again
160  // after moving the cursor. There doesn't seem to be anything we can do
161  // from here to cause libedit to move the cursor immediately. This will
162  // break horribly if the user has rebound their keys, so for now we do
163  // not permit user rebinding.
164  ::el_push(EL, const_cast<char *>("\05\t"));
165 
166  // This assembles the output for the continuation block above.
167  raw_string_ostream OS(Data->ContinuationOutput);
168 
169  // Move cursor to a blank line.
170  OS << "\n";
171 
172  // Emit the completions.
173  for (std::vector<std::string>::iterator I = Action.Completions.begin(),
174  E = Action.Completions.end();
175  I != E; ++I) {
176  OS << *I << "\n";
177  }
178 
179  // Fool libedit into thinking nothing has changed. Reprint its prompt
180  // and the user input. Note that the cursor will remain at the end of
181  // the line after this.
182  OS << Data->LE->getPrompt()
183  << StringRef(LI->buffer, LI->lastchar - LI->buffer);
184 
185  // This is the number of characters we need to tell libedit to go back:
186  // the distance between end of line and the original cursor position.
187  Data->PrevCount = LI->lastchar - LI->cursor;
188 
189  return CC_REFRESH;
190  }
191  }
192  }
193  return CC_ERROR;
194 }
195 
196 } // end anonymous namespace
197 
198 LineEditor::LineEditor(StringRef ProgName, StringRef HistoryPath, FILE *In,
199  FILE *Out, FILE *Err)
200  : Prompt((ProgName + "> ").str()), HistoryPath(std::string(HistoryPath)),
201  Data(new InternalData) {
202  if (HistoryPath.empty())
203  this->HistoryPath = getDefaultHistoryPath(ProgName);
204 
205  Data->LE = this;
206  Data->Out = Out;
207 
208  Data->Hist = ::history_init();
209  assert(Data->Hist);
210 
211  Data->EL = ::el_init(ProgName.str().c_str(), In, Out, Err);
212  assert(Data->EL);
213 
214  ::el_set(Data->EL, EL_PROMPT, ElGetPromptFn);
215  ::el_set(Data->EL, EL_EDITOR, "emacs");
216  ::el_set(Data->EL, EL_HIST, history, Data->Hist);
217  ::el_set(Data->EL, EL_ADDFN, "tab_complete", "Tab completion function",
218  ElCompletionFn);
219  ::el_set(Data->EL, EL_BIND, "\t", "tab_complete", NULL);
220  ::el_set(Data->EL, EL_BIND, "^r", "em-inc-search-prev",
221  NULL); // Cycle through backwards search, entering string
222  ::el_set(Data->EL, EL_BIND, "^w", "ed-delete-prev-word",
223  NULL); // Delete previous word, behave like bash does.
224  ::el_set(Data->EL, EL_BIND, "\033[3~", "ed-delete-next-char",
225  NULL); // Fix the delete key.
226  ::el_set(Data->EL, EL_CLIENTDATA, Data.get());
227 
228  HistEvent HE;
229  ::history(Data->Hist, &HE, H_SETSIZE, 800);
230  ::history(Data->Hist, &HE, H_SETUNIQUE, 1);
231  loadHistory();
232 }
233 
235  saveHistory();
236 
237  ::history_end(Data->Hist);
238  ::el_end(Data->EL);
239  ::fwrite("\n", 1, 1, Data->Out);
240 }
241 
243  if (!HistoryPath.empty()) {
244  HistEvent HE;
245  ::history(Data->Hist, &HE, H_SAVE, HistoryPath.c_str());
246  }
247 }
248 
250  if (!HistoryPath.empty()) {
251  HistEvent HE;
252  ::history(Data->Hist, &HE, H_LOAD, HistoryPath.c_str());
253  }
254 }
255 
257  // Call el_gets to prompt the user and read the user's input.
258  int LineLen = 0;
259  const char *Line = ::el_gets(Data->EL, &LineLen);
260 
261  // Either of these may mean end-of-file.
262  if (!Line || LineLen == 0)
263  return Optional<std::string>();
264 
265  // Strip any newlines off the end of the string.
266  while (LineLen > 0 &&
267  (Line[LineLen - 1] == '\n' || Line[LineLen - 1] == '\r'))
268  --LineLen;
269 
270  HistEvent HE;
271  if (LineLen > 0)
272  ::history(Data->Hist, &HE, H_ENTER, Line);
273 
274  return std::string(Line, LineLen);
275 }
276 
277 #else // HAVE_LIBEDIT
278 
279 // Simple fgets-based implementation.
280 
282  FILE *In;
283  FILE *Out;
284 };
285 
286 LineEditor::LineEditor(StringRef ProgName, StringRef HistoryPath, FILE *In,
287  FILE *Out, FILE *Err)
288  : Prompt((ProgName + "> ").str()), Data(new InternalData) {
289  Data->In = In;
290  Data->Out = Out;
291 }
292 
294  ::fwrite("\n", 1, 1, Data->Out);
295 }
296 
299 
301  ::fprintf(Data->Out, "%s", Prompt.c_str());
302 
303  std::string Line;
304  do {
305  char Buf[64];
306  char *Res = ::fgets(Buf, sizeof(Buf), Data->In);
307  if (!Res) {
308  if (Line.empty())
309  return Optional<std::string>();
310  else
311  return Line;
312  }
313  Line.append(Buf);
314  } while (Line.empty() ||
315  (Line[Line.size() - 1] != '\n' && Line[Line.size() - 1] != '\r'));
316 
317  while (!Line.empty() &&
318  (Line[Line.size() - 1] == '\n' || Line[Line.size() - 1] == '\r'))
319  Line.resize(Line.size() - 1);
320 
321  return Line;
322 }
323 
324 #endif // HAVE_LIBEDIT
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::StringRef::empty
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:152
llvm::sys::path::home_directory
bool home_directory(SmallVectorImpl< char > &result)
Get the user's home directory.
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:625
llvm::LineEditor::InternalData::In
FILE * In
Definition: LineEditor.cpp:282
Path.h
llvm::LineEditor::readLine
llvm::Optional< std::string > readLine() const
Reads a line.
Definition: LineEditor.cpp:300
llvm::LineEditor::InternalData::Out
FILE * Out
Definition: LineEditor.cpp:283
llvm::Optional< std::string >
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
new
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM ID Predecessors according to mbb< bb27, 0x8b0a7c0 > Note ADDri is not a two address instruction its result reg1037 is an operand of the PHI node in bb76 and its operand reg1039 is the result of the PHI node We should treat it as a two address code and make sure the ADDri is scheduled after any node that reads reg1039 Use info(i.e. register scavenger) to assign it a free register to allow reuse the collector could move the objects and invalidate the derived pointer This is bad enough in the first but safe points can crop up unpredictably **array_addr i32 n y store obj * new
Definition: README.txt:125
llvm::sys::path::append
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:456
llvm::LineEditor::CompletionAction::AK_Insert
@ AK_Insert
Insert Text at the cursor position.
Definition: LineEditor.h:51
SmallString.h
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::LineEditor
Definition: LineEditor.h:22
llvm::AArch64CC::LE
@ LE
Definition: AArch64BaseInfo.h:268
llvm::StringRef::str
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:244
llvm::LineEditor::CompletionAction::Kind
ActionKind Kind
Definition: LineEditor.h:56
llvm::LineEditor::getCompletionAction
CompletionAction getCompletionAction(StringRef Buffer, size_t Pos) const
Use the current completer to produce a CompletionAction for the given completion request.
Definition: LineEditor.cpp:83
llvm::SmallString< 32 >
llvm::tgtok::In
@ In
Definition: TGLexer.h:51
llvm::LineEditor::CompletionAction
The action to perform upon a completion request.
Definition: LineEditor.h:48
llvm::LineEditor::LineEditor
LineEditor(StringRef ProgName, StringRef HistoryPath="", FILE *In=stdin, FILE *Out=stdout, FILE *Err=stderr)
Create a LineEditor object.
Definition: LineEditor.cpp:286
llvm::LineEditor::CompletionAction::Text
std::string Text
The text to insert.
Definition: LineEditor.h:59
llvm::LineEditor::~LineEditor
~LineEditor()
Definition: LineEditor.cpp:293
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::LineEditor::InternalData
Definition: LineEditor.cpp:281
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LineEditor.h
llvm::LineEditor::saveHistory
void saveHistory()
Definition: LineEditor.cpp:297
llvm::LineEditor::loadHistory
void loadHistory()
Definition: LineEditor.cpp:298
llvm::min
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
Definition: FileCheck.cpp:357
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
std
Definition: BitVector.h:838
llvm::LineEditor::getDefaultHistoryPath
static std::string getDefaultHistoryPath(StringRef ProgName)
Definition: LineEditor.cpp:23
llvm::SmallString::str
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:259
llvm::LineEditor::CompletionAction::Completions
std::vector< std::string > Completions
The list of completions to show.
Definition: LineEditor.h:62
llvm::LineEditor::CompletionAction::AK_ShowCompletions
@ AK_ShowCompletions
Show Completions, or beep if the list is empty.
Definition: LineEditor.h:53
raw_ostream.h
SpecialSubKind::string
@ string