mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 05:08:13 +00:00
Shell: Allow parts of globs to be named in match expressions
This patchset allows a match expression to have a list of names for its glob parts, which are assigned to the matched values in the body of the match. For example, ```sh stuff=foobarblahblah/target_{1..30} for $stuff { match $it { */* as (dir sub) { echo "doing things with $sub in $dir" make -C $dir $sub # or whatever... } } } ``` With this, match expressions are now significantly more powerful!
This commit is contained in:
parent
0801b1fada
commit
1a4ac3531f
6 changed files with 115 additions and 10 deletions
|
@ -1520,7 +1520,23 @@ void MatchExpr::dump(int level) const
|
|||
print_indented(String::format("(named: %s)", m_expr_name.characters()), level + 1);
|
||||
print_indented("(entries)", level + 1);
|
||||
for (auto& entry : m_entries) {
|
||||
print_indented("(match)", level + 2);
|
||||
StringBuilder builder;
|
||||
builder.append("(match");
|
||||
if (entry.match_names.has_value()) {
|
||||
builder.append(" to names (");
|
||||
bool first = true;
|
||||
for (auto& name : entry.match_names.value()) {
|
||||
if (!first)
|
||||
builder.append(' ');
|
||||
first = false;
|
||||
builder.append(name);
|
||||
}
|
||||
builder.append("))");
|
||||
|
||||
} else {
|
||||
builder.append(')');
|
||||
}
|
||||
print_indented(builder.string_view(), level + 2);
|
||||
for (auto& node : entry.options)
|
||||
node.dump(level + 3);
|
||||
print_indented("(execute)", level + 2);
|
||||
|
@ -1536,13 +1552,16 @@ RefPtr<Value> MatchExpr::run(RefPtr<Shell> shell)
|
|||
auto value = m_matched_expr->run(shell)->resolve_without_cast(shell);
|
||||
auto list = value->resolve_as_list(shell);
|
||||
|
||||
auto list_matches = [&](auto&& pattern) {
|
||||
auto list_matches = [&](auto&& pattern, auto& spans) {
|
||||
if (pattern.size() != list.size())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < pattern.size(); ++i) {
|
||||
if (!list[i].matches(pattern[i]))
|
||||
Vector<AK::MaskSpan> mask_spans;
|
||||
if (!list[i].matches(pattern[i], mask_spans))
|
||||
return false;
|
||||
for (auto& span : mask_spans)
|
||||
spans.append(list[i].substring(span.start, span.length));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1554,7 +1573,7 @@ RefPtr<Value> MatchExpr::run(RefPtr<Shell> shell)
|
|||
pattern.append(static_cast<const Glob*>(&option)->text());
|
||||
} else if (option.is_bareword()) {
|
||||
pattern.append(static_cast<const BarewordLiteral*>(&option)->text());
|
||||
} else if (option.is_list()) {
|
||||
} else {
|
||||
auto list = option.run(shell);
|
||||
option.for_each_entry(shell, [&](auto&& value) {
|
||||
pattern.append(value->resolve_as_list(nullptr)); // Note: 'nullptr' incurs special behaviour,
|
||||
|
@ -1572,11 +1591,21 @@ RefPtr<Value> MatchExpr::run(RefPtr<Shell> shell)
|
|||
|
||||
for (auto& entry : m_entries) {
|
||||
for (auto& option : entry.options) {
|
||||
if (list_matches(resolve_pattern(option))) {
|
||||
if (entry.body)
|
||||
Vector<String> spans;
|
||||
if (list_matches(resolve_pattern(option), spans)) {
|
||||
if (entry.body) {
|
||||
if (entry.match_names.has_value()) {
|
||||
size_t i = 0;
|
||||
for (auto& name : entry.match_names.value()) {
|
||||
if (spans.size() > i)
|
||||
shell->set_local_variable(name, create<AST::StringValue>(spans[i]));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return entry.body->run(shell);
|
||||
else
|
||||
} else {
|
||||
return create<AST::ListValue>({});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1606,6 +1635,9 @@ void MatchExpr::highlight_in_editor(Line::Editor& editor, Shell& shell, Highligh
|
|||
|
||||
for (auto& position : entry.pipe_positions)
|
||||
editor.stylize({ position.start_offset, position.end_offset }, { Line::Style::Foreground(Line::Style::XtermColor::Yellow) });
|
||||
|
||||
if (entry.match_as_position.has_value())
|
||||
editor.stylize({ entry.match_as_position.value().start_offset, entry.match_as_position.value().end_offset }, { Line::Style::Foreground(Line::Style::XtermColor::Yellow) });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue