Skip to content

Commit a05e769

Browse files
committed
Fix a bug in handling ^C at the "y/n/a" completion prompt.
We just forget to check for interrupt while waiting for the answer to the prompt. But if we are in the interrupt state then the lower layers of the EditLine code just eat all characters so we never get out of the query prompt. You're pretty much stuck and have to kill lldb. The solution is to check for the interrupt. The patch is a little bigger because where I needed to check the Interrupt state I only had the ::EditLine object, but the editor state is held in lldb's EditLine wrapper, so I had to do a little work to get my hands on it. (cherry picked from commit 0f339e6)
1 parent 5641077 commit a05e769

File tree

3 files changed

+28
-10
lines changed

3 files changed

+28
-10
lines changed

lldb/include/lldb/Host/Editline.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ class Editline {
163163
/// of Editline.
164164
static Editline *InstanceFor(::EditLine *editline);
165165

166+
static void
167+
DisplayCompletions(Editline &editline,
168+
llvm::ArrayRef<CompletionResult::Completion> results);
169+
166170
/// Sets a string to be used as a prompt, or combined with a line number to
167171
/// form a prompt.
168172
void SetPrompt(const char *prompt);

lldb/source/Host/common/Editline.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -939,12 +939,12 @@ PrintCompletion(FILE *output_file,
939939
}
940940
}
941941

942-
static void
943-
DisplayCompletions(::EditLine *editline, FILE *output_file,
944-
llvm::ArrayRef<CompletionResult::Completion> results) {
942+
void Editline::DisplayCompletions(
943+
Editline &editline, llvm::ArrayRef<CompletionResult::Completion> results) {
945944
assert(!results.empty());
946945

947-
fprintf(output_file, "\n" ANSI_CLEAR_BELOW "Available completions:\n");
946+
fprintf(editline.m_output_file,
947+
"\n" ANSI_CLEAR_BELOW "Available completions:\n");
948948
const size_t page_size = 40;
949949
bool all = false;
950950

@@ -956,7 +956,7 @@ DisplayCompletions(::EditLine *editline, FILE *output_file,
956956
const size_t max_len = longest->GetCompletion().size();
957957

958958
if (results.size() < page_size) {
959-
PrintCompletion(output_file, results, max_len);
959+
PrintCompletion(editline.m_output_file, results, max_len);
960960
return;
961961
}
962962

@@ -965,17 +965,25 @@ DisplayCompletions(::EditLine *editline, FILE *output_file,
965965
size_t remaining = results.size() - cur_pos;
966966
size_t next_size = all ? remaining : std::min(page_size, remaining);
967967

968-
PrintCompletion(output_file, results.slice(cur_pos, next_size), max_len);
968+
PrintCompletion(editline.m_output_file, results.slice(cur_pos, next_size),
969+
max_len);
969970

970971
cur_pos += next_size;
971972

972973
if (cur_pos >= results.size())
973974
break;
974975

975-
fprintf(output_file, "More (Y/n/a): ");
976+
fprintf(editline.m_output_file, "More (Y/n/a): ");
976977
char reply = 'n';
977-
int got_char = el_getc(editline, &reply);
978-
fprintf(output_file, "\n");
978+
int got_char = el_getc(editline.m_editline, &reply);
979+
// Check for a ^C or other interruption.
980+
if (editline.m_editor_status == EditorStatus::Interrupted) {
981+
editline.m_editor_status = EditorStatus::Editing;
982+
fprintf(editline.m_output_file, "^C\n");
983+
break;
984+
}
985+
986+
fprintf(editline.m_output_file, "\n");
979987
if (got_char == -1 || reply == 'n')
980988
break;
981989
if (reply == 'a')
@@ -1046,7 +1054,7 @@ unsigned char Editline::TabCommand(int ch) {
10461054
return CC_REDISPLAY;
10471055
}
10481056

1049-
DisplayCompletions(m_editline, m_output_file, results);
1057+
DisplayCompletions(*this, results);
10501058

10511059
DisplayInput();
10521060
MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);

lldb/test/API/iohandler/completion/TestIOHandlerCompletion.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ def test_completion(self):
7575
self.child.send("n")
7676
self.expect_prompt()
7777

78+
# Start tab completion and abort showing more commands with '^C'.
79+
self.child.send("\t")
80+
self.child.expect_exact("More (Y/n/a)")
81+
self.child.sendcontrol("c")
82+
self.expect_prompt()
83+
7884
# Shouldn't crash or anything like that.
7985
self.child.send("regoinvalid\t")
8086
self.expect_prompt()

0 commit comments

Comments
 (0)