Index: include/lldb/Host/Editline.h =================================================================== --- include/lldb/Host/Editline.h +++ include/lldb/Host/Editline.h @@ -280,10 +280,14 @@ 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); @@ -300,6 +304,14 @@ 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); @@ -307,7 +319,7 @@ /// Buffer end command used when Esc > is typed in multi-line emacs mode. unsigned char BufferEndCommand (int ch); - + /// Context-sensitive tab insertion or code completion command used when the tab key is typed. unsigned char TabCommand (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,6 +688,47 @@ } unsigned char +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)); @@ -860,6 +869,22 @@ } unsigned char +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) @@ -1074,11 +1099,19 @@ })); // Commands used for multiline support, registered whether or not they're used - 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-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) { + EditLineConstString("Delete next character"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch); })); el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-delete-previous-char"), @@ -1087,21 +1120,38 @@ return Editline::InstanceFor(editline)->DeletePreviousCharCommand(ch); })); el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-line"), - EditLineConstString("Move to previous line"), (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + EditLineConstString("Move to previous line"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->PreviousLineCommand(ch); })); - 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-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)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->BufferStartCommand(ch); })); - el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-end"), EditLineConstString("Move to end of buffer"), - (EditlineCommandCallbackType)( - [](EditLine *editline, int ch) { return Editline::InstanceFor(editline)->BufferEndCommand(ch); })); + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->BufferStartCommand(ch); + })); + el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-end"), + EditLineConstString("Move to end of buffer"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + return Editline::InstanceFor(editline)->BufferEndCommand(ch); + })); el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-fix-indentation"), - EditLineConstString("Fix line indentation"), (EditlineCommandCallbackType)([](EditLine *editline, int ch) { + EditLineConstString("Fix line indentation"), + (EditlineCommandCallbackType)([](EditLine *editline, int ch) { return Editline::InstanceFor (editline)->FixIndentationCommand (ch); })); @@ -1149,8 +1199,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); @@ -1157,7 +1209,7 @@ el_set (m_editline, EL_BIND, "^d", "lldb-delete-next-char", NULL); el_set (m_editline, EL_BIND, ESCAPE "[3~", "lldb-delete-next-char", NULL); el_set (m_editline, EL_BIND, ESCAPE "[\\^", "lldb-revert-line", NULL); - + // Editor-specific bindings if (IsEmacs()) { @@ -1165,6 +1217,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 {