1 //===-- Editline.cpp ------------------------------------------------------===//
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 
9 #include <iomanip>
10 #include <limits.h>
11 
12 #include "lldb/Host/Editline.h"
13 
14 #include "lldb/Host/ConnectionFileDescriptor.h"
15 #include "lldb/Host/FileSystem.h"
16 #include "lldb/Host/Host.h"
17 #include "lldb/Utility/CompletionRequest.h"
18 #include "lldb/Utility/FileSpec.h"
19 #include "lldb/Utility/LLDBAssert.h"
20 #include "lldb/Utility/SelectHelper.h"
21 #include "lldb/Utility/Status.h"
22 #include "lldb/Utility/StreamString.h"
23 #include "lldb/Utility/StringList.h"
24 #include "lldb/Utility/Timeout.h"
25 
26 #include "llvm/Support/FileSystem.h"
27 #include "llvm/Support/Threading.h"
28 
29 using namespace lldb_private;
30 using namespace lldb_private::line_editor;
31 
32 // Workaround for what looks like an OS X-specific issue, but other platforms
33 // may benefit from something similar if issues arise.  The libedit library
34 // doesn't explicitly initialize the curses termcap library, which it gets away
35 // with until TERM is set to VT100 where it stumbles over an implementation
36 // assumption that may not exist on other platforms.  The setupterm() function
37 // would normally require headers that don't work gracefully in this context,
38 // so the function declaration has been hoisted here.
39 #if defined(__APPLE__)
40 extern "C" {
41 int setupterm(char *term, int fildes, int *errret);
42 }
43 #define USE_SETUPTERM_WORKAROUND
44 #endif
45 
46 // Editline uses careful cursor management to achieve the illusion of editing a
47 // multi-line block of text with a single line editor.  Preserving this
48 // illusion requires fairly careful management of cursor state.  Read and
49 // understand the relationship between DisplayInput(), MoveCursor(),
50 // SetCurrentLine(), and SaveEditedLine() before making changes.
51 
52 /// https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
53 #define ESCAPE "\x1b"
54 /// Faint, decreased intensity or second colour.
55 #define ANSI_FAINT ESCAPE "[2m"
56 /// Normal colour or normal intensity (neither bold nor faint).
57 #define ANSI_UNFAINT ESCAPE "[0m"
58 #define ANSI_CLEAR_BELOW ESCAPE "[J"
59 #define ANSI_CLEAR_RIGHT ESCAPE "[K"
60 #define ANSI_SET_COLUMN_N ESCAPE "[%dG"
61 #define ANSI_UP_N_ROWS ESCAPE "[%dA"
62 #define ANSI_DOWN_N_ROWS ESCAPE "[%dB"
63 
64 #if LLDB_EDITLINE_USE_WCHAR
65 
66 #define EditLineConstString(str) L##str
67 #define EditLineStringFormatSpec "%ls"
68 
69 #else
70 
71 #define EditLineConstString(str) str
72 #define EditLineStringFormatSpec "%s"
73 
74 // use #defines so wide version functions and structs will resolve to old
75 // versions for case of libedit not built with wide char support
76 #define history_w history
77 #define history_winit history_init
78 #define history_wend history_end
79 #define HistoryW History
80 #define HistEventW HistEvent
81 #define LineInfoW LineInfo
82 
83 #define el_wgets el_gets
84 #define el_wgetc el_getc
85 #define el_wpush el_push
86 #define el_wparse el_parse
87 #define el_wset el_set
88 #define el_wget el_get
89 #define el_wline el_line
90 #define el_winsertstr el_insertstr
91 #define el_wdeletestr el_deletestr
92 
93 #endif // #if LLDB_EDITLINE_USE_WCHAR
94 
95 bool IsOnlySpaces(const EditLineStringType &content) {
96   for (wchar_t ch : content) {
97     if (ch != EditLineCharType(' '))
98       return false;
99   }
100   return true;
101 }
102 
103 static int GetOperation(HistoryOperation op) {
104   // The naming used by editline for the history operations is counter
105   // intuitive to how it's used in LLDB's editline implementation.
106   //
107   //  - The H_LAST returns the oldest entry in the history.
108   //
109   //  - The H_PREV operation returns the previous element in the history, which
110   //    is newer than the current one.
111   //
112   //  - The H_CURR returns the current entry in the history.
113   //
114   //  - The H_NEXT operation returns the next element in the history, which is
115   //    older than the current one.
116   //
117   //  - The H_FIRST returns the most recent entry in the history.
118   //
119   // The naming of the enum entries match the semantic meaning.
120   switch(op) {
121     case HistoryOperation::Oldest:
122       return H_LAST;
123     case HistoryOperation::Older:
124       return H_NEXT;
125     case HistoryOperation::Current:
126       return H_CURR;
127     case HistoryOperation::Newer:
128       return H_PREV;
129     case HistoryOperation::Newest:
130       return H_FIRST;
131   }
132   llvm_unreachable("Fully covered switch!");
133 }
134 
135 
136 EditLineStringType CombineLines(const std::vector<EditLineStringType> &lines) {
137   EditLineStringStreamType combined_stream;
138   for (EditLineStringType line : lines) {
139     combined_stream << line.c_str() << "\n";
140   }
141   return combined_stream.str();
142 }
143 
144 std::vector<EditLineStringType> SplitLines(const EditLineStringType &input) {
145   std::vector<EditLineStringType> result;
146   size_t start = 0;
147   while (start < input.length()) {
148     size_t end = input.find('\n', start);
149     if (end == std::string::npos) {
150       result.push_back(input.substr(start));
151       break;
152     }
153     result.push_back(input.substr(start, end - start));
154     start = end + 1;
155   }
156   return result;
157 }
158 
159 EditLineStringType FixIndentation(const EditLineStringType &line,
160                                   int indent_correction) {
161   if (indent_correction == 0)
162     return line;
163   if (indent_correction < 0)
164     return line.substr(-indent_correction);
165   return EditLineStringType(indent_correction, EditLineCharType(' ')) + line;
166 }
167 
168 int GetIndentation(const EditLineStringType &line) {
169   int space_count = 0;
170   for (EditLineCharType ch : line) {
171     if (ch != EditLineCharType(' '))
172       break;
173     ++space_count;
174   }
175   return space_count;
176 }
177 
178 bool IsInputPending(FILE *file) {
179   // FIXME: This will be broken on Windows if we ever re-enable Editline.  You
180   // can't use select
181   // on something that isn't a socket.  This will have to be re-written to not
182   // use a FILE*, but instead use some kind of yet-to-be-created abstraction
183   // that select-like functionality on non-socket objects.
184   const int fd = fileno(file);
185   SelectHelper select_helper;
186   select_helper.SetTimeout(std::chrono::microseconds(0));
187   select_helper.FDSetRead(fd);
188   return select_helper.Select().Success();
189 }
190 
191 namespace lldb_private {
192 namespace line_editor {
193 typedef std::weak_ptr<EditlineHistory> EditlineHistoryWP;
194 
195 // EditlineHistory objects are sometimes shared between multiple Editline
196 // instances with the same program name.
197 
198 class EditlineHistory {
199 private:
200   // Use static GetHistory() function to get a EditlineHistorySP to one of
201   // these objects
202   EditlineHistory(const std::string &prefix, uint32_t size, bool unique_entries)
203       : m_history(nullptr), m_event(), m_prefix(prefix), m_path() {
204     m_history = history_winit();
205     history_w(m_history, &m_event, H_SETSIZE, size);
206     if (unique_entries)
207       history_w(m_history, &m_event, H_SETUNIQUE, 1);
208   }
209 
210   const char *GetHistoryFilePath() {
211     // Compute the history path lazily.
212     if (m_path.empty() && m_history && !m_prefix.empty()) {
213       llvm::SmallString<128> lldb_history_file;
214       FileSystem::Instance().GetHomeDirectory(lldb_history_file);
215       llvm::sys::path::append(lldb_history_file, ".lldb");
216 
217       // LLDB stores its history in ~/.lldb/. If for some reason this directory
218       // isn't writable or cannot be created, history won't be available.
219       if (!llvm::sys::fs::create_directory(lldb_history_file)) {
220 #if LLDB_EDITLINE_USE_WCHAR
221         std::string filename = m_prefix + "-widehistory";
222 #else
223         std::string filename = m_prefix + "-history";
224 #endif
225         llvm::sys::path::append(lldb_history_file, filename);
226         m_path = std::string(lldb_history_file.str());
227       }
228     }
229 
230     if (m_path.empty())
231       return nullptr;
232 
233     return m_path.c_str();
234   }
235 
236 public:
237   ~EditlineHistory() {
238     Save();
239 
240     if (m_history) {
241       history_wend(m_history);
242       m_history = nullptr;
243     }
244   }
245 
246   static EditlineHistorySP GetHistory(const std::string &prefix) {
247     typedef std::map<std::string, EditlineHistoryWP> WeakHistoryMap;
248     static std::recursive_mutex g_mutex;
249     static WeakHistoryMap g_weak_map;
250     std::lock_guard<std::recursive_mutex> guard(g_mutex);
251     WeakHistoryMap::const_iterator pos = g_weak_map.find(prefix);
252     EditlineHistorySP history_sp;
253     if (pos != g_weak_map.end()) {
254       history_sp = pos->second.lock();
255       if (history_sp)
256         return history_sp;
257       g_weak_map.erase(pos);
258     }
259     history_sp.reset(new EditlineHistory(prefix, 800, true));
260     g_weak_map[prefix] = history_sp;
261     return history_sp;
262   }
263 
264   bool IsValid() const { return m_history != nullptr; }
265 
266   HistoryW *GetHistoryPtr() { return m_history; }
267 
268   void Enter(const EditLineCharType *line_cstr) {
269     if (m_history)
270       history_w(m_history, &m_event, H_ENTER, line_cstr);
271   }
272 
273   bool Load() {
274     if (m_history) {
275       const char *path = GetHistoryFilePath();
276       if (path) {
277         history_w(m_history, &m_event, H_LOAD, path);
278         return true;
279       }
280     }
281     return false;
282   }
283 
284   bool Save() {
285     if (m_history) {
286       const char *path = GetHistoryFilePath();
287       if (path) {
288         history_w(m_history, &m_event, H_SAVE, path);
289         return true;
290       }
291     }
292     return false;
293   }
294 
295 protected:
296   HistoryW *m_history; // The history object
297   HistEventW m_event;  // The history event needed to contain all history events
298   std::string m_prefix; // The prefix name (usually the editline program name)
299                         // to use when loading/saving history
300   std::string m_path;   // Path to the history file
301 };
302 }
303 }
304 
305 // Editline private methods
306 
307 void Editline::SetBaseLineNumber(int line_number) {
308   m_base_line_number = line_number;
309   m_line_number_digits =
310       std::max<int>(3, std::to_string(line_number).length() + 1);
311 }
312 
313 std::string Editline::PromptForIndex(int line_index) {
314   bool use_line_numbers = m_multiline_enabled && m_base_line_number > 0;
315   std::string prompt = m_set_prompt;
316   if (use_line_numbers && prompt.length() == 0)
317     prompt = ": ";
318   std::string continuation_prompt = prompt;
319   if (m_set_continuation_prompt.length() > 0) {
320     continuation_prompt = m_set_continuation_prompt;
321 
322     // Ensure that both prompts are the same length through space padding
323     while (continuation_prompt.length() < prompt.length()) {
324       continuation_prompt += ' ';
325     }
326     while (prompt.length() < continuation_prompt.length()) {
327       prompt += ' ';
328     }
329   }
330 
331   if (use_line_numbers) {
332     StreamString prompt_stream;
333     prompt_stream.Printf(
334         "%*d%s", m_line_number_digits, m_base_line_number + line_index,
335         (line_index == 0) ? prompt.c_str() : continuation_prompt.c_str());
336     return std::string(std::move(prompt_stream.GetString()));
337   }
338   return (line_index == 0) ? prompt : continuation_prompt;
339 }
340 
341 void Editline::SetCurrentLine(int line_index) {
342   m_current_line_index = line_index;
343   m_current_prompt = PromptForIndex(line_index);
344 }
345 
346 int Editline::GetPromptWidth() { return (int)PromptForIndex(0).length(); }
347 
348 bool Editline::IsEmacs() {
349   const char *editor;
350   el_get(m_editline, EL_EDITOR, &editor);
351   return editor[0] == 'e';
352 }
353 
354 bool Editline::IsOnlySpaces() {
355   const LineInfoW *info = el_wline(m_editline);
356   for (const EditLineCharType *character = info->buffer;
357        character < info->lastchar; character++) {
358     if (*character != ' ')
359       return false;
360   }
361   return true;
362 }
363 
364 int Editline::GetLineIndexForLocation(CursorLocation location, int cursor_row) {
365   int line = 0;
366   if (location == CursorLocation::EditingPrompt ||
367       location == CursorLocation::BlockEnd ||
368       location == CursorLocation::EditingCursor) {
369     for (unsigned index = 0; index < m_current_line_index; index++) {
370       line += CountRowsForLine(m_input_lines[index]);
371     }
372     if (location == CursorLocation::EditingCursor) {
373       line += cursor_row;
374     } else if (location == CursorLocation::BlockEnd) {
375       for (unsigned index = m_current_line_index; index < m_input_lines.size();
376            index++) {
377         line += CountRowsForLine(m_input_lines[index]);
378       }
379       --line;
380     }
381   }
382   return line;
383 }
384 
385 void Editline::MoveCursor(CursorLocation from, CursorLocation to) {
386   const LineInfoW *info = el_wline(m_editline);
387   int editline_cursor_position =
388       (int)((info->cursor - info->buffer) + GetPromptWidth());
389   int editline_cursor_row = editline_cursor_position / m_terminal_width;
390 
391   // Determine relative starting and ending lines
392   int fromLine = GetLineIndexForLocation(from, editline_cursor_row);
393   int toLine = GetLineIndexForLocation(to, editline_cursor_row);
394   if (toLine != fromLine) {
395     fprintf(m_output_file,
396             (toLine > fromLine) ? ANSI_DOWN_N_ROWS : ANSI_UP_N_ROWS,
397             std::abs(toLine - fromLine));
398   }
399 
400   // Determine target column
401   int toColumn = 1;
402   if (to == CursorLocation::EditingCursor) {
403     toColumn =
404         editline_cursor_position - (editline_cursor_row * m_terminal_width) + 1;
405   } else if (to == CursorLocation::BlockEnd && !m_input_lines.empty()) {
406     toColumn =
407         ((m_input_lines[m_input_lines.size() - 1].length() + GetPromptWidth()) %
408          80) +
409         1;
410   }
411   fprintf(m_output_file, ANSI_SET_COLUMN_N, toColumn);
412 }
413 
414 void Editline::DisplayInput(int firstIndex) {
415   fprintf(m_output_file, ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1);
416   int line_count = (int)m_input_lines.size();
417   const char *faint = m_color_prompts ? ANSI_FAINT : "";
418   const char *unfaint = m_color_prompts ? ANSI_UNFAINT : "";
419 
420   for (int index = firstIndex; index < line_count; index++) {
421     fprintf(m_output_file, "%s"
422                            "%s"
423                            "%s" EditLineStringFormatSpec " ",
424             faint, PromptForIndex(index).c_str(), unfaint,
425             m_input_lines[index].c_str());
426     if (index < line_count - 1)
427       fprintf(m_output_file, "\n");
428   }
429 }
430 
431 int Editline::CountRowsForLine(const EditLineStringType &content) {
432   std::string prompt =
433       PromptForIndex(0); // Prompt width is constant during an edit session
434   int line_length = (int)(content.length() + prompt.length());
435   return (line_length / m_terminal_width) + 1;
436 }
437 
438 void Editline::SaveEditedLine() {
439   const LineInfoW *info = el_wline(m_editline);
440   m_input_lines[m_current_line_index] =
441       EditLineStringType(info->buffer, info->lastchar - info->buffer);
442 }
443 
444 StringList Editline::GetInputAsStringList(int line_count) {
445   StringList lines;
446   for (EditLineStringType line : m_input_lines) {
447     if (line_count == 0)
448       break;
449 #if LLDB_EDITLINE_USE_WCHAR
450     lines.AppendString(m_utf8conv.to_bytes(line));
451 #else
452     lines.AppendString(line);
453 #endif
454     --line_count;
455   }
456   return lines;
457 }
458 
459 unsigned char Editline::RecallHistory(HistoryOperation op) {
460   assert(op == HistoryOperation::Older || op == HistoryOperation::Newer);
461   if (!m_history_sp || !m_history_sp->IsValid())
462     return CC_ERROR;
463 
464   HistoryW *pHistory = m_history_sp->GetHistoryPtr();
465   HistEventW history_event;
466   std::vector<EditLineStringType> new_input_lines;
467 
468   // Treat moving from the "live" entry differently
469   if (!m_in_history) {
470     switch (op) {
471     case HistoryOperation::Newer:
472       return CC_ERROR; // Can't go newer than the "live" entry
473     case HistoryOperation::Older: {
474       if (history_w(pHistory, &history_event,
475                     GetOperation(HistoryOperation::Newest)) == -1)
476         return CC_ERROR;
477       // Save any edits to the "live" entry in case we return by moving forward
478       // in history (it would be more bash-like to save over any current entry,
479       // but libedit doesn't offer the ability to add entries anywhere except
480       // the end.)
481       SaveEditedLine();
482       m_live_history_lines = m_input_lines;
483       m_in_history = true;
484     } break;
485     default:
486       llvm_unreachable("unsupported history direction");
487     }
488   } else {
489     if (history_w(pHistory, &history_event, GetOperation(op)) == -1) {
490       switch (op) {
491       case HistoryOperation::Older:
492         // Can't move earlier than the earliest entry.
493         return CC_ERROR;
494       case HistoryOperation::Newer:
495         // Moving to newer-than-the-newest entry yields the "live" entry.
496         new_input_lines = m_live_history_lines;
497         m_in_history = false;
498         break;
499       default:
500         llvm_unreachable("unsupported history direction");
501       }
502     }
503   }
504 
505   // If we're pulling the lines from history, split them apart
506   if (m_in_history)
507     new_input_lines = SplitLines(history_event.str);
508 
509   // Erase the current edit session and replace it with a new one
510   MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
511   m_input_lines = new_input_lines;
512   DisplayInput();
513 
514   // Prepare to edit the last line when moving to previous entry, or the first
515   // line when moving to next entry
516   switch (op) {
517   case HistoryOperation::Older:
518     m_current_line_index = (int)m_input_lines.size() - 1;
519     break;
520   case HistoryOperation::Newer:
521     m_current_line_index = 0;
522     break;
523   default:
524     llvm_unreachable("unsupported history direction");
525   }
526   SetCurrentLine(m_current_line_index);
527   MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
528   return CC_NEWLINE;
529 }
530 
531 int Editline::GetCharacter(EditLineGetCharType *c) {
532   const LineInfoW *info = el_wline(m_editline);
533 
534   // Paint a faint version of the desired prompt over the version libedit draws
535   // (will only be requested if colors are supported)
536   if (m_needs_prompt_repaint) {
537     MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
538     fprintf(m_output_file, "%s"
539                            "%s"
540                            "%s",
541             ANSI_FAINT, Prompt(), ANSI_UNFAINT);
542     MoveCursor(CursorLocation::EditingPrompt, CursorLocation::EditingCursor);
543     m_needs_prompt_repaint = false;
544   }
545 
546   if (m_multiline_enabled) {
547     // Detect when the number of rows used for this input line changes due to
548     // an edit
549     int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth());
550     int new_line_rows = (lineLength / m_terminal_width) + 1;
551     if (m_current_line_rows != -1 && new_line_rows != m_current_line_rows) {
552       // Respond by repainting the current state from this line on
553       MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
554       SaveEditedLine();
555       DisplayInput(m_current_line_index);
556       MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
557     }
558     m_current_line_rows = new_line_rows;
559   }
560 
561   // Read an actual character
562   while (true) {
563     lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
564     char ch = 0;
565 
566     if (m_terminal_size_has_changed)
567       ApplyTerminalSizeChange();
568 
569     // This mutex is locked by our caller (GetLine). Unlock it while we read a
570     // character (blocking operation), so we do not hold the mutex
571     // indefinitely. This gives a chance for someone to interrupt us. After
572     // Read returns, immediately lock the mutex again and check if we were
573     // interrupted.
574     m_output_mutex.unlock();
575     int read_count =
576         m_input_connection.Read(&ch, 1, llvm::None, status, nullptr);
577     m_output_mutex.lock();
578     if (m_editor_status == EditorStatus::Interrupted) {
579       while (read_count > 0 && status == lldb::eConnectionStatusSuccess)
580         read_count =
581             m_input_connection.Read(&ch, 1, llvm::None, status, nullptr);
582       lldbassert(status == lldb::eConnectionStatusInterrupted);
583       return 0;
584     }
585 
586     if (read_count) {
587       if (CompleteCharacter(ch, *c))
588         return 1;
589     } else {
590       switch (status) {
591       case lldb::eConnectionStatusSuccess: // Success
592         break;
593 
594       case lldb::eConnectionStatusInterrupted:
595         llvm_unreachable("Interrupts should have been handled above.");
596 
597       case lldb::eConnectionStatusError:        // Check GetError() for details
598       case lldb::eConnectionStatusTimedOut:     // Request timed out
599       case lldb::eConnectionStatusEndOfFile:    // End-of-file encountered
600       case lldb::eConnectionStatusNoConnection: // No connection
601       case lldb::eConnectionStatusLostConnection: // Lost connection while
602                                                   // connected to a valid
603                                                   // connection
604         m_editor_status = EditorStatus::EndOfInput;
605         return 0;
606       }
607     }
608   }
609 }
610 
611 const char *Editline::Prompt() {
612   if (m_color_prompts)
613     m_needs_prompt_repaint = true;
614   return m_current_prompt.c_str();
615 }
616 
617 unsigned char Editline::BreakLineCommand(int ch) {
618   // Preserve any content beyond the cursor, truncate and save the current line
619   const LineInfoW *info = el_wline(m_editline);
620   auto current_line =
621       EditLineStringType(info->buffer, info->cursor - info->buffer);
622   auto new_line_fragment =
623       EditLineStringType(info->cursor, info->lastchar - info->cursor);
624   m_input_lines[m_current_line_index] = current_line;
625 
626   // Ignore whitespace-only extra fragments when breaking a line
627   if (::IsOnlySpaces(new_line_fragment))
628     new_line_fragment = EditLineConstString("");
629 
630   // Establish the new cursor position at the start of a line when inserting a
631   // line break
632   m_revert_cursor_index = 0;
633 
634   // Don't perform automatic formatting when pasting
635   if (!IsInputPending(m_input_file)) {
636     // Apply smart indentation
637     if (m_fix_indentation_callback) {
638       StringList lines = GetInputAsStringList(m_current_line_index + 1);
639 #if LLDB_EDITLINE_USE_WCHAR
640       lines.AppendString(m_utf8conv.to_bytes(new_line_fragment));
641 #else
642       lines.AppendString(new_line_fragment);
643 #endif
644 
645       int indent_correction = m_fix_indentation_callback(this, lines, 0);
646       new_line_fragment = FixIndentation(new_line_fragment, indent_correction);
647       m_revert_cursor_index = GetIndentation(new_line_fragment);
648     }
649   }
650 
651   // Insert the new line and repaint everything from the split line on down
652   m_input_lines.insert(m_input_lines.begin() + m_current_line_index + 1,
653                        new_line_fragment);
654   MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
655   DisplayInput(m_current_line_index);
656 
657   // Reposition the cursor to the right line and prepare to edit the new line
658   SetCurrentLine(m_current_line_index + 1);
659   MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
660   return CC_NEWLINE;
661 }
662 
663 unsigned char Editline::EndOrAddLineCommand(int ch) {
664   // Don't perform end of input detection when pasting, always treat this as a
665   // line break
666   if (IsInputPending(m_input_file)) {
667     return BreakLineCommand(ch);
668   }
669 
670   // Save any edits to this line
671   SaveEditedLine();
672 
673   // If this is the end of the last line, consider whether to add a line
674   // instead
675   const LineInfoW *info = el_wline(m_editline);
676   if (m_current_line_index == m_input_lines.size() - 1 &&
677       info->cursor == info->lastchar) {
678     if (m_is_input_complete_callback) {
679       auto lines = GetInputAsStringList();
680       if (!m_is_input_complete_callback(this, lines)) {
681         return BreakLineCommand(ch);
682       }
683 
684       // The completion test is allowed to change the input lines when complete
685       m_input_lines.clear();
686       for (unsigned index = 0; index < lines.GetSize(); index++) {
687 #if LLDB_EDITLINE_USE_WCHAR
688         m_input_lines.insert(m_input_lines.end(),
689                              m_utf8conv.from_bytes(lines[index]));
690 #else
691         m_input_lines.insert(m_input_lines.end(), lines[index]);
692 #endif
693       }
694     }
695   }
696   MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd);
697   fprintf(m_output_file, "\n");
698   m_editor_status = EditorStatus::Complete;
699   return CC_NEWLINE;
700 }
701 
702 unsigned char Editline::DeleteNextCharCommand(int ch) {
703   LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline));
704 
705   // Just delete the next character normally if possible
706   if (info->cursor < info->lastchar) {
707     info->cursor++;
708     el_deletestr(m_editline, 1);
709     return CC_REFRESH;
710   }
711 
712   // Fail when at the end of the last line, except when ^D is pressed on the
713   // line is empty, in which case it is treated as EOF
714   if (m_current_line_index == m_input_lines.size() - 1) {
715     if (ch == 4 && info->buffer == info->lastchar) {
716       fprintf(m_output_file, "^D\n");
717       m_editor_status = EditorStatus::EndOfInput;
718       return CC_EOF;
719     }
720     return CC_ERROR;
721   }
722 
723   // Prepare to combine this line with the one below
724   MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
725 
726   // Insert the next line of text at the cursor and restore the cursor position
727   const EditLineCharType *cursor = info->cursor;
728   el_winsertstr(m_editline, m_input_lines[m_current_line_index + 1].c_str());
729   info->cursor = cursor;
730   SaveEditedLine();
731 
732   // Delete the extra line
733   m_input_lines.erase(m_input_lines.begin() + m_current_line_index + 1);
734 
735   // Clear and repaint from this line on down
736   DisplayInput(m_current_line_index);
737   MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
738   return CC_REFRESH;
739 }
740 
741 unsigned char Editline::DeletePreviousCharCommand(int ch) {
742   LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline));
743 
744   // Just delete the previous character normally when not at the start of a
745   // line
746   if (info->cursor > info->buffer) {
747     el_deletestr(m_editline, 1);
748     return CC_REFRESH;
749   }
750 
751   // No prior line and no prior character?  Let the user know
752   if (m_current_line_index == 0)
753     return CC_ERROR;
754 
755   // No prior character, but prior line?  Combine with the line above
756   SaveEditedLine();
757   SetCurrentLine(m_current_line_index - 1);
758   auto priorLine = m_input_lines[m_current_line_index];
759   m_input_lines.erase(m_input_lines.begin() + m_current_line_index);
760   m_input_lines[m_current_line_index] =
761       priorLine + m_input_lines[m_current_line_index];
762 
763   // Repaint from the new line down
764   fprintf(m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N,
765           CountRowsForLine(priorLine), 1);
766   DisplayInput(m_current_line_index);
767 
768   // Put the cursor back where libedit expects it to be before returning to
769   // editing by telling libedit about the newly inserted text
770   MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
771   el_winsertstr(m_editline, priorLine.c_str());
772   return CC_REDISPLAY;
773 }
774 
775 unsigned char Editline::PreviousLineCommand(int ch) {
776   SaveEditedLine();
777 
778   if (m_current_line_index == 0) {
779     return RecallHistory(HistoryOperation::Older);
780   }
781 
782   // Start from a known location
783   MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
784 
785   // Treat moving up from a blank last line as a deletion of that line
786   if (m_current_line_index == m_input_lines.size() - 1 && IsOnlySpaces()) {
787     m_input_lines.erase(m_input_lines.begin() + m_current_line_index);
788     fprintf(m_output_file, ANSI_CLEAR_BELOW);
789   }
790 
791   SetCurrentLine(m_current_line_index - 1);
792   fprintf(m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N,
793           CountRowsForLine(m_input_lines[m_current_line_index]), 1);
794   return CC_NEWLINE;
795 }
796 
797 unsigned char Editline::NextLineCommand(int ch) {
798   SaveEditedLine();
799 
800   // Handle attempts to move down from the last line
801   if (m_current_line_index == m_input_lines.size() - 1) {
802     // Don't add an extra line if the existing last line is blank, move through
803     // history instead
804     if (IsOnlySpaces()) {
805       return RecallHistory(HistoryOperation::Newer);
806     }
807 
808     // Determine indentation for the new line
809     int indentation = 0;
810     if (m_fix_indentation_callback) {
811       StringList lines = GetInputAsStringList();
812       lines.AppendString("");
813       indentation = m_fix_indentation_callback(this, lines, 0);
814     }
815     m_input_lines.insert(
816         m_input_lines.end(),
817         EditLineStringType(indentation, EditLineCharType(' ')));
818   }
819 
820   // Move down past the current line using newlines to force scrolling if
821   // needed
822   SetCurrentLine(m_current_line_index + 1);
823   const LineInfoW *info = el_wline(m_editline);
824   int cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth());
825   int cursor_row = cursor_position / m_terminal_width;
826   for (int line_count = 0; line_count < m_current_line_rows - cursor_row;
827        line_count++) {
828     fprintf(m_output_file, "\n");
829   }
830   return CC_NEWLINE;
831 }
832 
833 unsigned char Editline::PreviousHistoryCommand(int ch) {
834   SaveEditedLine();
835 
836   return RecallHistory(HistoryOperation::Older);
837 }
838 
839 unsigned char Editline::NextHistoryCommand(int ch) {
840   SaveEditedLine();
841 
842   return RecallHistory(HistoryOperation::Newer);
843 }
844 
845 unsigned char Editline::FixIndentationCommand(int ch) {
846   if (!m_fix_indentation_callback)
847     return CC_NORM;
848 
849   // Insert the character typed before proceeding
850   EditLineCharType inserted[] = {(EditLineCharType)ch, 0};
851   el_winsertstr(m_editline, inserted);
852   LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline));
853   int cursor_position = info->cursor - info->buffer;
854 
855   // Save the edits and determine the correct indentation level
856   SaveEditedLine();
857   StringList lines = GetInputAsStringList(m_current_line_index + 1);
858   int indent_correction =
859       m_fix_indentation_callback(this, lines, cursor_position);
860 
861   // If it is already correct no special work is needed
862   if (indent_correction == 0)
863     return CC_REFRESH;
864 
865   // Change the indentation level of the line
866   std::string currentLine = lines.GetStringAtIndex(m_current_line_index);
867   if (indent_correction > 0) {
868     currentLine = currentLine.insert(0, indent_correction, ' ');
869   } else {
870     currentLine = currentLine.erase(0, -indent_correction);
871   }
872 #if LLDB_EDITLINE_USE_WCHAR
873   m_input_lines[m_current_line_index] = m_utf8conv.from_bytes(currentLine);
874 #else
875   m_input_lines[m_current_line_index] = currentLine;
876 #endif
877 
878   // Update the display to reflect the change
879   MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
880   DisplayInput(m_current_line_index);
881 
882   // Reposition the cursor back on the original line and prepare to restart
883   // editing with a new cursor position
884   SetCurrentLine(m_current_line_index);
885   MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
886   m_revert_cursor_index = cursor_position + indent_correction;
887   return CC_NEWLINE;
888 }
889 
890 unsigned char Editline::RevertLineCommand(int ch) {
891   el_winsertstr(m_editline, m_input_lines[m_current_line_index].c_str());
892   if (m_revert_cursor_index >= 0) {
893     LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline));
894     info->cursor = info->buffer + m_revert_cursor_index;
895     if (info->cursor > info->lastchar) {
896       info->cursor = info->lastchar;
897     }
898     m_revert_cursor_index = -1;
899   }
900   return CC_REFRESH;
901 }
902 
903 unsigned char Editline::BufferStartCommand(int ch) {
904   SaveEditedLine();
905   MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
906   SetCurrentLine(0);
907   m_revert_cursor_index = 0;
908   return CC_NEWLINE;
909 }
910 
911 unsigned char Editline::BufferEndCommand(int ch) {
912   SaveEditedLine();
913   MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd);
914   SetCurrentLine((int)m_input_lines.size() - 1);
915   MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
916   return CC_NEWLINE;
917 }
918 
919 /// Prints completions and their descriptions to the given file. Only the
920 /// completions in the interval [start, end) are printed.
921 static void
922 PrintCompletion(FILE *output_file,
923                 llvm::ArrayRef<CompletionResult::Completion> results,
924                 size_t max_len) {
925   for (const CompletionResult::Completion &c : results) {
926     fprintf(output_file, "\t%-*s", (int)max_len, c.GetCompletion().c_str());
927     if (!c.GetDescription().empty())
928       fprintf(output_file, " -- %s", c.GetDescription().c_str());
929     fprintf(output_file, "\n");
930   }
931 }
932 
933 static void
934 DisplayCompletions(::EditLine *editline, FILE *output_file,
935                    llvm::ArrayRef<CompletionResult::Completion> results) {
936   assert(!results.empty());
937 
938   fprintf(output_file, "\n" ANSI_CLEAR_BELOW "Available completions:\n");
939   const size_t page_size = 40;
940   bool all = false;
941 
942   auto longest =
943       std::max_element(results.begin(), results.end(), [](auto &c1, auto &c2) {
944         return c1.GetCompletion().size() < c2.GetCompletion().size();
945       });
946 
947   const size_t max_len = longest->GetCompletion().size();
948 
949   if (results.size() < page_size) {
950     PrintCompletion(output_file, results, max_len);
951     return;
952   }
953 
954   size_t cur_pos = 0;
955   while (cur_pos < results.size()) {
956     size_t remaining = results.size() - cur_pos;
957     size_t next_size = all ? remaining : std::min(page_size, remaining);
958 
959     PrintCompletion(output_file, results.slice(cur_pos, next_size), max_len);
960 
961     cur_pos += next_size;
962 
963     if (cur_pos >= results.size())
964       break;
965 
966     fprintf(output_file, "More (Y/n/a): ");
967     char reply = 'n';
968     int got_char = el_getc(editline, &reply);
969     fprintf(output_file, "\n");
970     if (got_char == -1 || reply == 'n')
971       break;
972     if (reply == 'a')
973       all = true;
974   }
975 }
976 
977 unsigned char Editline::TabCommand(int ch) {
978   if (!m_completion_callback)
979     return CC_ERROR;
980 
981   const LineInfo *line_info = el_line(m_editline);
982 
983   llvm::StringRef line(line_info->buffer,
984                        line_info->lastchar - line_info->buffer);
985   unsigned cursor_index = line_info->cursor - line_info->buffer;
986   CompletionResult result;
987   CompletionRequest request(line, cursor_index, result);
988 
989   m_completion_callback(request);
990 
991   llvm::ArrayRef<CompletionResult::Completion> results = result.GetResults();
992 
993   StringList completions;
994   result.GetMatches(completions);
995 
996   if (results.size() == 0)
997     return CC_ERROR;
998 
999   if (results.size() == 1) {
1000     CompletionResult::Completion completion = results.front();
1001     switch (completion.GetMode()) {
1002     case CompletionMode::Normal: {
1003       std::string to_add = completion.GetCompletion();
1004       to_add = to_add.substr(request.GetCursorArgumentPrefix().size());
1005       // Terminate the current argument with a quote if it started with a quote.
1006       if (!request.GetParsedLine().empty() && request.GetParsedArg().IsQuoted())
1007         to_add.push_back(request.GetParsedArg().GetQuoteChar());
1008       to_add.push_back(' ');
1009       el_insertstr(m_editline, to_add.c_str());
1010       // Clear all the autosuggestion parts if the only single space can be completed.
1011       if (to_add == " ")
1012         return CC_REDISPLAY;
1013       return CC_REFRESH;
1014     }
1015     case CompletionMode::Partial: {
1016       std::string to_add = completion.GetCompletion();
1017       to_add = to_add.substr(request.GetCursorArgumentPrefix().size());
1018       el_insertstr(m_editline, to_add.c_str());
1019       break;
1020     }
1021     case CompletionMode::RewriteLine: {
1022       el_deletestr(m_editline, line_info->cursor - line_info->buffer);
1023       el_insertstr(m_editline, completion.GetCompletion().c_str());
1024       break;
1025     }
1026     }
1027     return CC_REDISPLAY;
1028   }
1029 
1030   // If we get a longer match display that first.
1031   std::string longest_prefix = completions.LongestCommonPrefix();
1032   if (!longest_prefix.empty())
1033     longest_prefix =
1034         longest_prefix.substr(request.GetCursorArgumentPrefix().size());
1035   if (!longest_prefix.empty()) {
1036     el_insertstr(m_editline, longest_prefix.c_str());
1037     return CC_REDISPLAY;
1038   }
1039 
1040   DisplayCompletions(m_editline, m_output_file, results);
1041 
1042   DisplayInput();
1043   MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
1044   return CC_REDISPLAY;
1045 }
1046 
1047 unsigned char Editline::ApplyAutosuggestCommand(int ch) {
1048   if (!m_suggestion_callback) {
1049     return CC_REDISPLAY;
1050   }
1051 
1052   const LineInfo *line_info = el_line(m_editline);
1053   llvm::StringRef line(line_info->buffer,
1054                        line_info->lastchar - line_info->buffer);
1055 
1056   if (llvm::Optional<std::string> to_add = m_suggestion_callback(line))
1057     el_insertstr(m_editline, to_add->c_str());
1058 
1059   return CC_REDISPLAY;
1060 }
1061 
1062 unsigned char Editline::TypedCharacter(int ch) {
1063   std::string typed = std::string(1, ch);
1064   el_insertstr(m_editline, typed.c_str());
1065 
1066   if (!m_suggestion_callback) {
1067     return CC_REDISPLAY;
1068   }
1069 
1070   const LineInfo *line_info = el_line(m_editline);
1071   llvm::StringRef line(line_info->buffer,
1072                        line_info->lastchar - line_info->buffer);
1073 
1074   if (llvm::Optional<std::string> to_add = m_suggestion_callback(line)) {
1075     std::string to_add_color = ANSI_FAINT + to_add.getValue() + ANSI_UNFAINT;
1076     fputs(typed.c_str(), m_output_file);
1077     fputs(to_add_color.c_str(), m_output_file);
1078     size_t new_autosuggestion_size = line.size() + to_add->length();
1079     // Print spaces to hide any remains of a previous longer autosuggestion.
1080     if (new_autosuggestion_size < m_previous_autosuggestion_size) {
1081       size_t spaces_to_print =
1082           m_previous_autosuggestion_size - new_autosuggestion_size;
1083       std::string spaces = std::string(spaces_to_print, ' ');
1084       fputs(spaces.c_str(), m_output_file);
1085     }
1086     m_previous_autosuggestion_size = new_autosuggestion_size;
1087 
1088     int editline_cursor_position =
1089         (int)((line_info->cursor - line_info->buffer) + GetPromptWidth());
1090     int editline_cursor_row = editline_cursor_position / m_terminal_width;
1091     int toColumn =
1092         editline_cursor_position - (editline_cursor_row * m_terminal_width);
1093     fprintf(m_output_file, ANSI_SET_COLUMN_N, toColumn);
1094     return CC_REFRESH;
1095   }
1096 
1097   return CC_REDISPLAY;
1098 }
1099 
1100 void Editline::ConfigureEditor(bool multiline) {
1101   if (m_editline && m_multiline_enabled == multiline)
1102     return;
1103   m_multiline_enabled = multiline;
1104 
1105   if (m_editline) {
1106     // Disable edit mode to stop the terminal from flushing all input during
1107     // the call to el_end() since we expect to have multiple editline instances
1108     // in this program.
1109     el_set(m_editline, EL_EDITMODE, 0);
1110     el_end(m_editline);
1111   }
1112 
1113   m_editline =
1114       el_init(m_editor_name.c_str(), m_input_file, m_output_file, m_error_file);
1115   ApplyTerminalSizeChange();
1116 
1117   if (m_history_sp && m_history_sp->IsValid()) {
1118     if (!m_history_sp->Load()) {
1119         fputs("Could not load history file\n.", m_output_file);
1120     }
1121     el_wset(m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr());
1122   }
1123   el_set(m_editline, EL_CLIENTDATA, this);
1124   el_set(m_editline, EL_SIGNAL, 0);
1125   el_set(m_editline, EL_EDITOR, "emacs");
1126   el_set(m_editline, EL_PROMPT,
1127          (EditlinePromptCallbackType)([](EditLine *editline) {
1128            return Editline::InstanceFor(editline)->Prompt();
1129          }));
1130 
1131   el_wset(m_editline, EL_GETCFN, (EditlineGetCharCallbackType)([](
1132                                      EditLine *editline, EditLineGetCharType *c) {
1133             return Editline::InstanceFor(editline)->GetCharacter(c);
1134           }));
1135 
1136   // Commands used for multiline support, registered whether or not they're
1137   // used
1138   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-break-line"),
1139           EditLineConstString("Insert a line break"),
1140           (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1141             return Editline::InstanceFor(editline)->BreakLineCommand(ch);
1142           }));
1143   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-end-or-add-line"),
1144           EditLineConstString("End editing or continue when incomplete"),
1145           (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1146             return Editline::InstanceFor(editline)->EndOrAddLineCommand(ch);
1147           }));
1148   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-delete-next-char"),
1149           EditLineConstString("Delete next character"),
1150           (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1151             return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch);
1152           }));
1153   el_wset(
1154       m_editline, EL_ADDFN, EditLineConstString("lldb-delete-previous-char"),
1155       EditLineConstString("Delete previous character"),
1156       (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1157         return Editline::InstanceFor(editline)->DeletePreviousCharCommand(ch);
1158       }));
1159   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-line"),
1160           EditLineConstString("Move to previous line"),
1161           (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1162             return Editline::InstanceFor(editline)->PreviousLineCommand(ch);
1163           }));
1164   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-line"),
1165           EditLineConstString("Move to next line"),
1166           (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1167             return Editline::InstanceFor(editline)->NextLineCommand(ch);
1168           }));
1169   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-history"),
1170           EditLineConstString("Move to previous history"),
1171           (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1172             return Editline::InstanceFor(editline)->PreviousHistoryCommand(ch);
1173           }));
1174   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-history"),
1175           EditLineConstString("Move to next history"),
1176           (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1177             return Editline::InstanceFor(editline)->NextHistoryCommand(ch);
1178           }));
1179   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-start"),
1180           EditLineConstString("Move to start of buffer"),
1181           (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1182             return Editline::InstanceFor(editline)->BufferStartCommand(ch);
1183           }));
1184   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-end"),
1185           EditLineConstString("Move to end of buffer"),
1186           (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1187             return Editline::InstanceFor(editline)->BufferEndCommand(ch);
1188           }));
1189   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-fix-indentation"),
1190           EditLineConstString("Fix line indentation"),
1191           (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1192             return Editline::InstanceFor(editline)->FixIndentationCommand(ch);
1193           }));
1194 
1195   // Register the complete callback under two names for compatibility with
1196   // older clients using custom .editrc files (largely because libedit has a
1197   // bad bug where if you have a bind command that tries to bind to a function
1198   // name that doesn't exist, it can corrupt the heap and crash your process
1199   // later.)
1200   EditlineCommandCallbackType complete_callback = [](EditLine *editline,
1201                                                      int ch) {
1202     return Editline::InstanceFor(editline)->TabCommand(ch);
1203   };
1204   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-complete"),
1205           EditLineConstString("Invoke completion"), complete_callback);
1206   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb_complete"),
1207           EditLineConstString("Invoke completion"), complete_callback);
1208 
1209   // General bindings we don't mind being overridden
1210   if (!multiline) {
1211     el_set(m_editline, EL_BIND, "^r", "em-inc-search-prev",
1212            NULL); // Cycle through backwards search, entering string
1213 
1214     if (m_suggestion_callback) {
1215       el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-apply-complete"),
1216               EditLineConstString("Adopt autocompletion"),
1217               (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1218                 return Editline::InstanceFor(editline)->ApplyAutosuggestCommand(
1219                     ch);
1220               }));
1221 
1222       el_set(m_editline, EL_BIND, "^f", "lldb-apply-complete",
1223              NULL); // Apply a part that is suggested automatically
1224 
1225       el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-typed-character"),
1226               EditLineConstString("Typed character"),
1227               (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1228                 return Editline::InstanceFor(editline)->TypedCharacter(ch);
1229               }));
1230 
1231       char bind_key[2] = {0, 0};
1232       llvm::StringRef ascii_chars =
1233           "abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXZY1234567890!\"#$%"
1234           "&'()*+,./:;<=>?@[]_`{|}~ ";
1235       for (char c : ascii_chars) {
1236         bind_key[0] = c;
1237         el_set(m_editline, EL_BIND, bind_key, "lldb-typed-character", NULL);
1238       }
1239       el_set(m_editline, EL_BIND, "\\-", "lldb-typed-character", NULL);
1240       el_set(m_editline, EL_BIND, "\\^", "lldb-typed-character", NULL);
1241       el_set(m_editline, EL_BIND, "\\\\", "lldb-typed-character", NULL);
1242     }
1243   }
1244 
1245   el_set(m_editline, EL_BIND, "^w", "ed-delete-prev-word",
1246          NULL); // Delete previous word, behave like bash in emacs mode
1247   el_set(m_editline, EL_BIND, "\t", "lldb-complete",
1248          NULL); // Bind TAB to auto complete
1249 
1250   // Allow ctrl-left-arrow and ctrl-right-arrow for navigation, behave like
1251   // bash in emacs mode.
1252   el_set(m_editline, EL_BIND, ESCAPE "[1;5C", "em-next-word", NULL);
1253   el_set(m_editline, EL_BIND, ESCAPE "[1;5D", "ed-prev-word", NULL);
1254   el_set(m_editline, EL_BIND, ESCAPE "[5C", "em-next-word", NULL);
1255   el_set(m_editline, EL_BIND, ESCAPE "[5D", "ed-prev-word", NULL);
1256   el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[C", "em-next-word", NULL);
1257   el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[D", "ed-prev-word", NULL);
1258 
1259   // Allow user-specific customization prior to registering bindings we
1260   // absolutely require
1261   el_source(m_editline, nullptr);
1262 
1263   // Register an internal binding that external developers shouldn't use
1264   el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-revert-line"),
1265           EditLineConstString("Revert line to saved state"),
1266           (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
1267             return Editline::InstanceFor(editline)->RevertLineCommand(ch);
1268           }));
1269 
1270   // Register keys that perform auto-indent correction
1271   if (m_fix_indentation_callback && m_fix_indentation_callback_chars) {
1272     char bind_key[2] = {0, 0};
1273     const char *indent_chars = m_fix_indentation_callback_chars;
1274     while (*indent_chars) {
1275       bind_key[0] = *indent_chars;
1276       el_set(m_editline, EL_BIND, bind_key, "lldb-fix-indentation", NULL);
1277       ++indent_chars;
1278     }
1279   }
1280 
1281   // Multi-line editor bindings
1282   if (multiline) {
1283     el_set(m_editline, EL_BIND, "\n", "lldb-end-or-add-line", NULL);
1284     el_set(m_editline, EL_BIND, "\r", "lldb-end-or-add-line", NULL);
1285     el_set(m_editline, EL_BIND, ESCAPE "\n", "lldb-break-line", NULL);
1286     el_set(m_editline, EL_BIND, ESCAPE "\r", "lldb-break-line", NULL);
1287     el_set(m_editline, EL_BIND, "^p", "lldb-previous-line", NULL);
1288     el_set(m_editline, EL_BIND, "^n", "lldb-next-line", NULL);
1289     el_set(m_editline, EL_BIND, "^?", "lldb-delete-previous-char", NULL);
1290     el_set(m_editline, EL_BIND, "^d", "lldb-delete-next-char", NULL);
1291     el_set(m_editline, EL_BIND, ESCAPE "[3~", "lldb-delete-next-char", NULL);
1292     el_set(m_editline, EL_BIND, ESCAPE "[\\^", "lldb-revert-line", NULL);
1293 
1294     // Editor-specific bindings
1295     if (IsEmacs()) {
1296       el_set(m_editline, EL_BIND, ESCAPE "<", "lldb-buffer-start", NULL);
1297       el_set(m_editline, EL_BIND, ESCAPE ">", "lldb-buffer-end", NULL);
1298       el_set(m_editline, EL_BIND, ESCAPE "[A", "lldb-previous-line", NULL);
1299       el_set(m_editline, EL_BIND, ESCAPE "[B", "lldb-next-line", NULL);
1300       el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[A", "lldb-previous-history",
1301              NULL);
1302       el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[B", "lldb-next-history",
1303              NULL);
1304       el_set(m_editline, EL_BIND, ESCAPE "[1;3A", "lldb-previous-history",
1305              NULL);
1306       el_set(m_editline, EL_BIND, ESCAPE "[1;3B", "lldb-next-history", NULL);
1307     } else {
1308       el_set(m_editline, EL_BIND, "^H", "lldb-delete-previous-char", NULL);
1309 
1310       el_set(m_editline, EL_BIND, "-a", ESCAPE "[A", "lldb-previous-line",
1311              NULL);
1312       el_set(m_editline, EL_BIND, "-a", ESCAPE "[B", "lldb-next-line", NULL);
1313       el_set(m_editline, EL_BIND, "-a", "x", "lldb-delete-next-char", NULL);
1314       el_set(m_editline, EL_BIND, "-a", "^H", "lldb-delete-previous-char",
1315              NULL);
1316       el_set(m_editline, EL_BIND, "-a", "^?", "lldb-delete-previous-char",
1317              NULL);
1318 
1319       // Escape is absorbed exiting edit mode, so re-register important
1320       // sequences without the prefix
1321       el_set(m_editline, EL_BIND, "-a", "[A", "lldb-previous-line", NULL);
1322       el_set(m_editline, EL_BIND, "-a", "[B", "lldb-next-line", NULL);
1323       el_set(m_editline, EL_BIND, "-a", "[\\^", "lldb-revert-line", NULL);
1324     }
1325   }
1326 }
1327 
1328 // Editline public methods
1329 
1330 Editline *Editline::InstanceFor(EditLine *editline) {
1331   Editline *editor;
1332   el_get(editline, EL_CLIENTDATA, &editor);
1333   return editor;
1334 }
1335 
1336 Editline::Editline(const char *editline_name, FILE *input_file,
1337                    FILE *output_file, FILE *error_file, bool color_prompts)
1338     : m_editor_status(EditorStatus::Complete), m_color_prompts(color_prompts),
1339       m_input_file(input_file), m_output_file(output_file),
1340       m_error_file(error_file), m_input_connection(fileno(input_file), false) {
1341   // Get a shared history instance
1342   m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name;
1343   m_history_sp = EditlineHistory::GetHistory(m_editor_name);
1344 
1345 #ifdef USE_SETUPTERM_WORKAROUND
1346   if (m_output_file) {
1347     const int term_fd = fileno(m_output_file);
1348     if (term_fd != -1) {
1349       static std::mutex *g_init_terminal_fds_mutex_ptr = nullptr;
1350       static std::set<int> *g_init_terminal_fds_ptr = nullptr;
1351       static llvm::once_flag g_once_flag;
1352       llvm::call_once(g_once_flag, [&]() {
1353         g_init_terminal_fds_mutex_ptr =
1354             new std::mutex(); // NOTE: Leak to avoid C++ destructor chain issues
1355         g_init_terminal_fds_ptr = new std::set<int>(); // NOTE: Leak to avoid
1356                                                        // C++ destructor chain
1357                                                        // issues
1358       });
1359 
1360       // We must make sure to initialize the terminal a given file descriptor
1361       // only once. If we do this multiple times, we start leaking memory.
1362       std::lock_guard<std::mutex> guard(*g_init_terminal_fds_mutex_ptr);
1363       if (g_init_terminal_fds_ptr->find(term_fd) ==
1364           g_init_terminal_fds_ptr->end()) {
1365         g_init_terminal_fds_ptr->insert(term_fd);
1366         setupterm((char *)0, term_fd, (int *)0);
1367       }
1368     }
1369   }
1370 #endif
1371 }
1372 
1373 Editline::~Editline() {
1374   if (m_editline) {
1375     // Disable edit mode to stop the terminal from flushing all input during
1376     // the call to el_end() since we expect to have multiple editline instances
1377     // in this program.
1378     el_set(m_editline, EL_EDITMODE, 0);
1379     el_end(m_editline);
1380     m_editline = nullptr;
1381   }
1382 
1383   // EditlineHistory objects are sometimes shared between multiple Editline
1384   // instances with the same program name. So just release our shared pointer
1385   // and if we are the last owner, it will save the history to the history save
1386   // file automatically.
1387   m_history_sp.reset();
1388 }
1389 
1390 void Editline::SetPrompt(const char *prompt) {
1391   m_set_prompt = prompt == nullptr ? "" : prompt;
1392 }
1393 
1394 void Editline::SetContinuationPrompt(const char *continuation_prompt) {
1395   m_set_continuation_prompt =
1396       continuation_prompt == nullptr ? "" : continuation_prompt;
1397 }
1398 
1399 void Editline::TerminalSizeChanged() { m_terminal_size_has_changed = 1; }
1400 
1401 void Editline::ApplyTerminalSizeChange() {
1402   if (!m_editline)
1403     return;
1404 
1405   m_terminal_size_has_changed = 0;
1406   el_resize(m_editline);
1407   int columns;
1408   // This function is documenting as taking (const char *, void *) for the
1409   // vararg part, but in reality in was consuming arguments until the first
1410   // null pointer. This was fixed in libedit in April 2019
1411   // <http://mail-index.netbsd.org/source-changes/2019/04/26/msg105454.html>,
1412   // but we're keeping the workaround until a version with that fix is more
1413   // widely available.
1414   if (el_get(m_editline, EL_GETTC, "co", &columns, nullptr) == 0) {
1415     m_terminal_width = columns;
1416     if (m_current_line_rows != -1) {
1417       const LineInfoW *info = el_wline(m_editline);
1418       int lineLength =
1419           (int)((info->lastchar - info->buffer) + GetPromptWidth());
1420       m_current_line_rows = (lineLength / columns) + 1;
1421     }
1422   } else {
1423     m_terminal_width = INT_MAX;
1424     m_current_line_rows = 1;
1425   }
1426 }
1427 
1428 const char *Editline::GetPrompt() { return m_set_prompt.c_str(); }
1429 
1430 uint32_t Editline::GetCurrentLine() { return m_current_line_index; }
1431 
1432 bool Editline::Interrupt() {
1433   bool result = true;
1434   std::lock_guard<std::mutex> guard(m_output_mutex);
1435   if (m_editor_status == EditorStatus::Editing) {
1436     fprintf(m_output_file, "^C\n");
1437     result = m_input_connection.InterruptRead();
1438   }
1439   m_editor_status = EditorStatus::Interrupted;
1440   return result;
1441 }
1442 
1443 bool Editline::Cancel() {
1444   bool result = true;
1445   std::lock_guard<std::mutex> guard(m_output_mutex);
1446   if (m_editor_status == EditorStatus::Editing) {
1447     MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
1448     fprintf(m_output_file, ANSI_CLEAR_BELOW);
1449     result = m_input_connection.InterruptRead();
1450   }
1451   m_editor_status = EditorStatus::Interrupted;
1452   return result;
1453 }
1454 
1455 bool Editline::GetLine(std::string &line, bool &interrupted) {
1456   ConfigureEditor(false);
1457   m_input_lines = std::vector<EditLineStringType>();
1458   m_input_lines.insert(m_input_lines.begin(), EditLineConstString(""));
1459 
1460   std::lock_guard<std::mutex> guard(m_output_mutex);
1461 
1462   lldbassert(m_editor_status != EditorStatus::Editing);
1463   if (m_editor_status == EditorStatus::Interrupted) {
1464     m_editor_status = EditorStatus::Complete;
1465     interrupted = true;
1466     return true;
1467   }
1468 
1469   SetCurrentLine(0);
1470   m_in_history = false;
1471   m_editor_status = EditorStatus::Editing;
1472   m_revert_cursor_index = -1;
1473 
1474   int count;
1475   auto input = el_wgets(m_editline, &count);
1476 
1477   interrupted = m_editor_status == EditorStatus::Interrupted;
1478   if (!interrupted) {
1479     if (input == nullptr) {
1480       fprintf(m_output_file, "\n");
1481       m_editor_status = EditorStatus::EndOfInput;
1482     } else {
1483       m_history_sp->Enter(input);
1484 #if LLDB_EDITLINE_USE_WCHAR
1485       line = m_utf8conv.to_bytes(SplitLines(input)[0]);
1486 #else
1487       line = SplitLines(input)[0];
1488 #endif
1489       m_editor_status = EditorStatus::Complete;
1490     }
1491   }
1492   return m_editor_status != EditorStatus::EndOfInput;
1493 }
1494 
1495 bool Editline::GetLines(int first_line_number, StringList &lines,
1496                         bool &interrupted) {
1497   ConfigureEditor(true);
1498 
1499   // Print the initial input lines, then move the cursor back up to the start
1500   // of input
1501   SetBaseLineNumber(first_line_number);
1502   m_input_lines = std::vector<EditLineStringType>();
1503   m_input_lines.insert(m_input_lines.begin(), EditLineConstString(""));
1504 
1505   std::lock_guard<std::mutex> guard(m_output_mutex);
1506   // Begin the line editing loop
1507   DisplayInput();
1508   SetCurrentLine(0);
1509   MoveCursor(CursorLocation::BlockEnd, CursorLocation::BlockStart);
1510   m_editor_status = EditorStatus::Editing;
1511   m_in_history = false;
1512 
1513   m_revert_cursor_index = -1;
1514   while (m_editor_status == EditorStatus::Editing) {
1515     int count;
1516     m_current_line_rows = -1;
1517     el_wpush(m_editline, EditLineConstString(
1518                              "\x1b[^")); // Revert to the existing line content
1519     el_wgets(m_editline, &count);
1520   }
1521 
1522   interrupted = m_editor_status == EditorStatus::Interrupted;
1523   if (!interrupted) {
1524     // Save the completed entry in history before returning
1525     m_history_sp->Enter(CombineLines(m_input_lines).c_str());
1526 
1527     lines = GetInputAsStringList();
1528   }
1529   return m_editor_status != EditorStatus::EndOfInput;
1530 }
1531 
1532 void Editline::PrintAsync(Stream *stream, const char *s, size_t len) {
1533   std::lock_guard<std::mutex> guard(m_output_mutex);
1534   if (m_editor_status == EditorStatus::Editing) {
1535     MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
1536     fprintf(m_output_file, ANSI_CLEAR_BELOW);
1537   }
1538   stream->Write(s, len);
1539   stream->Flush();
1540   if (m_editor_status == EditorStatus::Editing) {
1541     DisplayInput();
1542     MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
1543   }
1544 }
1545 
1546 bool Editline::CompleteCharacter(char ch, EditLineGetCharType &out) {
1547 #if !LLDB_EDITLINE_USE_WCHAR
1548   if (ch == (char)EOF)
1549     return false;
1550 
1551   out = (unsigned char)ch;
1552   return true;
1553 #else
1554   std::codecvt_utf8<wchar_t> cvt;
1555   llvm::SmallString<4> input;
1556   for (;;) {
1557     const char *from_next;
1558     wchar_t *to_next;
1559     std::mbstate_t state = std::mbstate_t();
1560     input.push_back(ch);
1561     switch (cvt.in(state, input.begin(), input.end(), from_next, &out, &out + 1,
1562                    to_next)) {
1563     case std::codecvt_base::ok:
1564       return out != (int)WEOF;
1565 
1566     case std::codecvt_base::error:
1567     case std::codecvt_base::noconv:
1568       return false;
1569 
1570     case std::codecvt_base::partial:
1571       lldb::ConnectionStatus status;
1572       size_t read_count = m_input_connection.Read(
1573           &ch, 1, std::chrono::seconds(0), status, nullptr);
1574       if (read_count == 0)
1575         return false;
1576       break;
1577     }
1578   }
1579 #endif
1580 }
1581