17#include "lldb/Host/Config.h"
27#if LLDB_ENABLE_LIBEDIT
32#include "llvm/ADT/StringRef.h"
68 : m_debugger(debugger), m_input_sp(input_sp), m_output_sp(output_sp),
69 m_error_sp(error_sp), m_popped(false), m_flags(flags), m_type(type),
70 m_user_data(nullptr), m_done(false), m_active(false) {
124 stream->Write(s, len);
129 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
137 bool default_response)
146 m_default_response(default_response), m_user_response(default_response) {
150 prompt_stream.
Printf(
": [Y/n] ");
152 prompt_stream.
Printf(
": [y/N] ");
175 if (line.size() == 1) {
192 if (line ==
"yes" || line ==
"YES" || line ==
"Yes") {
195 }
else if (line ==
"no" || line ==
"NO" || line ==
"No") {
201std::optional<std::string>
203 llvm::StringRef line) {
227 const char *editline_name,
228 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
229 bool multi_line,
bool color, uint32_t line_number_start,
237 prompt, continuation_prompt, multi_line, color,
238 line_number_start, delegate) {}
244 const char *editline_name,
245 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
246 bool multi_line,
bool color, uint32_t line_number_start,
248 :
IOHandler(debugger, type, input_sp, output_sp, error_sp, flags),
249#if LLDB_ENABLE_LIBEDIT
252 m_delegate(delegate), m_prompt(), m_continuation_prompt(),
253 m_current_lines_ptr(nullptr), m_base_line_number(line_number_start),
254 m_curr_line_idx(
UINT32_MAX), m_multi_line(multi_line), m_color(color),
255 m_interrupt_exits(true) {
258#if LLDB_ENABLE_LIBEDIT
259 bool use_editline =
false;
265 m_editline_up = std::make_unique<Editline>(editline_name,
GetInputFILE(),
268 m_editline_up->SetIsInputCompleteCallback(
270 return this->IsInputCompleteCallback(editline, lines);
274 this->AutoCompleteCallback(request);
278 m_editline_up->SetSuggestionCallback([
this](llvm::StringRef line) {
279 return this->SuggestionCallback(line);
295 int cursor_position) {
296 return this->FixIndentationCallback(editline, lines, cursor_position);
298 m_editline_up->SetFixIndentationCallback(std::move(f), indent_chars);
308#if LLDB_ENABLE_LIBEDIT
309 m_editline_up.reset();
324#if LLDB_ENABLE_LIBEDIT
326 m_editline_up->TerminalSizeChanged();
331static std::optional<std::string>
SplitLine(std::string &line_buffer) {
332 size_t pos = line_buffer.find(
'\n');
333 if (pos == std::string::npos)
336 std::string(StringRef(line_buffer.c_str(), pos).rtrim(
"\n\r"));
337 line_buffer = line_buffer.substr(pos + 1);
343static std::optional<std::string>
SplitLineEOF(std::string &line_buffer) {
344 if (llvm::all_of(line_buffer, llvm::isSpace))
346 std::string line = std::move(line_buffer);
352#if LLDB_ENABLE_LIBEDIT
354 return m_editline_up->GetLine(line, interrupted);
361 const char *prompt =
nullptr;
366 if (prompt ==
nullptr)
369 if (prompt && prompt[0]) {
391 size_t bytes_read =
sizeof(buffer);
393 if (
error.Success() && !bytes_read) {
404 if (!got_line && in) {
406 char *r = fgets(buffer,
sizeof(buffer), in);
415 r = fgets(buffer,
sizeof(buffer), in);
417 if (r ==
nullptr && GetLastError() == ERROR_OPERATION_ABORTED)
421 if (ferror(in) && errno == EINTR)
436 return (
bool)got_line;
439#if LLDB_ENABLE_LIBEDIT
440bool IOHandlerEditline::IsInputCompleteCallback(
Editline *editline,
445int IOHandlerEditline::FixIndentationCallback(
Editline *editline,
447 int cursor_position) {
451std::optional<std::string>
452IOHandlerEditline::SuggestionCallback(llvm::StringRef line) {
462#if LLDB_ENABLE_LIBEDIT
464 return m_editline_up->GetPrompt();
469#if LLDB_ENABLE_LIBEDIT
478#if LLDB_ENABLE_LIBEDIT
482 m_editline_up->SetPromptAnsiPrefix(
484 m_editline_up->SetPromptAnsiSuffix(
500#if LLDB_ENABLE_LIBEDIT
513#if LLDB_ENABLE_LIBEDIT
515 return m_editline_up->GetCurrentLine();
521#if LLDB_ENABLE_LIBEDIT
523 return m_editline_up->GetInputAsStringList();
538 bool success =
false;
539#if LLDB_ENABLE_LIBEDIT
560 bool interrupted =
false;
561 if (
GetLine(line, interrupted) && !interrupted) {
569#if LLDB_ENABLE_LIBEDIT
580 bool interrupted =
false;
596 if (
GetLine(line, interrupted)) {
609#if LLDB_ENABLE_LIBEDIT
611 m_editline_up->Cancel();
620#if LLDB_ENABLE_LIBEDIT
622 return m_editline_up->Interrupt();
628#if LLDB_ENABLE_LIBEDIT
630 m_editline_up->Interrupt();
635#if LLDB_ENABLE_LIBEDIT
639 m_editline_up->PrintAsync(stream.get(), s, len);
647 CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
648 HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
649 GetConsoleScreenBufferInfo(console_handle, &screen_buffer_info);
650 COORD coord = screen_buffer_info.dwCursorPosition;
651 coord.X -= strlen(prompt);
654 SetConsoleCursorPosition(console_handle, coord);
static llvm::raw_ostream & error(Stream &strm)
static std::optional< std::string > SplitLine(std::string &line_buffer)
static std::optional< std::string > SplitLineEOF(std::string &line_buffer)
static bool InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, uint32_t completion_mask, lldb_private::CompletionRequest &request, SearchFilter *searcher)
std::optional< std::string > GetAutoSuggestionForCommand(llvm::StringRef line)
Returns the auto-suggestion string that should be added to the given command line.
void HandleCompletion(CompletionRequest &request)
"lldb/Utility/ArgCompletionRequest.h"
void AddCompletion(llvm::StringRef completion, llvm::StringRef description="", CompletionMode mode=CompletionMode::Normal)
Adds a possible completion string.
unsigned GetRawCursorPos() const
A class to manage flag bits.
llvm::StringRef GetAutosuggestionAnsiPrefix() const
CommandInterpreter & GetCommandInterpreter()
llvm::StringRef GetAutosuggestionAnsiSuffix() const
llvm::StringRef GetPromptAnsiSuffix() const
llvm::StringRef GetPromptAnsiPrefix() const
bool GetUseAutosuggestion() const
void AdoptTopIOHandlerFilesIfInvalid(lldb::FileSP &in, lldb::StreamFileSP &out, lldb::StreamFileSP &err)
Instances of Editline provide an abstraction over libedit's EditLine facility.
const bool m_default_response
IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt, bool default_response)
void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override
Called when a line or lines have been retrieved.
void IOHandlerComplete(IOHandler &io_handler, CompletionRequest &request) override
~IOHandlerConfirm() override
A delegate class for use with IOHandler subclasses.
virtual void IOHandlerActivated(IOHandler &io_handler, bool interactive)
virtual void IOHandlerComplete(IOHandler &io_handler, CompletionRequest &request)
virtual const char * IOHandlerGetFixIndentationCharacters()
virtual void IOHandlerInputComplete(IOHandler &io_handler, std::string &data)=0
Called when a line or lines have been retrieved.
virtual bool IOHandlerInterrupt(IOHandler &io_handler)
virtual void IOHandlerDeactivated(IOHandler &io_handler)
virtual bool IOHandlerIsInputComplete(IOHandler &io_handler, StringList &lines)
Called to determine whether typing enter after the last line in lines should end input.
virtual std::optional< std::string > IOHandlerSuggestion(IOHandler &io_handler, llvm::StringRef line)
virtual int IOHandlerFixIndentation(IOHandler &io_handler, const StringList &lines, int cursor_position)
Called when a new line is created or one of an identified set of indentation characters is typed.
virtual void IOHandlerInputInterrupted(IOHandler &io_handler, std::string &data)
void PrintAsync(const char *s, size_t len, bool is_stdout) override
bool SetPrompt(llvm::StringRef prompt) override
bool Interrupt() override
bool GetLine(std::string &line, bool &interrupted)
void TerminalSizeChanged() override
~IOHandlerEditline() override
uint32_t m_base_line_number
bool GetLines(StringList &lines, bool &interrupted)
std::string m_continuation_prompt
const char * GetContinuationPrompt()
void SetBaseLineNumber(uint32_t line)
IOHandlerEditline(Debugger &debugger, IOHandler::Type type, const char *editline_name, llvm::StringRef prompt, llvm::StringRef continuation_prompt, bool multi_line, bool color, uint32_t line_number_start, IOHandlerDelegate &delegate)
void SetContinuationPrompt(llvm::StringRef prompt)
StringList * m_current_lines_ptr
IOHandlerDelegate & m_delegate
std::string m_line_buffer
const char * GetPrompt() override
uint32_t GetCurrentLineIndex() const
void Deactivate() override
StringList GetCurrentLines() const
bool PrintAsync(const char *s, size_t len, bool is_stdout)
std::recursive_mutex m_mutex
virtual void PrintAsync(const char *s, size_t len, bool is_stdout)
Predicate< bool > m_popped
lldb::StreamFileSP GetErrorStreamFileSP()
bool GetIsRealTerminal()
Check if the input is coming from a real terminal.
lldb::FileSP GetInputFileSP()
std::recursive_mutex & GetOutputMutex()
std::recursive_mutex m_output_mutex
virtual void Deactivate()
lldb::StreamFileSP m_error_sp
lldb::StreamFileSP GetOutputStreamFileSP()
IOHandler(Debugger &debugger, IOHandler::Type type)
bool GetIsInteractive()
Check if the input is being supplied interactively by a user.
lldb::StreamFileSP m_output_sp
void SetValue(T value, PredicateBroadcastType broadcast_type)
Value set accessor.
bool WaitForValueEqualTo(T value, const Timeout< std::micro > &timeout=std::nullopt)
Wait for m_value to be equal to value.
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
std::string CopyList(const char *item_preamble=nullptr, const char *items_sep="\n") const
void AppendString(const std::string &s)
std::string FormatAnsiTerminalCodes(llvm::StringRef format, bool do_color=true)
llvm::unique_function< int(Editline *, StringList &, int)> FixIndentationCallbackType
A class that represents a running process on the host machine.
@ eBroadcastOnChange
Only broadcast if the value changes when the value is modified.
@ eVariablePathCompletion
std::shared_ptr< lldb_private::StreamFile > StreamFileSP
std::shared_ptr< lldb_private::File > FileSP