]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Host/common/Editline.cpp
Since contrib/libc++'s ancestry was never correct, subversion 1.8 and
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Host / common / Editline.cpp
1 //===-- Editline.cpp --------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include <iomanip>
11 #include <iostream>
12 #include <limits.h>
13
14 #include "lldb/Host/Editline.h"
15 #include "lldb/Host/ConnectionFileDescriptor.h"
16 #include "lldb/Core/Error.h"
17 #include "lldb/Core/StringList.h"
18 #include "lldb/Core/StreamString.h"
19 #include "lldb/Host/FileSpec.h"
20 #include "lldb/Host/FileSystem.h"
21 #include "lldb/Host/Host.h"
22 #include "lldb/Host/Mutex.h"
23
24 using namespace lldb_private;
25 using namespace lldb_private::line_editor;
26
27 // Editline uses careful cursor management to achieve the illusion of editing a multi-line block of text
28 // with a single line editor.  Preserving this illusion requires fairly careful management of cursor
29 // state.  Read and understand the relationship between DisplayInput(), MoveCursor(), SetCurrentLine(),
30 // and SaveEditedLine() before making changes.
31
32 #define ESCAPE "\x1b"
33 #define ANSI_FAINT ESCAPE "[2m"
34 #define ANSI_UNFAINT ESCAPE "[22m"
35 #define ANSI_CLEAR_BELOW ESCAPE "[J"
36 #define ANSI_CLEAR_RIGHT ESCAPE "[K"
37 #define ANSI_SET_COLUMN_N ESCAPE "[%dG"
38 #define ANSI_UP_N_ROWS ESCAPE "[%dA"
39 #define ANSI_DOWN_N_ROWS ESCAPE "[%dB"
40
41 #if LLDB_EDITLINE_USE_WCHAR
42
43 #define EditLineConstString(str) L##str
44 #define EditLineStringFormatSpec "%ls"
45
46 #else
47
48 #define EditLineConstString(str) str
49 #define EditLineStringFormatSpec "%s"
50
51 // use #defines so wide version functions and structs will resolve to old versions
52 // for case of libedit not built with wide char support
53 #define history_w history
54 #define history_winit history_init
55 #define history_wend history_end
56 #define HistoryW History
57 #define HistEventW HistEvent
58 #define LineInfoW LineInfo
59
60 #define el_wgets el_gets
61 #define el_wgetc el_getc
62 #define el_wpush el_push
63 #define el_wparse el_parse
64 #define el_wset  el_set
65 #define el_wget  el_get
66 #define el_wline el_line
67 #define el_winsertstr el_insertstr
68 #define  el_wdeletestr el_deletestr
69
70 #endif // #if LLDB_EDITLINE_USE_WCHAR
71
72 bool
73 IsOnlySpaces (const EditLineStringType & content)
74 {
75     for (wchar_t ch : content)
76     {
77         if (ch != EditLineCharType(' ')) 
78             return false;
79     }
80     return true;
81 }
82
83 EditLineStringType
84 CombineLines (const std::vector<EditLineStringType> & lines)
85 {
86     EditLineStringStreamType combined_stream;
87     for (EditLineStringType line : lines)
88     {
89         combined_stream << line.c_str() << "\n";
90     }
91     return combined_stream.str();
92 }
93
94 std::vector<EditLineStringType>
95 SplitLines (const EditLineStringType & input)
96 {
97     std::vector<EditLineStringType> result;
98     size_t start = 0;
99     while (start < input.length()) 
100     {
101         size_t end = input.find ('\n', start);
102         if (end == std::string::npos)
103         {
104             result.insert (result.end(), input.substr (start));
105             break;
106         }
107         result.insert (result.end(), input.substr (start, end - start));
108         start = end + 1;
109     }
110     return result;
111 }
112
113 EditLineStringType
114 FixIndentation (const EditLineStringType & line, int indent_correction)
115 {
116     if (indent_correction == 0) 
117         return line;
118     if (indent_correction < 0) 
119         return line.substr (-indent_correction);
120     return EditLineStringType (indent_correction, EditLineCharType(' ')) + line;
121 }
122
123 int
124 GetIndentation (const EditLineStringType & line)
125 {
126     int space_count = 0;
127     for (EditLineCharType ch : line)
128     {
129         if (ch != EditLineCharType(' ')) 
130             break;
131         ++space_count;
132     }
133     return space_count;
134 }
135
136 bool
137 IsInputPending (FILE * file)
138 {
139     // FIXME: This will be broken on Windows if we ever re-enable Editline.  You can't use select
140     // on something that isn't a socket.  This will have to be re-written to not use a FILE*, but
141     // instead use some kind of yet-to-be-created abstraction that select-like functionality on
142     // non-socket objects.
143     const int fd = fileno (file);
144     fd_set fds;
145     FD_ZERO (&fds);
146     FD_SET (fd, &fds);
147     timeval timeout = { 0, 0 };
148     return select (fd + 1, &fds, NULL, NULL, &timeout);
149 }
150
151 namespace lldb_private
152 {
153     namespace line_editor
154     {
155         typedef std::weak_ptr<EditlineHistory> EditlineHistoryWP;
156
157         // EditlineHistory objects are sometimes shared between multiple
158         // Editline instances with the same program name.
159         
160         class EditlineHistory
161         {
162         private:
163             // Use static GetHistory() function to get a EditlineHistorySP to one of these objects
164             EditlineHistory (const std::string &prefix, uint32_t size, bool unique_entries) :
165                 m_history (NULL),
166                 m_event (),
167                 m_prefix (prefix),
168                 m_path ()
169             {
170                 m_history = history_winit();
171                 history_w (m_history, &m_event, H_SETSIZE, size);
172                 if (unique_entries)
173                     history_w (m_history, &m_event, H_SETUNIQUE, 1);
174             }
175
176             const char *
177             GetHistoryFilePath()
178             {
179                 if (m_path.empty() && m_history && !m_prefix.empty())
180                 {
181                     std::string parent_path = FileSpec ("~/.lldb", true).GetPath();
182                     char history_path[PATH_MAX];
183                     if (FileSystem::MakeDirectory(parent_path.c_str(), lldb::eFilePermissionsDirectoryDefault).Success())
184                     {
185                         snprintf (history_path, sizeof (history_path), "~/.lldb/%s-history", m_prefix.c_str());
186                     }
187                     else
188                     {
189                         snprintf (history_path, sizeof (history_path), "~/%s-widehistory", m_prefix.c_str());
190                     }
191                     m_path = std::move (FileSpec (history_path, true).GetPath());
192                 }
193                 if (m_path.empty())
194                     return NULL;
195                 return m_path.c_str();
196             }
197             
198         public:
199             
200             ~EditlineHistory()
201             {
202                 Save();
203                 
204                 if (m_history)
205                 {
206                     history_wend (m_history);
207                     m_history = NULL;
208                 }
209             }
210             
211             static EditlineHistorySP
212             GetHistory (const std::string &prefix)
213             {
214                 typedef std::map<std::string, EditlineHistoryWP> WeakHistoryMap;
215                 static Mutex g_mutex (Mutex::eMutexTypeRecursive);
216                 static WeakHistoryMap g_weak_map;
217                 Mutex::Locker locker (g_mutex);
218                 WeakHistoryMap::const_iterator pos = g_weak_map.find (prefix);
219                 EditlineHistorySP history_sp;
220                 if (pos != g_weak_map.end())
221                 {
222                     history_sp = pos->second.lock();
223                     if (history_sp)
224                         return history_sp;
225                     g_weak_map.erase (pos);
226                 }
227                 history_sp.reset (new EditlineHistory (prefix, 800, true));
228                 g_weak_map[prefix] = history_sp;
229                 return history_sp;
230             }
231             
232             bool IsValid() const
233             {
234                 return m_history != NULL;
235             }
236             
237             HistoryW *
238             GetHistoryPtr ()
239             {
240                 return m_history;
241             }
242             
243             void
244             Enter (const EditLineCharType *line_cstr)
245             {
246                 if (m_history)
247                     history_w (m_history, &m_event, H_ENTER, line_cstr);
248             }
249             
250             bool
251             Load ()
252             {
253                 if (m_history)
254                 {
255                     const char *path = GetHistoryFilePath();
256                     if (path)
257                     {
258                         history_w (m_history, &m_event, H_LOAD, path);
259                         return true;
260                     }
261                 }
262                 return false;
263             }
264             
265             bool
266             Save ()
267             {
268                 if (m_history)
269                 {
270                     const char *path = GetHistoryFilePath();
271                     if (path)
272                     {
273                         history_w (m_history, &m_event, H_SAVE, path);
274                         return true;
275                     }
276                 }
277                 return false;
278             }
279             
280         protected:
281             HistoryW * m_history;   // The history object
282             HistEventW m_event;      // The history event needed to contain all history events
283             std::string m_prefix;     // The prefix name (usually the editline program name) to use when loading/saving history
284             std::string m_path;       // Path to the history file
285         };
286     }
287 }
288
289 //------------------------------------------------------------------
290 // Editline private methods
291 //------------------------------------------------------------------
292
293 void
294 Editline::SetBaseLineNumber (int line_number)
295 {
296     std::stringstream line_number_stream;
297     line_number_stream << line_number;
298     m_base_line_number = line_number;
299     m_line_number_digits = std::max (3, (int)line_number_stream.str().length() + 1);
300 }
301
302 std::string
303 Editline::PromptForIndex (int line_index)
304 {
305     bool use_line_numbers = m_multiline_enabled && m_base_line_number > 0;
306     std::string prompt = m_set_prompt;
307     if (use_line_numbers && prompt.length() == 0)
308     {
309         prompt = ": ";
310     }
311     std::string continuation_prompt = prompt;
312     if (m_set_continuation_prompt.length() > 0)
313     {
314         continuation_prompt = m_set_continuation_prompt;
315         
316         // Ensure that both prompts are the same length through space padding
317         while (continuation_prompt.length() < prompt.length())
318         {
319             continuation_prompt += ' ';
320         }
321         while (prompt.length() < continuation_prompt.length())
322         {
323             prompt += ' ';
324         }
325     }
326     
327     if (use_line_numbers)
328     {
329         StreamString prompt_stream;
330         prompt_stream.Printf("%*d%s", m_line_number_digits, m_base_line_number + line_index,
331                              (line_index == 0) ? prompt.c_str() : continuation_prompt.c_str());
332         return std::move (prompt_stream.GetString());
333     }
334     return (line_index == 0) ? prompt : continuation_prompt;
335 }
336
337 void
338 Editline::SetCurrentLine (int line_index)
339 {
340     m_current_line_index = line_index;
341     m_current_prompt = PromptForIndex (line_index);
342 }
343
344 int
345 Editline::GetPromptWidth()
346 {
347     return (int)PromptForIndex (0).length();
348 }
349
350 bool
351 Editline::IsEmacs()
352 {
353     const char * editor;
354     el_get (m_editline, EL_EDITOR, &editor);
355     return editor[0] == 'e';
356 }
357
358 bool
359 Editline::IsOnlySpaces()
360 {
361     const LineInfoW * info = el_wline (m_editline);
362     for (const EditLineCharType * character = info->buffer; character < info->lastchar; character++)
363     {
364         if (*character != ' ') 
365             return false;
366     }
367     return true;
368 }
369
370 int
371 Editline::GetLineIndexForLocation (CursorLocation location, int cursor_row)
372 {
373     int line = 0;
374     if (location == CursorLocation::EditingPrompt || location == CursorLocation::BlockEnd ||
375         location == CursorLocation::EditingCursor)
376     {
377         for (unsigned index = 0; index < m_current_line_index; index++)
378         {
379             line += CountRowsForLine (m_input_lines[index]);
380         }
381         if (location == CursorLocation::EditingCursor)
382         {
383             line += cursor_row;
384         }
385         else if (location == CursorLocation::BlockEnd)
386         {
387             for (unsigned index = m_current_line_index; index < m_input_lines.size(); index++)
388             {
389                 line += CountRowsForLine (m_input_lines[index]);
390             }
391             --line;
392         }
393     }
394     return line;
395 }
396
397 void
398 Editline::MoveCursor (CursorLocation from, CursorLocation to)
399 {
400     const LineInfoW * info = el_wline (m_editline);
401     int editline_cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth());
402     int editline_cursor_row = editline_cursor_position / m_terminal_width;
403     
404     // Determine relative starting and ending lines
405     int fromLine = GetLineIndexForLocation (from, editline_cursor_row);
406     int toLine = GetLineIndexForLocation (to, editline_cursor_row);
407     if (toLine != fromLine)
408     {
409         fprintf (m_output_file, (toLine > fromLine) ? ANSI_DOWN_N_ROWS : ANSI_UP_N_ROWS, std::abs (toLine - fromLine));
410     }
411     
412     // Determine target column
413     int toColumn = 1;
414     if (to == CursorLocation::EditingCursor)
415     {
416         toColumn = editline_cursor_position - (editline_cursor_row * m_terminal_width) + 1;
417     }
418     else if (to == CursorLocation::BlockEnd)
419     {
420         toColumn = ((m_input_lines[m_input_lines.size() - 1].length() + GetPromptWidth()) % 80) + 1;
421     }
422     fprintf (m_output_file, ANSI_SET_COLUMN_N, toColumn);
423 }
424
425 void
426 Editline::DisplayInput (int firstIndex)
427 {
428     fprintf (m_output_file, ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1);
429     int line_count = (int)m_input_lines.size();
430     const char *faint  = m_color_prompts ? ANSI_FAINT : "";
431     const char *unfaint  = m_color_prompts ? ANSI_UNFAINT : "";
432     
433     for (int index = firstIndex; index < line_count; index++)
434     {
435         fprintf (m_output_file, "%s" "%s" "%s" EditLineStringFormatSpec " ",
436                 faint,
437                 PromptForIndex (index).c_str(),
438                 unfaint,
439                 m_input_lines[index].c_str());
440         if (index < line_count - 1) 
441             fprintf (m_output_file, "\n");
442     }
443 }
444
445
446 int
447 Editline::CountRowsForLine (const EditLineStringType & content)
448 {
449     auto prompt = PromptForIndex (0); // Prompt width is constant during an edit session
450     int line_length = (int)(content.length() + prompt.length());
451     return (line_length / m_terminal_width) + 1;
452 }
453
454 void
455 Editline::SaveEditedLine()
456 {
457     const LineInfoW * info = el_wline (m_editline);
458     m_input_lines[m_current_line_index] = EditLineStringType (info->buffer, info->lastchar - info->buffer);
459 }
460
461 StringList
462 Editline::GetInputAsStringList(int line_count)
463 {
464     StringList lines;
465     for (EditLineStringType line : m_input_lines)
466     {
467         if (line_count == 0) 
468             break;
469 #if LLDB_EDITLINE_USE_WCHAR
470         lines.AppendString (m_utf8conv.to_bytes (line));
471 #else
472         lines.AppendString(line);
473 #endif
474         --line_count;
475     }
476     return lines;
477 }
478
479 unsigned char
480 Editline::RecallHistory (bool earlier)
481 {
482     if (!m_history_sp || !m_history_sp->IsValid()) 
483         return CC_ERROR;
484     
485     HistoryW * pHistory = m_history_sp->GetHistoryPtr();
486     HistEventW history_event;
487     std::vector<EditLineStringType> new_input_lines;
488     
489     // Treat moving from the "live" entry differently
490     if (!m_in_history)
491     {
492         if (earlier == false) 
493             return CC_ERROR; // Can't go newer than the "live" entry
494         if (history_w (pHistory, &history_event, H_FIRST) == -1) 
495             return CC_ERROR;
496
497         // Save any edits to the "live" entry in case we return by moving forward in history
498         // (it would be more bash-like to save over any current entry, but libedit doesn't
499         // offer the ability to add entries anywhere except the end.)
500         SaveEditedLine();
501         m_live_history_lines = m_input_lines;
502         m_in_history = true;
503     }
504     else
505     {
506         if (history_w (pHistory, &history_event, earlier ? H_NEXT : H_PREV) == -1)
507         {
508             // Can't move earlier than the earliest entry
509             if (earlier) 
510                 return CC_ERROR;
511
512             // ... but moving to newer than the newest yields the "live" entry
513             new_input_lines = m_live_history_lines;
514             m_in_history = false;
515         }
516     }
517     
518     // If we're pulling the lines from history, split them apart
519     if (m_in_history) 
520         new_input_lines = SplitLines (history_event.str);
521
522     // Erase the current edit session and replace it with a new one
523     MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockStart);
524     m_input_lines = new_input_lines;
525     DisplayInput();
526     
527     // Prepare to edit the last line when moving to previous entry, or the first line
528     // when moving to next entry
529     SetCurrentLine (m_current_line_index = earlier ? (int)m_input_lines.size() - 1 : 0);
530     MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
531     return CC_NEWLINE;
532 }
533
534 int
535 Editline::GetCharacter (EditLineCharType * c)
536 {
537     const LineInfoW * info = el_wline (m_editline);
538     
539     // Paint a faint version of the desired prompt over the version libedit draws
540     // (will only be requested if colors are supported)
541     if (m_needs_prompt_repaint)
542     {
543         MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
544         fprintf (m_output_file, "%s" "%s" "%s", ANSI_FAINT, Prompt(), ANSI_UNFAINT);
545         MoveCursor (CursorLocation::EditingPrompt, CursorLocation::EditingCursor);
546         m_needs_prompt_repaint = false;
547     }
548     
549     if (m_multiline_enabled)
550     {
551         // Detect when the number of rows used for this input line changes due to 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         {
556             // Respond by repainting the current state from this line on
557             MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
558             SaveEditedLine();
559             DisplayInput (m_current_line_index);
560             MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingCursor);
561         }
562         m_current_line_rows = new_line_rows;
563     }
564     
565     // Read an actual character
566     while (true)
567     {
568         lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
569         char ch = 0;
570         m_editor_getting_char = true;
571         int read_count = m_input_connection.Read(&ch, 1, UINT32_MAX, status, NULL);
572         m_editor_getting_char = false;
573         if (read_count)
574         {
575 #if LLDB_EDITLINE_USE_WCHAR
576             // After the initial interruptible read, this is guaranteed not to block
577             ungetc (ch, m_input_file);
578             *c = fgetwc (m_input_file);
579             if (*c != WEOF) 
580                 return 1;
581 #else
582             *c = ch;
583             if(*c != EOF) 
584                 return 1;
585 #endif
586         }
587         else
588         {
589             switch (status)
590             {
591                 case lldb::eConnectionStatusInterrupted:
592                     m_editor_status = EditorStatus::Interrupted;
593                     printf ("^C\n");
594                     return 0;
595                     
596                 case lldb::eConnectionStatusSuccess:         // Success
597                     break;
598                     
599                 case lldb::eConnectionStatusError:           // Check GetError() for details
600                 case lldb::eConnectionStatusTimedOut:        // Request timed out
601                 case lldb::eConnectionStatusEndOfFile:       // End-of-file encountered
602                 case lldb::eConnectionStatusNoConnection:    // No connection
603                 case lldb::eConnectionStatusLostConnection:  // Lost connection while connected to a valid connection
604                     m_editor_status = EditorStatus::EndOfInput;
605                     return 0;
606             }
607         }
608     }
609 }
610
611 const char *
612 Editline::Prompt()
613 {
614     if (m_color_prompts) 
615         m_needs_prompt_repaint = true;
616     return m_current_prompt.c_str();
617 }
618
619 unsigned char
620 Editline::BreakLineCommand (int ch)
621 {
622     // Preserve any content beyond the cursor, truncate and save the current line
623     const LineInfoW * info = el_wline (m_editline);
624     auto current_line = EditLineStringType (info->buffer, info->cursor - info->buffer);
625     auto new_line_fragment = EditLineStringType (info->cursor, info->lastchar - info->cursor);
626     m_input_lines[m_current_line_index] = current_line;
627     
628     // Ignore whitespace-only extra fragments when breaking a line
629     if (::IsOnlySpaces (new_line_fragment)) 
630         new_line_fragment = EditLineConstString("");
631
632     // Establish the new cursor position at the start of a line when inserting a line break
633     m_revert_cursor_index = 0;
634
635     // Don't perform end of input detection or automatic formatting when pasting
636     if (!IsInputPending (m_input_file))
637     {
638         // If this is the end of the last line, treat this as a potential exit
639         if (m_current_line_index == m_input_lines.size() - 1 && new_line_fragment.length() == 0)
640         {
641             bool end_of_input = true;
642             if (m_is_input_complete_callback) 
643             {
644                 SaveEditedLine();
645                 auto lines = GetInputAsStringList();
646                 end_of_input = m_is_input_complete_callback (this, lines, m_is_input_complete_callback_baton);
647
648                 // The completion test is allowed to change the input lines when complete
649                 if (end_of_input)
650                 {
651                     m_input_lines.clear();
652                     for (unsigned index = 0; index < lines.GetSize(); index++)
653                     {
654 #if LLDB_EDITLINE_USE_WCHAR
655                         m_input_lines.insert (m_input_lines.end(), m_utf8conv.from_bytes (lines[index]));
656 #else
657                         m_input_lines.insert (m_input_lines.end(), lines[index]);
658 #endif
659                     }
660                 }
661             }
662             if (end_of_input)
663             {
664                 fprintf (m_output_file, "\n");
665                 m_editor_status = EditorStatus::Complete;
666                 return CC_NEWLINE;
667             }
668         }
669         
670         // Apply smart indentation
671         if (m_fix_indentation_callback) 
672         {
673             StringList lines = GetInputAsStringList (m_current_line_index + 1);
674 #if LLDB_EDITLINE_USE_WCHAR
675             lines.AppendString (m_utf8conv.to_bytes (new_line_fragment));
676 #else
677             lines.AppendString (new_line_fragment);
678 #endif
679             
680             int indent_correction = m_fix_indentation_callback (this, lines, 0, m_fix_indentation_callback_baton);
681             new_line_fragment = FixIndentation(new_line_fragment, indent_correction);
682             m_revert_cursor_index = GetIndentation(new_line_fragment);
683         }
684     }
685     
686     // Insert the new line and repaint everything from the split line on down
687     m_input_lines.insert (m_input_lines.begin() + m_current_line_index + 1, new_line_fragment);
688     MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
689     DisplayInput (m_current_line_index);
690     
691     // Reposition the cursor to the right line and prepare to edit the new line
692     SetCurrentLine (m_current_line_index + 1);
693     MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
694     return CC_NEWLINE;
695 }
696
697 unsigned char
698 Editline::DeleteNextCharCommand (int ch)
699 {
700     LineInfoW * info = (LineInfoW *)el_wline (m_editline);
701     
702     // Just delete the next character normally if possible
703     if (info->cursor < info->lastchar) 
704     {
705         info->cursor++;
706         el_deletestr (m_editline, 1);
707         return CC_REFRESH;
708     }
709
710     // Fail when at the end of the last line, except when ^D is pressed on
711     // the line is empty, in which case it is treated as EOF
712     if (m_current_line_index == m_input_lines.size() - 1)
713     {
714         if (ch == 4 && info->buffer == info->lastchar)
715         {
716             fprintf (m_output_file, "^D\n");
717             m_editor_status = EditorStatus::EndOfInput;
718             return CC_EOF;
719         }
720         return CC_ERROR;
721     }
722     
723     // Prepare to combine this line with the one below
724     MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
725     
726     // Insert the next line of text at the cursor and restore the cursor position
727     const EditLineCharType * cursor = info->cursor;
728     el_winsertstr (m_editline, m_input_lines[m_current_line_index + 1].c_str());
729     info->cursor = cursor;
730     SaveEditedLine();
731     
732     // Delete the extra line
733     m_input_lines.erase (m_input_lines.begin() + m_current_line_index + 1);
734     
735     // Clear and repaint from this line on down
736     DisplayInput (m_current_line_index);
737     MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingCursor);
738     return CC_REFRESH;
739 }
740
741 unsigned char
742 Editline::DeletePreviousCharCommand (int ch)
743 {
744     LineInfoW * info = (LineInfoW *)el_wline (m_editline);
745     
746     // Just delete the previous character normally when not at the start of a line
747     if (info->cursor > info->buffer) 
748     {
749         el_deletestr (m_editline, 1);
750         return CC_REFRESH;
751     }
752     
753     // No prior line and no prior character?  Let the user know
754     if (m_current_line_index == 0) 
755         return CC_ERROR;
756     
757     // No prior character, but prior line?  Combine with the line above
758     SaveEditedLine();
759     SetCurrentLine (m_current_line_index - 1);
760     auto priorLine = m_input_lines[m_current_line_index];
761     m_input_lines.erase (m_input_lines.begin() + m_current_line_index);
762     m_input_lines[m_current_line_index] = 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, CountRowsForLine (priorLine), 1);
766     DisplayInput (m_current_line_index);
767     
768     // Put the cursor back where libedit expects it to be before returning to editing
769     // by telling libedit about the newly inserted text
770     MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
771     el_winsertstr (m_editline, priorLine.c_str());
772     return CC_REDISPLAY;
773 }
774
775 unsigned char
776 Editline::PreviousLineCommand (int ch)
777 {
778     SaveEditedLine();
779
780     if (m_current_line_index == 0) {
781         return RecallHistory (true);
782     }
783     
784     // Start from a known location
785     MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
786     
787     // Treat moving up from a blank last line as a deletion of that line
788     if (m_current_line_index == m_input_lines.size() - 1 && IsOnlySpaces()) 
789     {
790         m_input_lines.erase (m_input_lines.begin() + m_current_line_index);
791         fprintf (m_output_file, ANSI_CLEAR_BELOW);
792     }
793     
794     SetCurrentLine (m_current_line_index - 1);
795     fprintf (m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N,
796             CountRowsForLine (m_input_lines[m_current_line_index]), 1);
797     return CC_NEWLINE;
798 }
799
800 unsigned char
801 Editline::NextLineCommand (int ch)
802 {
803     SaveEditedLine();
804
805     // Handle attempts to move down from the last line
806     if (m_current_line_index == m_input_lines.size() - 1) 
807     {
808         // Don't add an extra line if the existing last line is blank, move through history instead
809         if (IsOnlySpaces()) 
810         {
811             return RecallHistory (false);
812         }
813         
814         // Determine indentation for the new line
815         int indentation = 0;
816         if (m_fix_indentation_callback)
817         {
818             StringList lines = GetInputAsStringList();
819             lines.AppendString("");
820             indentation = m_fix_indentation_callback (this, lines, 0, m_fix_indentation_callback_baton);
821         }
822         m_input_lines.insert (m_input_lines.end(), EditLineStringType (indentation, EditLineCharType(' ')));
823     }
824     
825     // Move down past the current line using newlines to force scrolling if needed
826     SetCurrentLine (m_current_line_index + 1);
827     const LineInfoW * info = el_wline (m_editline);
828     int cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth());
829     int cursor_row = cursor_position / m_terminal_width;
830     for (int line_count = 0; line_count < m_current_line_rows - cursor_row; line_count++) 
831     {
832         fprintf (m_output_file, "\n");
833     }
834     return CC_NEWLINE;
835 }
836
837 unsigned char
838 Editline::FixIndentationCommand (int ch)
839 {
840     if (!m_fix_indentation_callback) 
841         return CC_NORM;
842     
843     // Insert the character by hand prior to correction
844     EditLineCharType inserted[] = { (EditLineCharType)ch, 0 };
845     el_winsertstr (m_editline, inserted);
846     SaveEditedLine();
847     StringList lines = GetInputAsStringList (m_current_line_index + 1);
848
849     // Determine the cursor position
850     LineInfoW * info = (LineInfoW *)el_wline (m_editline);
851     int cursor_position = info->cursor - info->buffer;
852     
853     int indent_correction = m_fix_indentation_callback (this, lines, cursor_position, m_fix_indentation_callback_baton);
854     
855     // Adjust the input buffer to correct indentation
856     if (indent_correction > 0)
857     {
858         info->cursor = info->buffer;
859         el_winsertstr (m_editline, EditLineStringType (indent_correction, EditLineCharType(' ')).c_str());
860     }
861     else if (indent_correction < 0)
862     {
863         info->cursor = info->buffer - indent_correction;
864         el_wdeletestr (m_editline, -indent_correction);
865     }
866     info->cursor = info->buffer + cursor_position + indent_correction;
867     return CC_REFRESH;
868 }
869
870 unsigned char
871 Editline::RevertLineCommand (int ch)
872 {
873     el_winsertstr (m_editline, m_input_lines[m_current_line_index].c_str());
874     if (m_revert_cursor_index >= 0)
875     {
876         LineInfoW * info = (LineInfoW *)el_wline (m_editline);
877         info->cursor = info->buffer + m_revert_cursor_index;
878         if (info->cursor > info->lastchar)
879         {
880             info->cursor = info->lastchar;
881         }
882         m_revert_cursor_index = -1;
883     }
884     return CC_REFRESH;
885 }
886
887 unsigned char
888 Editline::BufferStartCommand (int ch)
889 {
890     SaveEditedLine();
891     MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockStart);
892     SetCurrentLine (0);
893     m_revert_cursor_index = 0;
894     return CC_NEWLINE;
895 }
896
897 unsigned char
898 Editline::BufferEndCommand (int ch)
899 {
900     SaveEditedLine();
901     MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockEnd);
902     SetCurrentLine ((int)m_input_lines.size() - 1);
903     MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
904     return CC_NEWLINE;
905 }
906
907 unsigned char
908 Editline::TabCommand (int ch)
909 {
910     if (m_completion_callback == nullptr) 
911         return CC_ERROR;
912     
913     const LineInfo *line_info  = el_line (m_editline);
914     StringList completions;
915     int page_size = 40;
916     
917     const int num_completions = m_completion_callback (line_info->buffer,
918                                                        line_info->cursor,
919                                                        line_info->lastchar,
920                                                        0,     // Don't skip any matches (start at match zero)
921                                                        -1,    // Get all the matches
922                                                        completions,
923                                                        m_completion_callback_baton);
924     
925     if (num_completions == 0) 
926         return CC_ERROR;
927     //    if (num_completions == -1)
928     //    {
929     //        el_insertstr (m_editline, m_completion_key);
930     //        return CC_REDISPLAY;
931     //    }
932     //    else
933     if (num_completions == -2)
934     {
935         // Replace the entire line with the first string...
936         el_deletestr (m_editline, line_info->cursor - line_info->buffer);
937         el_insertstr (m_editline, completions.GetStringAtIndex (0));
938         return CC_REDISPLAY;
939     }
940     
941     // If we get a longer match display that first.
942     const char *completion_str = completions.GetStringAtIndex (0);
943     if (completion_str != nullptr && *completion_str != '\0')
944     {
945         el_insertstr (m_editline, completion_str);
946         return CC_REDISPLAY;
947     }
948     
949     if (num_completions > 1)
950     {
951         int num_elements = num_completions + 1;
952         fprintf (m_output_file, "\n" ANSI_CLEAR_BELOW "Available completions:");
953         if (num_completions < page_size)
954         {
955             for (int i = 1; i < num_elements; i++)
956             {
957                 completion_str = completions.GetStringAtIndex (i);
958                 fprintf (m_output_file, "\n\t%s", completion_str);
959             }
960             fprintf (m_output_file, "\n");
961         }
962         else
963         {
964             int cur_pos = 1;
965             char reply;
966             int got_char;
967             while (cur_pos < num_elements)
968             {
969                 int endpoint = cur_pos + page_size;
970                 if (endpoint > num_elements)
971                     endpoint = num_elements;
972                 for (; cur_pos < endpoint; cur_pos++)
973                 {
974                     completion_str = completions.GetStringAtIndex (cur_pos);
975                     fprintf (m_output_file, "\n\t%s", completion_str);
976                 }
977                 
978                 if (cur_pos >= num_elements)
979                 {
980                     fprintf (m_output_file, "\n");
981                     break;
982                 }
983                 
984                 fprintf (m_output_file, "\nMore (Y/n/a): ");
985                 reply = 'n';
986                 got_char = el_getc(m_editline, &reply);
987                 if (got_char == -1 || reply == 'n')
988                     break;
989                 if (reply == 'a')
990                     page_size = num_elements - cur_pos;
991             }
992         }
993         DisplayInput();
994         MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
995     }
996     return CC_REDISPLAY;
997 }
998
999 void
1000 Editline::ConfigureEditor (bool multiline)
1001 {
1002     if (m_editline && m_multiline_enabled == multiline) 
1003         return;
1004     m_multiline_enabled = multiline;
1005     
1006     if (m_editline) 
1007     {
1008         // Disable edit mode to stop the terminal from flushing all input
1009         // during the call to el_end() since we expect to have multiple editline
1010         // instances in this program.
1011         el_set (m_editline, EL_EDITMODE, 0);
1012         el_end (m_editline);
1013     }
1014     
1015     m_editline = el_init (m_editor_name.c_str(), m_input_file, m_output_file, m_error_file);
1016     TerminalSizeChanged();
1017     
1018     if (m_history_sp && m_history_sp->IsValid())
1019     {
1020         m_history_sp->Load();
1021         el_wset (m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr());
1022     }
1023     el_set (m_editline, EL_CLIENTDATA, this);
1024     el_set (m_editline, EL_SIGNAL, 0);
1025     el_set (m_editline, EL_EDITOR, "emacs");
1026     el_set (m_editline, EL_PROMPT, (EditlinePromptCallbackType)([] (EditLine *editline) {
1027         return Editline::InstanceFor (editline)->Prompt();
1028     }));
1029
1030     el_wset (m_editline, EL_GETCFN,
1031             (EditlineGetCharCallbackType)([] (EditLine * editline, EditLineCharType * c) {
1032                 return Editline::InstanceFor (editline)->GetCharacter (c);
1033             }));
1034     
1035     // Commands used for multiline support, registered whether or not they're used
1036     el_set (m_editline, EL_ADDFN, "lldb-break-line", "Insert a line break",
1037            (EditlineCommandCallbackType)([] (EditLine * editline, int ch) {
1038                return Editline::InstanceFor (editline)->BreakLineCommand (ch);
1039            }));
1040     el_set (m_editline, EL_ADDFN, "lldb-delete-next-char", "Delete next character",
1041            (EditlineCommandCallbackType)([] (EditLine * editline, int ch) {
1042                return Editline::InstanceFor (editline)->DeleteNextCharCommand (ch);
1043            }));
1044     el_set (m_editline, EL_ADDFN, "lldb-delete-previous-char", "Delete previous character",
1045            (EditlineCommandCallbackType)([] (EditLine * editline, int ch) {
1046                return Editline::InstanceFor (editline)->DeletePreviousCharCommand (ch);
1047            }));
1048     el_set (m_editline, EL_ADDFN, "lldb-previous-line", "Move to previous line",
1049            (EditlineCommandCallbackType)([] (EditLine * editline, int ch) {
1050                return Editline::InstanceFor (editline)->PreviousLineCommand (ch);
1051            }));
1052     el_set (m_editline, EL_ADDFN, "lldb-next-line", "Move to next line",
1053            (EditlineCommandCallbackType)([] (EditLine * editline, int ch) {
1054                return Editline::InstanceFor (editline)->NextLineCommand (ch);
1055            }));
1056     el_set (m_editline, EL_ADDFN, "lldb-buffer-start", "Move to start of buffer",
1057            (EditlineCommandCallbackType)([] (EditLine * editline, int ch) {
1058                return Editline::InstanceFor (editline)->BufferStartCommand (ch);
1059            }));
1060     el_set (m_editline, EL_ADDFN, "lldb-buffer-end", "Move to end of buffer",
1061            (EditlineCommandCallbackType)([] (EditLine * editline, int ch) {
1062                 return Editline::InstanceFor (editline)->BufferEndCommand (ch);
1063             }));
1064     el_set (m_editline, EL_ADDFN, "lldb-fix-indentation", "Fix line indentation",
1065            (EditlineCommandCallbackType)([] (EditLine * editline, int ch) {
1066                 return Editline::InstanceFor (editline)->FixIndentationCommand (ch);
1067             }));
1068
1069     // Register the complete callback under two names for compatibility with older clients using
1070     // custom .editrc files (largely becuase libedit has a bad bug where if you have a bind command
1071     // that tries to bind to a function name that doesn't exist, it can corrupt the heap and
1072     // crash your process later.)
1073     EditlineCommandCallbackType complete_callback = [] (EditLine * editline, int ch) {
1074         return Editline::InstanceFor (editline)->TabCommand (ch);
1075     };
1076     el_set (m_editline, EL_ADDFN, "lldb-complete", "Invoke completion", complete_callback);
1077     el_set (m_editline, EL_ADDFN, "lldb_complete", "Invoke completion", complete_callback);
1078     
1079     // General bindings we don't mind being overridden
1080     if (!multiline) {
1081         el_set (m_editline, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string
1082     }
1083     el_set (m_editline, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash in emacs mode
1084     el_set (m_editline, EL_BIND, "\t", "lldb-complete", NULL); // Bind TAB to auto complete
1085     
1086     // Allow user-specific customization prior to registering bindings we absolutely require
1087     el_source (m_editline, NULL);
1088
1089     // Register an internal binding that external developers shouldn't use
1090     el_set (m_editline, EL_ADDFN, "lldb-revert-line", "Revert line to saved state",
1091            (EditlineCommandCallbackType)([] (EditLine * editline, int ch) {
1092                return Editline::InstanceFor (editline)->RevertLineCommand (ch);
1093            }));
1094
1095     // Register keys that perform auto-indent correction
1096     if (m_fix_indentation_callback && m_fix_indentation_callback_chars)
1097     {
1098         char bind_key[2] = { 0, 0 };
1099         const char * indent_chars = m_fix_indentation_callback_chars;
1100         while (*indent_chars)
1101         {
1102             bind_key[0] = *indent_chars;
1103             el_set (m_editline, EL_BIND, bind_key, "lldb-fix-indentation", NULL);
1104             ++indent_chars;
1105         }
1106     }
1107
1108     // Multi-line editor bindings
1109     if (multiline)
1110     {
1111         el_set (m_editline, EL_BIND, "\n", "lldb-break-line", NULL);
1112         el_set (m_editline, EL_BIND, "\r", "lldb-break-line", NULL);
1113         el_set (m_editline, EL_BIND, "^p", "lldb-previous-line", NULL);
1114         el_set (m_editline, EL_BIND, "^n", "lldb-next-line", NULL);
1115         el_set (m_editline, EL_BIND, "^?", "lldb-delete-previous-char", NULL);
1116         el_set (m_editline, EL_BIND, "^d", "lldb-delete-next-char", NULL);
1117         el_set (m_editline, EL_BIND, ESCAPE "[3~", "lldb-delete-next-char", NULL);
1118         el_set (m_editline, EL_BIND, ESCAPE "[\\^", "lldb-revert-line", NULL);
1119
1120         // Editor-specific bindings
1121         if (IsEmacs())
1122         {
1123             el_set (m_editline, EL_BIND, ESCAPE "<", "lldb-buffer-start", NULL);
1124             el_set (m_editline, EL_BIND, ESCAPE ">", "lldb-buffer-end", NULL);
1125             el_set (m_editline, EL_BIND, ESCAPE "[A", "lldb-previous-line", NULL);
1126             el_set (m_editline, EL_BIND, ESCAPE "[B", "lldb-next-line", NULL);
1127         }
1128         else
1129         {
1130             el_set (m_editline, EL_BIND, "^H", "lldb-delete-previous-char", NULL);
1131             
1132             el_set (m_editline, EL_BIND, "-a", ESCAPE "[A", "lldb-previous-line", NULL);
1133             el_set (m_editline, EL_BIND, "-a", ESCAPE "[B", "lldb-next-line", NULL);
1134             el_set (m_editline, EL_BIND, "-a", "x", "lldb-delete-next-char", NULL);
1135             el_set (m_editline, EL_BIND, "-a", "^H", "lldb-delete-previous-char", NULL);
1136             el_set (m_editline, EL_BIND, "-a", "^?", "lldb-delete-previous-char", NULL);
1137             
1138             // Escape is absorbed exiting edit mode, so re-register important sequences
1139             // without the prefix
1140             el_set (m_editline, EL_BIND, "-a", "[A", "lldb-previous-line", NULL);
1141             el_set (m_editline, EL_BIND, "-a", "[B", "lldb-next-line", NULL);
1142             el_set (m_editline, EL_BIND, "-a", "[\\^", "lldb-revert-line", NULL);
1143         }
1144     }
1145 }
1146
1147 //------------------------------------------------------------------
1148 // Editline public methods
1149 //------------------------------------------------------------------
1150
1151 Editline *
1152 Editline::InstanceFor (EditLine * editline)
1153 {
1154     Editline * editor;
1155     el_get (editline, EL_CLIENTDATA, &editor);
1156     return editor;
1157 }
1158
1159 Editline::Editline (const char * editline_name, FILE * input_file, FILE * output_file, FILE * error_file, bool color_prompts) :
1160     m_editor_status (EditorStatus::Complete),
1161     m_color_prompts(color_prompts),
1162     m_input_file (input_file),
1163     m_output_file (output_file),
1164     m_error_file (error_file),
1165     m_input_connection (fileno(input_file), false)
1166 {
1167     // Get a shared history instance
1168     m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name;
1169     m_history_sp = EditlineHistory::GetHistory (m_editor_name);
1170 }
1171
1172 Editline::~Editline()
1173 {
1174     if (m_editline) 
1175     {
1176         // Disable edit mode to stop the terminal from flushing all input
1177         // during the call to el_end() since we expect to have multiple editline
1178         // instances in this program.
1179         el_set (m_editline, EL_EDITMODE, 0);
1180         el_end (m_editline);
1181         m_editline = nullptr;
1182     }
1183
1184     // EditlineHistory objects are sometimes shared between multiple
1185     // Editline instances with the same program name. So just release
1186     // our shared pointer and if we are the last owner, it will save the
1187     // history to the history save file automatically.
1188     m_history_sp.reset();
1189 }
1190
1191 void
1192 Editline::SetPrompt (const char * prompt)
1193 {
1194     m_set_prompt = prompt == nullptr ? "" : prompt;
1195 }
1196
1197 void
1198 Editline::SetContinuationPrompt (const char * continuation_prompt)
1199 {
1200     m_set_continuation_prompt = continuation_prompt == nullptr ? "" : continuation_prompt;
1201 }
1202
1203 void
1204 Editline::TerminalSizeChanged()
1205 {
1206     if (m_editline != nullptr) 
1207     {
1208         el_resize (m_editline);
1209         int columns;
1210         // Despite the man page claiming non-zero indicates success, it's actually zero
1211         if (el_get (m_editline, EL_GETTC, "co", &columns) == 0) 
1212         {
1213             m_terminal_width = columns;
1214             if (m_current_line_rows != -1) 
1215             {
1216                 const LineInfoW * info = el_wline (m_editline);
1217                 int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth());
1218                 m_current_line_rows = (lineLength / columns) + 1;
1219             }
1220         }
1221         else 
1222         {
1223             m_terminal_width = INT_MAX;
1224             m_current_line_rows = 1;
1225         }
1226     }
1227 }
1228
1229 const char *
1230 Editline::GetPrompt()
1231 {
1232     return m_set_prompt.c_str();
1233 }
1234
1235 uint32_t
1236 Editline::GetCurrentLine()
1237 {
1238     return m_current_line_index;
1239 }
1240
1241 void
1242 Editline::Hide()
1243 {
1244     // Make sure we're at a stable location waiting for input
1245     while (m_editor_status == EditorStatus::Editing && !m_editor_getting_char)
1246     {
1247         usleep(100000);
1248     }
1249     
1250     // Clear the existing input
1251     if (m_editor_status == EditorStatus::Editing)
1252     {
1253         MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
1254         fprintf(m_output_file, ANSI_CLEAR_BELOW);
1255     }
1256 }
1257
1258 void
1259 Editline::Refresh()
1260 {
1261     if (m_editor_status == EditorStatus::Editing)
1262     {
1263         DisplayInput();
1264         MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
1265     }
1266 }
1267
1268 bool
1269 Editline::Interrupt()
1270 {
1271     if (m_editor_status == EditorStatus::Editing)
1272     {
1273         return m_input_connection.InterruptRead();
1274     }
1275     return false; // Interrupt not handled as we weren't getting a line or lines
1276 }
1277
1278 void
1279 Editline::SetAutoCompleteCallback (CompleteCallbackType callback, void * baton)
1280 {
1281     m_completion_callback = callback;
1282     m_completion_callback_baton = baton;
1283 }
1284
1285 void
1286 Editline::SetIsInputCompleteCallback (IsInputCompleteCallbackType callback, void * baton)
1287 {
1288     m_is_input_complete_callback = callback;
1289     m_is_input_complete_callback_baton = baton;
1290 }
1291
1292 bool
1293 Editline::SetFixIndentationCallback (FixIndentationCallbackType callback,
1294                                      void * baton,
1295                                      const char * indent_chars)
1296 {
1297     m_fix_indentation_callback = callback;
1298     m_fix_indentation_callback_baton = baton;
1299     m_fix_indentation_callback_chars = indent_chars;
1300     return false;
1301 }
1302
1303 bool
1304 Editline::GetLine (std::string &line, bool &interrupted)
1305 {
1306     ConfigureEditor (false);
1307     m_input_lines = std::vector<EditLineStringType>();
1308     m_input_lines.insert (m_input_lines.begin(), EditLineConstString(""));
1309     
1310     SetCurrentLine (0);
1311     m_in_history = false;
1312     m_editor_status = EditorStatus::Editing;
1313     m_editor_getting_char = false;
1314     m_revert_cursor_index = -1;
1315
1316     int count;
1317     auto input = el_wgets (m_editline, &count);
1318
1319     interrupted = m_editor_status == EditorStatus::Interrupted;
1320     if (!interrupted)
1321     {
1322         if (input == nullptr)
1323         {
1324             fprintf (m_output_file, "\n");
1325             m_editor_status = EditorStatus::EndOfInput;
1326         }
1327         else
1328         {
1329             m_history_sp->Enter (input);
1330 #if LLDB_EDITLINE_USE_WCHAR
1331             line = m_utf8conv.to_bytes (SplitLines (input)[0]);
1332 #else
1333             line = SplitLines (input)[0];
1334 #endif
1335             m_editor_status = EditorStatus::Complete;
1336         }
1337     }
1338     return m_editor_status != EditorStatus::EndOfInput;
1339 }
1340
1341 bool
1342 Editline::GetLines (int first_line_number, StringList &lines, bool &interrupted)
1343 {
1344     ConfigureEditor (true);
1345     
1346     // Print the initial input lines, then move the cursor back up to the start of input
1347     SetBaseLineNumber (first_line_number);
1348     m_input_lines = std::vector<EditLineStringType>();
1349     m_input_lines.insert (m_input_lines.begin(), EditLineConstString(""));
1350     
1351     // Begin the line editing loop
1352     DisplayInput();
1353     SetCurrentLine (0);
1354     MoveCursor (CursorLocation::BlockEnd, CursorLocation::BlockStart);
1355     m_editor_status = EditorStatus::Editing;
1356     m_editor_getting_char = false;
1357     m_in_history = false;
1358
1359     m_revert_cursor_index = -1;
1360     while (m_editor_status == EditorStatus::Editing)
1361     {
1362         int count;
1363         m_current_line_rows = -1;
1364         el_wpush (m_editline, EditLineConstString("\x1b[^")); // Revert to the existing line content
1365         el_wgets (m_editline, &count);
1366     }
1367     
1368     interrupted = m_editor_status == EditorStatus::Interrupted;
1369     if (!interrupted)
1370     {
1371         // Save the completed entry in history before returning
1372         m_history_sp->Enter (CombineLines (m_input_lines).c_str());
1373
1374         lines = GetInputAsStringList();
1375     }
1376     return m_editor_status != EditorStatus::EndOfInput;
1377 }