1 //===-- Editline.cpp --------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
24 using namespace lldb_private;
25 using namespace lldb_private::line_editor;
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.
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"
41 #if LLDB_EDITLINE_USE_WCHAR
43 #define EditLineConstString(str) L##str
44 #define EditLineStringFormatSpec "%ls"
48 #define EditLineConstString(str) str
49 #define EditLineStringFormatSpec "%s"
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
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
70 #endif // #if LLDB_EDITLINE_USE_WCHAR
73 IsOnlySpaces (const EditLineStringType & content)
75 for (wchar_t ch : content)
77 if (ch != EditLineCharType(' '))
84 CombineLines (const std::vector<EditLineStringType> & lines)
86 EditLineStringStreamType combined_stream;
87 for (EditLineStringType line : lines)
89 combined_stream << line.c_str() << "\n";
91 return combined_stream.str();
94 std::vector<EditLineStringType>
95 SplitLines (const EditLineStringType & input)
97 std::vector<EditLineStringType> result;
99 while (start < input.length())
101 size_t end = input.find ('\n', start);
102 if (end == std::string::npos)
104 result.insert (result.end(), input.substr (start));
107 result.insert (result.end(), input.substr (start, end - start));
114 FixIndentation (const EditLineStringType & line, int indent_correction)
116 if (indent_correction == 0)
118 if (indent_correction < 0)
119 return line.substr (-indent_correction);
120 return EditLineStringType (indent_correction, EditLineCharType(' ')) + line;
124 GetIndentation (const EditLineStringType & line)
127 for (EditLineCharType ch : line)
129 if (ch != EditLineCharType(' '))
137 IsInputPending (FILE * file)
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);
147 timeval timeout = { 0, 0 };
148 return select (fd + 1, &fds, NULL, NULL, &timeout);
151 namespace lldb_private
153 namespace line_editor
155 typedef std::weak_ptr<EditlineHistory> EditlineHistoryWP;
157 // EditlineHistory objects are sometimes shared between multiple
158 // Editline instances with the same program name.
160 class EditlineHistory
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) :
170 m_history = history_winit();
171 history_w (m_history, &m_event, H_SETSIZE, size);
173 history_w (m_history, &m_event, H_SETUNIQUE, 1);
179 if (m_path.empty() && m_history && !m_prefix.empty())
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())
185 snprintf (history_path, sizeof (history_path), "~/.lldb/%s-history", m_prefix.c_str());
189 snprintf (history_path, sizeof (history_path), "~/%s-widehistory", m_prefix.c_str());
191 m_path = std::move (FileSpec (history_path, true).GetPath());
195 return m_path.c_str();
206 history_wend (m_history);
211 static EditlineHistorySP
212 GetHistory (const std::string &prefix)
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())
222 history_sp = pos->second.lock();
225 g_weak_map.erase (pos);
227 history_sp.reset (new EditlineHistory (prefix, 800, true));
228 g_weak_map[prefix] = history_sp;
234 return m_history != NULL;
244 Enter (const EditLineCharType *line_cstr)
247 history_w (m_history, &m_event, H_ENTER, line_cstr);
255 const char *path = GetHistoryFilePath();
258 history_w (m_history, &m_event, H_LOAD, path);
270 const char *path = GetHistoryFilePath();
273 history_w (m_history, &m_event, H_SAVE, path);
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
289 //------------------------------------------------------------------
290 // Editline private methods
291 //------------------------------------------------------------------
294 Editline::SetBaseLineNumber (int line_number)
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);
303 Editline::PromptForIndex (int line_index)
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)
311 std::string continuation_prompt = prompt;
312 if (m_set_continuation_prompt.length() > 0)
314 continuation_prompt = m_set_continuation_prompt;
316 // Ensure that both prompts are the same length through space padding
317 while (continuation_prompt.length() < prompt.length())
319 continuation_prompt += ' ';
321 while (prompt.length() < continuation_prompt.length())
327 if (use_line_numbers)
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());
334 return (line_index == 0) ? prompt : continuation_prompt;
338 Editline::SetCurrentLine (int line_index)
340 m_current_line_index = line_index;
341 m_current_prompt = PromptForIndex (line_index);
345 Editline::GetPromptWidth()
347 return (int)PromptForIndex (0).length();
354 el_get (m_editline, EL_EDITOR, &editor);
355 return editor[0] == 'e';
359 Editline::IsOnlySpaces()
361 const LineInfoW * info = el_wline (m_editline);
362 for (const EditLineCharType * character = info->buffer; character < info->lastchar; character++)
364 if (*character != ' ')
371 Editline::GetLineIndexForLocation (CursorLocation location, int cursor_row)
374 if (location == CursorLocation::EditingPrompt || location == CursorLocation::BlockEnd ||
375 location == CursorLocation::EditingCursor)
377 for (unsigned index = 0; index < m_current_line_index; index++)
379 line += CountRowsForLine (m_input_lines[index]);
381 if (location == CursorLocation::EditingCursor)
385 else if (location == CursorLocation::BlockEnd)
387 for (unsigned index = m_current_line_index; index < m_input_lines.size(); index++)
389 line += CountRowsForLine (m_input_lines[index]);
398 Editline::MoveCursor (CursorLocation from, CursorLocation to)
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;
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)
409 fprintf (m_output_file, (toLine > fromLine) ? ANSI_DOWN_N_ROWS : ANSI_UP_N_ROWS, std::abs (toLine - fromLine));
412 // Determine target column
414 if (to == CursorLocation::EditingCursor)
416 toColumn = editline_cursor_position - (editline_cursor_row * m_terminal_width) + 1;
418 else if (to == CursorLocation::BlockEnd)
420 toColumn = ((m_input_lines[m_input_lines.size() - 1].length() + GetPromptWidth()) % 80) + 1;
422 fprintf (m_output_file, ANSI_SET_COLUMN_N, toColumn);
426 Editline::DisplayInput (int firstIndex)
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 : "";
433 for (int index = firstIndex; index < line_count; index++)
435 fprintf (m_output_file, "%s" "%s" "%s" EditLineStringFormatSpec " ",
437 PromptForIndex (index).c_str(),
439 m_input_lines[index].c_str());
440 if (index < line_count - 1)
441 fprintf (m_output_file, "\n");
447 Editline::CountRowsForLine (const EditLineStringType & content)
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;
455 Editline::SaveEditedLine()
457 const LineInfoW * info = el_wline (m_editline);
458 m_input_lines[m_current_line_index] = EditLineStringType (info->buffer, info->lastchar - info->buffer);
462 Editline::GetInputAsStringList(int line_count)
465 for (EditLineStringType line : m_input_lines)
469 #if LLDB_EDITLINE_USE_WCHAR
470 lines.AppendString (m_utf8conv.to_bytes (line));
472 lines.AppendString(line);
480 Editline::RecallHistory (bool earlier)
482 if (!m_history_sp || !m_history_sp->IsValid())
485 HistoryW * pHistory = m_history_sp->GetHistoryPtr();
486 HistEventW history_event;
487 std::vector<EditLineStringType> new_input_lines;
489 // Treat moving from the "live" entry differently
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)
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.)
501 m_live_history_lines = m_input_lines;
506 if (history_w (pHistory, &history_event, earlier ? H_NEXT : H_PREV) == -1)
508 // Can't move earlier than the earliest entry
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;
518 // If we're pulling the lines from history, split them apart
520 new_input_lines = SplitLines (history_event.str);
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;
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);
535 Editline::GetCharacter (EditLineCharType * c)
537 const LineInfoW * info = el_wline (m_editline);
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)
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;
549 if (m_multiline_enabled)
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)
556 // Respond by repainting the current state from this line on
557 MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
559 DisplayInput (m_current_line_index);
560 MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingCursor);
562 m_current_line_rows = new_line_rows;
565 // Read an actual character
568 lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
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;
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);
591 case lldb::eConnectionStatusInterrupted:
592 m_editor_status = EditorStatus::Interrupted;
596 case lldb::eConnectionStatusSuccess: // Success
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;
615 m_needs_prompt_repaint = true;
616 return m_current_prompt.c_str();
620 Editline::BreakLineCommand (int ch)
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;
628 // Ignore whitespace-only extra fragments when breaking a line
629 if (::IsOnlySpaces (new_line_fragment))
630 new_line_fragment = EditLineConstString("");
632 // Establish the new cursor position at the start of a line when inserting a line break
633 m_revert_cursor_index = 0;
635 // Don't perform end of input detection or automatic formatting when pasting
636 if (!IsInputPending (m_input_file))
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)
641 bool end_of_input = true;
642 if (m_is_input_complete_callback)
645 auto lines = GetInputAsStringList();
646 end_of_input = m_is_input_complete_callback (this, lines, m_is_input_complete_callback_baton);
648 // The completion test is allowed to change the input lines when complete
651 m_input_lines.clear();
652 for (unsigned index = 0; index < lines.GetSize(); index++)
654 #if LLDB_EDITLINE_USE_WCHAR
655 m_input_lines.insert (m_input_lines.end(), m_utf8conv.from_bytes (lines[index]));
657 m_input_lines.insert (m_input_lines.end(), lines[index]);
664 fprintf (m_output_file, "\n");
665 m_editor_status = EditorStatus::Complete;
670 // Apply smart indentation
671 if (m_fix_indentation_callback)
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));
677 lines.AppendString (new_line_fragment);
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);
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);
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);
698 Editline::DeleteNextCharCommand (int ch)
700 LineInfoW * info = (LineInfoW *)el_wline (m_editline);
702 // Just delete the next character normally if possible
703 if (info->cursor < info->lastchar)
706 el_deletestr (m_editline, 1);
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)
714 if (ch == 4 && info->buffer == info->lastchar)
716 fprintf (m_output_file, "^D\n");
717 m_editor_status = EditorStatus::EndOfInput;
723 // Prepare to combine this line with the one below
724 MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
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;
732 // Delete the extra line
733 m_input_lines.erase (m_input_lines.begin() + m_current_line_index + 1);
735 // Clear and repaint from this line on down
736 DisplayInput (m_current_line_index);
737 MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingCursor);
742 Editline::DeletePreviousCharCommand (int ch)
744 LineInfoW * info = (LineInfoW *)el_wline (m_editline);
746 // Just delete the previous character normally when not at the start of a line
747 if (info->cursor > info->buffer)
749 el_deletestr (m_editline, 1);
753 // No prior line and no prior character? Let the user know
754 if (m_current_line_index == 0)
757 // No prior character, but prior line? Combine with the line above
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];
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);
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());
776 Editline::PreviousLineCommand (int ch)
780 if (m_current_line_index == 0) {
781 return RecallHistory (true);
784 // Start from a known location
785 MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
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())
790 m_input_lines.erase (m_input_lines.begin() + m_current_line_index);
791 fprintf (m_output_file, ANSI_CLEAR_BELOW);
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);
801 Editline::NextLineCommand (int ch)
805 // Handle attempts to move down from the last line
806 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 history instead
811 return RecallHistory (false);
814 // Determine indentation for the new line
816 if (m_fix_indentation_callback)
818 StringList lines = GetInputAsStringList();
819 lines.AppendString("");
820 indentation = m_fix_indentation_callback (this, lines, 0, m_fix_indentation_callback_baton);
822 m_input_lines.insert (m_input_lines.end(), EditLineStringType (indentation, EditLineCharType(' ')));
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++)
832 fprintf (m_output_file, "\n");
838 Editline::FixIndentationCommand (int ch)
840 if (!m_fix_indentation_callback)
843 // Insert the character by hand prior to correction
844 EditLineCharType inserted[] = { (EditLineCharType)ch, 0 };
845 el_winsertstr (m_editline, inserted);
847 StringList lines = GetInputAsStringList (m_current_line_index + 1);
849 // Determine the cursor position
850 LineInfoW * info = (LineInfoW *)el_wline (m_editline);
851 int cursor_position = info->cursor - info->buffer;
853 int indent_correction = m_fix_indentation_callback (this, lines, cursor_position, m_fix_indentation_callback_baton);
855 // Adjust the input buffer to correct indentation
856 if (indent_correction > 0)
858 info->cursor = info->buffer;
859 el_winsertstr (m_editline, EditLineStringType (indent_correction, EditLineCharType(' ')).c_str());
861 else if (indent_correction < 0)
863 info->cursor = info->buffer - indent_correction;
864 el_wdeletestr (m_editline, -indent_correction);
866 info->cursor = info->buffer + cursor_position + indent_correction;
871 Editline::RevertLineCommand (int ch)
873 el_winsertstr (m_editline, m_input_lines[m_current_line_index].c_str());
874 if (m_revert_cursor_index >= 0)
876 LineInfoW * info = (LineInfoW *)el_wline (m_editline);
877 info->cursor = info->buffer + m_revert_cursor_index;
878 if (info->cursor > info->lastchar)
880 info->cursor = info->lastchar;
882 m_revert_cursor_index = -1;
888 Editline::BufferStartCommand (int ch)
891 MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockStart);
893 m_revert_cursor_index = 0;
898 Editline::BufferEndCommand (int ch)
901 MoveCursor (CursorLocation::EditingCursor, CursorLocation::BlockEnd);
902 SetCurrentLine ((int)m_input_lines.size() - 1);
903 MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
908 Editline::TabCommand (int ch)
910 if (m_completion_callback == nullptr)
913 const LineInfo *line_info = el_line (m_editline);
914 StringList completions;
917 const int num_completions = m_completion_callback (line_info->buffer,
920 0, // Don't skip any matches (start at match zero)
921 -1, // Get all the matches
923 m_completion_callback_baton);
925 if (num_completions == 0)
927 // if (num_completions == -1)
929 // el_insertstr (m_editline, m_completion_key);
930 // return CC_REDISPLAY;
933 if (num_completions == -2)
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));
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')
945 el_insertstr (m_editline, completion_str);
949 if (num_completions > 1)
951 int num_elements = num_completions + 1;
952 fprintf (m_output_file, "\n" ANSI_CLEAR_BELOW "Available completions:");
953 if (num_completions < page_size)
955 for (int i = 1; i < num_elements; i++)
957 completion_str = completions.GetStringAtIndex (i);
958 fprintf (m_output_file, "\n\t%s", completion_str);
960 fprintf (m_output_file, "\n");
967 while (cur_pos < num_elements)
969 int endpoint = cur_pos + page_size;
970 if (endpoint > num_elements)
971 endpoint = num_elements;
972 for (; cur_pos < endpoint; cur_pos++)
974 completion_str = completions.GetStringAtIndex (cur_pos);
975 fprintf (m_output_file, "\n\t%s", completion_str);
978 if (cur_pos >= num_elements)
980 fprintf (m_output_file, "\n");
984 fprintf (m_output_file, "\nMore (Y/n/a): ");
986 got_char = el_getc(m_editline, &reply);
987 if (got_char == -1 || reply == 'n')
990 page_size = num_elements - cur_pos;
994 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
1000 Editline::ConfigureEditor (bool multiline)
1002 if (m_editline && m_multiline_enabled == multiline)
1004 m_multiline_enabled = multiline;
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);
1015 m_editline = el_init (m_editor_name.c_str(), m_input_file, m_output_file, m_error_file);
1016 TerminalSizeChanged();
1018 if (m_history_sp && m_history_sp->IsValid())
1020 m_history_sp->Load();
1021 el_wset (m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr());
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();
1030 el_wset (m_editline, EL_GETCFN,
1031 (EditlineGetCharCallbackType)([] (EditLine * editline, EditLineCharType * c) {
1032 return Editline::InstanceFor (editline)->GetCharacter (c);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1079 // General bindings we don't mind being overridden
1081 el_set (m_editline, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string
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
1086 // Allow user-specific customization prior to registering bindings we absolutely require
1087 el_source (m_editline, NULL);
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);
1095 // Register keys that perform auto-indent correction
1096 if (m_fix_indentation_callback && m_fix_indentation_callback_chars)
1098 char bind_key[2] = { 0, 0 };
1099 const char * indent_chars = m_fix_indentation_callback_chars;
1100 while (*indent_chars)
1102 bind_key[0] = *indent_chars;
1103 el_set (m_editline, EL_BIND, bind_key, "lldb-fix-indentation", NULL);
1108 // Multi-line editor bindings
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);
1120 // Editor-specific bindings
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);
1130 el_set (m_editline, EL_BIND, "^H", "lldb-delete-previous-char", NULL);
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);
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);
1147 //------------------------------------------------------------------
1148 // Editline public methods
1149 //------------------------------------------------------------------
1152 Editline::InstanceFor (EditLine * editline)
1155 el_get (editline, EL_CLIENTDATA, &editor);
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)
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);
1172 Editline::~Editline()
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;
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();
1192 Editline::SetPrompt (const char * prompt)
1194 m_set_prompt = prompt == nullptr ? "" : prompt;
1198 Editline::SetContinuationPrompt (const char * continuation_prompt)
1200 m_set_continuation_prompt = continuation_prompt == nullptr ? "" : continuation_prompt;
1204 Editline::TerminalSizeChanged()
1206 if (m_editline != nullptr)
1208 el_resize (m_editline);
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)
1213 m_terminal_width = columns;
1214 if (m_current_line_rows != -1)
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;
1223 m_terminal_width = INT_MAX;
1224 m_current_line_rows = 1;
1230 Editline::GetPrompt()
1232 return m_set_prompt.c_str();
1236 Editline::GetCurrentLine()
1238 return m_current_line_index;
1244 // Make sure we're at a stable location waiting for input
1245 while (m_editor_status == EditorStatus::Editing && !m_editor_getting_char)
1250 // Clear the existing input
1251 if (m_editor_status == EditorStatus::Editing)
1253 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
1254 fprintf(m_output_file, ANSI_CLEAR_BELOW);
1261 if (m_editor_status == EditorStatus::Editing)
1264 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
1269 Editline::Interrupt()
1271 if (m_editor_status == EditorStatus::Editing)
1273 return m_input_connection.InterruptRead();
1275 return false; // Interrupt not handled as we weren't getting a line or lines
1279 Editline::SetAutoCompleteCallback (CompleteCallbackType callback, void * baton)
1281 m_completion_callback = callback;
1282 m_completion_callback_baton = baton;
1286 Editline::SetIsInputCompleteCallback (IsInputCompleteCallbackType callback, void * baton)
1288 m_is_input_complete_callback = callback;
1289 m_is_input_complete_callback_baton = baton;
1293 Editline::SetFixIndentationCallback (FixIndentationCallbackType callback,
1295 const char * indent_chars)
1297 m_fix_indentation_callback = callback;
1298 m_fix_indentation_callback_baton = baton;
1299 m_fix_indentation_callback_chars = indent_chars;
1304 Editline::GetLine (std::string &line, bool &interrupted)
1306 ConfigureEditor (false);
1307 m_input_lines = std::vector<EditLineStringType>();
1308 m_input_lines.insert (m_input_lines.begin(), EditLineConstString(""));
1311 m_in_history = false;
1312 m_editor_status = EditorStatus::Editing;
1313 m_editor_getting_char = false;
1314 m_revert_cursor_index = -1;
1317 auto input = el_wgets (m_editline, &count);
1319 interrupted = m_editor_status == EditorStatus::Interrupted;
1322 if (input == nullptr)
1324 fprintf (m_output_file, "\n");
1325 m_editor_status = EditorStatus::EndOfInput;
1329 m_history_sp->Enter (input);
1330 #if LLDB_EDITLINE_USE_WCHAR
1331 line = m_utf8conv.to_bytes (SplitLines (input)[0]);
1333 line = SplitLines (input)[0];
1335 m_editor_status = EditorStatus::Complete;
1338 return m_editor_status != EditorStatus::EndOfInput;
1342 Editline::GetLines (int first_line_number, StringList &lines, bool &interrupted)
1344 ConfigureEditor (true);
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(""));
1351 // Begin the line editing loop
1354 MoveCursor (CursorLocation::BlockEnd, CursorLocation::BlockStart);
1355 m_editor_status = EditorStatus::Editing;
1356 m_editor_getting_char = false;
1357 m_in_history = false;
1359 m_revert_cursor_index = -1;
1360 while (m_editor_status == EditorStatus::Editing)
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);
1368 interrupted = m_editor_status == EditorStatus::Interrupted;
1371 // Save the completed entry in history before returning
1372 m_history_sp->Enter (CombineLines (m_input_lines).c_str());
1374 lines = GetInputAsStringList();
1376 return m_editor_status != EditorStatus::EndOfInput;