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