1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-16 19:55:06 +00:00

Shell: Allow a command sequence to be delimited by newlines

This commit is contained in:
AnotherTest 2020-06-28 18:43:37 +04:30 committed by Andreas Kling
parent 639c1a1737
commit 034be8e74c
3 changed files with 26 additions and 10 deletions

View file

@ -102,6 +102,11 @@ static constexpr auto is_not(char c)
return [c](char ch) { return ch != c; }; return [c](char ch) { return ch != c; };
} }
static constexpr auto is_any_of(StringView s)
{
return [s](char ch) { return s.contains(ch); };
}
static inline char to_byte(char a, char b) static inline char to_byte(char a, char b)
{ {
char buf[3] { a, b, 0 }; char buf[3] { a, b, 0 };
@ -139,6 +144,15 @@ RefPtr<AST::Node> Parser::parse_sequence()
auto rule_start = push_start(); auto rule_start = push_start();
auto var_decls = parse_variable_decls(); auto var_decls = parse_variable_decls();
switch (peek()) {
case ';':
case '\n':
consume_while(is_any_of("\n;"));
break;
default:
break;
}
auto pipe_seq = parse_pipe_sequence(); auto pipe_seq = parse_pipe_sequence();
if (!pipe_seq) if (!pipe_seq)
return var_decls; return var_decls;
@ -150,7 +164,8 @@ RefPtr<AST::Node> Parser::parse_sequence()
switch (peek()) { switch (peek()) {
case ';': case ';':
consume(); case '\n':
consume_while(is_any_of("\n;"));
if (auto expr = parse_sequence()) { if (auto expr = parse_sequence()) {
return create<AST::Sequence>(move(pipe_seq), move(expr)); // Sequence return create<AST::Sequence>(move(pipe_seq), move(expr)); // Sequence
} }
@ -429,7 +444,7 @@ RefPtr<AST::Node> Parser::parse_expression()
return expr; return expr;
}; };
if (strchr("&|[]){} ;<>", starting_char) != nullptr) if (strchr("&|[]){} ;<>\n", starting_char) != nullptr)
return nullptr; return nullptr;
if (isdigit(starting_char)) { if (isdigit(starting_char)) {
@ -710,7 +725,7 @@ RefPtr<AST::Node> Parser::parse_bareword()
auto rule_start = push_start(); auto rule_start = push_start();
StringBuilder builder; StringBuilder builder;
auto is_acceptable_bareword_character = [](char c) { auto is_acceptable_bareword_character = [](char c) {
return strchr("\\\"'*$&#|()[]{} ?;<>", c) == nullptr; return strchr("\\\"'*$&#|()[]{} ?;<>\n", c) == nullptr;
}; };
while (!at_end()) { while (!at_end()) {
char ch = peek(); char ch = peek();

View file

@ -100,11 +100,15 @@ private:
constexpr auto the_grammar = R"( constexpr auto the_grammar = R"(
toplevel :: sequence? toplevel :: sequence?
sequence :: variable_decls? pipe_sequence ';' sequence sequence :: variable_decls? pipe_sequence terminator sequence
| variable_decls? pipe_sequence '&' | variable_decls? pipe_sequence '&'
| variable_decls? pipe_sequence '&' '&' sequence | variable_decls? pipe_sequence '&' '&' sequence
| variable_decls? pipe_sequence '|' '|' sequence | variable_decls? pipe_sequence '|' '|' sequence
| variable_decls? pipe_sequence | variable_decls? pipe_sequence
| variable_decls? terminator pipe_sequence
terminator :: ';'
| '\n'
variable_decls :: identifier '=' expression (' '+ variable_decls)? ' '* variable_decls :: identifier '=' expression (' '+ variable_decls)? ' '*
| identifier '=' '(' pipe_sequence ')' (' '+ variable_decls)? ' '* | identifier '=' '(' pipe_sequence ')' (' '+ variable_decls)? ' '*
@ -118,6 +122,7 @@ command :: redirection command
redirection :: number? '>'{1,2} ' '* string_composite redirection :: number? '>'{1,2} ' '* string_composite
| number? '<' ' '* string_composite | number? '<' ' '* string_composite
| number? '>' '&' number | number? '>' '&' number
| number? '>' '&' '-'
list_expression :: ' '* expression (' '+ list_expression)? list_expression :: ' '* expression (' '+ list_expression)?

View file

@ -497,12 +497,8 @@ bool Shell::run_file(const String& filename)
return false; return false;
} }
auto file = file_result.value(); auto file = file_result.value();
for (;;) { auto data = file->read_all();
auto line = file->read_line(4096); run_command(data);
if (line.is_null())
break;
run_command(String::copy(line, Chomp));
}
return true; return true;
} }
void Shell::take_back_stdin() void Shell::take_back_stdin()