LibLine: Check if operating on a TTY before using TTY features

This makes the line editor behave well when input is passed in from
pipes as well.
This commit is contained in:
AnotherTest 2020-08-05 09:58:47 +04:30 committed by Andreas Kling
parent a7ea7b3a66
commit 70eb7aa627
2 changed files with 36 additions and 13 deletions

View file

@ -250,11 +250,18 @@ void Editor::initialize()
if (m_was_resized) if (m_was_resized)
get_terminal_size(); get_terminal_size();
auto* term = getenv("TERM"); if (m_configuration.operation_mode == Configuration::Unset) {
if (StringView { term }.starts_with("xterm")) auto istty = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO);
m_configuration.set(Configuration::Full); if (!istty) {
else m_configuration.set(Configuration::NonInteractive);
m_configuration.set(Configuration::NoEscapeSequences); } else {
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, // Because we use our own line discipline which includes echoing,
// we disable ICANON and ECHO. // we disable ICANON and ECHO.
@ -272,15 +279,26 @@ auto Editor::get_line(const String& prompt) -> Result<String, Editor::Error>
initialize(); initialize();
m_is_editing = true; m_is_editing = true;
if (m_configuration.operation_mode == Configuration::NoEscapeSequences) { if (m_configuration.operation_mode == Configuration::NoEscapeSequences || m_configuration.operation_mode == Configuration::NonInteractive) {
// Do not use escape sequences, instead, use LibC's getline. // Do not use escape sequences, instead, use LibC's getline.
size_t size = 0; size_t size = 0;
char* line = nullptr; char* line = nullptr;
fputs(prompt.characters(), stderr); // Show the prompt only on interactive mode (NoEscapeSequences in this case).
size_t line_length = getline(&line, &size, stdin); if (m_configuration.operation_mode != Configuration::NonInteractive)
fputs(prompt.characters(), stderr);
auto line_length = getline(&line, &size, stdin);
// getline() returns -1 and sets errno=0 on EOF.
if (line_length == -1) {
if (line)
free(line);
if (errno == 0)
return Error::Eof;
return Error::ReadFailure;
}
restore(); restore();
if (line) { if (line) {
String result { line, line_length, Chomp }; String result { line, (size_t)line_length, Chomp };
free(line); free(line);
return result; return result;
} }
@ -429,7 +447,10 @@ void Editor::handle_read_event()
Utf8View input_view { StringView { m_incomplete_data.data(), valid_bytes } }; Utf8View input_view { StringView { m_incomplete_data.data(), valid_bytes } };
size_t consumed_code_pointss = 0; size_t consumed_code_pointss = 0;
enum Amount { Character, Word }; enum Amount {
Character,
Word,
};
auto do_cursor_left = [&](Amount amount) { auto do_cursor_left = [&](Amount amount) {
if (m_cursor > 0) { if (m_cursor > 0) {
if (amount == Word) { if (amount == Word) {
@ -565,12 +586,12 @@ void Editor::handle_read_event()
ctrl_held = false; ctrl_held = false;
continue; continue;
case 'D': // left case 'D': // left
do_cursor_left(ctrl_held ? Word : Character); do_cursor_left(ctrl_held ? Word : Character);
m_state = InputState::Free; m_state = InputState::Free;
ctrl_held = false; ctrl_held = false;
continue; continue;
case 'C': // right case 'C': // right
do_cursor_right(ctrl_held ? Word : Character); do_cursor_right(ctrl_held ? Word : Character);
m_state = InputState::Free; m_state = InputState::Free;
ctrl_held = false; ctrl_held = false;
continue; continue;

View file

@ -61,8 +61,10 @@ struct Configuration {
Eager, Eager,
}; };
enum OperationMode { enum OperationMode {
Unset,
Full, Full,
NoEscapeSequences, NoEscapeSequences,
NonInteractive,
}; };
Configuration() Configuration()
@ -82,7 +84,7 @@ struct Configuration {
RefreshBehaviour refresh_behaviour { RefreshBehaviour::Lazy }; RefreshBehaviour refresh_behaviour { RefreshBehaviour::Lazy };
TokenSplitMechanism split_mechanism { TokenSplitMechanism::Spaces }; TokenSplitMechanism split_mechanism { TokenSplitMechanism::Spaces };
OperationMode operation_mode { OperationMode::Full }; OperationMode operation_mode { OperationMode::Unset };
}; };
class Editor : public Core::Object { class Editor : public Core::Object {