LLVM  15.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() = default;
33 LineEditor::ListCompleterConcept::~ListCompleterConcept() = default;
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 (const Completion &Comp : Comps)
73  Action.Completions.push_back(Comp.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 
98  LineEditor *LE;
99 
100  History *Hist;
101  EditLine *EL;
102 
103  unsigned PrevCount;
104  std::string ContinuationOutput;
105 
106  FILE *Out;
107 };
108 
109 namespace {
110 
111 const char *ElGetPromptFn(EditLine *EL) {
113  if (el_get(EL, EL_CLIENTDATA, &Data) == 0)
114  return Data->LE->getPrompt().c_str();
115  return "> ";
116 }
117 
118 // Handles tab completion.
119 //
120 // This function is really horrible. But since the alternative is to get into
121 // the line editor business, here we are.
122 unsigned char ElCompletionFn(EditLine *EL, int ch) {
124  if (el_get(EL, EL_CLIENTDATA, &Data) == 0) {
125  if (!Data->ContinuationOutput.empty()) {
126  // This is the continuation of the AK_ShowCompletions branch below.
127  FILE *Out = Data->Out;
128 
129  // Print the required output (see below).
130  ::fwrite(Data->ContinuationOutput.c_str(),
131  Data->ContinuationOutput.size(), 1, Out);
132 
133  // Push a sequence of Ctrl-B characters to move the cursor back to its
134  // original position.
135  std::string Prevs(Data->PrevCount, '\02');
136  ::el_push(EL, const_cast<char *>(Prevs.c_str()));
137 
138  Data->ContinuationOutput.clear();
139 
140  return CC_REFRESH;
141  }
142 
143  const LineInfo *LI = ::el_line(EL);
144  LineEditor::CompletionAction Action = Data->LE->getCompletionAction(
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());
150  return CC_REFRESH;
151 
153  if (Action.Completions.empty()) {
154  return CC_REFRESH_BEEP;
155  } else {
156  // Push a Ctrl-E and a tab. The Ctrl-E causes libedit to move the cursor
157  // to the end of the line, so that when we emit a newline we will be on
158  // a new blank line. The tab causes libedit to call this function again
159  // after moving the cursor. There doesn't seem to be anything we can do
160  // from here to cause libedit to move the cursor immediately. This will
161  // break horribly if the user has rebound their keys, so for now we do
162  // not permit user rebinding.
163  ::el_push(EL, const_cast<char *>("\05\t"));
164 
165  // This assembles the output for the continuation block above.
166  raw_string_ostream OS(Data->ContinuationOutput);
167 
168  // Move cursor to a blank line.
169  OS << "\n";
170 
171  // Emit the completions.
172  for (std::vector<std::string>::iterator I = Action.Completions.begin(),
173  E = Action.Completions.end();
174  I != E; ++I) {
175  OS << *I << "\n";
176  }
177 
178  // Fool libedit into thinking nothing has changed. Reprint its prompt
179  // and the user input. Note that the cursor will remain at the end of
180  // the line after this.
181  OS << Data->LE->getPrompt()
182  << StringRef(LI->buffer, LI->lastchar - LI->buffer);
183 
184  // This is the number of characters we need to tell libedit to go back:
185  // the distance between end of line and the original cursor position.
186  Data->PrevCount = LI->lastchar - LI->cursor;
187 
188  return CC_REFRESH;
189  }
190  }
191  }
192  return CC_ERROR;
193 }
194 
195 } // end anonymous namespace
196 
197 LineEditor::LineEditor(StringRef ProgName, StringRef HistoryPath, FILE *In,
198  FILE *Out, FILE *Err)
199  : Prompt((ProgName + "> ").str()), HistoryPath(std::string(HistoryPath)),
200  Data(new InternalData) {
201  if (HistoryPath.empty())
202  this->HistoryPath = getDefaultHistoryPath(ProgName);
203 
204  Data->LE = this;
205  Data->Out = Out;
206 
207  Data->Hist = ::history_init();
208  assert(Data->Hist);
209 
210  Data->EL = ::el_init(ProgName.str().c_str(), In, Out, Err);
211  assert(Data->EL);
212 
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",
217  ElCompletionFn);
218  ::el_set(Data->EL, EL_BIND, "\t", "tab_complete", NULL);
219  ::el_set(Data->EL, EL_BIND, "^r", "em-inc-search-prev",
220  NULL); // Cycle through backwards search, entering string
221  ::el_set(Data->EL, EL_BIND, "^w", "ed-delete-prev-word",
222  NULL); // Delete previous word, behave like bash does.
223  ::el_set(Data->EL, EL_BIND, "\033[3~", "ed-delete-next-char",
224  NULL); // Fix the delete key.
225  ::el_set(Data->EL, EL_CLIENTDATA, Data.get());
226 
227  HistEvent HE;
228  ::history(Data->Hist, &HE, H_SETSIZE, 800);
229  ::history(Data->Hist, &HE, H_SETUNIQUE, 1);
230  loadHistory();
231 }
232 
234  saveHistory();
235 
236  ::history_end(Data->Hist);
237  ::el_end(Data->EL);
238  ::fwrite("\n", 1, 1, Data->Out);
239 }
240 
242  if (!HistoryPath.empty()) {
243  HistEvent HE;
244  ::history(Data->Hist, &HE, H_SAVE, HistoryPath.c_str());
245  }
246 }
247 
249  if (!HistoryPath.empty()) {
250  HistEvent HE;
251  ::history(Data->Hist, &HE, H_LOAD, HistoryPath.c_str());
252  }
253 }
254 
256  // Call el_gets to prompt the user and read the user's input.
257  int LineLen = 0;
258  const char *Line = ::el_gets(Data->EL, &LineLen);
259 
260  // Either of these may mean end-of-file.
261  if (!Line || LineLen == 0)
262  return Optional<std::string>();
263 
264  // Strip any newlines off the end of the string.
265  while (LineLen > 0 &&
266  (Line[LineLen - 1] == '\n' || Line[LineLen - 1] == '\r'))
267  --LineLen;
268 
269  HistEvent HE;
270  if (LineLen > 0)
271  ::history(Data->Hist, &HE, H_ENTER, Line);
272 
273  return std::string(Line, LineLen);
274 }
275 
276 #else // HAVE_LIBEDIT
277 
278 // Simple fgets-based implementation.
279 
281  FILE *In;
282  FILE *Out;
283 };
284 
285 LineEditor::LineEditor(StringRef ProgName, StringRef HistoryPath, FILE *In,
286  FILE *Out, FILE *Err)
287  : Prompt((ProgName + "> ").str()), Data(new InternalData) {
288  Data->In = In;
289  Data->Out = Out;
290 }
291 
293  ::fwrite("\n", 1, 1, Data->Out);
294 }
295 
298 
300  ::fprintf(Data->Out, "%s", Prompt.c_str());
301 
302  std::string Line;
303  do {
304  char Buf[64];
305  char *Res = ::fgets(Buf, sizeof(Buf), Data->In);
306  if (!Res) {
307  if (Line.empty())
308  return Optional<std::string>();
309  else
310  return Line;
311  }
312  Line.append(Buf);
313  } while (Line.empty() ||
314  (Line[Line.size() - 1] != '\n' && Line[Line.size() - 1] != '\r'));
315 
316  while (!Line.empty() &&
317  (Line[Line.size() - 1] == '\n' || Line[Line.size() - 1] == '\r'))
318  Line.resize(Line.size() - 1);
319 
320  return Line;
321 }
322 
323 #endif // HAVE_LIBEDIT
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
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:632
llvm::LineEditor::InternalData::In
FILE * In
Definition: LineEditor.cpp:281
Path.h
llvm::LineEditor::readLine
llvm::Optional< std::string > readLine() const
Reads a line.
Definition: LineEditor.cpp:299
llvm::LineEditor::InternalData::Out
FILE * Out
Definition: LineEditor.cpp:282
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:245
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:82
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::StringRef::empty
constexpr LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:153
llvm::LineEditor::LineEditor
LineEditor(StringRef ProgName, StringRef HistoryPath="", FILE *In=stdin, FILE *Out=stdout, FILE *Err=stderr)
Create a LineEditor object.
Definition: LineEditor.cpp:285
llvm::LineEditor::CompletionAction::Text
std::string Text
The text to insert.
Definition: LineEditor.h:59
llvm::LineEditor::~LineEditor
~LineEditor()
Definition: LineEditor.cpp:292
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::LineEditor::InternalData
Definition: LineEditor.cpp:280
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LineEditor.h
llvm::LineEditor::saveHistory
void saveHistory()
Definition: LineEditor.cpp:296
llvm::LineEditor::loadHistory
void loadHistory()
Definition: LineEditor.cpp:297
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:58
std
Definition: BitVector.h:851
llvm::LineEditor::getDefaultHistoryPath
static std::string getDefaultHistoryPath(StringRef ProgName)
Definition: LineEditor.cpp:23
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