[Editline] Redesign automatic indentation fix command for robustness

The FixIndentationCommand implementation has proven to be fragile across various libedit iterations. This patch reworks the command to use the same basic strategy as when moving between lines in a multi-line edit session: when indentation changes are required, exit line editing completely and restart with amended content. This approach won't be susceptible to subtle behavior differences libedit has introduced over time.

llvm-svn: 255548
This commit is contained in:
Kate Stone 2015-12-14 21:43:59 +00:00
parent 798ea5b6ff
commit a11959dbf7
1 changed files with 33 additions and 20 deletions
lldb/source/Host/common

View File

@ -863,37 +863,50 @@ Editline::NextLineCommand (int ch)
unsigned char
Editline::FixIndentationCommand (int ch)
{
if (!m_fix_indentation_callback)
if (!m_fix_indentation_callback)
return CC_NORM;
// Insert the character by hand prior to correction
// Insert the character typed before proceeding
EditLineCharType inserted[] = { (EditLineCharType)ch, 0 };
el_winsertstr (m_editline, inserted);
SaveEditedLine();
StringList lines = GetInputAsStringList (m_current_line_index + 1);
// Determine the cursor position
LineInfoW * info = const_cast<LineInfoW *>(el_wline (m_editline));
int cursor_position = info->cursor - info->buffer;
// Save the edits and determine the correct indentation level
SaveEditedLine();
StringList lines = GetInputAsStringList (m_current_line_index + 1);
int indent_correction = m_fix_indentation_callback (this, lines, cursor_position, m_fix_indentation_callback_baton);
// Adjust the input buffer to correct indentation
// If it is already correct no special work is needed
if (indent_correction == 0)
return CC_REFRESH;
// Change the indentation level of the line
std::string currentLine = lines.GetStringAtIndex (m_current_line_index);
if (indent_correction > 0)
{
info->cursor = info->buffer;
el_winsertstr (m_editline, EditLineStringType (indent_correction, EditLineCharType(' ')).c_str());
currentLine = currentLine.insert (0, indent_correction, ' ');
}
else if (indent_correction < 0)
else
{
// Delete characters for the unindentation AND including the character we just added.
el_wdeletestr (m_editline, -indent_correction + 1);
// Rewrite the character that caused the unindentation.
el_winsertstr (m_editline, inserted);
currentLine = currentLine.erase (0, -indent_correction);
}
info->cursor = info->buffer + cursor_position + indent_correction;
return CC_REFRESH;
#if LLDB_EDITLINE_USE_WCHAR
m_input_lines[m_current_line_index] = m_utf8conv.from_bytes (currentLine);
#else
m_input_lines[m_current_line_index] = currentLine;
#endif
// Update the display to reflect the change
MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
DisplayInput (m_current_line_index);
// Reposition the cursor back on the original line and prepare to restart editing
// with a new cursor position
SetCurrentLine (m_current_line_index);
MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
m_revert_cursor_index = cursor_position + indent_correction;
return CC_NEWLINE;
}
unsigned char