comparison lldb/source/Host/common/Editline.cpp @ 173:0572611fdcc8 llvm10 llvm12

reorgnization done
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 11:55:54 +0900
parents 1d019706d866
children 2e18cbf3894f
comparison
equal deleted inserted replaced
172:9fbae9c8bf63 173:0572611fdcc8
33 // may benefit from something similar if issues arise. The libedit library 33 // may benefit from something similar if issues arise. The libedit library
34 // doesn't explicitly initialize the curses termcap library, which it gets away 34 // doesn't explicitly initialize the curses termcap library, which it gets away
35 // with until TERM is set to VT100 where it stumbles over an implementation 35 // with until TERM is set to VT100 where it stumbles over an implementation
36 // assumption that may not exist on other platforms. The setupterm() function 36 // assumption that may not exist on other platforms. The setupterm() function
37 // would normally require headers that don't work gracefully in this context, 37 // would normally require headers that don't work gracefully in this context,
38 // so the function declaraction has been hoisted here. 38 // so the function declaration has been hoisted here.
39 #if defined(__APPLE__) 39 #if defined(__APPLE__)
40 extern "C" { 40 extern "C" {
41 int setupterm(char *term, int fildes, int *errret); 41 int setupterm(char *term, int fildes, int *errret);
42 } 42 }
43 #define USE_SETUPTERM_WORKAROUND 43 #define USE_SETUPTERM_WORKAROUND
97 return true; 97 return true;
98 } 98 }
99 99
100 static int GetOperation(HistoryOperation op) { 100 static int GetOperation(HistoryOperation op) {
101 // The naming used by editline for the history operations is counter 101 // The naming used by editline for the history operations is counter
102 // intuitive to how it's used here. 102 // intuitive to how it's used in LLDB's editline implementation.
103 //
104 // - The H_LAST returns the oldest entry in the history.
103 // 105 //
104 // - The H_PREV operation returns the previous element in the history, which 106 // - The H_PREV operation returns the previous element in the history, which
105 // is newer than the current one. 107 // is newer than the current one.
106 // 108 //
109 // - The H_CURR returns the current entry in the history.
110 //
107 // - The H_NEXT operation returns the next element in the history, which is 111 // - The H_NEXT operation returns the next element in the history, which is
108 // older than the current one. 112 // older than the current one.
113 //
114 // - The H_FIRST returns the most recent entry in the history.
109 // 115 //
110 // The naming of the enum entries match the semantic meaning. 116 // The naming of the enum entries match the semantic meaning.
111 switch(op) { 117 switch(op) {
112 case HistoryOperation::Oldest: 118 case HistoryOperation::Oldest:
113 return H_FIRST; 119 return H_LAST;
114 case HistoryOperation::Older: 120 case HistoryOperation::Older:
115 return H_NEXT; 121 return H_NEXT;
116 case HistoryOperation::Current: 122 case HistoryOperation::Current:
117 return H_CURR; 123 return H_CURR;
118 case HistoryOperation::Newer: 124 case HistoryOperation::Newer:
119 return H_PREV; 125 return H_PREV;
120 case HistoryOperation::Newest: 126 case HistoryOperation::Newest:
121 return H_LAST; 127 return H_FIRST;
122 } 128 }
123 llvm_unreachable("Fully covered switch!"); 129 llvm_unreachable("Fully covered switch!");
124 } 130 }
125 131
126 132
136 std::vector<EditLineStringType> result; 142 std::vector<EditLineStringType> result;
137 size_t start = 0; 143 size_t start = 0;
138 while (start < input.length()) { 144 while (start < input.length()) {
139 size_t end = input.find('\n', start); 145 size_t end = input.find('\n', start);
140 if (end == std::string::npos) { 146 if (end == std::string::npos) {
141 result.insert(result.end(), input.substr(start)); 147 result.push_back(input.substr(start));
142 break; 148 break;
143 } 149 }
144 result.insert(result.end(), input.substr(start, end - start)); 150 result.push_back(input.substr(start, end - start));
145 start = end + 1; 151 start = end + 1;
146 } 152 }
147 return result; 153 return result;
148 } 154 }
149 155
294 } 300 }
295 301
296 // Editline private methods 302 // Editline private methods
297 303
298 void Editline::SetBaseLineNumber(int line_number) { 304 void Editline::SetBaseLineNumber(int line_number) {
299 std::stringstream line_number_stream;
300 line_number_stream << line_number;
301 m_base_line_number = line_number; 305 m_base_line_number = line_number;
302 m_line_number_digits = 306 m_line_number_digits =
303 std::max(3, (int)line_number_stream.str().length() + 1); 307 std::max<int>(3, std::to_string(line_number).length() + 1);
304 } 308 }
305 309
306 std::string Editline::PromptForIndex(int line_index) { 310 std::string Editline::PromptForIndex(int line_index) {
307 bool use_line_numbers = m_multiline_enabled && m_base_line_number > 0; 311 bool use_line_numbers = m_multiline_enabled && m_base_line_number > 0;
308 std::string prompt = m_set_prompt; 312 std::string prompt = m_set_prompt;
309 if (use_line_numbers && prompt.length() == 0) { 313 if (use_line_numbers && prompt.length() == 0)
310 prompt = ": "; 314 prompt = ": ";
311 }
312 std::string continuation_prompt = prompt; 315 std::string continuation_prompt = prompt;
313 if (m_set_continuation_prompt.length() > 0) { 316 if (m_set_continuation_prompt.length() > 0) {
314 continuation_prompt = m_set_continuation_prompt; 317 continuation_prompt = m_set_continuation_prompt;
315 318
316 // Ensure that both prompts are the same length through space padding 319 // Ensure that both prompts are the same length through space padding
421 fprintf(m_output_file, "\n"); 424 fprintf(m_output_file, "\n");
422 } 425 }
423 } 426 }
424 427
425 int Editline::CountRowsForLine(const EditLineStringType &content) { 428 int Editline::CountRowsForLine(const EditLineStringType &content) {
426 auto prompt = 429 std::string prompt =
427 PromptForIndex(0); // Prompt width is constant during an edit session 430 PromptForIndex(0); // Prompt width is constant during an edit session
428 int line_length = (int)(content.length() + prompt.length()); 431 int line_length = (int)(content.length() + prompt.length());
429 return (line_length / m_terminal_width) + 1; 432 return (line_length / m_terminal_width) + 1;
430 } 433 }
431 434
555 // Read an actual character 558 // Read an actual character
556 while (true) { 559 while (true) {
557 lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; 560 lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
558 char ch = 0; 561 char ch = 0;
559 562
563 if (m_terminal_size_has_changed)
564 ApplyTerminalSizeChange();
565
560 // This mutex is locked by our caller (GetLine). Unlock it while we read a 566 // This mutex is locked by our caller (GetLine). Unlock it while we read a
561 // character (blocking operation), so we do not hold the mutex 567 // character (blocking operation), so we do not hold the mutex
562 // indefinitely. This gives a chance for someone to interrupt us. After 568 // indefinitely. This gives a chance for someone to interrupt us. After
563 // Read returns, immediately lock the mutex again and check if we were 569 // Read returns, immediately lock the mutex again and check if we were
564 // interrupted. 570 // interrupted.
1047 el_end(m_editline); 1053 el_end(m_editline);
1048 } 1054 }
1049 1055
1050 m_editline = 1056 m_editline =
1051 el_init(m_editor_name.c_str(), m_input_file, m_output_file, m_error_file); 1057 el_init(m_editor_name.c_str(), m_input_file, m_output_file, m_error_file);
1052 TerminalSizeChanged(); 1058 ApplyTerminalSizeChange();
1053 1059
1054 if (m_history_sp && m_history_sp->IsValid()) { 1060 if (m_history_sp && m_history_sp->IsValid()) {
1055 if (!m_history_sp->Load()) { 1061 if (!m_history_sp->Load()) {
1056 fputs("Could not load history file\n.", m_output_file); 1062 fputs("Could not load history file\n.", m_output_file);
1057 } 1063 }
1300 void Editline::SetContinuationPrompt(const char *continuation_prompt) { 1306 void Editline::SetContinuationPrompt(const char *continuation_prompt) {
1301 m_set_continuation_prompt = 1307 m_set_continuation_prompt =
1302 continuation_prompt == nullptr ? "" : continuation_prompt; 1308 continuation_prompt == nullptr ? "" : continuation_prompt;
1303 } 1309 }
1304 1310
1305 void Editline::TerminalSizeChanged() { 1311 void Editline::TerminalSizeChanged() { m_terminal_size_has_changed = 1; }
1306 if (m_editline != nullptr) { 1312
1307 el_resize(m_editline); 1313 void Editline::ApplyTerminalSizeChange() {
1308 int columns; 1314 if (!m_editline)
1309 // This function is documenting as taking (const char *, void *) for the 1315 return;
1310 // vararg part, but in reality in was consuming arguments until the first 1316
1311 // null pointer. This was fixed in libedit in April 2019 1317 m_terminal_size_has_changed = 0;
1312 // <http://mail-index.netbsd.org/source-changes/2019/04/26/msg105454.html>, 1318 el_resize(m_editline);
1313 // but we're keeping the workaround until a version with that fix is more 1319 int columns;
1314 // widely available. 1320 // This function is documenting as taking (const char *, void *) for the
1315 if (el_get(m_editline, EL_GETTC, "co", &columns, nullptr) == 0) { 1321 // vararg part, but in reality in was consuming arguments until the first
1316 m_terminal_width = columns; 1322 // null pointer. This was fixed in libedit in April 2019
1317 if (m_current_line_rows != -1) { 1323 // <http://mail-index.netbsd.org/source-changes/2019/04/26/msg105454.html>,
1318 const LineInfoW *info = el_wline(m_editline); 1324 // but we're keeping the workaround until a version with that fix is more
1319 int lineLength = 1325 // widely available.
1320 (int)((info->lastchar - info->buffer) + GetPromptWidth()); 1326 if (el_get(m_editline, EL_GETTC, "co", &columns, nullptr) == 0) {
1321 m_current_line_rows = (lineLength / columns) + 1; 1327 m_terminal_width = columns;
1322 } 1328 if (m_current_line_rows != -1) {
1323 } else { 1329 const LineInfoW *info = el_wline(m_editline);
1324 m_terminal_width = INT_MAX; 1330 int lineLength =
1325 m_current_line_rows = 1; 1331 (int)((info->lastchar - info->buffer) + GetPromptWidth());
1326 } 1332 m_current_line_rows = (lineLength / columns) + 1;
1333 }
1334 } else {
1335 m_terminal_width = INT_MAX;
1336 m_current_line_rows = 1;
1327 } 1337 }
1328 } 1338 }
1329 1339
1330 const char *Editline::GetPrompt() { return m_set_prompt.c_str(); } 1340 const char *Editline::GetPrompt() { return m_set_prompt.c_str(); }
1331 1341