[Lldb-commits] [lldb] r275482 - Editing multi-line content in a terminal environment involves a lot of

Kate Stone via lldb-commits lldb-commits at lists.llvm.org
Thu Jul 14 15:00:04 PDT 2016


Author: kate
Date: Thu Jul 14 17:00:04 2016
New Revision: 275482

URL: http://llvm.org/viewvc/llvm-project?rev=275482&view=rev
Log:
Editing multi-line content in a terminal environment involves a lot of
trade-offs. When LLDB's multi-line editing support was first introduced
for expressions / REPL contexts the behavior was as follows:

* The Return key is treated as a line-break except at the end of the input
  buffer, where a completeness test is applied

This worked well enough when writing code, and makes it trivial to insert
new lines above code you've already typed. Just use cursor navigation to
move up and type freely. Where it was awkward is that the gesture to insert
a line break and end editing is conflated for most people. Sometimes you
want Return to end the editing session and other times you want to insert
a line break.

This commit changes the behavior as follows:

* The Return key is treated as the end of editing except at the end of the
  input buffer, where a completeness test is applied

* The Meta+Return sequence is always treated as a line break. This is
  consistent with conventions in Facebook and elsewhere since
  Alt/Option+Return is often mapped to Meta+Return. The unfortunate
  exception is on macOS where this *can* be the case, but isn't by
  default. Sigh.

Note that by design both before and after the patch pasting a Return
character always introduces a line break.

<rdar://problem/26886287>

Modified:
    lldb/trunk/include/lldb/Host/Editline.h
    lldb/trunk/source/Host/common/Editline.cpp

Modified: lldb/trunk/include/lldb/Host/Editline.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/Editline.h?rev=275482&r1=275481&r2=275482&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/Editline.h (original)
+++ lldb/trunk/include/lldb/Host/Editline.h Thu Jul 14 17:00:04 2016
@@ -279,11 +279,15 @@ namespace lldb_private {
         /// 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 @@ namespace lldb_private {
         /// 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);

Modified: lldb/trunk/source/Host/common/Editline.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Editline.cpp?rev=275482&r1=275481&r2=275482&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/Editline.cpp (original)
+++ lldb/trunk/source/Host/common/Editline.cpp Thu Jul 14 17:00:04 2016
@@ -657,41 +657,9 @@ Editline::BreakLineCommand (int ch)
     // 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,7 +688,49 @@ Editline::BreakLineCommand (int ch)
 }
 
 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<LineInfoW *>(el_wline (m_editline));
     
@@ -860,7 +870,23 @@ Editline::NextLineCommand (int ch)
 }
 
 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 @@ Editline::ConfigureEditor (bool multilin
     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 @@ Editline::ConfigureEditor (bool multilin
     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 @@ Editline::ConfigureEditor (bool multilin
     // 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 @@ Editline::ConfigureEditor (bool multilin
             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
         {




More information about the lldb-commits mailing list