summaryrefslogtreecommitdiff
path: root/Shell
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-06-28 18:43:37 +0430
committerAndreas Kling <kling@serenityos.org>2020-07-05 15:43:14 +0200
commit034be8e74c946f2820ab7a31f04d168574456f7c (patch)
treebc7e068a7387a6289106e1689dab3bec03195d51 /Shell
parent639c1a17379054138d350c85e6fcab3d886707d8 (diff)
downloadserenity-034be8e74c946f2820ab7a31f04d168574456f7c.zip
Shell: Allow a command sequence to be delimited by newlines
Diffstat (limited to 'Shell')
-rw-r--r--Shell/Parser.cpp21
-rw-r--r--Shell/Parser.h7
-rw-r--r--Shell/Shell.cpp8
3 files changed, 26 insertions, 10 deletions
diff --git a/Shell/Parser.cpp b/Shell/Parser.cpp
index ebb81bf79e..9d018f0cef 100644
--- a/Shell/Parser.cpp
+++ b/Shell/Parser.cpp
@@ -102,6 +102,11 @@ static constexpr auto is_not(char 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)
{
char buf[3] { a, b, 0 };
@@ -139,6 +144,15 @@ RefPtr<AST::Node> Parser::parse_sequence()
auto rule_start = push_start();
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();
if (!pipe_seq)
return var_decls;
@@ -150,7 +164,8 @@ RefPtr<AST::Node> Parser::parse_sequence()
switch (peek()) {
case ';':
- consume();
+ case '\n':
+ consume_while(is_any_of("\n;"));
if (auto expr = parse_sequence()) {
return create<AST::Sequence>(move(pipe_seq), move(expr)); // Sequence
}
@@ -429,7 +444,7 @@ RefPtr<AST::Node> Parser::parse_expression()
return expr;
};
- if (strchr("&|[]){} ;<>", starting_char) != nullptr)
+ if (strchr("&|[]){} ;<>\n", starting_char) != nullptr)
return nullptr;
if (isdigit(starting_char)) {
@@ -710,7 +725,7 @@ RefPtr<AST::Node> Parser::parse_bareword()
auto rule_start = push_start();
StringBuilder builder;
auto is_acceptable_bareword_character = [](char c) {
- return strchr("\\\"'*$&#|()[]{} ?;<>", c) == nullptr;
+ return strchr("\\\"'*$&#|()[]{} ?;<>\n", c) == nullptr;
};
while (!at_end()) {
char ch = peek();
diff --git a/Shell/Parser.h b/Shell/Parser.h
index de47af0b46..681d0d29df 100644
--- a/Shell/Parser.h
+++ b/Shell/Parser.h
@@ -100,11 +100,15 @@ private:
constexpr auto the_grammar = R"(
toplevel :: sequence?
-sequence :: variable_decls? pipe_sequence ';' sequence
+sequence :: variable_decls? pipe_sequence terminator sequence
| variable_decls? pipe_sequence '&'
| variable_decls? pipe_sequence '&' '&' sequence
| variable_decls? pipe_sequence '|' '|' sequence
| variable_decls? pipe_sequence
+ | variable_decls? terminator pipe_sequence
+
+terminator :: ';'
+ | '\n'
variable_decls :: identifier '=' expression (' '+ variable_decls)? ' '*
| identifier '=' '(' pipe_sequence ')' (' '+ variable_decls)? ' '*
@@ -118,6 +122,7 @@ command :: redirection command
redirection :: number? '>'{1,2} ' '* string_composite
| number? '<' ' '* string_composite
| number? '>' '&' number
+ | number? '>' '&' '-'
list_expression :: ' '* expression (' '+ list_expression)?
diff --git a/Shell/Shell.cpp b/Shell/Shell.cpp
index 715a8d3f64..3bfbb0c84e 100644
--- a/Shell/Shell.cpp
+++ b/Shell/Shell.cpp
@@ -497,12 +497,8 @@ bool Shell::run_file(const String& filename)
return false;
}
auto file = file_result.value();
- for (;;) {
- auto line = file->read_line(4096);
- if (line.is_null())
- break;
- run_command(String::copy(line, Chomp));
- }
+ auto data = file->read_all();
+ run_command(data);
return true;
}
void Shell::take_back_stdin()