mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 03:17:35 +00:00
Shell: Add support for heredocs
Closes #4283. Heredocs are implemented in a way that makes them feel more like a string (and not a weird redirection, a la bash). There are two tunables, whether the string is dedented (`<<-` vs `<<~`) and whether it allows interpolation (quoted key vs not). To the familiar people, this is how Ruby handles them, and I feel is the most elegant heredoc syntax. Unlike the oddjob that is bash, heredocs are treated exactly as normal strings, and can be used _anywhere_ where a string can be used. They are *required* to appear in the same order as used after a newline is seen when parsing the sequence that the heredoc is used in. For instance: ```sh echo <<-doc1 <<-doc2 | blah blah contents for doc1 doc1 contents for doc2 doc2 ``` The typical nice errors are also implemented :^)
This commit is contained in:
parent
7c8d39e002
commit
3048274f5e
7 changed files with 364 additions and 10 deletions
|
@ -474,6 +474,7 @@ public:
|
|||
ForLoop,
|
||||
FunctionDeclaration,
|
||||
Glob,
|
||||
Heredoc,
|
||||
HistoryEvent,
|
||||
IfCond,
|
||||
ImmediateExpression,
|
||||
|
@ -1313,6 +1314,39 @@ private:
|
|||
NonnullRefPtr<Node> m_right;
|
||||
};
|
||||
|
||||
class Heredoc final : public Node {
|
||||
public:
|
||||
Heredoc(Position, String end, bool allow_interpolation, bool deindent);
|
||||
virtual ~Heredoc();
|
||||
virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
|
||||
|
||||
const String& end() const { return m_end; }
|
||||
bool allow_interpolation() const { return m_allows_interpolation; }
|
||||
bool deindent() const { return m_deindent; }
|
||||
const RefPtr<AST::Node>& contents() const { return m_contents; }
|
||||
void set_contents(RefPtr<AST::Node> contents)
|
||||
{
|
||||
m_contents = move(contents);
|
||||
if (m_contents->is_syntax_error())
|
||||
set_is_syntax_error(m_contents->syntax_error_node());
|
||||
else
|
||||
clear_syntax_error();
|
||||
}
|
||||
|
||||
private:
|
||||
NODE(Heredoc);
|
||||
virtual void dump(int level) const override;
|
||||
virtual RefPtr<Value> run(RefPtr<Shell>) override;
|
||||
virtual void highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
|
||||
virtual HitTestResult hit_test_position(size_t) const override;
|
||||
virtual RefPtr<Node> leftmost_trivial_literal() const override { return this; };
|
||||
|
||||
String m_end;
|
||||
bool m_allows_interpolation { false };
|
||||
bool m_deindent { false };
|
||||
RefPtr<AST::Node> m_contents;
|
||||
};
|
||||
|
||||
class StringLiteral final : public Node {
|
||||
public:
|
||||
StringLiteral(Position, String);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue