18#include "lldb/Host/Config.h"
27#if LLDB_ENABLE_LIBEDIT
32#include "llvm/ADT/StringRef.h"
65 const lldb::FileSP &input_sp,
66 const lldb::StreamFileSP &output_sp,
67 const lldb::StreamFileSP &error_sp,
uint32_t flags)
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_prompts,
uint32_t line_number_start,
237 prompt, continuation_prompt, multi_line, color_prompts,
238 line_number_start, delegate) {}
242 const lldb::StreamFileSP &output_sp,
const lldb::StreamFileSP &error_sp,
244 const char *editline_name,
245 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
246 bool multi_line,
bool color_prompts,
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),
255 m_color_prompts(color_prompts), m_interrupt_exits(true) {
258#if LLDB_ENABLE_LIBEDIT
259 bool use_editline =
false;
265 m_editline_up = std::make_unique<Editline>(
268 m_editline_up->SetIsInputCompleteCallback(
269 [
this](Editline *editline,
StringList &lines) {
270 return this->IsInputCompleteCallback(editline, lines);
274 this->AutoCompleteCallback(request);
278 m_editline_up->SetSuggestionCallback([
this](llvm::StringRef line) {
279 return this->SuggestionCallback(line);
291 FixIndentationCallbackType f = [
this](Editline *editline,
293 int cursor_position) {
294 return this->FixIndentationCallback(editline, lines, cursor_position);
296 m_editline_up->SetFixIndentationCallback(std::move(f), indent_chars);
306#if LLDB_ENABLE_LIBEDIT
307 m_editline_up.reset();
322#if LLDB_ENABLE_LIBEDIT
324 m_editline_up->TerminalSizeChanged();
329static std::optional<std::string>
SplitLine(std::string &line_buffer) {
330 size_t pos = line_buffer.find(
'\n');
331 if (pos == std::string::npos)
334 std::string(StringRef(line_buffer.c_str(), pos).rtrim(
"\n\r"));
335 line_buffer = line_buffer.substr(pos + 1);
341static std::optional<std::string>
SplitLineEOF(std::string &line_buffer) {
342 if (llvm::all_of(line_buffer, llvm::isSpace))
344 std::string line = std::move(line_buffer);
350#if LLDB_ENABLE_LIBEDIT
352 return m_editline_up->GetLine(line, interrupted);
359 const char *prompt =
nullptr;
364 if (prompt ==
nullptr)
367 if (prompt && prompt[0]) {
389 size_t bytes_read =
sizeof(buffer);
391 if (
error.Success() && !bytes_read) {
402 if (!got_line && in) {
404 char *r = fgets(buffer,
sizeof(buffer), in);
413 r = fgets(buffer,
sizeof(buffer), in);
415 if (r ==
nullptr && GetLastError() == ERROR_OPERATION_ABORTED)
419 if (ferror(in) && errno == EINTR)
434 return (
bool)got_line;
437#if LLDB_ENABLE_LIBEDIT
438bool IOHandlerEditline::IsInputCompleteCallback(Editline *editline,
443int IOHandlerEditline::FixIndentationCallback(Editline *editline,
445 int cursor_position) {
449std::optional<std::string>
450IOHandlerEditline::SuggestionCallback(llvm::StringRef line) {
460#if LLDB_ENABLE_LIBEDIT
462 return m_editline_up->GetPrompt();
467#if LLDB_ENABLE_LIBEDIT
476#if LLDB_ENABLE_LIBEDIT
491#if LLDB_ENABLE_LIBEDIT
504#if LLDB_ENABLE_LIBEDIT
506 return m_editline_up->GetCurrentLine();
514 bool success =
false;
515#if LLDB_ENABLE_LIBEDIT
536 bool interrupted =
false;
537 if (
GetLine(line, interrupted) && !interrupted) {
545#if LLDB_ENABLE_LIBEDIT
556 bool interrupted =
false;
572 if (
GetLine(line, interrupted)) {
585#if LLDB_ENABLE_LIBEDIT
587 m_editline_up->Cancel();
596#if LLDB_ENABLE_LIBEDIT
598 return m_editline_up->Interrupt();
604#if LLDB_ENABLE_LIBEDIT
606 m_editline_up->Interrupt();
611#if LLDB_ENABLE_LIBEDIT
615 m_editline_up->PrintAsync(stream.get(), s, len);
623 CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
624 HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
625 GetConsoleScreenBufferInfo(console_handle, &screen_buffer_info);
626 COORD coord = screen_buffer_info.dwCursorPosition;
627 coord.X -= strlen(prompt);
630 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
bool GetUseAutosuggestion() const
void AdoptTopIOHandlerFilesIfInvalid(lldb::FileSP &in, lldb::StreamFileSP &out, lldb::StreamFileSP &err)
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)
void SetContinuationPrompt(llvm::StringRef prompt)
StringList * m_current_lines_ptr
IOHandlerEditline(Debugger &debugger, IOHandler::Type type, const char *editline_name, llvm::StringRef prompt, llvm::StringRef continuation_prompt, bool multi_line, bool color_prompts, uint32_t line_number_start, IOHandlerDelegate &delegate)
IOHandlerDelegate & m_delegate
std::string m_line_buffer
const char * GetPrompt() override
uint32_t GetCurrentLineIndex() const
void Deactivate() override
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)
A class that represents a running process on the host machine.
@ eBroadcastOnChange
Only broadcast if the value changes when the value is modified.
@ eVariablePathCompletion