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().
This commit is contained in:
AnotherTest 2020-05-26 19:52:01 +04:30 committed by Andreas Kling
parent e4760e5b42
commit 8b3eb4535d
Notes: sideshowbarker 2024-07-19 06:06:19 +09:00
2 changed files with 49 additions and 15 deletions

View file

@ -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<String, Editor::Error> 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();

View file

@ -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<String, Error> 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<String>& history() const { return m_history; }