Mercurial > hg > CbC > CbC_llvm
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 |