Skip to content

Commit 33c958a

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 4647531 commit 33c958a

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
@@ -164,6 +164,10 @@ class Editline {
164164
/// of Editline.
165165
static Editline *InstanceFor(::EditLine *editline);
166166

167+
static void
168+
DisplayCompletions(Editline &editline,
169+
llvm::ArrayRef<CompletionResult::Completion> results);
170+
167171
/// Sets a string to be used as a prompt, or combined with a line number to
168172
/// form a prompt.
169173
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
@@ -940,12 +940,12 @@ PrintCompletion(FILE *output_file,
940940
}
941941
}
942942

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

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

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

959959
if (results.size() < page_size) {
960-
PrintCompletion(output_file, results, max_len);
960+
PrintCompletion(editline.m_output_file, results, max_len);
961961
return;
962962
}
963963

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

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

971972
cur_pos += next_size;
972973

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

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

1050-
DisplayCompletions(m_editline, m_output_file, results);
1058+
DisplayCompletions(*this, results);
10511059

10521060
DisplayInput();
10531061
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)