Index: include/lldb/Host/Editline.h =================================================================== --- include/lldb/Host/Editline.h +++ include/lldb/Host/Editline.h @@ -279,11 +279,15 @@ /// Prompt implementation for EditLine. const char * Prompt(); - - /// Line break command used when return is pressed in multi-line mode. + + /// Line break command used when meta+return is pressed in multi-line mode. unsigned char BreakLineCommand (int ch); - + + /// Command used when return is pressed in multi-line mode. + unsigned char + EndOrAddLineCommand(int ch); + /// Delete command used when delete is pressed in multi-line mode. unsigned char DeleteNextCharCommand (int ch); @@ -299,7 +303,15 @@ /// Line navigation command used when ^N or down arrow are pressed in multi-line mode. unsigned char NextLineCommand (int ch); - + + /// History navigation command used when Alt + up arrow is pressed in multi-line mode. + unsigned char + PreviousHistoryCommand(int ch); + + /// History navigation command used when Alt + down arrow is pressed in multi-line mode. + unsigned char + NextHistoryCommand(int ch); + /// Buffer start command used when Esc < is typed in multi-line emacs mode. unsigned char BufferStartCommand (int ch); Index: source/Host/common/Editline.cpp =================================================================== --- source/Host/common/Editline.cpp +++ source/Host/common/Editline.cpp @@ -657,41 +657,9 @@ // Establish the new cursor position at the start of a line when inserting a line break m_revert_cursor_index = 0; - // Don't perform end of input detection or automatic formatting when pasting + // Don't perform automatic formatting when pasting if (!IsInputPending (m_input_file)) { - // If this is the end of the last line, treat this as a potential exit - if (m_current_line_index == m_input_lines.size() - 1 && new_line_fragment.length() == 0) - { - bool end_of_input = true; - if (m_is_input_complete_callback) - { - SaveEditedLine(); - auto lines = GetInputAsStringList(); - end_of_input = m_is_input_complete_callback (this, lines, m_is_input_complete_callback_baton); - - // The completion test is allowed to change the input lines when complete - if (end_of_input) - { - m_input_lines.clear(); - for (unsigned index = 0; index < lines.GetSize(); index++) - { -#if LLDB_EDITLINE_USE_WCHAR - m_input_lines.insert (m_input_lines.end(), m_utf8conv.from_bytes (lines[index])); -#else - m_input_lines.insert (m_input_lines.end(), lines[index]); -#endif - } - } - } - if (end_of_input) - { - fprintf (m_output_file, "\n"); - m_editor_status = EditorStatus::Complete; - return CC_NEWLINE; - } - } - // Apply smart indentation if (m_fix_indentation_callback) { @@ -720,8 +688,50 @@ } unsigned char -Editline::DeleteNextCharCommand (int ch) +Editline::EndOrAddLineCommand(int ch) { + // Don't perform end of input detection when pasting, always treat this as a line break + if (IsInputPending(m_input_file)) + { + return BreakLineCommand(ch); + } + + // Save any edits to this line + SaveEditedLine(); + + // If this is the end of the last line, consider whether to add a line instead + const LineInfoW *info = el_wline(m_editline); + if (m_current_line_index == m_input_lines.size() - 1 && info->cursor == info->lastchar) + { + if (m_is_input_complete_callback) + { + auto lines = GetInputAsStringList(); + if (!m_is_input_complete_callback(this, lines, m_is_input_complete_callback_baton)) + { + return BreakLineCommand(ch); + } + + // The completion test is allowed to change the input lines when complete + m_input_lines.clear(); + for (unsigned index = 0; index < lines.GetSize(); index++) + { +#if LLDB_EDITLINE_USE_WCHAR + m_input_lines.insert(m_input_lines.end(), m_utf8conv.from_bytes(lines[index])); +#else + m_input_lines.insert(m_input_lines.end(), lines[index]); +#endif + } + } + } + MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd); + fprintf(m_output_file, "\n"); + m_editor_status = EditorStatus::Complete; + return CC_NEWLINE; +} + +unsigned char +Editline::DeleteNextCharCommand(int ch) +{ LineInfoW * info = const_cast(el_wline (m_editline)); // Just delete the next character normally if possible @@ -860,8 +870,24 @@ } unsigned char -Editline::FixIndentationCommand (int ch) +Editline::PreviousHistoryCommand(int ch) { + SaveEditedLine(); + + return RecallHistory(true); +} + +unsigned char +Editline::NextHistoryCommand(int ch) +{ + SaveEditedLine(); + + return RecallHistory(false); +} + +unsigned char +Editline::FixIndentationCommand(int ch) +{ if (!m_fix_indentation_callback) return CC_NORM; @@ -1077,6 +1103,10 @@ el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-break-line"), EditLineConstString("Insert a line break"), (EditlineCommandCallbackType)( [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->BreakLineCommand(ch); })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-end-or-add-line"), + EditLineConstString("End editing or continue when incomplete"), + (EditlineCommandCallbackType)( + [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->EndOrAddLineCommand(ch); })); el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-delete-next-char"), EditLineConstString("Delete next character"), (EditlineCommandCallbackType)([](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch); @@ -1093,6 +1123,14 @@ el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-line"), EditLineConstString("Move to next line"), (EditlineCommandCallbackType)( [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->NextLineCommand(ch); })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-history"), + EditLineConstString("Move to previous history"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->PreviousHistoryCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-history"), EditLineConstString("Move to next history"), + (EditlineCommandCallbackType)( + [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->NextHistoryCommand(ch); })); el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-start"), EditLineConstString("Move to start of buffer"), (EditlineCommandCallbackType)( @@ -1149,8 +1187,10 @@ // Multi-line editor bindings if (multiline) { - el_set (m_editline, EL_BIND, "\n", "lldb-break-line", NULL); - el_set (m_editline, EL_BIND, "\r", "lldb-break-line", NULL); + el_set(m_editline, EL_BIND, "\n", "lldb-end-or-add-line", NULL); + el_set(m_editline, EL_BIND, "\r", "lldb-end-or-add-line", NULL); + el_set(m_editline, EL_BIND, ESCAPE "\n", "lldb-break-line", NULL); + el_set(m_editline, EL_BIND, ESCAPE "\r", "lldb-break-line", NULL); el_set (m_editline, EL_BIND, "^p", "lldb-previous-line", NULL); el_set (m_editline, EL_BIND, "^n", "lldb-next-line", NULL); el_set (m_editline, EL_BIND, "^?", "lldb-delete-previous-char", NULL); @@ -1165,6 +1205,10 @@ el_set (m_editline, EL_BIND, ESCAPE ">", "lldb-buffer-end", NULL); el_set (m_editline, EL_BIND, ESCAPE "[A", "lldb-previous-line", NULL); el_set (m_editline, EL_BIND, ESCAPE "[B", "lldb-next-line", NULL); + el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[A", "lldb-previous-history", NULL); + el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[B", "lldb-next-history", NULL); + el_set(m_editline, EL_BIND, ESCAPE "[1;3A", "lldb-previous-history", NULL); + el_set(m_editline, EL_BIND, ESCAPE "[1;3B", "lldb-next-history", NULL); } else {