mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 06:08:10 +00:00
Shell: Highlight redirections
This commit is contained in:
parent
07c070745f
commit
2714bba3f0
3 changed files with 46 additions and 6 deletions
|
@ -147,6 +147,8 @@ Vector<Command> Parser::parse()
|
||||||
if (ch == '>') {
|
if (ch == '>') {
|
||||||
commit_token(Token::Special);
|
commit_token(Token::Special);
|
||||||
begin_redirect_write(STDOUT_FILENO);
|
begin_redirect_write(STDOUT_FILENO);
|
||||||
|
ASSERT(!m_redirections.is_empty());
|
||||||
|
m_redirections.last().redirection_op_start = m_position;
|
||||||
|
|
||||||
// Search for another > for append.
|
// Search for another > for append.
|
||||||
push_state(State::InWriteAppendOrRedirectionPath);
|
push_state(State::InWriteAppendOrRedirectionPath);
|
||||||
|
@ -155,6 +157,8 @@ Vector<Command> Parser::parse()
|
||||||
if (ch == '<') {
|
if (ch == '<') {
|
||||||
commit_token(Token::Special);
|
commit_token(Token::Special);
|
||||||
begin_redirect_read(STDIN_FILENO);
|
begin_redirect_read(STDIN_FILENO);
|
||||||
|
ASSERT(!m_redirections.is_empty());
|
||||||
|
m_redirections.last().redirection_op_start = m_position;
|
||||||
push_state(State::InRedirectionPath);
|
push_state(State::InRedirectionPath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -208,11 +212,15 @@ Vector<Command> Parser::parse()
|
||||||
|
|
||||||
if (m_input.characters()[redir_end] == '>') {
|
if (m_input.characters()[redir_end] == '>') {
|
||||||
begin_redirect_write(fd);
|
begin_redirect_write(fd);
|
||||||
|
ASSERT(!m_redirections.is_empty());
|
||||||
|
m_redirections.last().redirection_op_start = m_position;
|
||||||
// Search for another > for append.
|
// Search for another > for append.
|
||||||
push_state(State::InWriteAppendOrRedirectionPath);
|
push_state(State::InWriteAppendOrRedirectionPath);
|
||||||
}
|
}
|
||||||
if (m_input.characters()[redir_end] == '<') {
|
if (m_input.characters()[redir_end] == '<') {
|
||||||
begin_redirect_read(fd);
|
begin_redirect_read(fd);
|
||||||
|
ASSERT(!m_redirections.is_empty());
|
||||||
|
m_redirections.last().redirection_op_start = m_position;
|
||||||
push_state(State::InRedirectionPath);
|
push_state(State::InRedirectionPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,6 +235,8 @@ Vector<Command> Parser::parse()
|
||||||
if (next_ch == '>') {
|
if (next_ch == '>') {
|
||||||
commit_token(Token::Special);
|
commit_token(Token::Special);
|
||||||
begin_redirect_write(ch - '0');
|
begin_redirect_write(ch - '0');
|
||||||
|
ASSERT(!m_redirections.is_empty());
|
||||||
|
m_redirections.last().redirection_op_start = m_position;
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
// Search for another > for append.
|
// Search for another > for append.
|
||||||
|
@ -236,6 +246,8 @@ Vector<Command> Parser::parse()
|
||||||
if (next_ch == '<') {
|
if (next_ch == '<') {
|
||||||
commit_token(Token::Special);
|
commit_token(Token::Special);
|
||||||
begin_redirect_read(ch - '0');
|
begin_redirect_read(ch - '0');
|
||||||
|
ASSERT(!m_redirections.is_empty());
|
||||||
|
m_redirections.last().redirection_op_start = m_position;
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
push_state(State::InRedirectionPath);
|
push_state(State::InRedirectionPath);
|
||||||
|
@ -251,7 +263,7 @@ Vector<Command> Parser::parse()
|
||||||
pop_state();
|
pop_state();
|
||||||
push_state(State::InRedirectionPath);
|
push_state(State::InRedirectionPath);
|
||||||
ASSERT(m_redirections.size());
|
ASSERT(m_redirections.size());
|
||||||
m_redirections[m_redirections.size() - 1].type = Redirection::FileWriteAppend;
|
m_redirections.last().type = Redirection::FileWriteAppend;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,15 +275,11 @@ Vector<Command> Parser::parse()
|
||||||
if (ch == '<') {
|
if (ch == '<') {
|
||||||
commit_token(Token::Special);
|
commit_token(Token::Special);
|
||||||
begin_redirect_read(STDIN_FILENO);
|
begin_redirect_read(STDIN_FILENO);
|
||||||
pop_state();
|
|
||||||
push_state(State::InRedirectionPath);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ch == '>') {
|
if (ch == '>') {
|
||||||
commit_token(Token::Special);
|
commit_token(Token::Special);
|
||||||
begin_redirect_read(STDOUT_FILENO);
|
begin_redirect_read(STDOUT_FILENO);
|
||||||
pop_state();
|
|
||||||
push_state(State::InRedirectionPath);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ch == '|') {
|
if (ch == '|') {
|
||||||
|
@ -292,8 +300,20 @@ Vector<Command> Parser::parse()
|
||||||
push_state(State::InSingleQuotes);
|
push_state(State::InSingleQuotes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ch == ' ')
|
if (ch == ' ') {
|
||||||
|
if (m_token.is_empty()) {
|
||||||
|
// foo > bar
|
||||||
|
// ^ We are at this space, we want to ignore it but not leave the state.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
commit_token(Token::Special);
|
||||||
|
if (m_tokens.is_empty()) {
|
||||||
|
fprintf(stderr, "Syntax error: Redirection without a path\n");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
pop_state();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
m_token.append(ch);
|
m_token.append(ch);
|
||||||
break;
|
break;
|
||||||
case State::InSingleQuotes:
|
case State::InSingleQuotes:
|
||||||
|
|
|
@ -61,6 +61,7 @@ struct Redirection {
|
||||||
Type type;
|
Type type;
|
||||||
int fd { -1 };
|
int fd { -1 };
|
||||||
int rewire_fd { -1 };
|
int rewire_fd { -1 };
|
||||||
|
size_t redirection_op_start { 0 };
|
||||||
Token path {};
|
Token path {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1482,17 +1482,36 @@ void Shell::cache_path()
|
||||||
void Shell::highlight(Line::Editor& editor) const
|
void Shell::highlight(Line::Editor& editor) const
|
||||||
{
|
{
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
|
bool is_offset_by_string_start = false;
|
||||||
if (m_should_continue == ExitCodeOrContinuationRequest::DoubleQuotedString) {
|
if (m_should_continue == ExitCodeOrContinuationRequest::DoubleQuotedString) {
|
||||||
builder.append('"');
|
builder.append('"');
|
||||||
|
is_offset_by_string_start = true;
|
||||||
}
|
}
|
||||||
if (m_should_continue == ExitCodeOrContinuationRequest::SingleQuotedString) {
|
if (m_should_continue == ExitCodeOrContinuationRequest::SingleQuotedString) {
|
||||||
builder.append('\'');
|
builder.append('\'');
|
||||||
|
is_offset_by_string_start = true;
|
||||||
}
|
}
|
||||||
builder.append(editor.line());
|
builder.append(editor.line());
|
||||||
auto commands = Parser { builder.string_view() }.parse();
|
auto commands = Parser { builder.string_view() }.parse();
|
||||||
auto first_command { true };
|
auto first_command { true };
|
||||||
for (auto& command : commands) {
|
for (auto& command : commands) {
|
||||||
for (auto& subcommand : command.subcommands) {
|
for (auto& subcommand : command.subcommands) {
|
||||||
|
auto& redirections = subcommand.redirections;
|
||||||
|
for (auto& redirection : redirections) {
|
||||||
|
if (redirection.type == Redirection::Pipe)
|
||||||
|
continue;
|
||||||
|
if (redirection.path.length == 0)
|
||||||
|
continue;
|
||||||
|
Line::Style redirection_style { Line::Style::Foreground(0x87, 0x9b, 0xcd) }; // 25% darkened periwinkle :)
|
||||||
|
auto end = redirection.path.end;
|
||||||
|
auto redirection_op_start = redirection.redirection_op_start;
|
||||||
|
if (is_offset_by_string_start) {
|
||||||
|
end--;
|
||||||
|
redirection_op_start--;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.stylize({ redirection_op_start, end }, redirection_style);
|
||||||
|
}
|
||||||
auto first { true };
|
auto first { true };
|
||||||
for (auto& arg : subcommand.args) {
|
for (auto& arg : subcommand.args) {
|
||||||
auto start = arg.end - arg.length;
|
auto start = arg.end - arg.length;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue