comparison lldb/source/Host/common/Editline.cpp @ 221:79ff65ed7e25

LLVM12 Original
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 15 Jun 2021 19:15:29 +0900
parents 0572611fdcc8
children c4bab56944e8
comparison
equal deleted inserted replaced
220:42394fc6a535 221:79ff65ed7e25
4 // See https://llvm.org/LICENSE.txt for license information. 4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 // 6 //
7 //===----------------------------------------------------------------------===// 7 //===----------------------------------------------------------------------===//
8 8
9 #include <climits>
9 #include <iomanip> 10 #include <iomanip>
10 #include <iostream> 11
11 #include <limits.h> 12 #include "lldb/Host/Editline.h"
12 13
13 #include "lldb/Host/ConnectionFileDescriptor.h" 14 #include "lldb/Host/ConnectionFileDescriptor.h"
14 #include "lldb/Host/Editline.h"
15 #include "lldb/Host/FileSystem.h" 15 #include "lldb/Host/FileSystem.h"
16 #include "lldb/Host/Host.h" 16 #include "lldb/Host/Host.h"
17 #include "lldb/Utility/CompletionRequest.h" 17 #include "lldb/Utility/CompletionRequest.h"
18 #include "lldb/Utility/FileSpec.h" 18 #include "lldb/Utility/FileSpec.h"
19 #include "lldb/Utility/LLDBAssert.h" 19 #include "lldb/Utility/LLDBAssert.h"
47 // multi-line block of text with a single line editor. Preserving this 47 // multi-line block of text with a single line editor. Preserving this
48 // illusion requires fairly careful management of cursor state. Read and 48 // illusion requires fairly careful management of cursor state. Read and
49 // understand the relationship between DisplayInput(), MoveCursor(), 49 // understand the relationship between DisplayInput(), MoveCursor(),
50 // SetCurrentLine(), and SaveEditedLine() before making changes. 50 // SetCurrentLine(), and SaveEditedLine() before making changes.
51 51
52 /// https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
52 #define ESCAPE "\x1b" 53 #define ESCAPE "\x1b"
54 /// Faint, decreased intensity or second colour.
53 #define ANSI_FAINT ESCAPE "[2m" 55 #define ANSI_FAINT ESCAPE "[2m"
54 #define ANSI_UNFAINT ESCAPE "[22m" 56 /// Normal colour or normal intensity (neither bold nor faint).
57 #define ANSI_UNFAINT ESCAPE "[0m"
55 #define ANSI_CLEAR_BELOW ESCAPE "[J" 58 #define ANSI_CLEAR_BELOW ESCAPE "[J"
56 #define ANSI_CLEAR_RIGHT ESCAPE "[K" 59 #define ANSI_CLEAR_RIGHT ESCAPE "[K"
57 #define ANSI_SET_COLUMN_N ESCAPE "[%dG" 60 #define ANSI_SET_COLUMN_N ESCAPE "[%dG"
58 #define ANSI_UP_N_ROWS ESCAPE "[%dA" 61 #define ANSI_UP_N_ROWS ESCAPE "[%dA"
59 #define ANSI_DOWN_N_ROWS ESCAPE "[%dB" 62 #define ANSI_DOWN_N_ROWS ESCAPE "[%dB"
148 break; 151 break;
149 } 152 }
150 result.push_back(input.substr(start, end - start)); 153 result.push_back(input.substr(start, end - start));
151 start = end + 1; 154 start = end + 1;
152 } 155 }
156 // Treat an empty history session as a single command of zero-length instead
157 // of returning an empty vector.
158 if (result.empty()) {
159 result.emplace_back();
160 }
153 return result; 161 return result;
154 } 162 }
155 163
156 EditLineStringType FixIndentation(const EditLineStringType &line, 164 EditLineStringType FixIndentation(const EditLineStringType &line,
157 int indent_correction) { 165 int indent_correction) {
206 214
207 const char *GetHistoryFilePath() { 215 const char *GetHistoryFilePath() {
208 // Compute the history path lazily. 216 // Compute the history path lazily.
209 if (m_path.empty() && m_history && !m_prefix.empty()) { 217 if (m_path.empty() && m_history && !m_prefix.empty()) {
210 llvm::SmallString<128> lldb_history_file; 218 llvm::SmallString<128> lldb_history_file;
211 llvm::sys::path::home_directory(lldb_history_file); 219 FileSystem::Instance().GetHomeDirectory(lldb_history_file);
212 llvm::sys::path::append(lldb_history_file, ".lldb"); 220 llvm::sys::path::append(lldb_history_file, ".lldb");
213 221
214 // LLDB stores its history in ~/.lldb/. If for some reason this directory 222 // LLDB stores its history in ~/.lldb/. If for some reason this directory
215 // isn't writable or cannot be created, history won't be available. 223 // isn't writable or cannot be created, history won't be available.
216 if (!llvm::sys::fs::create_directory(lldb_history_file)) { 224 if (!llvm::sys::fs::create_directory(lldb_history_file)) {
637 lines.AppendString(m_utf8conv.to_bytes(new_line_fragment)); 645 lines.AppendString(m_utf8conv.to_bytes(new_line_fragment));
638 #else 646 #else
639 lines.AppendString(new_line_fragment); 647 lines.AppendString(new_line_fragment);
640 #endif 648 #endif
641 649
642 int indent_correction = m_fix_indentation_callback( 650 int indent_correction = m_fix_indentation_callback(this, lines, 0);
643 this, lines, 0, m_fix_indentation_callback_baton);
644 new_line_fragment = FixIndentation(new_line_fragment, indent_correction); 651 new_line_fragment = FixIndentation(new_line_fragment, indent_correction);
645 m_revert_cursor_index = GetIndentation(new_line_fragment); 652 m_revert_cursor_index = GetIndentation(new_line_fragment);
646 } 653 }
647 } 654 }
648 655
673 const LineInfoW *info = el_wline(m_editline); 680 const LineInfoW *info = el_wline(m_editline);
674 if (m_current_line_index == m_input_lines.size() - 1 && 681 if (m_current_line_index == m_input_lines.size() - 1 &&
675 info->cursor == info->lastchar) { 682 info->cursor == info->lastchar) {
676 if (m_is_input_complete_callback) { 683 if (m_is_input_complete_callback) {
677 auto lines = GetInputAsStringList(); 684 auto lines = GetInputAsStringList();
678 if (!m_is_input_complete_callback(this, lines, 685 if (!m_is_input_complete_callback(this, lines)) {
679 m_is_input_complete_callback_baton)) {
680 return BreakLineCommand(ch); 686 return BreakLineCommand(ch);
681 } 687 }
682 688
683 // The completion test is allowed to change the input lines when complete 689 // The completion test is allowed to change the input lines when complete
684 m_input_lines.clear(); 690 m_input_lines.clear();
807 // Determine indentation for the new line 813 // Determine indentation for the new line
808 int indentation = 0; 814 int indentation = 0;
809 if (m_fix_indentation_callback) { 815 if (m_fix_indentation_callback) {
810 StringList lines = GetInputAsStringList(); 816 StringList lines = GetInputAsStringList();
811 lines.AppendString(""); 817 lines.AppendString("");
812 indentation = m_fix_indentation_callback( 818 indentation = m_fix_indentation_callback(this, lines, 0);
813 this, lines, 0, m_fix_indentation_callback_baton);
814 } 819 }
815 m_input_lines.insert( 820 m_input_lines.insert(
816 m_input_lines.end(), 821 m_input_lines.end(),
817 EditLineStringType(indentation, EditLineCharType(' '))); 822 EditLineStringType(indentation, EditLineCharType(' ')));
818 } 823 }
853 int cursor_position = info->cursor - info->buffer; 858 int cursor_position = info->cursor - info->buffer;
854 859
855 // Save the edits and determine the correct indentation level 860 // Save the edits and determine the correct indentation level
856 SaveEditedLine(); 861 SaveEditedLine();
857 StringList lines = GetInputAsStringList(m_current_line_index + 1); 862 StringList lines = GetInputAsStringList(m_current_line_index + 1);
858 int indent_correction = m_fix_indentation_callback( 863 int indent_correction =
859 this, lines, cursor_position, m_fix_indentation_callback_baton); 864 m_fix_indentation_callback(this, lines, cursor_position);
860 865
861 // If it is already correct no special work is needed 866 // If it is already correct no special work is needed
862 if (indent_correction == 0) 867 if (indent_correction == 0)
863 return CC_REFRESH; 868 return CC_REFRESH;
864 869
973 all = true; 978 all = true;
974 } 979 }
975 } 980 }
976 981
977 unsigned char Editline::TabCommand(int ch) { 982 unsigned char Editline::TabCommand(int ch) {
978 if (m_completion_callback == nullptr) 983 if (!m_completion_callback)
979 return CC_ERROR; 984 return CC_ERROR;
980 985
981 const LineInfo *line_info = el_line(m_editline); 986 const LineInfo *line_info = el_line(m_editline);
982 987
983 llvm::StringRef line(line_info->buffer, 988 llvm::StringRef line(line_info->buffer,
984 line_info->lastchar - line_info->buffer); 989 line_info->lastchar - line_info->buffer);
985 unsigned cursor_index = line_info->cursor - line_info->buffer; 990 unsigned cursor_index = line_info->cursor - line_info->buffer;
986 CompletionResult result; 991 CompletionResult result;
987 CompletionRequest request(line, cursor_index, result); 992 CompletionRequest request(line, cursor_index, result);
988 993
989 m_completion_callback(request, m_completion_callback_baton); 994 m_completion_callback(request);
990 995
991 llvm::ArrayRef<CompletionResult::Completion> results = result.GetResults(); 996 llvm::ArrayRef<CompletionResult::Completion> results = result.GetResults();
992 997
993 StringList completions; 998 StringList completions;
994 result.GetMatches(completions); 999 result.GetMatches(completions);
1000 CompletionResult::Completion completion = results.front(); 1005 CompletionResult::Completion completion = results.front();
1001 switch (completion.GetMode()) { 1006 switch (completion.GetMode()) {
1002 case CompletionMode::Normal: { 1007 case CompletionMode::Normal: {
1003 std::string to_add = completion.GetCompletion(); 1008 std::string to_add = completion.GetCompletion();
1004 to_add = to_add.substr(request.GetCursorArgumentPrefix().size()); 1009 to_add = to_add.substr(request.GetCursorArgumentPrefix().size());
1005 if (request.GetParsedArg().IsQuoted()) 1010 // Terminate the current argument with a quote if it started with a quote.
1011 if (!request.GetParsedLine().empty() && request.GetParsedArg().IsQuoted())
1006 to_add.push_back(request.GetParsedArg().GetQuoteChar()); 1012 to_add.push_back(request.GetParsedArg().GetQuoteChar());
1007 to_add.push_back(' '); 1013 to_add.push_back(' ');
1008 el_insertstr(m_editline, to_add.c_str()); 1014 el_insertstr(m_editline, to_add.c_str());
1009 break; 1015 // Clear all the autosuggestion parts if the only single space can be completed.
1016 if (to_add == " ")
1017 return CC_REDISPLAY;
1018 return CC_REFRESH;
1010 } 1019 }
1011 case CompletionMode::Partial: { 1020 case CompletionMode::Partial: {
1012 std::string to_add = completion.GetCompletion(); 1021 std::string to_add = completion.GetCompletion();
1013 to_add = to_add.substr(request.GetCursorArgumentPrefix().size()); 1022 to_add = to_add.substr(request.GetCursorArgumentPrefix().size());
1014 el_insertstr(m_editline, to_add.c_str()); 1023 el_insertstr(m_editline, to_add.c_str());
1038 DisplayInput(); 1047 DisplayInput();
1039 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); 1048 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
1040 return CC_REDISPLAY; 1049 return CC_REDISPLAY;
1041 } 1050 }
1042 1051
1052 unsigned char Editline::ApplyAutosuggestCommand(int ch) {
1053 if (!m_suggestion_callback) {
1054 return CC_REDISPLAY;
1055 }
1056
1057 const LineInfo *line_info = el_line(m_editline);
1058 llvm::StringRef line(line_info->buffer,
1059 line_info->lastchar - line_info->buffer);
1060
1061 if (llvm::Optional<std::string> to_add = m_suggestion_callback(line))
1062 el_insertstr(m_editline, to_add->c_str());
1063
1064 return CC_REDISPLAY;
1065 }
1066
1067 unsigned char Editline::TypedCharacter(int ch) {
1068 std::string typed = std::string(1, ch);
1069 el_insertstr(m_editline, typed.c_str());
1070
1071 if (!m_suggestion_callback) {
1072 return CC_REDISPLAY;
1073 }
1074
1075 const LineInfo *line_info = el_line(m_editline);
1076 llvm::StringRef line(line_info->buffer,
1077 line_info->lastchar - line_info->buffer);
1078
1079 if (llvm::Optional<std::string> to_add = m_suggestion_callback(line)) {
1080 std::string to_add_color = ANSI_FAINT + to_add.getValue() + ANSI_UNFAINT;
1081 fputs(typed.c_str(), m_output_file);
1082 fputs(to_add_color.c_str(), m_output_file);
1083 size_t new_autosuggestion_size = line.size() + to_add->length();
1084 // Print spaces to hide any remains of a previous longer autosuggestion.
1085 if (new_autosuggestion_size < m_previous_autosuggestion_size) {
1086 size_t spaces_to_print =
1087 m_previous_autosuggestion_size - new_autosuggestion_size;
1088 std::string spaces = std::string(spaces_to_print, ' ');
1089 fputs(spaces.c_str(), m_output_file);
1090 }
1091 m_previous_autosuggestion_size = new_autosuggestion_size;
1092
1093 int editline_cursor_position =
1094 (int)((line_info->cursor - line_info->buffer) + GetPromptWidth());
1095 int editline_cursor_row = editline_cursor_position / m_terminal_width;
1096 int toColumn =
1097 editline_cursor_position - (editline_cursor_row * m_terminal_width);
1098 fprintf(m_output_file, ANSI_SET_COLUMN_N, toColumn);
1099 return CC_REFRESH;
1100 }
1101
1102 return CC_REDISPLAY;
1103 }
1104
1105 void Editline::AddFunctionToEditLine(const EditLineCharType *command,
1106 const EditLineCharType *helptext,
1107 EditlineCommandCallbackType callbackFn) {
1108 el_wset(m_editline, EL_ADDFN, command, helptext, callbackFn);
1109 }
1110
1111 void Editline::SetEditLinePromptCallback(
1112 EditlinePromptCallbackType callbackFn) {
1113 el_set(m_editline, EL_PROMPT, callbackFn);
1114 }
1115
1116 void Editline::SetGetCharacterFunction(EditlineGetCharCallbackType callbackFn) {
1117 el_wset(m_editline, EL_GETCFN, callbackFn);
1118 }
1119
1043 void Editline::ConfigureEditor(bool multiline) { 1120 void Editline::ConfigureEditor(bool multiline) {
1044 if (m_editline && m_multiline_enabled == multiline) 1121 if (m_editline && m_multiline_enabled == multiline)
1045 return; 1122 return;
1046 m_multiline_enabled = multiline; 1123 m_multiline_enabled = multiline;
1047 1124
1064 el_wset(m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr()); 1141 el_wset(m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr());
1065 } 1142 }
1066 el_set(m_editline, EL_CLIENTDATA, this); 1143 el_set(m_editline, EL_CLIENTDATA, this);
1067 el_set(m_editline, EL_SIGNAL, 0); 1144 el_set(m_editline, EL_SIGNAL, 0);
1068 el_set(m_editline, EL_EDITOR, "emacs"); 1145 el_set(m_editline, EL_EDITOR, "emacs");
1069 el_set(m_editline, EL_PROMPT, 1146
1070 (EditlinePromptCallbackType)([](EditLine *editline) { 1147 SetGetCharacterFunction([](EditLine *editline, EditLineGetCharType *c) {
1071 return Editline::InstanceFor(editline)->Prompt(); 1148 return Editline::InstanceFor(editline)->GetCharacter(c);
1072 })); 1149 });
1073 1150
1074 el_wset(m_editline, EL_GETCFN, (EditlineGetCharCallbackType)([]( 1151 SetEditLinePromptCallback([](EditLine *editline) {
1075 EditLine *editline, EditLineGetCharType *c) { 1152 return Editline::InstanceFor(editline)->Prompt();
1076 return Editline::InstanceFor(editline)->GetCharacter(c); 1153 });
1077 }));
1078 1154
1079 // Commands used for multiline support, registered whether or not they're 1155 // Commands used for multiline support, registered whether or not they're
1080 // used 1156 // used
1081 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-break-line"), 1157 AddFunctionToEditLine(
1082 EditLineConstString("Insert a line break"), 1158 EditLineConstString("lldb-break-line"),
1083 (EditlineCommandCallbackType)([](EditLine *editline, int ch) { 1159 EditLineConstString("Insert a line break"),
1084 return Editline::InstanceFor(editline)->BreakLineCommand(ch); 1160 [](EditLine *editline, int ch) {
1085 })); 1161 return Editline::InstanceFor(editline)->BreakLineCommand(ch);
1086 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-end-or-add-line"), 1162 });
1087 EditLineConstString("End editing or continue when incomplete"), 1163
1088 (EditlineCommandCallbackType)([](EditLine *editline, int ch) { 1164 AddFunctionToEditLine(
1089 return Editline::InstanceFor(editline)->EndOrAddLineCommand(ch); 1165 EditLineConstString("lldb-end-or-add-line"),
1090 })); 1166 EditLineConstString("End editing or continue when incomplete"),
1091 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-delete-next-char"), 1167 [](EditLine *editline, int ch) {
1092 EditLineConstString("Delete next character"), 1168 return Editline::InstanceFor(editline)->EndOrAddLineCommand(ch);
1093 (EditlineCommandCallbackType)([](EditLine *editline, int ch) { 1169 });
1094 return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch); 1170 AddFunctionToEditLine(
1095 })); 1171 EditLineConstString("lldb-delete-next-char"),
1096 el_wset( 1172 EditLineConstString("Delete next character"),
1097 m_editline, EL_ADDFN, EditLineConstString("lldb-delete-previous-char"), 1173 [](EditLine *editline, int ch) {
1174 return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch);
1175 });
1176 AddFunctionToEditLine(
1177 EditLineConstString("lldb-delete-previous-char"),
1098 EditLineConstString("Delete previous character"), 1178 EditLineConstString("Delete previous character"),
1099 (EditlineCommandCallbackType)([](EditLine *editline, int ch) { 1179 [](EditLine *editline, int ch) {
1100 return Editline::InstanceFor(editline)->DeletePreviousCharCommand(ch); 1180 return Editline::InstanceFor(editline)->DeletePreviousCharCommand(ch);
1101 })); 1181 });
1102 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-line"), 1182 AddFunctionToEditLine(
1103 EditLineConstString("Move to previous line"), 1183 EditLineConstString("lldb-previous-line"),
1104 (EditlineCommandCallbackType)([](EditLine *editline, int ch) { 1184 EditLineConstString("Move to previous line"),
1105 return Editline::InstanceFor(editline)->PreviousLineCommand(ch); 1185 [](EditLine *editline, int ch) {
1106 })); 1186 return Editline::InstanceFor(editline)->PreviousLineCommand(ch);
1107 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-line"), 1187 });
1108 EditLineConstString("Move to next line"), 1188 AddFunctionToEditLine(
1109 (EditlineCommandCallbackType)([](EditLine *editline, int ch) { 1189 EditLineConstString("lldb-next-line"),
1110 return Editline::InstanceFor(editline)->NextLineCommand(ch); 1190 EditLineConstString("Move to next line"), [](EditLine *editline, int ch) {
1111 })); 1191 return Editline::InstanceFor(editline)->NextLineCommand(ch);
1112 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-history"), 1192 });
1113 EditLineConstString("Move to previous history"), 1193 AddFunctionToEditLine(
1114 (EditlineCommandCallbackType)([](EditLine *editline, int ch) { 1194 EditLineConstString("lldb-previous-history"),
1115 return Editline::InstanceFor(editline)->PreviousHistoryCommand(ch); 1195 EditLineConstString("Move to previous history"),
1116 })); 1196 [](EditLine *editline, int ch) {
1117 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-history"), 1197 return Editline::InstanceFor(editline)->PreviousHistoryCommand(ch);
1118 EditLineConstString("Move to next history"), 1198 });
1119 (EditlineCommandCallbackType)([](EditLine *editline, int ch) { 1199 AddFunctionToEditLine(
1120 return Editline::InstanceFor(editline)->NextHistoryCommand(ch); 1200 EditLineConstString("lldb-next-history"),
1121 })); 1201 EditLineConstString("Move to next history"),
1122 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-start"), 1202 [](EditLine *editline, int ch) {
1123 EditLineConstString("Move to start of buffer"), 1203 return Editline::InstanceFor(editline)->NextHistoryCommand(ch);
1124 (EditlineCommandCallbackType)([](EditLine *editline, int ch) { 1204 });
1125 return Editline::InstanceFor(editline)->BufferStartCommand(ch); 1205 AddFunctionToEditLine(
1126 })); 1206 EditLineConstString("lldb-buffer-start"),
1127 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-end"), 1207 EditLineConstString("Move to start of buffer"),
1128 EditLineConstString("Move to end of buffer"), 1208 [](EditLine *editline, int ch) {
1129 (EditlineCommandCallbackType)([](EditLine *editline, int ch) { 1209 return Editline::InstanceFor(editline)->BufferStartCommand(ch);
1130 return Editline::InstanceFor(editline)->BufferEndCommand(ch); 1210 });
1131 })); 1211 AddFunctionToEditLine(
1132 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-fix-indentation"), 1212 EditLineConstString("lldb-buffer-end"),
1133 EditLineConstString("Fix line indentation"), 1213 EditLineConstString("Move to end of buffer"),
1134 (EditlineCommandCallbackType)([](EditLine *editline, int ch) { 1214 [](EditLine *editline, int ch) {
1135 return Editline::InstanceFor(editline)->FixIndentationCommand(ch); 1215 return Editline::InstanceFor(editline)->BufferEndCommand(ch);
1136 })); 1216 });
1217 AddFunctionToEditLine(
1218 EditLineConstString("lldb-fix-indentation"),
1219 EditLineConstString("Fix line indentation"),
1220 [](EditLine *editline, int ch) {
1221 return Editline::InstanceFor(editline)->FixIndentationCommand(ch);
1222 });
1137 1223
1138 // Register the complete callback under two names for compatibility with 1224 // Register the complete callback under two names for compatibility with
1139 // older clients using custom .editrc files (largely because libedit has a 1225 // older clients using custom .editrc files (largely because libedit has a
1140 // bad bug where if you have a bind command that tries to bind to a function 1226 // bad bug where if you have a bind command that tries to bind to a function
1141 // name that doesn't exist, it can corrupt the heap and crash your process 1227 // name that doesn't exist, it can corrupt the heap and crash your process
1142 // later.) 1228 // later.)
1143 EditlineCommandCallbackType complete_callback = [](EditLine *editline, 1229 EditlineCommandCallbackType complete_callback = [](EditLine *editline,
1144 int ch) { 1230 int ch) {
1145 return Editline::InstanceFor(editline)->TabCommand(ch); 1231 return Editline::InstanceFor(editline)->TabCommand(ch);
1146 }; 1232 };
1147 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-complete"), 1233 AddFunctionToEditLine(EditLineConstString("lldb-complete"),
1148 EditLineConstString("Invoke completion"), complete_callback); 1234 EditLineConstString("Invoke completion"),
1149 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb_complete"), 1235 complete_callback);
1150 EditLineConstString("Invoke completion"), complete_callback); 1236 AddFunctionToEditLine(EditLineConstString("lldb_complete"),
1237 EditLineConstString("Invoke completion"),
1238 complete_callback);
1151 1239
1152 // General bindings we don't mind being overridden 1240 // General bindings we don't mind being overridden
1153 if (!multiline) { 1241 if (!multiline) {
1154 el_set(m_editline, EL_BIND, "^r", "em-inc-search-prev", 1242 el_set(m_editline, EL_BIND, "^r", "em-inc-search-prev",
1155 NULL); // Cycle through backwards search, entering string 1243 NULL); // Cycle through backwards search, entering string
1156 } 1244
1245 if (m_suggestion_callback) {
1246 AddFunctionToEditLine(
1247 EditLineConstString("lldb-apply-complete"),
1248 EditLineConstString("Adopt autocompletion"),
1249 [](EditLine *editline, int ch) {
1250 return Editline::InstanceFor(editline)->ApplyAutosuggestCommand(ch);
1251 });
1252
1253 el_set(m_editline, EL_BIND, "^f", "lldb-apply-complete",
1254 NULL); // Apply a part that is suggested automatically
1255
1256 AddFunctionToEditLine(
1257 EditLineConstString("lldb-typed-character"),
1258 EditLineConstString("Typed character"),
1259 [](EditLine *editline, int ch) {
1260 return Editline::InstanceFor(editline)->TypedCharacter(ch);
1261 });
1262
1263 char bind_key[2] = {0, 0};
1264 llvm::StringRef ascii_chars =
1265 "abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXZY1234567890!\"#$%"
1266 "&'()*+,./:;<=>?@[]_`{|}~ ";
1267 for (char c : ascii_chars) {
1268 bind_key[0] = c;
1269 el_set(m_editline, EL_BIND, bind_key, "lldb-typed-character", NULL);
1270 }
1271 el_set(m_editline, EL_BIND, "\\-", "lldb-typed-character", NULL);
1272 el_set(m_editline, EL_BIND, "\\^", "lldb-typed-character", NULL);
1273 el_set(m_editline, EL_BIND, "\\\\", "lldb-typed-character", NULL);
1274 }
1275 }
1276
1157 el_set(m_editline, EL_BIND, "^w", "ed-delete-prev-word", 1277 el_set(m_editline, EL_BIND, "^w", "ed-delete-prev-word",
1158 NULL); // Delete previous word, behave like bash in emacs mode 1278 NULL); // Delete previous word, behave like bash in emacs mode
1159 el_set(m_editline, EL_BIND, "\t", "lldb-complete", 1279 el_set(m_editline, EL_BIND, "\t", "lldb-complete",
1160 NULL); // Bind TAB to auto complete 1280 NULL); // Bind TAB to auto complete
1161 1281
1171 // Allow user-specific customization prior to registering bindings we 1291 // Allow user-specific customization prior to registering bindings we
1172 // absolutely require 1292 // absolutely require
1173 el_source(m_editline, nullptr); 1293 el_source(m_editline, nullptr);
1174 1294
1175 // Register an internal binding that external developers shouldn't use 1295 // Register an internal binding that external developers shouldn't use
1176 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-revert-line"), 1296 AddFunctionToEditLine(
1177 EditLineConstString("Revert line to saved state"), 1297 EditLineConstString("lldb-revert-line"),
1178 (EditlineCommandCallbackType)([](EditLine *editline, int ch) { 1298 EditLineConstString("Revert line to saved state"),
1179 return Editline::InstanceFor(editline)->RevertLineCommand(ch); 1299 [](EditLine *editline, int ch) {
1180 })); 1300 return Editline::InstanceFor(editline)->RevertLineCommand(ch);
1301 });
1181 1302
1182 // Register keys that perform auto-indent correction 1303 // Register keys that perform auto-indent correction
1183 if (m_fix_indentation_callback && m_fix_indentation_callback_chars) { 1304 if (m_fix_indentation_callback && m_fix_indentation_callback_chars) {
1184 char bind_key[2] = {0, 0}; 1305 char bind_key[2] = {0, 0};
1185 const char *indent_chars = m_fix_indentation_callback_chars; 1306 const char *indent_chars = m_fix_indentation_callback_chars;
1362 } 1483 }
1363 m_editor_status = EditorStatus::Interrupted; 1484 m_editor_status = EditorStatus::Interrupted;
1364 return result; 1485 return result;
1365 } 1486 }
1366 1487
1367 void Editline::SetAutoCompleteCallback(CompleteCallbackType callback,
1368 void *baton) {
1369 m_completion_callback = callback;
1370 m_completion_callback_baton = baton;
1371 }
1372
1373 void Editline::SetIsInputCompleteCallback(IsInputCompleteCallbackType callback,
1374 void *baton) {
1375 m_is_input_complete_callback = callback;
1376 m_is_input_complete_callback_baton = baton;
1377 }
1378
1379 bool Editline::SetFixIndentationCallback(FixIndentationCallbackType callback,
1380 void *baton,
1381 const char *indent_chars) {
1382 m_fix_indentation_callback = callback;
1383 m_fix_indentation_callback_baton = baton;
1384 m_fix_indentation_callback_chars = indent_chars;
1385 return false;
1386 }
1387
1388 bool Editline::GetLine(std::string &line, bool &interrupted) { 1488 bool Editline::GetLine(std::string &line, bool &interrupted) {
1389 ConfigureEditor(false); 1489 ConfigureEditor(false);
1390 m_input_lines = std::vector<EditLineStringType>(); 1490 m_input_lines = std::vector<EditLineStringType>();
1391 m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); 1491 m_input_lines.insert(m_input_lines.begin(), EditLineConstString(""));
1392 1492