mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-05-04 02:08:53 +00:00
Shell: Allow control structures to appear in pipe sequences
This makes commands like the following to be possible: ```sh $ ls && for $(seq 10) { echo $it } $ ls | for $(seq 1) { cat > foobar } ```
This commit is contained in:
parent
7b5ead64a5
commit
aa2df9277d
Notes:
sideshowbarker
2024-07-19 02:48:51 +09:00
Author: https://github.com/alimpfard
Commit: aa2df9277d
Pull-request: https://github.com/SerenityOS/serenity/pull/3372
Reviewed-by: https://github.com/tomuta
5 changed files with 73 additions and 41 deletions
|
@ -107,6 +107,18 @@ void Node::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(RefPtr
|
|||
}
|
||||
}
|
||||
|
||||
Vector<Command> Node::to_lazy_evaluated_commands(RefPtr<Shell> shell)
|
||||
{
|
||||
if (would_execute()) {
|
||||
// Wrap the node in a "should immediately execute next" command.
|
||||
return {
|
||||
Command { {}, {}, true, false, true, true, {}, { NodeWithAction(*this, NodeWithAction::Sequence) } }
|
||||
};
|
||||
}
|
||||
|
||||
return run(shell)->resolve_as_commands(shell);
|
||||
}
|
||||
|
||||
void Node::dump(int level) const
|
||||
{
|
||||
print_indented(String::format("%s at %d:%d", class_name().characters(), m_position.start_offset, m_position.end_offset), level);
|
||||
|
@ -184,7 +196,7 @@ void And::dump(int level) const
|
|||
|
||||
RefPtr<Value> And::run(RefPtr<Shell> shell)
|
||||
{
|
||||
auto commands = m_left->run(shell)->resolve_as_commands(shell);
|
||||
auto commands = m_left->to_lazy_evaluated_commands(shell);
|
||||
commands.last().next_chain.append(NodeWithAction { *m_right, NodeWithAction::And });
|
||||
return create<CommandSequenceValue>(move(commands));
|
||||
}
|
||||
|
@ -340,10 +352,7 @@ RefPtr<Value> Background::run(RefPtr<Shell> shell)
|
|||
// as it runs the node, which means nodes likes And and Or will evaluate
|
||||
// all but their last subnode before yielding to this, causing a command
|
||||
// like `foo && bar&` to effectively be `foo && (bar&)`.
|
||||
auto value = m_command->run(shell)->resolve_without_cast(shell);
|
||||
ASSERT(!value->is_job());
|
||||
|
||||
auto commands = value->resolve_as_commands(shell);
|
||||
auto commands = m_command->to_lazy_evaluated_commands(shell);
|
||||
for (auto& command : commands)
|
||||
command.should_wait = false;
|
||||
|
||||
|
@ -1207,8 +1216,8 @@ void Join::dump(int level) const
|
|||
|
||||
RefPtr<Value> Join::run(RefPtr<Shell> shell)
|
||||
{
|
||||
auto left = m_left->run(shell)->resolve_as_commands(shell);
|
||||
auto right = m_right->run(shell)->resolve_as_commands(shell);
|
||||
auto left = m_left->to_lazy_evaluated_commands(shell);
|
||||
auto right = m_right->to_lazy_evaluated_commands(shell);
|
||||
|
||||
return create<CommandSequenceValue>(join_commands(move(left), move(right)));
|
||||
}
|
||||
|
@ -1263,7 +1272,7 @@ void Or::dump(int level) const
|
|||
|
||||
RefPtr<Value> Or::run(RefPtr<Shell> shell)
|
||||
{
|
||||
auto commands = m_left->run(shell)->resolve_as_commands(shell);
|
||||
auto commands = m_left->to_lazy_evaluated_commands(shell);
|
||||
commands.last().next_chain.empend(*m_right, NodeWithAction::Or);
|
||||
return create<CommandSequenceValue>(move(commands));
|
||||
}
|
||||
|
@ -1315,8 +1324,8 @@ void Pipe::dump(int level) const
|
|||
|
||||
RefPtr<Value> Pipe::run(RefPtr<Shell> shell)
|
||||
{
|
||||
auto left = m_left->run(shell)->resolve_as_commands(shell);
|
||||
auto right = m_right->run(shell)->resolve_as_commands(shell);
|
||||
auto left = m_left->to_lazy_evaluated_commands(shell);
|
||||
auto right = m_right->to_lazy_evaluated_commands(shell);
|
||||
|
||||
auto last_in_left = left.take_last();
|
||||
auto first_in_right = right.take_first();
|
||||
|
@ -1512,7 +1521,7 @@ RefPtr<Value> Sequence::run(RefPtr<Shell> shell)
|
|||
return execute_node->run(shell);
|
||||
}
|
||||
|
||||
auto left = m_left->run(shell)->resolve_as_commands(shell);
|
||||
auto left = m_left->to_lazy_evaluated_commands(shell);
|
||||
// This could happen if a comment is next to a command.
|
||||
if (left.size() == 1) {
|
||||
auto& command = left.first();
|
||||
|
@ -1523,7 +1532,7 @@ RefPtr<Value> Sequence::run(RefPtr<Shell> shell)
|
|||
if (left.last().should_wait)
|
||||
left.last().next_chain.append(NodeWithAction { *m_right, NodeWithAction::Sequence });
|
||||
else
|
||||
left.append(m_right->run(shell)->resolve_as_commands(shell));
|
||||
left.append(m_right->to_lazy_evaluated_commands(shell));
|
||||
|
||||
return create<CommandSequenceValue>(move(left));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue