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