1 //===-- Editline.cpp ------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include <climits> 10 #include <iomanip> 11 12 #include "lldb/Host/Editline.h" 13 14 #include "lldb/Host/ConnectionFileDescriptor.h" 15 #include "lldb/Host/FileSystem.h" 16 #include "lldb/Host/Host.h" 17 #include "lldb/Utility/CompletionRequest.h" 18 #include "lldb/Utility/FileSpec.h" 19 #include "lldb/Utility/LLDBAssert.h" 20 #include "lldb/Utility/SelectHelper.h" 21 #include "lldb/Utility/Status.h" 22 #include "lldb/Utility/StreamString.h" 23 #include "lldb/Utility/StringList.h" 24 #include "lldb/Utility/Timeout.h" 25 26 #include "llvm/Support/FileSystem.h" 27 #include "llvm/Support/Threading.h" 28 29 using namespace lldb_private; 30 using namespace lldb_private::line_editor; 31 32 // Workaround for what looks like an OS X-specific issue, but other platforms 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 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 37 // would normally require headers that don't work gracefully in this context, 38 // so the function declaration has been hoisted here. 39 #if defined(__APPLE__) 40 extern "C" { 41 int setupterm(char *term, int fildes, int *errret); 42 } 43 #define USE_SETUPTERM_WORKAROUND 44 #endif 45 46 // Editline uses careful cursor management to achieve the illusion of editing a 47 // multi-line block of text with a single line editor. Preserving this 48 // illusion requires fairly careful management of cursor state. Read and 49 // understand the relationship between DisplayInput(), MoveCursor(), 50 // SetCurrentLine(), and SaveEditedLine() before making changes. 51 52 /// https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf 53 #define ESCAPE "\x1b" 54 /// Faint, decreased intensity or second colour. 55 #define ANSI_FAINT ESCAPE "[2m" 56 /// Normal colour or normal intensity (neither bold nor faint). 57 #define ANSI_UNFAINT ESCAPE "[0m" 58 #define ANSI_CLEAR_BELOW ESCAPE "[J" 59 #define ANSI_CLEAR_RIGHT ESCAPE "[K" 60 #define ANSI_SET_COLUMN_N ESCAPE "[%dG" 61 #define ANSI_UP_N_ROWS ESCAPE "[%dA" 62 #define ANSI_DOWN_N_ROWS ESCAPE "[%dB" 63 64 #if LLDB_EDITLINE_USE_WCHAR 65 66 #define EditLineConstString(str) L##str 67 #define EditLineStringFormatSpec "%ls" 68 69 #else 70 71 #define EditLineConstString(str) str 72 #define EditLineStringFormatSpec "%s" 73 74 // use #defines so wide version functions and structs will resolve to old 75 // versions for case of libedit not built with wide char support 76 #define history_w history 77 #define history_winit history_init 78 #define history_wend history_end 79 #define HistoryW History 80 #define HistEventW HistEvent 81 #define LineInfoW LineInfo 82 83 #define el_wgets el_gets 84 #define el_wgetc el_getc 85 #define el_wpush el_push 86 #define el_wparse el_parse 87 #define el_wset el_set 88 #define el_wget el_get 89 #define el_wline el_line 90 #define el_winsertstr el_insertstr 91 #define el_wdeletestr el_deletestr 92 93 #endif // #if LLDB_EDITLINE_USE_WCHAR 94 95 bool IsOnlySpaces(const EditLineStringType &content) { 96 for (wchar_t ch : content) { 97 if (ch != EditLineCharType(' ')) 98 return false; 99 } 100 return true; 101 } 102 103 static int GetOperation(HistoryOperation op) { 104 // The naming used by editline for the history operations is counter 105 // intuitive to how it's used in LLDB's editline implementation. 106 // 107 // - The H_LAST returns the oldest entry in the history. 108 // 109 // - The H_PREV operation returns the previous element in the history, which 110 // is newer than the current one. 111 // 112 // - The H_CURR returns the current entry in the history. 113 // 114 // - The H_NEXT operation returns the next element in the history, which is 115 // older than the current one. 116 // 117 // - The H_FIRST returns the most recent entry in the history. 118 // 119 // The naming of the enum entries match the semantic meaning. 120 switch(op) { 121 case HistoryOperation::Oldest: 122 return H_LAST; 123 case HistoryOperation::Older: 124 return H_NEXT; 125 case HistoryOperation::Current: 126 return H_CURR; 127 case HistoryOperation::Newer: 128 return H_PREV; 129 case HistoryOperation::Newest: 130 return H_FIRST; 131 } 132 llvm_unreachable("Fully covered switch!"); 133 } 134 135 136 EditLineStringType CombineLines(const std::vector<EditLineStringType> &lines) { 137 EditLineStringStreamType combined_stream; 138 for (EditLineStringType line : lines) { 139 combined_stream << line.c_str() << "\n"; 140 } 141 return combined_stream.str(); 142 } 143 144 std::vector<EditLineStringType> SplitLines(const EditLineStringType &input) { 145 std::vector<EditLineStringType> result; 146 size_t start = 0; 147 while (start < input.length()) { 148 size_t end = input.find('\n', start); 149 if (end == std::string::npos) { 150 result.push_back(input.substr(start)); 151 break; 152 } 153 result.push_back(input.substr(start, end - start)); 154 start = end + 1; 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 } 161 return result; 162 } 163 164 EditLineStringType FixIndentation(const EditLineStringType &line, 165 int indent_correction) { 166 if (indent_correction == 0) 167 return line; 168 if (indent_correction < 0) 169 return line.substr(-indent_correction); 170 return EditLineStringType(indent_correction, EditLineCharType(' ')) + line; 171 } 172 173 int GetIndentation(const EditLineStringType &line) { 174 int space_count = 0; 175 for (EditLineCharType ch : line) { 176 if (ch != EditLineCharType(' ')) 177 break; 178 ++space_count; 179 } 180 return space_count; 181 } 182 183 bool IsInputPending(FILE *file) { 184 // FIXME: This will be broken on Windows if we ever re-enable Editline. You 185 // can't use select 186 // on something that isn't a socket. This will have to be re-written to not 187 // use a FILE*, but instead use some kind of yet-to-be-created abstraction 188 // that select-like functionality on non-socket objects. 189 const int fd = fileno(file); 190 SelectHelper select_helper; 191 select_helper.SetTimeout(std::chrono::microseconds(0)); 192 select_helper.FDSetRead(fd); 193 return select_helper.Select().Success(); 194 } 195 196 namespace lldb_private { 197 namespace line_editor { 198 typedef std::weak_ptr<EditlineHistory> EditlineHistoryWP; 199 200 // EditlineHistory objects are sometimes shared between multiple Editline 201 // instances with the same program name. 202 203 class EditlineHistory { 204 private: 205 // Use static GetHistory() function to get a EditlineHistorySP to one of 206 // these objects 207 EditlineHistory(const std::string &prefix, uint32_t size, bool unique_entries) 208 : m_history(nullptr), m_event(), m_prefix(prefix), m_path() { 209 m_history = history_winit(); 210 history_w(m_history, &m_event, H_SETSIZE, size); 211 if (unique_entries) 212 history_w(m_history, &m_event, H_SETUNIQUE, 1); 213 } 214 215 const char *GetHistoryFilePath() { 216 // Compute the history path lazily. 217 if (m_path.empty() && m_history && !m_prefix.empty()) { 218 llvm::SmallString<128> lldb_history_file; 219 FileSystem::Instance().GetHomeDirectory(lldb_history_file); 220 llvm::sys::path::append(lldb_history_file, ".lldb"); 221 222 // LLDB stores its history in ~/.lldb/. If for some reason this directory 223 // isn't writable or cannot be created, history won't be available. 224 if (!llvm::sys::fs::create_directory(lldb_history_file)) { 225 #if LLDB_EDITLINE_USE_WCHAR 226 std::string filename = m_prefix + "-widehistory"; 227 #else 228 std::string filename = m_prefix + "-history"; 229 #endif 230 llvm::sys::path::append(lldb_history_file, filename); 231 m_path = std::string(lldb_history_file.str()); 232 } 233 } 234 235 if (m_path.empty()) 236 return nullptr; 237 238 return m_path.c_str(); 239 } 240 241 public: 242 ~EditlineHistory() { 243 Save(); 244 245 if (m_history) { 246 history_wend(m_history); 247 m_history = nullptr; 248 } 249 } 250 251 static EditlineHistorySP GetHistory(const std::string &prefix) { 252 typedef std::map<std::string, EditlineHistoryWP> WeakHistoryMap; 253 static std::recursive_mutex g_mutex; 254 static WeakHistoryMap g_weak_map; 255 std::lock_guard<std::recursive_mutex> guard(g_mutex); 256 WeakHistoryMap::const_iterator pos = g_weak_map.find(prefix); 257 EditlineHistorySP history_sp; 258 if (pos != g_weak_map.end()) { 259 history_sp = pos->second.lock(); 260 if (history_sp) 261 return history_sp; 262 g_weak_map.erase(pos); 263 } 264 history_sp.reset(new EditlineHistory(prefix, 800, true)); 265 g_weak_map[prefix] = history_sp; 266 return history_sp; 267 } 268 269 bool IsValid() const { return m_history != nullptr; } 270 271 HistoryW *GetHistoryPtr() { return m_history; } 272 273 void Enter(const EditLineCharType *line_cstr) { 274 if (m_history) 275 history_w(m_history, &m_event, H_ENTER, line_cstr); 276 } 277 278 bool Load() { 279 if (m_history) { 280 const char *path = GetHistoryFilePath(); 281 if (path) { 282 history_w(m_history, &m_event, H_LOAD, path); 283 return true; 284 } 285 } 286 return false; 287 } 288 289 bool Save() { 290 if (m_history) { 291 const char *path = GetHistoryFilePath(); 292 if (path) { 293 history_w(m_history, &m_event, H_SAVE, path); 294 return true; 295 } 296 } 297 return false; 298 } 299 300 protected: 301 HistoryW *m_history; // The history object 302 HistEventW m_event; // The history event needed to contain all history events 303 std::string m_prefix; // The prefix name (usually the editline program name) 304 // to use when loading/saving history 305 std::string m_path; // Path to the history file 306 }; 307 } 308 } 309 310 // Editline private methods 311 312 void Editline::SetBaseLineNumber(int line_number) { 313 m_base_line_number = line_number; 314 m_line_number_digits = 315 std::max<int>(3, std::to_string(line_number).length() + 1); 316 } 317 318 std::string Editline::PromptForIndex(int line_index) { 319 bool use_line_numbers = m_multiline_enabled && m_base_line_number > 0; 320 std::string prompt = m_set_prompt; 321 if (use_line_numbers && prompt.length() == 0) 322 prompt = ": "; 323 std::string continuation_prompt = prompt; 324 if (m_set_continuation_prompt.length() > 0) { 325 continuation_prompt = m_set_continuation_prompt; 326 327 // Ensure that both prompts are the same length through space padding 328 while (continuation_prompt.length() < prompt.length()) { 329 continuation_prompt += ' '; 330 } 331 while (prompt.length() < continuation_prompt.length()) { 332 prompt += ' '; 333 } 334 } 335 336 if (use_line_numbers) { 337 StreamString prompt_stream; 338 prompt_stream.Printf( 339 "%*d%s", m_line_number_digits, m_base_line_number + line_index, 340 (line_index == 0) ? prompt.c_str() : continuation_prompt.c_str()); 341 return std::string(std::move(prompt_stream.GetString())); 342 } 343 return (line_index == 0) ? prompt : continuation_prompt; 344 } 345 346 void Editline::SetCurrentLine(int line_index) { 347 m_current_line_index = line_index; 348 m_current_prompt = PromptForIndex(line_index); 349 } 350 351 int Editline::GetPromptWidth() { return (int)PromptForIndex(0).length(); } 352 353 bool Editline::IsEmacs() { 354 const char *editor; 355 el_get(m_editline, EL_EDITOR, &editor); 356 return editor[0] == 'e'; 357 } 358 359 bool Editline::IsOnlySpaces() { 360 const LineInfoW *info = el_wline(m_editline); 361 for (const EditLineCharType *character = info->buffer; 362 character < info->lastchar; character++) { 363 if (*character != ' ') 364 return false; 365 } 366 return true; 367 } 368 369 int Editline::GetLineIndexForLocation(CursorLocation location, int cursor_row) { 370 int line = 0; 371 if (location == CursorLocation::EditingPrompt || 372 location == CursorLocation::BlockEnd || 373 location == CursorLocation::EditingCursor) { 374 for (unsigned index = 0; index < m_current_line_index; index++) { 375 line += CountRowsForLine(m_input_lines[index]); 376 } 377 if (location == CursorLocation::EditingCursor) { 378 line += cursor_row; 379 } else if (location == CursorLocation::BlockEnd) { 380 for (unsigned index = m_current_line_index; index < m_input_lines.size(); 381 index++) { 382 line += CountRowsForLine(m_input_lines[index]); 383 } 384 --line; 385 } 386 } 387 return line; 388 } 389 390 void Editline::MoveCursor(CursorLocation from, CursorLocation to) { 391 const LineInfoW *info = el_wline(m_editline); 392 int editline_cursor_position = 393 (int)((info->cursor - info->buffer) + GetPromptWidth()); 394 int editline_cursor_row = editline_cursor_position / m_terminal_width; 395 396 // Determine relative starting and ending lines 397 int fromLine = GetLineIndexForLocation(from, editline_cursor_row); 398 int toLine = GetLineIndexForLocation(to, editline_cursor_row); 399 if (toLine != fromLine) { 400 fprintf(m_output_file, 401 (toLine > fromLine) ? ANSI_DOWN_N_ROWS : ANSI_UP_N_ROWS, 402 std::abs(toLine - fromLine)); 403 } 404 405 // Determine target column 406 int toColumn = 1; 407 if (to == CursorLocation::EditingCursor) { 408 toColumn = 409 editline_cursor_position - (editline_cursor_row * m_terminal_width) + 1; 410 } else if (to == CursorLocation::BlockEnd && !m_input_lines.empty()) { 411 toColumn = 412 ((m_input_lines[m_input_lines.size() - 1].length() + GetPromptWidth()) % 413 80) + 414 1; 415 } 416 fprintf(m_output_file, ANSI_SET_COLUMN_N, toColumn); 417 } 418 419 void Editline::DisplayInput(int firstIndex) { 420 fprintf(m_output_file, ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1); 421 int line_count = (int)m_input_lines.size(); 422 const char *faint = m_color_prompts ? ANSI_FAINT : ""; 423 const char *unfaint = m_color_prompts ? ANSI_UNFAINT : ""; 424 425 for (int index = firstIndex; index < line_count; index++) { 426 fprintf(m_output_file, "%s" 427 "%s" 428 "%s" EditLineStringFormatSpec " ", 429 faint, PromptForIndex(index).c_str(), unfaint, 430 m_input_lines[index].c_str()); 431 if (index < line_count - 1) 432 fprintf(m_output_file, "\n"); 433 } 434 } 435 436 int Editline::CountRowsForLine(const EditLineStringType &content) { 437 std::string prompt = 438 PromptForIndex(0); // Prompt width is constant during an edit session 439 int line_length = (int)(content.length() + prompt.length()); 440 return (line_length / m_terminal_width) + 1; 441 } 442 443 void Editline::SaveEditedLine() { 444 const LineInfoW *info = el_wline(m_editline); 445 m_input_lines[m_current_line_index] = 446 EditLineStringType(info->buffer, info->lastchar - info->buffer); 447 } 448 449 StringList Editline::GetInputAsStringList(int line_count) { 450 StringList lines; 451 for (EditLineStringType line : m_input_lines) { 452 if (line_count == 0) 453 break; 454 #if LLDB_EDITLINE_USE_WCHAR 455 lines.AppendString(m_utf8conv.to_bytes(line)); 456 #else 457 lines.AppendString(line); 458 #endif 459 --line_count; 460 } 461 return lines; 462 } 463 464 unsigned char Editline::RecallHistory(HistoryOperation op) { 465 assert(op == HistoryOperation::Older || op == HistoryOperation::Newer); 466 if (!m_history_sp || !m_history_sp->IsValid()) 467 return CC_ERROR; 468 469 HistoryW *pHistory = m_history_sp->GetHistoryPtr(); 470 HistEventW history_event; 471 std::vector<EditLineStringType> new_input_lines; 472 473 // Treat moving from the "live" entry differently 474 if (!m_in_history) { 475 switch (op) { 476 case HistoryOperation::Newer: 477 return CC_ERROR; // Can't go newer than the "live" entry 478 case HistoryOperation::Older: { 479 if (history_w(pHistory, &history_event, 480 GetOperation(HistoryOperation::Newest)) == -1) 481 return CC_ERROR; 482 // Save any edits to the "live" entry in case we return by moving forward 483 // in history (it would be more bash-like to save over any current entry, 484 // but libedit doesn't offer the ability to add entries anywhere except 485 // the end.) 486 SaveEditedLine(); 487 m_live_history_lines = m_input_lines; 488 m_in_history = true; 489 } break; 490 default: 491 llvm_unreachable("unsupported history direction"); 492 } 493 } else { 494 if (history_w(pHistory, &history_event, GetOperation(op)) == -1) { 495 switch (op) { 496 case HistoryOperation::Older: 497 // Can't move earlier than the earliest entry. 498 return CC_ERROR; 499 case HistoryOperation::Newer: 500 // Moving to newer-than-the-newest entry yields the "live" entry. 501 new_input_lines = m_live_history_lines; 502 m_in_history = false; 503 break; 504 default: 505 llvm_unreachable("unsupported history direction"); 506 } 507 } 508 } 509 510 // If we're pulling the lines from history, split them apart 511 if (m_in_history) 512 new_input_lines = SplitLines(history_event.str); 513 514 // Erase the current edit session and replace it with a new one 515 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); 516 m_input_lines = new_input_lines; 517 DisplayInput(); 518 519 // Prepare to edit the last line when moving to previous entry, or the first 520 // line when moving to next entry 521 switch (op) { 522 case HistoryOperation::Older: 523 m_current_line_index = (int)m_input_lines.size() - 1; 524 break; 525 case HistoryOperation::Newer: 526 m_current_line_index = 0; 527 break; 528 default: 529 llvm_unreachable("unsupported history direction"); 530 } 531 SetCurrentLine(m_current_line_index); 532 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); 533 return CC_NEWLINE; 534 } 535 536 int Editline::GetCharacter(EditLineGetCharType *c) { 537 const LineInfoW *info = el_wline(m_editline); 538 539 // Paint a faint version of the desired prompt over the version libedit draws 540 // (will only be requested if colors are supported) 541 if (m_needs_prompt_repaint) { 542 MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); 543 fprintf(m_output_file, "%s" 544 "%s" 545 "%s", 546 ANSI_FAINT, Prompt(), ANSI_UNFAINT); 547 MoveCursor(CursorLocation::EditingPrompt, CursorLocation::EditingCursor); 548 m_needs_prompt_repaint = false; 549 } 550 551 if (m_multiline_enabled) { 552 // Detect when the number of rows used for this input line changes due to 553 // an edit 554 int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth()); 555 int new_line_rows = (lineLength / m_terminal_width) + 1; 556 if (m_current_line_rows != -1 && new_line_rows != m_current_line_rows) { 557 // Respond by repainting the current state from this line on 558 MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); 559 SaveEditedLine(); 560 DisplayInput(m_current_line_index); 561 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); 562 } 563 m_current_line_rows = new_line_rows; 564 } 565 566 // Read an actual character 567 while (true) { 568 lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; 569 char ch = 0; 570 571 if (m_terminal_size_has_changed) 572 ApplyTerminalSizeChange(); 573 574 // This mutex is locked by our caller (GetLine). Unlock it while we read a 575 // character (blocking operation), so we do not hold the mutex 576 // indefinitely. This gives a chance for someone to interrupt us. After 577 // Read returns, immediately lock the mutex again and check if we were 578 // interrupted. 579 m_output_mutex.unlock(); 580 int read_count = 581 m_input_connection.Read(&ch, 1, llvm::None, status, nullptr); 582 m_output_mutex.lock(); 583 if (m_editor_status == EditorStatus::Interrupted) { 584 while (read_count > 0 && status == lldb::eConnectionStatusSuccess) 585 read_count = 586 m_input_connection.Read(&ch, 1, llvm::None, status, nullptr); 587 lldbassert(status == lldb::eConnectionStatusInterrupted); 588 return 0; 589 } 590 591 if (read_count) { 592 if (CompleteCharacter(ch, *c)) 593 return 1; 594 } else { 595 switch (status) { 596 case lldb::eConnectionStatusSuccess: // Success 597 break; 598 599 case lldb::eConnectionStatusInterrupted: 600 llvm_unreachable("Interrupts should have been handled above."); 601 602 case lldb::eConnectionStatusError: // Check GetError() for details 603 case lldb::eConnectionStatusTimedOut: // Request timed out 604 case lldb::eConnectionStatusEndOfFile: // End-of-file encountered 605 case lldb::eConnectionStatusNoConnection: // No connection 606 case lldb::eConnectionStatusLostConnection: // Lost connection while 607 // connected to a valid 608 // connection 609 m_editor_status = EditorStatus::EndOfInput; 610 return 0; 611 } 612 } 613 } 614 } 615 616 const char *Editline::Prompt() { 617 if (m_color_prompts) 618 m_needs_prompt_repaint = true; 619 return m_current_prompt.c_str(); 620 } 621 622 unsigned char Editline::BreakLineCommand(int ch) { 623 // Preserve any content beyond the cursor, truncate and save the current line 624 const LineInfoW *info = el_wline(m_editline); 625 auto current_line = 626 EditLineStringType(info->buffer, info->cursor - info->buffer); 627 auto new_line_fragment = 628 EditLineStringType(info->cursor, info->lastchar - info->cursor); 629 m_input_lines[m_current_line_index] = current_line; 630 631 // Ignore whitespace-only extra fragments when breaking a line 632 if (::IsOnlySpaces(new_line_fragment)) 633 new_line_fragment = EditLineConstString(""); 634 635 // Establish the new cursor position at the start of a line when inserting a 636 // line break 637 m_revert_cursor_index = 0; 638 639 // Don't perform automatic formatting when pasting 640 if (!IsInputPending(m_input_file)) { 641 // Apply smart indentation 642 if (m_fix_indentation_callback) { 643 StringList lines = GetInputAsStringList(m_current_line_index + 1); 644 #if LLDB_EDITLINE_USE_WCHAR 645 lines.AppendString(m_utf8conv.to_bytes(new_line_fragment)); 646 #else 647 lines.AppendString(new_line_fragment); 648 #endif 649 650 int indent_correction = m_fix_indentation_callback(this, lines, 0); 651 new_line_fragment = FixIndentation(new_line_fragment, indent_correction); 652 m_revert_cursor_index = GetIndentation(new_line_fragment); 653 } 654 } 655 656 // Insert the new line and repaint everything from the split line on down 657 m_input_lines.insert(m_input_lines.begin() + m_current_line_index + 1, 658 new_line_fragment); 659 MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); 660 DisplayInput(m_current_line_index); 661 662 // Reposition the cursor to the right line and prepare to edit the new line 663 SetCurrentLine(m_current_line_index + 1); 664 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); 665 return CC_NEWLINE; 666 } 667 668 unsigned char Editline::EndOrAddLineCommand(int ch) { 669 // Don't perform end of input detection when pasting, always treat this as a 670 // line break 671 if (IsInputPending(m_input_file)) { 672 return BreakLineCommand(ch); 673 } 674 675 // Save any edits to this line 676 SaveEditedLine(); 677 678 // If this is the end of the last line, consider whether to add a line 679 // instead 680 const LineInfoW *info = el_wline(m_editline); 681 if (m_current_line_index == m_input_lines.size() - 1 && 682 info->cursor == info->lastchar) { 683 if (m_is_input_complete_callback) { 684 auto lines = GetInputAsStringList(); 685 if (!m_is_input_complete_callback(this, lines)) { 686 return BreakLineCommand(ch); 687 } 688 689 // The completion test is allowed to change the input lines when complete 690 m_input_lines.clear(); 691 for (unsigned index = 0; index < lines.GetSize(); index++) { 692 #if LLDB_EDITLINE_USE_WCHAR 693 m_input_lines.insert(m_input_lines.end(), 694 m_utf8conv.from_bytes(lines[index])); 695 #else 696 m_input_lines.insert(m_input_lines.end(), lines[index]); 697 #endif 698 } 699 } 700 } 701 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd); 702 fprintf(m_output_file, "\n"); 703 m_editor_status = EditorStatus::Complete; 704 return CC_NEWLINE; 705 } 706 707 unsigned char Editline::DeleteNextCharCommand(int ch) { 708 LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline)); 709 710 // Just delete the next character normally if possible 711 if (info->cursor < info->lastchar) { 712 info->cursor++; 713 el_deletestr(m_editline, 1); 714 return CC_REFRESH; 715 } 716 717 // Fail when at the end of the last line, except when ^D is pressed on the 718 // line is empty, in which case it is treated as EOF 719 if (m_current_line_index == m_input_lines.size() - 1) { 720 if (ch == 4 && info->buffer == info->lastchar) { 721 fprintf(m_output_file, "^D\n"); 722 m_editor_status = EditorStatus::EndOfInput; 723 return CC_EOF; 724 } 725 return CC_ERROR; 726 } 727 728 // Prepare to combine this line with the one below 729 MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); 730 731 // Insert the next line of text at the cursor and restore the cursor position 732 const EditLineCharType *cursor = info->cursor; 733 el_winsertstr(m_editline, m_input_lines[m_current_line_index + 1].c_str()); 734 info->cursor = cursor; 735 SaveEditedLine(); 736 737 // Delete the extra line 738 m_input_lines.erase(m_input_lines.begin() + m_current_line_index + 1); 739 740 // Clear and repaint from this line on down 741 DisplayInput(m_current_line_index); 742 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); 743 return CC_REFRESH; 744 } 745 746 unsigned char Editline::DeletePreviousCharCommand(int ch) { 747 LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline)); 748 749 // Just delete the previous character normally when not at the start of a 750 // line 751 if (info->cursor > info->buffer) { 752 el_deletestr(m_editline, 1); 753 return CC_REFRESH; 754 } 755 756 // No prior line and no prior character? Let the user know 757 if (m_current_line_index == 0) 758 return CC_ERROR; 759 760 // No prior character, but prior line? Combine with the line above 761 SaveEditedLine(); 762 SetCurrentLine(m_current_line_index - 1); 763 auto priorLine = m_input_lines[m_current_line_index]; 764 m_input_lines.erase(m_input_lines.begin() + m_current_line_index); 765 m_input_lines[m_current_line_index] = 766 priorLine + m_input_lines[m_current_line_index]; 767 768 // Repaint from the new line down 769 fprintf(m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N, 770 CountRowsForLine(priorLine), 1); 771 DisplayInput(m_current_line_index); 772 773 // Put the cursor back where libedit expects it to be before returning to 774 // editing by telling libedit about the newly inserted text 775 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); 776 el_winsertstr(m_editline, priorLine.c_str()); 777 return CC_REDISPLAY; 778 } 779 780 unsigned char Editline::PreviousLineCommand(int ch) { 781 SaveEditedLine(); 782 783 if (m_current_line_index == 0) { 784 return RecallHistory(HistoryOperation::Older); 785 } 786 787 // Start from a known location 788 MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); 789 790 // Treat moving up from a blank last line as a deletion of that line 791 if (m_current_line_index == m_input_lines.size() - 1 && IsOnlySpaces()) { 792 m_input_lines.erase(m_input_lines.begin() + m_current_line_index); 793 fprintf(m_output_file, ANSI_CLEAR_BELOW); 794 } 795 796 SetCurrentLine(m_current_line_index - 1); 797 fprintf(m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N, 798 CountRowsForLine(m_input_lines[m_current_line_index]), 1); 799 return CC_NEWLINE; 800 } 801 802 unsigned char Editline::NextLineCommand(int ch) { 803 SaveEditedLine(); 804 805 // Handle attempts to move down from the last line 806 if (m_current_line_index == m_input_lines.size() - 1) { 807 // Don't add an extra line if the existing last line is blank, move through 808 // history instead 809 if (IsOnlySpaces()) { 810 return RecallHistory(HistoryOperation::Newer); 811 } 812 813 // Determine indentation for the new line 814 int indentation = 0; 815 if (m_fix_indentation_callback) { 816 StringList lines = GetInputAsStringList(); 817 lines.AppendString(""); 818 indentation = m_fix_indentation_callback(this, lines, 0); 819 } 820 m_input_lines.insert( 821 m_input_lines.end(), 822 EditLineStringType(indentation, EditLineCharType(' '))); 823 } 824 825 // Move down past the current line using newlines to force scrolling if 826 // needed 827 SetCurrentLine(m_current_line_index + 1); 828 const LineInfoW *info = el_wline(m_editline); 829 int cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth()); 830 int cursor_row = cursor_position / m_terminal_width; 831 for (int line_count = 0; line_count < m_current_line_rows - cursor_row; 832 line_count++) { 833 fprintf(m_output_file, "\n"); 834 } 835 return CC_NEWLINE; 836 } 837 838 unsigned char Editline::PreviousHistoryCommand(int ch) { 839 SaveEditedLine(); 840 841 return RecallHistory(HistoryOperation::Older); 842 } 843 844 unsigned char Editline::NextHistoryCommand(int ch) { 845 SaveEditedLine(); 846 847 return RecallHistory(HistoryOperation::Newer); 848 } 849 850 unsigned char Editline::FixIndentationCommand(int ch) { 851 if (!m_fix_indentation_callback) 852 return CC_NORM; 853 854 // Insert the character typed before proceeding 855 EditLineCharType inserted[] = {(EditLineCharType)ch, 0}; 856 el_winsertstr(m_editline, inserted); 857 LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline)); 858 int cursor_position = info->cursor - info->buffer; 859 860 // Save the edits and determine the correct indentation level 861 SaveEditedLine(); 862 StringList lines = GetInputAsStringList(m_current_line_index + 1); 863 int indent_correction = 864 m_fix_indentation_callback(this, lines, cursor_position); 865 866 // If it is already correct no special work is needed 867 if (indent_correction == 0) 868 return CC_REFRESH; 869 870 // Change the indentation level of the line 871 std::string currentLine = lines.GetStringAtIndex(m_current_line_index); 872 if (indent_correction > 0) { 873 currentLine = currentLine.insert(0, indent_correction, ' '); 874 } else { 875 currentLine = currentLine.erase(0, -indent_correction); 876 } 877 #if LLDB_EDITLINE_USE_WCHAR 878 m_input_lines[m_current_line_index] = m_utf8conv.from_bytes(currentLine); 879 #else 880 m_input_lines[m_current_line_index] = currentLine; 881 #endif 882 883 // Update the display to reflect the change 884 MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); 885 DisplayInput(m_current_line_index); 886 887 // Reposition the cursor back on the original line and prepare to restart 888 // editing with a new cursor position 889 SetCurrentLine(m_current_line_index); 890 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); 891 m_revert_cursor_index = cursor_position + indent_correction; 892 return CC_NEWLINE; 893 } 894 895 unsigned char Editline::RevertLineCommand(int ch) { 896 el_winsertstr(m_editline, m_input_lines[m_current_line_index].c_str()); 897 if (m_revert_cursor_index >= 0) { 898 LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline)); 899 info->cursor = info->buffer + m_revert_cursor_index; 900 if (info->cursor > info->lastchar) { 901 info->cursor = info->lastchar; 902 } 903 m_revert_cursor_index = -1; 904 } 905 return CC_REFRESH; 906 } 907 908 unsigned char Editline::BufferStartCommand(int ch) { 909 SaveEditedLine(); 910 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); 911 SetCurrentLine(0); 912 m_revert_cursor_index = 0; 913 return CC_NEWLINE; 914 } 915 916 unsigned char Editline::BufferEndCommand(int ch) { 917 SaveEditedLine(); 918 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd); 919 SetCurrentLine((int)m_input_lines.size() - 1); 920 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt); 921 return CC_NEWLINE; 922 } 923 924 /// Prints completions and their descriptions to the given file. Only the 925 /// completions in the interval [start, end) are printed. 926 static void 927 PrintCompletion(FILE *output_file, 928 llvm::ArrayRef<CompletionResult::Completion> results, 929 size_t max_len) { 930 for (const CompletionResult::Completion &c : results) { 931 fprintf(output_file, "\t%-*s", (int)max_len, c.GetCompletion().c_str()); 932 if (!c.GetDescription().empty()) 933 fprintf(output_file, " -- %s", c.GetDescription().c_str()); 934 fprintf(output_file, "\n"); 935 } 936 } 937 938 static void 939 DisplayCompletions(::EditLine *editline, FILE *output_file, 940 llvm::ArrayRef<CompletionResult::Completion> results) { 941 assert(!results.empty()); 942 943 fprintf(output_file, "\n" ANSI_CLEAR_BELOW "Available completions:\n"); 944 const size_t page_size = 40; 945 bool all = false; 946 947 auto longest = 948 std::max_element(results.begin(), results.end(), [](auto &c1, auto &c2) { 949 return c1.GetCompletion().size() < c2.GetCompletion().size(); 950 }); 951 952 const size_t max_len = longest->GetCompletion().size(); 953 954 if (results.size() < page_size) { 955 PrintCompletion(output_file, results, max_len); 956 return; 957 } 958 959 size_t cur_pos = 0; 960 while (cur_pos < results.size()) { 961 size_t remaining = results.size() - cur_pos; 962 size_t next_size = all ? remaining : std::min(page_size, remaining); 963 964 PrintCompletion(output_file, results.slice(cur_pos, next_size), max_len); 965 966 cur_pos += next_size; 967 968 if (cur_pos >= results.size()) 969 break; 970 971 fprintf(output_file, "More (Y/n/a): "); 972 char reply = 'n'; 973 int got_char = el_getc(editline, &reply); 974 fprintf(output_file, "\n"); 975 if (got_char == -1 || reply == 'n') 976 break; 977 if (reply == 'a') 978 all = true; 979 } 980 } 981 982 unsigned char Editline::TabCommand(int ch) { 983 if (!m_completion_callback) 984 return CC_ERROR; 985 986 const LineInfo *line_info = el_line(m_editline); 987 988 llvm::StringRef line(line_info->buffer, 989 line_info->lastchar - line_info->buffer); 990 unsigned cursor_index = line_info->cursor - line_info->buffer; 991 CompletionResult result; 992 CompletionRequest request(line, cursor_index, result); 993 994 m_completion_callback(request); 995 996 llvm::ArrayRef<CompletionResult::Completion> results = result.GetResults(); 997 998 StringList completions; 999 result.GetMatches(completions); 1000 1001 if (results.size() == 0) 1002 return CC_ERROR; 1003 1004 if (results.size() == 1) { 1005 CompletionResult::Completion completion = results.front(); 1006 switch (completion.GetMode()) { 1007 case CompletionMode::Normal: { 1008 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. 1011 if (!request.GetParsedLine().empty() && request.GetParsedArg().IsQuoted()) 1012 to_add.push_back(request.GetParsedArg().GetQuoteChar()); 1013 to_add.push_back(' '); 1014 el_insertstr(m_editline, to_add.c_str()); 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; 1019 } 1020 case CompletionMode::Partial: { 1021 std::string to_add = completion.GetCompletion(); 1022 to_add = to_add.substr(request.GetCursorArgumentPrefix().size()); 1023 el_insertstr(m_editline, to_add.c_str()); 1024 break; 1025 } 1026 case CompletionMode::RewriteLine: { 1027 el_deletestr(m_editline, line_info->cursor - line_info->buffer); 1028 el_insertstr(m_editline, completion.GetCompletion().c_str()); 1029 break; 1030 } 1031 } 1032 return CC_REDISPLAY; 1033 } 1034 1035 // If we get a longer match display that first. 1036 std::string longest_prefix = completions.LongestCommonPrefix(); 1037 if (!longest_prefix.empty()) 1038 longest_prefix = 1039 longest_prefix.substr(request.GetCursorArgumentPrefix().size()); 1040 if (!longest_prefix.empty()) { 1041 el_insertstr(m_editline, longest_prefix.c_str()); 1042 return CC_REDISPLAY; 1043 } 1044 1045 DisplayCompletions(m_editline, m_output_file, results); 1046 1047 DisplayInput(); 1048 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); 1049 return CC_REDISPLAY; 1050 } 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 1120 void Editline::ConfigureEditor(bool multiline) { 1121 if (m_editline && m_multiline_enabled == multiline) 1122 return; 1123 m_multiline_enabled = multiline; 1124 1125 if (m_editline) { 1126 // Disable edit mode to stop the terminal from flushing all input during 1127 // the call to el_end() since we expect to have multiple editline instances 1128 // in this program. 1129 el_set(m_editline, EL_EDITMODE, 0); 1130 el_end(m_editline); 1131 } 1132 1133 m_editline = 1134 el_init(m_editor_name.c_str(), m_input_file, m_output_file, m_error_file); 1135 ApplyTerminalSizeChange(); 1136 1137 if (m_history_sp && m_history_sp->IsValid()) { 1138 if (!m_history_sp->Load()) { 1139 fputs("Could not load history file\n.", m_output_file); 1140 } 1141 el_wset(m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr()); 1142 } 1143 el_set(m_editline, EL_CLIENTDATA, this); 1144 el_set(m_editline, EL_SIGNAL, 0); 1145 el_set(m_editline, EL_EDITOR, "emacs"); 1146 1147 SetGetCharacterFunction([](EditLine *editline, EditLineGetCharType *c) { 1148 return Editline::InstanceFor(editline)->GetCharacter(c); 1149 }); 1150 1151 SetEditLinePromptCallback([](EditLine *editline) { 1152 return Editline::InstanceFor(editline)->Prompt(); 1153 }); 1154 1155 // Commands used for multiline support, registered whether or not they're 1156 // used 1157 AddFunctionToEditLine( 1158 EditLineConstString("lldb-break-line"), 1159 EditLineConstString("Insert a line break"), 1160 [](EditLine *editline, int ch) { 1161 return Editline::InstanceFor(editline)->BreakLineCommand(ch); 1162 }); 1163 1164 AddFunctionToEditLine( 1165 EditLineConstString("lldb-end-or-add-line"), 1166 EditLineConstString("End editing or continue when incomplete"), 1167 [](EditLine *editline, int ch) { 1168 return Editline::InstanceFor(editline)->EndOrAddLineCommand(ch); 1169 }); 1170 AddFunctionToEditLine( 1171 EditLineConstString("lldb-delete-next-char"), 1172 EditLineConstString("Delete next character"), 1173 [](EditLine *editline, int ch) { 1174 return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch); 1175 }); 1176 AddFunctionToEditLine( 1177 EditLineConstString("lldb-delete-previous-char"), 1178 EditLineConstString("Delete previous character"), 1179 [](EditLine *editline, int ch) { 1180 return Editline::InstanceFor(editline)->DeletePreviousCharCommand(ch); 1181 }); 1182 AddFunctionToEditLine( 1183 EditLineConstString("lldb-previous-line"), 1184 EditLineConstString("Move to previous line"), 1185 [](EditLine *editline, int ch) { 1186 return Editline::InstanceFor(editline)->PreviousLineCommand(ch); 1187 }); 1188 AddFunctionToEditLine( 1189 EditLineConstString("lldb-next-line"), 1190 EditLineConstString("Move to next line"), [](EditLine *editline, int ch) { 1191 return Editline::InstanceFor(editline)->NextLineCommand(ch); 1192 }); 1193 AddFunctionToEditLine( 1194 EditLineConstString("lldb-previous-history"), 1195 EditLineConstString("Move to previous history"), 1196 [](EditLine *editline, int ch) { 1197 return Editline::InstanceFor(editline)->PreviousHistoryCommand(ch); 1198 }); 1199 AddFunctionToEditLine( 1200 EditLineConstString("lldb-next-history"), 1201 EditLineConstString("Move to next history"), 1202 [](EditLine *editline, int ch) { 1203 return Editline::InstanceFor(editline)->NextHistoryCommand(ch); 1204 }); 1205 AddFunctionToEditLine( 1206 EditLineConstString("lldb-buffer-start"), 1207 EditLineConstString("Move to start of buffer"), 1208 [](EditLine *editline, int ch) { 1209 return Editline::InstanceFor(editline)->BufferStartCommand(ch); 1210 }); 1211 AddFunctionToEditLine( 1212 EditLineConstString("lldb-buffer-end"), 1213 EditLineConstString("Move to end of buffer"), 1214 [](EditLine *editline, int ch) { 1215 return Editline::InstanceFor(editline)->BufferEndCommand(ch); 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 }); 1223 1224 // Register the complete callback under two names for compatibility with 1225 // older clients using custom .editrc files (largely because libedit has a 1226 // bad bug where if you have a bind command that tries to bind to a function 1227 // name that doesn't exist, it can corrupt the heap and crash your process 1228 // later.) 1229 EditlineCommandCallbackType complete_callback = [](EditLine *editline, 1230 int ch) { 1231 return Editline::InstanceFor(editline)->TabCommand(ch); 1232 }; 1233 AddFunctionToEditLine(EditLineConstString("lldb-complete"), 1234 EditLineConstString("Invoke completion"), 1235 complete_callback); 1236 AddFunctionToEditLine(EditLineConstString("lldb_complete"), 1237 EditLineConstString("Invoke completion"), 1238 complete_callback); 1239 1240 // General bindings we don't mind being overridden 1241 if (!multiline) { 1242 el_set(m_editline, EL_BIND, "^r", "em-inc-search-prev", 1243 NULL); // Cycle through backwards search, entering string 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 1277 el_set(m_editline, EL_BIND, "^w", "ed-delete-prev-word", 1278 NULL); // Delete previous word, behave like bash in emacs mode 1279 el_set(m_editline, EL_BIND, "\t", "lldb-complete", 1280 NULL); // Bind TAB to auto complete 1281 1282 // Allow ctrl-left-arrow and ctrl-right-arrow for navigation, behave like 1283 // bash in emacs mode. 1284 el_set(m_editline, EL_BIND, ESCAPE "[1;5C", "em-next-word", NULL); 1285 el_set(m_editline, EL_BIND, ESCAPE "[1;5D", "ed-prev-word", NULL); 1286 el_set(m_editline, EL_BIND, ESCAPE "[5C", "em-next-word", NULL); 1287 el_set(m_editline, EL_BIND, ESCAPE "[5D", "ed-prev-word", NULL); 1288 el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[C", "em-next-word", NULL); 1289 el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[D", "ed-prev-word", NULL); 1290 1291 // Allow user-specific customization prior to registering bindings we 1292 // absolutely require 1293 el_source(m_editline, nullptr); 1294 1295 // Register an internal binding that external developers shouldn't use 1296 AddFunctionToEditLine( 1297 EditLineConstString("lldb-revert-line"), 1298 EditLineConstString("Revert line to saved state"), 1299 [](EditLine *editline, int ch) { 1300 return Editline::InstanceFor(editline)->RevertLineCommand(ch); 1301 }); 1302 1303 // Register keys that perform auto-indent correction 1304 if (m_fix_indentation_callback && m_fix_indentation_callback_chars) { 1305 char bind_key[2] = {0, 0}; 1306 const char *indent_chars = m_fix_indentation_callback_chars; 1307 while (*indent_chars) { 1308 bind_key[0] = *indent_chars; 1309 el_set(m_editline, EL_BIND, bind_key, "lldb-fix-indentation", NULL); 1310 ++indent_chars; 1311 } 1312 } 1313 1314 // Multi-line editor bindings 1315 if (multiline) { 1316 el_set(m_editline, EL_BIND, "\n", "lldb-end-or-add-line", NULL); 1317 el_set(m_editline, EL_BIND, "\r", "lldb-end-or-add-line", NULL); 1318 el_set(m_editline, EL_BIND, ESCAPE "\n", "lldb-break-line", NULL); 1319 el_set(m_editline, EL_BIND, ESCAPE "\r", "lldb-break-line", NULL); 1320 el_set(m_editline, EL_BIND, "^p", "lldb-previous-line", NULL); 1321 el_set(m_editline, EL_BIND, "^n", "lldb-next-line", NULL); 1322 el_set(m_editline, EL_BIND, "^?", "lldb-delete-previous-char", NULL); 1323 el_set(m_editline, EL_BIND, "^d", "lldb-delete-next-char", NULL); 1324 el_set(m_editline, EL_BIND, ESCAPE "[3~", "lldb-delete-next-char", NULL); 1325 el_set(m_editline, EL_BIND, ESCAPE "[\\^", "lldb-revert-line", NULL); 1326 1327 // Editor-specific bindings 1328 if (IsEmacs()) { 1329 el_set(m_editline, EL_BIND, ESCAPE "<", "lldb-buffer-start", NULL); 1330 el_set(m_editline, EL_BIND, ESCAPE ">", "lldb-buffer-end", NULL); 1331 el_set(m_editline, EL_BIND, ESCAPE "[A", "lldb-previous-line", NULL); 1332 el_set(m_editline, EL_BIND, ESCAPE "[B", "lldb-next-line", NULL); 1333 el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[A", "lldb-previous-history", 1334 NULL); 1335 el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[B", "lldb-next-history", 1336 NULL); 1337 el_set(m_editline, EL_BIND, ESCAPE "[1;3A", "lldb-previous-history", 1338 NULL); 1339 el_set(m_editline, EL_BIND, ESCAPE "[1;3B", "lldb-next-history", NULL); 1340 } else { 1341 el_set(m_editline, EL_BIND, "^H", "lldb-delete-previous-char", NULL); 1342 1343 el_set(m_editline, EL_BIND, "-a", ESCAPE "[A", "lldb-previous-line", 1344 NULL); 1345 el_set(m_editline, EL_BIND, "-a", ESCAPE "[B", "lldb-next-line", NULL); 1346 el_set(m_editline, EL_BIND, "-a", "x", "lldb-delete-next-char", NULL); 1347 el_set(m_editline, EL_BIND, "-a", "^H", "lldb-delete-previous-char", 1348 NULL); 1349 el_set(m_editline, EL_BIND, "-a", "^?", "lldb-delete-previous-char", 1350 NULL); 1351 1352 // Escape is absorbed exiting edit mode, so re-register important 1353 // sequences without the prefix 1354 el_set(m_editline, EL_BIND, "-a", "[A", "lldb-previous-line", NULL); 1355 el_set(m_editline, EL_BIND, "-a", "[B", "lldb-next-line", NULL); 1356 el_set(m_editline, EL_BIND, "-a", "[\\^", "lldb-revert-line", NULL); 1357 } 1358 } 1359 } 1360 1361 // Editline public methods 1362 1363 Editline *Editline::InstanceFor(EditLine *editline) { 1364 Editline *editor; 1365 el_get(editline, EL_CLIENTDATA, &editor); 1366 return editor; 1367 } 1368 1369 Editline::Editline(const char *editline_name, FILE *input_file, 1370 FILE *output_file, FILE *error_file, bool color_prompts) 1371 : m_editor_status(EditorStatus::Complete), m_color_prompts(color_prompts), 1372 m_input_file(input_file), m_output_file(output_file), 1373 m_error_file(error_file), m_input_connection(fileno(input_file), false) { 1374 // Get a shared history instance 1375 m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name; 1376 m_history_sp = EditlineHistory::GetHistory(m_editor_name); 1377 1378 #ifdef USE_SETUPTERM_WORKAROUND 1379 if (m_output_file) { 1380 const int term_fd = fileno(m_output_file); 1381 if (term_fd != -1) { 1382 static std::mutex *g_init_terminal_fds_mutex_ptr = nullptr; 1383 static std::set<int> *g_init_terminal_fds_ptr = nullptr; 1384 static llvm::once_flag g_once_flag; 1385 llvm::call_once(g_once_flag, [&]() { 1386 g_init_terminal_fds_mutex_ptr = 1387 new std::mutex(); // NOTE: Leak to avoid C++ destructor chain issues 1388 g_init_terminal_fds_ptr = new std::set<int>(); // NOTE: Leak to avoid 1389 // C++ destructor chain 1390 // issues 1391 }); 1392 1393 // 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. 1395 std::lock_guard<std::mutex> guard(*g_init_terminal_fds_mutex_ptr); 1396 if (g_init_terminal_fds_ptr->find(term_fd) == 1397 g_init_terminal_fds_ptr->end()) { 1398 g_init_terminal_fds_ptr->insert(term_fd); 1399 setupterm((char *)0, term_fd, (int *)0); 1400 } 1401 } 1402 } 1403 #endif 1404 } 1405 1406 Editline::~Editline() { 1407 if (m_editline) { 1408 // Disable edit mode to stop the terminal from flushing all input during 1409 // the call to el_end() since we expect to have multiple editline instances 1410 // in this program. 1411 el_set(m_editline, EL_EDITMODE, 0); 1412 el_end(m_editline); 1413 m_editline = nullptr; 1414 } 1415 1416 // EditlineHistory objects are sometimes shared between multiple Editline 1417 // instances with the same program name. So just release our shared pointer 1418 // and if we are the last owner, it will save the history to the history save 1419 // file automatically. 1420 m_history_sp.reset(); 1421 } 1422 1423 void Editline::SetPrompt(const char *prompt) { 1424 m_set_prompt = prompt == nullptr ? "" : prompt; 1425 } 1426 1427 void Editline::SetContinuationPrompt(const char *continuation_prompt) { 1428 m_set_continuation_prompt = 1429 continuation_prompt == nullptr ? "" : continuation_prompt; 1430 } 1431 1432 void Editline::TerminalSizeChanged() { m_terminal_size_has_changed = 1; } 1433 1434 void Editline::ApplyTerminalSizeChange() { 1435 if (!m_editline) 1436 return; 1437 1438 m_terminal_size_has_changed = 0; 1439 el_resize(m_editline); 1440 int columns; 1441 // This function is documenting as taking (const char *, void *) for the 1442 // vararg part, but in reality in was consuming arguments until the first 1443 // null pointer. This was fixed in libedit in April 2019 1444 // <http://mail-index.netbsd.org/source-changes/2019/04/26/msg105454.html>, 1445 // but we're keeping the workaround until a version with that fix is more 1446 // widely available. 1447 if (el_get(m_editline, EL_GETTC, "co", &columns, nullptr) == 0) { 1448 m_terminal_width = columns; 1449 if (m_current_line_rows != -1) { 1450 const LineInfoW *info = el_wline(m_editline); 1451 int lineLength = 1452 (int)((info->lastchar - info->buffer) + GetPromptWidth()); 1453 m_current_line_rows = (lineLength / columns) + 1; 1454 } 1455 } else { 1456 m_terminal_width = INT_MAX; 1457 m_current_line_rows = 1; 1458 } 1459 } 1460 1461 const char *Editline::GetPrompt() { return m_set_prompt.c_str(); } 1462 1463 uint32_t Editline::GetCurrentLine() { return m_current_line_index; } 1464 1465 bool Editline::Interrupt() { 1466 bool result = true; 1467 std::lock_guard<std::mutex> guard(m_output_mutex); 1468 if (m_editor_status == EditorStatus::Editing) { 1469 fprintf(m_output_file, "^C\n"); 1470 result = m_input_connection.InterruptRead(); 1471 } 1472 m_editor_status = EditorStatus::Interrupted; 1473 return result; 1474 } 1475 1476 bool Editline::Cancel() { 1477 bool result = true; 1478 std::lock_guard<std::mutex> guard(m_output_mutex); 1479 if (m_editor_status == EditorStatus::Editing) { 1480 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); 1481 fprintf(m_output_file, ANSI_CLEAR_BELOW); 1482 result = m_input_connection.InterruptRead(); 1483 } 1484 m_editor_status = EditorStatus::Interrupted; 1485 return result; 1486 } 1487 1488 bool Editline::GetLine(std::string &line, bool &interrupted) { 1489 ConfigureEditor(false); 1490 m_input_lines = std::vector<EditLineStringType>(); 1491 m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); 1492 1493 std::lock_guard<std::mutex> guard(m_output_mutex); 1494 1495 lldbassert(m_editor_status != EditorStatus::Editing); 1496 if (m_editor_status == EditorStatus::Interrupted) { 1497 m_editor_status = EditorStatus::Complete; 1498 interrupted = true; 1499 return true; 1500 } 1501 1502 SetCurrentLine(0); 1503 m_in_history = false; 1504 m_editor_status = EditorStatus::Editing; 1505 m_revert_cursor_index = -1; 1506 1507 int count; 1508 auto input = el_wgets(m_editline, &count); 1509 1510 interrupted = m_editor_status == EditorStatus::Interrupted; 1511 if (!interrupted) { 1512 if (input == nullptr) { 1513 fprintf(m_output_file, "\n"); 1514 m_editor_status = EditorStatus::EndOfInput; 1515 } else { 1516 m_history_sp->Enter(input); 1517 #if LLDB_EDITLINE_USE_WCHAR 1518 line = m_utf8conv.to_bytes(SplitLines(input)[0]); 1519 #else 1520 line = SplitLines(input)[0]; 1521 #endif 1522 m_editor_status = EditorStatus::Complete; 1523 } 1524 } 1525 return m_editor_status != EditorStatus::EndOfInput; 1526 } 1527 1528 bool Editline::GetLines(int first_line_number, StringList &lines, 1529 bool &interrupted) { 1530 ConfigureEditor(true); 1531 1532 // Print the initial input lines, then move the cursor back up to the start 1533 // of input 1534 SetBaseLineNumber(first_line_number); 1535 m_input_lines = std::vector<EditLineStringType>(); 1536 m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); 1537 1538 std::lock_guard<std::mutex> guard(m_output_mutex); 1539 // Begin the line editing loop 1540 DisplayInput(); 1541 SetCurrentLine(0); 1542 MoveCursor(CursorLocation::BlockEnd, CursorLocation::BlockStart); 1543 m_editor_status = EditorStatus::Editing; 1544 m_in_history = false; 1545 1546 m_revert_cursor_index = -1; 1547 while (m_editor_status == EditorStatus::Editing) { 1548 int count; 1549 m_current_line_rows = -1; 1550 el_wpush(m_editline, EditLineConstString( 1551 "\x1b[^")); // Revert to the existing line content 1552 el_wgets(m_editline, &count); 1553 } 1554 1555 interrupted = m_editor_status == EditorStatus::Interrupted; 1556 if (!interrupted) { 1557 // Save the completed entry in history before returning 1558 m_history_sp->Enter(CombineLines(m_input_lines).c_str()); 1559 1560 lines = GetInputAsStringList(); 1561 } 1562 return m_editor_status != EditorStatus::EndOfInput; 1563 } 1564 1565 void Editline::PrintAsync(Stream *stream, const char *s, size_t len) { 1566 std::lock_guard<std::mutex> guard(m_output_mutex); 1567 if (m_editor_status == EditorStatus::Editing) { 1568 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); 1569 fprintf(m_output_file, ANSI_CLEAR_BELOW); 1570 } 1571 stream->Write(s, len); 1572 stream->Flush(); 1573 if (m_editor_status == EditorStatus::Editing) { 1574 DisplayInput(); 1575 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); 1576 } 1577 } 1578 1579 bool Editline::CompleteCharacter(char ch, EditLineGetCharType &out) { 1580 #if !LLDB_EDITLINE_USE_WCHAR 1581 if (ch == (char)EOF) 1582 return false; 1583 1584 out = (unsigned char)ch; 1585 return true; 1586 #else 1587 std::codecvt_utf8<wchar_t> cvt; 1588 llvm::SmallString<4> input; 1589 for (;;) { 1590 const char *from_next; 1591 wchar_t *to_next; 1592 std::mbstate_t state = std::mbstate_t(); 1593 input.push_back(ch); 1594 switch (cvt.in(state, input.begin(), input.end(), from_next, &out, &out + 1, 1595 to_next)) { 1596 case std::codecvt_base::ok: 1597 return out != (int)WEOF; 1598 1599 case std::codecvt_base::error: 1600 case std::codecvt_base::noconv: 1601 return false; 1602 1603 case std::codecvt_base::partial: 1604 lldb::ConnectionStatus status; 1605 size_t read_count = m_input_connection.Read( 1606 &ch, 1, std::chrono::seconds(0), status, nullptr); 1607 if (read_count == 0) 1608 return false; 1609 break; 1610 } 1611 } 1612 #endif 1613 } 1614