Skip to content

Commit 0f339e6

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.
1 parent a5e10e2 commit 0f339e6

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
@@ -161,6 +161,10 @@ class Editline {
161161
/// of Editline.
162162
static Editline *InstanceFor(::EditLine *editline);
163163

164+
static void
165+
DisplayCompletions(Editline &editline,
166+
llvm::ArrayRef<CompletionResult::Completion> results);
167+
164168
/// Sets a string to be used as a prompt, or combined with a line number to
165169
/// form a prompt.
166170
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
@@ -943,12 +943,12 @@ PrintCompletion(FILE *output_file,
943943
}
944944
}
945945

946-
static void
947-
DisplayCompletions(::EditLine *editline, FILE *output_file,
948-
llvm::ArrayRef<CompletionResult::Completion> results) {
946+
void Editline::DisplayCompletions(
947+
Editline &editline, llvm::ArrayRef<CompletionResult::Completion> results) {
949948
assert(!results.empty());
950949

951-
fprintf(output_file, "\n" ANSI_CLEAR_BELOW "Available completions:\n");
950+
fprintf(editline.m_output_file,
951+
"\n" ANSI_CLEAR_BELOW "Available completions:\n");
952952
const size_t page_size = 40;
953953
bool all = false;
954954

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

962962
if (results.size() < page_size) {
963-
PrintCompletion(output_file, results, max_len);
963+
PrintCompletion(editline.m_output_file, results, max_len);
964964
return;
965965
}
966966

@@ -969,17 +969,25 @@ DisplayCompletions(::EditLine *editline, FILE *output_file,
969969
size_t remaining = results.size() - cur_pos;
970970
size_t next_size = all ? remaining : std::min(page_size, remaining);
971971

972-
PrintCompletion(output_file, results.slice(cur_pos, next_size), max_len);
972+
PrintCompletion(editline.m_output_file, results.slice(cur_pos, next_size),
973+
max_len);
973974

974975
cur_pos += next_size;
975976

976977
if (cur_pos >= results.size())
977978
break;
978979

979-
fprintf(output_file, "More (Y/n/a): ");
980+
fprintf(editline.m_output_file, "More (Y/n/a): ");
980981
char reply = 'n';
981-
int got_char = el_getc(editline, &reply);
982-
fprintf(output_file, "\n");
982+
int got_char = el_getc(editline.m_editline, &reply);
983+
// Check for a ^C or other interruption.
984+
if (editline.m_editor_status == EditorStatus::Interrupted) {
985+
editline.m_editor_status = EditorStatus::Editing;
986+
fprintf(editline.m_output_file, "^C\n");
987+
break;
988+
}
989+
990+
fprintf(editline.m_output_file, "\n");
983991
if (got_char == -1 || reply == 'n')
984992
break;
985993
if (reply == 'a')
@@ -1050,7 +1058,7 @@ unsigned char Editline::TabCommand(int ch) {
10501058
return CC_REDISPLAY;
10511059
}
10521060

1053-
DisplayCompletions(m_editline, m_output_file, results);
1061+
DisplayCompletions(*this, results);
10541062

10551063
DisplayInput();
10561064
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)