comparison lldb/source/Host/common/Editline.cpp @ 236:c4bab56944e8 llvm-original

LLVM 16
author kono
date Wed, 09 Nov 2022 17:45:10 +0900
parents 79ff65ed7e25
children 1f2b6ac9f198
comparison
equal deleted inserted replaced
232:70dce7da266c 236:c4bab56944e8
203 class EditlineHistory { 203 class EditlineHistory {
204 private: 204 private:
205 // Use static GetHistory() function to get a EditlineHistorySP to one of 205 // Use static GetHistory() function to get a EditlineHistorySP to one of
206 // these objects 206 // these objects
207 EditlineHistory(const std::string &prefix, uint32_t size, bool unique_entries) 207 EditlineHistory(const std::string &prefix, uint32_t size, bool unique_entries)
208 : m_history(nullptr), m_event(), m_prefix(prefix), m_path() { 208 : m_prefix(prefix) {
209 m_history = history_winit(); 209 m_history = history_winit();
210 history_w(m_history, &m_event, H_SETSIZE, size); 210 history_w(m_history, &m_event, H_SETSIZE, size);
211 if (unique_entries) 211 if (unique_entries)
212 history_w(m_history, &m_event, H_SETUNIQUE, 1); 212 history_w(m_history, &m_event, H_SETUNIQUE, 1);
213 } 213 }
296 } 296 }
297 return false; 297 return false;
298 } 298 }
299 299
300 protected: 300 protected:
301 HistoryW *m_history; // The history object 301 /// The history object.
302 HistEventW m_event; // The history event needed to contain all history events 302 HistoryW *m_history = nullptr;
303 std::string m_prefix; // The prefix name (usually the editline program name) 303 /// The history event needed to contain all history events.
304 // to use when loading/saving history 304 HistEventW m_event;
305 std::string m_path; // Path to the history file 305 /// The prefix name (usually the editline program name) to use when
306 /// loading/saving history.
307 std::string m_prefix;
308 /// Path to the history file.
309 std::string m_path;
306 }; 310 };
307 } 311 }
308 } 312 }
309 313
310 // Editline private methods 314 // Editline private methods
1004 if (results.size() == 1) { 1008 if (results.size() == 1) {
1005 CompletionResult::Completion completion = results.front(); 1009 CompletionResult::Completion completion = results.front();
1006 switch (completion.GetMode()) { 1010 switch (completion.GetMode()) {
1007 case CompletionMode::Normal: { 1011 case CompletionMode::Normal: {
1008 std::string to_add = completion.GetCompletion(); 1012 std::string to_add = completion.GetCompletion();
1009 to_add = to_add.substr(request.GetCursorArgumentPrefix().size());
1010 // Terminate the current argument with a quote if it started with a quote. 1013 // Terminate the current argument with a quote if it started with a quote.
1011 if (!request.GetParsedLine().empty() && request.GetParsedArg().IsQuoted()) 1014 if (!request.GetParsedLine().empty() && request.GetParsedArg().IsQuoted())
1012 to_add.push_back(request.GetParsedArg().GetQuoteChar()); 1015 to_add.push_back(request.GetParsedArg().GetQuoteChar());
1013 to_add.push_back(' '); 1016 to_add.push_back(' ');
1017 el_deletestr(m_editline, request.GetCursorArgumentPrefix().size());
1014 el_insertstr(m_editline, to_add.c_str()); 1018 el_insertstr(m_editline, to_add.c_str());
1015 // Clear all the autosuggestion parts if the only single space can be completed. 1019 // Clear all the autosuggestion parts if the only single space can be completed.
1016 if (to_add == " ") 1020 if (to_add == " ")
1017 return CC_REDISPLAY; 1021 return CC_REDISPLAY;
1018 return CC_REFRESH; 1022 return CC_REFRESH;
1074 1078
1075 const LineInfo *line_info = el_line(m_editline); 1079 const LineInfo *line_info = el_line(m_editline);
1076 llvm::StringRef line(line_info->buffer, 1080 llvm::StringRef line(line_info->buffer,
1077 line_info->lastchar - line_info->buffer); 1081 line_info->lastchar - line_info->buffer);
1078 1082
1083 const char *ansi_prefix =
1084 m_color_prompts ? m_suggestion_ansi_prefix.c_str() : "";
1085 const char *ansi_suffix =
1086 m_color_prompts ? m_suggestion_ansi_suffix.c_str() : "";
1087
1079 if (llvm::Optional<std::string> to_add = m_suggestion_callback(line)) { 1088 if (llvm::Optional<std::string> to_add = m_suggestion_callback(line)) {
1080 std::string to_add_color = ANSI_FAINT + to_add.getValue() + ANSI_UNFAINT; 1089 std::string to_add_color = ansi_prefix + to_add.value() + ansi_suffix;
1081 fputs(typed.c_str(), m_output_file); 1090 fputs(typed.c_str(), m_output_file);
1082 fputs(to_add_color.c_str(), m_output_file); 1091 fputs(to_add_color.c_str(), m_output_file);
1083 size_t new_autosuggestion_size = line.size() + to_add->length(); 1092 size_t new_autosuggestion_size = line.size() + to_add->length();
1084 // Print spaces to hide any remains of a previous longer autosuggestion. 1093 // Print spaces to hide any remains of a previous longer autosuggestion.
1085 if (new_autosuggestion_size < m_previous_autosuggestion_size) { 1094 if (new_autosuggestion_size < m_previous_autosuggestion_size) {
1365 el_get(editline, EL_CLIENTDATA, &editor); 1374 el_get(editline, EL_CLIENTDATA, &editor);
1366 return editor; 1375 return editor;
1367 } 1376 }
1368 1377
1369 Editline::Editline(const char *editline_name, FILE *input_file, 1378 Editline::Editline(const char *editline_name, FILE *input_file,
1370 FILE *output_file, FILE *error_file, bool color_prompts) 1379 FILE *output_file, FILE *error_file,
1380 std::recursive_mutex &output_mutex, bool color_prompts)
1371 : m_editor_status(EditorStatus::Complete), m_color_prompts(color_prompts), 1381 : m_editor_status(EditorStatus::Complete), m_color_prompts(color_prompts),
1372 m_input_file(input_file), m_output_file(output_file), 1382 m_input_file(input_file), m_output_file(output_file),
1373 m_error_file(error_file), m_input_connection(fileno(input_file), false) { 1383 m_error_file(error_file), m_input_connection(fileno(input_file), false),
1384 m_output_mutex(output_mutex) {
1374 // Get a shared history instance 1385 // Get a shared history instance
1375 m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name; 1386 m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name;
1376 m_history_sp = EditlineHistory::GetHistory(m_editor_name); 1387 m_history_sp = EditlineHistory::GetHistory(m_editor_name);
1377 1388
1378 #ifdef USE_SETUPTERM_WORKAROUND 1389 #ifdef USE_SETUPTERM_WORKAROUND
1379 if (m_output_file) { 1390 if (m_output_file) {
1380 const int term_fd = fileno(m_output_file); 1391 const int term_fd = fileno(m_output_file);
1381 if (term_fd != -1) { 1392 if (term_fd != -1) {
1382 static std::mutex *g_init_terminal_fds_mutex_ptr = nullptr; 1393 static std::recursive_mutex *g_init_terminal_fds_mutex_ptr = nullptr;
1383 static std::set<int> *g_init_terminal_fds_ptr = nullptr; 1394 static std::set<int> *g_init_terminal_fds_ptr = nullptr;
1384 static llvm::once_flag g_once_flag; 1395 static llvm::once_flag g_once_flag;
1385 llvm::call_once(g_once_flag, [&]() { 1396 llvm::call_once(g_once_flag, [&]() {
1386 g_init_terminal_fds_mutex_ptr = 1397 g_init_terminal_fds_mutex_ptr =
1387 new std::mutex(); // NOTE: Leak to avoid C++ destructor chain issues 1398 new std::recursive_mutex(); // NOTE: Leak to avoid C++ destructor
1399 // chain issues
1388 g_init_terminal_fds_ptr = new std::set<int>(); // NOTE: Leak to avoid 1400 g_init_terminal_fds_ptr = new std::set<int>(); // NOTE: Leak to avoid
1389 // C++ destructor chain 1401 // C++ destructor chain
1390 // issues 1402 // issues
1391 }); 1403 });
1392 1404
1393 // We must make sure to initialize the terminal a given file descriptor 1405 // We must make sure to initialize the terminal a given file descriptor
1394 // only once. If we do this multiple times, we start leaking memory. 1406 // only once. If we do this multiple times, we start leaking memory.
1395 std::lock_guard<std::mutex> guard(*g_init_terminal_fds_mutex_ptr); 1407 std::lock_guard<std::recursive_mutex> guard(
1408 *g_init_terminal_fds_mutex_ptr);
1396 if (g_init_terminal_fds_ptr->find(term_fd) == 1409 if (g_init_terminal_fds_ptr->find(term_fd) ==
1397 g_init_terminal_fds_ptr->end()) { 1410 g_init_terminal_fds_ptr->end()) {
1398 g_init_terminal_fds_ptr->insert(term_fd); 1411 g_init_terminal_fds_ptr->insert(term_fd);
1399 setupterm((char *)0, term_fd, (int *)0); 1412 setupterm((char *)0, term_fd, (int *)0);
1400 } 1413 }
1462 1475
1463 uint32_t Editline::GetCurrentLine() { return m_current_line_index; } 1476 uint32_t Editline::GetCurrentLine() { return m_current_line_index; }
1464 1477
1465 bool Editline::Interrupt() { 1478 bool Editline::Interrupt() {
1466 bool result = true; 1479 bool result = true;
1467 std::lock_guard<std::mutex> guard(m_output_mutex); 1480 std::lock_guard<std::recursive_mutex> guard(m_output_mutex);
1468 if (m_editor_status == EditorStatus::Editing) { 1481 if (m_editor_status == EditorStatus::Editing) {
1469 fprintf(m_output_file, "^C\n"); 1482 fprintf(m_output_file, "^C\n");
1470 result = m_input_connection.InterruptRead(); 1483 result = m_input_connection.InterruptRead();
1471 } 1484 }
1472 m_editor_status = EditorStatus::Interrupted; 1485 m_editor_status = EditorStatus::Interrupted;
1473 return result; 1486 return result;
1474 } 1487 }
1475 1488
1476 bool Editline::Cancel() { 1489 bool Editline::Cancel() {
1477 bool result = true; 1490 bool result = true;
1478 std::lock_guard<std::mutex> guard(m_output_mutex); 1491 std::lock_guard<std::recursive_mutex> guard(m_output_mutex);
1479 if (m_editor_status == EditorStatus::Editing) { 1492 if (m_editor_status == EditorStatus::Editing) {
1480 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); 1493 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
1481 fprintf(m_output_file, ANSI_CLEAR_BELOW); 1494 fprintf(m_output_file, ANSI_CLEAR_BELOW);
1482 result = m_input_connection.InterruptRead(); 1495 result = m_input_connection.InterruptRead();
1483 } 1496 }
1488 bool Editline::GetLine(std::string &line, bool &interrupted) { 1501 bool Editline::GetLine(std::string &line, bool &interrupted) {
1489 ConfigureEditor(false); 1502 ConfigureEditor(false);
1490 m_input_lines = std::vector<EditLineStringType>(); 1503 m_input_lines = std::vector<EditLineStringType>();
1491 m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); 1504 m_input_lines.insert(m_input_lines.begin(), EditLineConstString(""));
1492 1505
1493 std::lock_guard<std::mutex> guard(m_output_mutex); 1506 std::lock_guard<std::recursive_mutex> guard(m_output_mutex);
1494 1507
1495 lldbassert(m_editor_status != EditorStatus::Editing); 1508 lldbassert(m_editor_status != EditorStatus::Editing);
1496 if (m_editor_status == EditorStatus::Interrupted) { 1509 if (m_editor_status == EditorStatus::Interrupted) {
1497 m_editor_status = EditorStatus::Complete; 1510 m_editor_status = EditorStatus::Complete;
1498 interrupted = true; 1511 interrupted = true;
1533 // of input 1546 // of input
1534 SetBaseLineNumber(first_line_number); 1547 SetBaseLineNumber(first_line_number);
1535 m_input_lines = std::vector<EditLineStringType>(); 1548 m_input_lines = std::vector<EditLineStringType>();
1536 m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); 1549 m_input_lines.insert(m_input_lines.begin(), EditLineConstString(""));
1537 1550
1538 std::lock_guard<std::mutex> guard(m_output_mutex); 1551 std::lock_guard<std::recursive_mutex> guard(m_output_mutex);
1539 // Begin the line editing loop 1552 // Begin the line editing loop
1540 DisplayInput(); 1553 DisplayInput();
1541 SetCurrentLine(0); 1554 SetCurrentLine(0);
1542 MoveCursor(CursorLocation::BlockEnd, CursorLocation::BlockStart); 1555 MoveCursor(CursorLocation::BlockEnd, CursorLocation::BlockStart);
1543 m_editor_status = EditorStatus::Editing; 1556 m_editor_status = EditorStatus::Editing;
1552 el_wgets(m_editline, &count); 1565 el_wgets(m_editline, &count);
1553 } 1566 }
1554 1567
1555 interrupted = m_editor_status == EditorStatus::Interrupted; 1568 interrupted = m_editor_status == EditorStatus::Interrupted;
1556 if (!interrupted) { 1569 if (!interrupted) {
1557 // Save the completed entry in history before returning 1570 // Save the completed entry in history before returning. Don't save empty
1558 m_history_sp->Enter(CombineLines(m_input_lines).c_str()); 1571 // input as that just clutters the command history.
1572 if (!m_input_lines.empty())
1573 m_history_sp->Enter(CombineLines(m_input_lines).c_str());
1559 1574
1560 lines = GetInputAsStringList(); 1575 lines = GetInputAsStringList();
1561 } 1576 }
1562 return m_editor_status != EditorStatus::EndOfInput; 1577 return m_editor_status != EditorStatus::EndOfInput;
1563 } 1578 }
1564 1579
1565 void Editline::PrintAsync(Stream *stream, const char *s, size_t len) { 1580 void Editline::PrintAsync(Stream *stream, const char *s, size_t len) {
1566 std::lock_guard<std::mutex> guard(m_output_mutex); 1581 std::lock_guard<std::recursive_mutex> guard(m_output_mutex);
1567 if (m_editor_status == EditorStatus::Editing) { 1582 if (m_editor_status == EditorStatus::Editing) {
1568 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); 1583 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
1569 fprintf(m_output_file, ANSI_CLEAR_BELOW); 1584 fprintf(m_output_file, ANSI_CLEAR_BELOW);
1570 } 1585 }
1571 stream->Write(s, len); 1586 stream->Write(s, len);
1592 std::mbstate_t state = std::mbstate_t(); 1607 std::mbstate_t state = std::mbstate_t();
1593 input.push_back(ch); 1608 input.push_back(ch);
1594 switch (cvt.in(state, input.begin(), input.end(), from_next, &out, &out + 1, 1609 switch (cvt.in(state, input.begin(), input.end(), from_next, &out, &out + 1,
1595 to_next)) { 1610 to_next)) {
1596 case std::codecvt_base::ok: 1611 case std::codecvt_base::ok:
1597 return out != (int)WEOF; 1612 return out != (EditLineGetCharType)WEOF;
1598 1613
1599 case std::codecvt_base::error: 1614 case std::codecvt_base::error:
1600 case std::codecvt_base::noconv: 1615 case std::codecvt_base::noconv:
1601 return false; 1616 return false;
1602 1617