1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 07:37:35 +00:00

Shell: Add support for brace expansions

This adds support for (basic) brace expansions with the following
syntaxes:
- `{expr?,expr?,expr?,...}` which is directly equivalent to `(expr expr
  expr ...)`, with the missing expressions replaced with an empty string
  literal.
- `{expr..expr}` which is a new range expansion, with two modes:
    - if both expressions are one unicode code point long, the range is
      equivalent to the two code points and all code points between the
      two (numerically).
    - if both expressions are numeric, the range is equivalent to both
      numbers, and all numbers between the two.
    - otherwise, it is equivalent to `(expr expr)`.

Closes #3832.
This commit is contained in:
AnotherTest 2020-10-24 18:13:02 +03:30 committed by Andreas Kling
parent 567f2f3548
commit 5640e1bc3a
9 changed files with 374 additions and 3 deletions

View file

@ -297,6 +297,10 @@ public:
: m_contained_values(move(static_cast<NonnullRefPtrVector<Value>&>(values)))
{
}
ListValue(NonnullRefPtrVector<Value> values)
: m_contained_values(move(values))
{
}
const NonnullRefPtrVector<Value>& values() const { return m_contained_values; }
NonnullRefPtrVector<Value>& values() { return m_contained_values; }
@ -433,6 +437,7 @@ public:
ListConcatenate,
Background,
BarewordLiteral,
BraceExpansion,
CastToCommand,
CastToList,
CloseFdRedirection,
@ -450,6 +455,7 @@ public:
MatchExpr,
Or,
Pipe,
Range,
ReadRedirection,
ReadWriteRedirection,
Sequence,
@ -576,6 +582,24 @@ private:
String m_text;
};
class BraceExpansion final : public Node {
public:
BraceExpansion(Position, NonnullRefPtrVector<Node>);
virtual ~BraceExpansion();
virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
const NonnullRefPtrVector<Node>& entries() const { return m_entries; }
private:
NODE(BraceExpansion);
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) override;
NonnullRefPtrVector<Node> m_entries;
};
class CastToCommand final : public Node {
public:
CastToCommand(Position, NonnullRefPtr<Node>);
@ -958,6 +982,26 @@ private:
NonnullRefPtr<Node> m_right;
};
class Range final : public Node {
public:
Range(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>);
virtual ~Range();
virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
const NonnullRefPtr<Node>& start() const { return m_start; }
const NonnullRefPtr<Node>& end() const { return m_end; }
private:
NODE(Range);
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) override;
NonnullRefPtr<Node> m_start;
NonnullRefPtr<Node> m_end;
};
class ReadRedirection final : public PathRedirectionNode {
public:
ReadRedirection(Position, int, NonnullRefPtr<Node>);