diff --git a/Libraries/LibLine/Editor.cpp b/Libraries/LibLine/Editor.cpp index bb11476717..2b38e7fa11 100644 --- a/Libraries/LibLine/Editor.cpp +++ b/Libraries/LibLine/Editor.cpp @@ -226,11 +226,53 @@ void Editor::suggest(size_t invariant_offset, size_t static_offset, Span::Mode o m_suggestion_manager.set_suggestion_variants(internal_static_offset, internal_invariant_offset, 0); } +void Editor::initialize() +{ + if (m_initialized) + return; + + struct termios termios; + tcgetattr(0, &termios); + m_default_termios = termios; // grab a copy to restore + + auto* term = getenv("TERM"); + if (StringView { term }.starts_with("xterm")) + m_configuration.set(Configuration::Full); + else + m_configuration.set(Configuration::NoEscapeSequences); + + // Because we use our own line discipline which includes echoing, + // we disable ICANON and ECHO. + if (m_configuration.operation_mode == Configuration::Full) { + termios.c_lflag &= ~(ECHO | ICANON); + tcsetattr(0, TCSANOW, &termios); + } + + m_termios = termios; + m_initialized = true; +} + Result Editor::get_line(const String& prompt) { initialize(); m_is_editing = true; + if (m_configuration.operation_mode == Configuration::NoEscapeSequences) { + // Do not use escape sequences, instead, use LibC's getline. + size_t size = 0; + char* line = nullptr; + fputs(prompt.characters(), stderr); + size_t line_length = getline(&line, &size, stdin); + restore(); + if (line) { + String result { line, line_length, Chomp }; + free(line); + return result; + } + + return Error::ReadFailure; + } + set_prompt(prompt); reset(); set_origin(); diff --git a/Libraries/LibLine/Editor.h b/Libraries/LibLine/Editor.h index 695345fe0e..07fe8f8797 100644 --- a/Libraries/LibLine/Editor.h +++ b/Libraries/LibLine/Editor.h @@ -57,6 +57,10 @@ struct Configuration { Lazy, Eager, }; + enum OperationMode { + Full, + NoEscapeSequences, + }; Configuration() { @@ -71,9 +75,11 @@ struct Configuration { void set(RefreshBehaviour refresh) { refresh_behaviour = refresh; } void set(TokenSplitMechanism split) { split_mechanism = split; } + void set(OperationMode mode) { operation_mode = mode; } RefreshBehaviour refresh_behaviour { RefreshBehaviour::Lazy }; TokenSplitMechanism split_mechanism { TokenSplitMechanism::Spaces }; + OperationMode operation_mode { OperationMode::Full }; }; class Editor { @@ -89,21 +95,7 @@ public: Result get_line(const String& prompt); - void initialize() - { - if (m_initialized) - return; - - struct termios termios; - tcgetattr(0, &termios); - m_default_termios = termios; // grab a copy to restore - // Because we use our own line discipline which includes echoing, - // we disable ICANON and ECHO. - termios.c_lflag &= ~(ECHO | ICANON); - tcsetattr(0, TCSANOW, &termios); - m_termios = termios; - m_initialized = true; - } + void initialize(); void add_to_history(const String&); const Vector& history() const { return m_history; }