From 8b3eb4535dc0cc7ee7fef73315a8537f0cb915d7 Mon Sep 17 00:00:00 2001 From: AnotherTest Date: Tue, 26 May 2020 19:52:01 +0430 Subject: [PATCH] LibLine: Use LibC's getline() when the terminal claims no support for escape sequences We just look at $TERM and refuse to emit any escape sequences if it doesn't start with "xterm". This could be made much better, at detecting, and at not caling getline(). --- Libraries/LibLine/Editor.cpp | 42 ++++++++++++++++++++++++++++++++++++ Libraries/LibLine/Editor.h | 22 ++++++------------- 2 files changed, 49 insertions(+), 15 deletions(-) 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; }