mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 14:15:07 +00:00
Shell: Expand Juxtaposition of lists to list products
This commit makes `echo x(foo bar)` create an argv of `echo xfoo xbar`, essentially modeling brace expansions in some shells.
This commit is contained in:
parent
16def040af
commit
8e078cf4ab
5 changed files with 119 additions and 68 deletions
136
Shell/AST.cpp
136
Shell/AST.cpp
|
@ -35,6 +35,18 @@
|
||||||
|
|
||||||
namespace AST {
|
namespace AST {
|
||||||
|
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
static inline RefPtr<T> create(Args... args)
|
||||||
|
{
|
||||||
|
return adopt(*new T(args...));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static inline RefPtr<T> create(std::initializer_list<RefPtr<Value>> arg)
|
||||||
|
{
|
||||||
|
return adopt(*new T(arg));
|
||||||
|
}
|
||||||
|
|
||||||
static inline void print_indented(const String& str, int indent)
|
static inline void print_indented(const String& str, int indent)
|
||||||
{
|
{
|
||||||
dbgprintf("%.*c%s\n", indent * 2, ' ', str.characters());
|
dbgprintf("%.*c%s\n", indent * 2, ' ', str.characters());
|
||||||
|
@ -155,7 +167,7 @@ RefPtr<Value> ListConcatenate::run(TheExecutionInputType input_value)
|
||||||
auto list = m_list->run(input_value);
|
auto list = m_list->run(input_value);
|
||||||
auto element = m_element->run(input_value);
|
auto element = m_element->run(input_value);
|
||||||
|
|
||||||
return adopt(*new ListValue({ move(element), move(list) }));
|
return create<ListValue>({ move(element), move(list) });
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListConcatenate::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void ListConcatenate::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -204,7 +216,7 @@ RefPtr<Value> Background::run(TheExecutionInputType input_value)
|
||||||
auto& last = commands.last();
|
auto& last = commands.last();
|
||||||
last.should_wait = false;
|
last.should_wait = false;
|
||||||
|
|
||||||
return adopt(*new CommandSequenceValue(move(commands)));
|
return create<CommandSequenceValue>(move(commands));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Background::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void Background::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -238,7 +250,7 @@ void BarewordLiteral::dump(int level) const
|
||||||
|
|
||||||
RefPtr<Value> BarewordLiteral::run(TheExecutionInputType)
|
RefPtr<Value> BarewordLiteral::run(TheExecutionInputType)
|
||||||
{
|
{
|
||||||
return adopt(*new StringValue(m_text));
|
return create<StringValue>(m_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BarewordLiteral::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void BarewordLiteral::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -294,7 +306,7 @@ RefPtr<Value> CastToCommand::run(TheExecutionInputType input_value)
|
||||||
auto shell = input_value;
|
auto shell = input_value;
|
||||||
auto argv = m_inner->run(input_value)->resolve_as_list(input_value);
|
auto argv = m_inner->run(input_value)->resolve_as_list(input_value);
|
||||||
|
|
||||||
return adopt(*new CommandValue(move(argv)));
|
return create<CommandValue>(move(argv));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CastToCommand::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void CastToCommand::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -350,9 +362,9 @@ RefPtr<Value> CastToList::run(TheExecutionInputType input_value)
|
||||||
auto values = m_inner->run(input_value)->resolve_as_list(input_value);
|
auto values = m_inner->run(input_value)->resolve_as_list(input_value);
|
||||||
Vector<RefPtr<Value>> cast_values;
|
Vector<RefPtr<Value>> cast_values;
|
||||||
for (auto& value : values)
|
for (auto& value : values)
|
||||||
cast_values.append(adopt(*new StringValue(value)));
|
cast_values.append(create<StringValue>(value));
|
||||||
|
|
||||||
return adopt(*new ListValue(cast_values));
|
return create<ListValue>(cast_values);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CastToList::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void CastToList::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -388,7 +400,7 @@ RefPtr<Value> CloseFdRedirection::run(TheExecutionInputType)
|
||||||
{
|
{
|
||||||
Command command;
|
Command command;
|
||||||
command.redirections.append(*new CloseRedirection(m_fd));
|
command.redirections.append(*new CloseRedirection(m_fd));
|
||||||
return adopt(*new CommandValue(move(command)));
|
return create<CommandValue>(move(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloseFdRedirection::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata)
|
void CloseFdRedirection::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata)
|
||||||
|
@ -415,7 +427,7 @@ void CommandLiteral::dump(int level) const
|
||||||
|
|
||||||
RefPtr<Value> CommandLiteral::run(TheExecutionInputType)
|
RefPtr<Value> CommandLiteral::run(TheExecutionInputType)
|
||||||
{
|
{
|
||||||
return adopt(*new CommandValue(m_command));
|
return create<CommandValue>(m_command);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandLiteral::CommandLiteral(Position position, Command command)
|
CommandLiteral::CommandLiteral(Position position, Command command)
|
||||||
|
@ -436,7 +448,7 @@ void Comment::dump(int level) const
|
||||||
|
|
||||||
RefPtr<Value> Comment::run(TheExecutionInputType)
|
RefPtr<Value> Comment::run(TheExecutionInputType)
|
||||||
{
|
{
|
||||||
return adopt(*new StringValue(""));
|
return create<StringValue>("");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Comment::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata)
|
void Comment::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata)
|
||||||
|
@ -468,7 +480,7 @@ RefPtr<Value> DoubleQuotedString::run(TheExecutionInputType input_value)
|
||||||
|
|
||||||
builder.join("", values);
|
builder.join("", values);
|
||||||
|
|
||||||
return adopt(*new StringValue(builder.to_string()));
|
return create<StringValue>(builder.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoubleQuotedString::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void DoubleQuotedString::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -514,12 +526,12 @@ RefPtr<Value> DynamicEvaluate::run(TheExecutionInputType input_value)
|
||||||
if (result->is_string()) {
|
if (result->is_string()) {
|
||||||
auto name_part = result->resolve_as_list(input_value);
|
auto name_part = result->resolve_as_list(input_value);
|
||||||
ASSERT(name_part.size() == 1);
|
ASSERT(name_part.size() == 1);
|
||||||
return adopt(*new SimpleVariableValue(name_part[0]));
|
return create<SimpleVariableValue>(name_part[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's anything else, we're just gonna cast it to a list.
|
// If it's anything else, we're just gonna cast it to a list.
|
||||||
auto list = result->resolve_as_list(input_value);
|
auto list = result->resolve_as_list(input_value);
|
||||||
return adopt(*new CommandValue(move(list)));
|
return create<CommandValue>(move(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicEvaluate::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void DynamicEvaluate::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -556,7 +568,7 @@ RefPtr<Value> Fd2FdRedirection::run(TheExecutionInputType)
|
||||||
{
|
{
|
||||||
Command command;
|
Command command;
|
||||||
command.redirections.append(*new FdRedirection(source_fd, dest_fd, Rewiring::Close::None));
|
command.redirections.append(*new FdRedirection(source_fd, dest_fd, Rewiring::Close::None));
|
||||||
return adopt(*new CommandValue(move(command)));
|
return create<CommandValue>(move(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fd2FdRedirection::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata)
|
void Fd2FdRedirection::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata)
|
||||||
|
@ -583,7 +595,7 @@ void Glob::dump(int level) const
|
||||||
|
|
||||||
RefPtr<Value> Glob::run(TheExecutionInputType)
|
RefPtr<Value> Glob::run(TheExecutionInputType)
|
||||||
{
|
{
|
||||||
return adopt(*new GlobValue(m_text));
|
return create<GlobValue>(m_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Glob::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata metadata)
|
void Glob::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata metadata)
|
||||||
|
@ -631,7 +643,7 @@ RefPtr<Value> Execute::run(TheExecutionInputType input_value)
|
||||||
auto* ast = static_cast<Execute*>(subcommand_ast.ptr());
|
auto* ast = static_cast<Execute*>(subcommand_ast.ptr());
|
||||||
subcommand_ast = ast->command();
|
subcommand_ast = ast->command();
|
||||||
}
|
}
|
||||||
RefPtr<Node> substitute = adopt(*new Join(position(), move(subcommand_ast), adopt(*new CommandLiteral(position(), command))));
|
RefPtr<Node> substitute = create<Join>(position(), move(subcommand_ast), create<CommandLiteral>(position(), command));
|
||||||
commands.append(substitute->run(input_value)->resolve_as_commands(input_value));
|
commands.append(substitute->run(input_value)->resolve_as_commands(input_value));
|
||||||
} else {
|
} else {
|
||||||
commands.append(command);
|
commands.append(command);
|
||||||
|
@ -685,7 +697,7 @@ RefPtr<Value> Execute::run(TheExecutionInputType input_value)
|
||||||
int rc = pipe(pipefd);
|
int rc = pipe(pipefd);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
dbg() << "Error: cannot pipe(): " << strerror(errno);
|
dbg() << "Error: cannot pipe(): " << strerror(errno);
|
||||||
return adopt(*new StringValue(""));
|
return create<StringValue>("");
|
||||||
}
|
}
|
||||||
auto last_in_commands = commands.take_last();
|
auto last_in_commands = commands.take_last();
|
||||||
|
|
||||||
|
@ -731,7 +743,7 @@ RefPtr<Value> Execute::run(TheExecutionInputType input_value)
|
||||||
dbg() << "close() failed: " << strerror(errno);
|
dbg() << "close() failed: " << strerror(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
return adopt(*new StringValue(builder.build(), shell->local_variable_or("IFS", "\n")));
|
return create<StringValue>(builder.build(), shell->local_variable_or("IFS", "\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
run_commands(commands);
|
run_commands(commands);
|
||||||
|
@ -739,7 +751,7 @@ RefPtr<Value> Execute::run(TheExecutionInputType input_value)
|
||||||
shell->block_on_job(job);
|
shell->block_on_job(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
return adopt(*new JobValue(move(job)));
|
return create<JobValue>(move(job));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void Execute::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -817,7 +829,7 @@ RefPtr<Value> Join::run(TheExecutionInputType input_value)
|
||||||
commands.append(command);
|
commands.append(command);
|
||||||
commands.append(right);
|
commands.append(right);
|
||||||
|
|
||||||
return adopt(*new CommandSequenceValue(move(commands)));
|
return create<CommandSequenceValue>(move(commands));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Join::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void Join::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -920,7 +932,7 @@ RefPtr<Value> Pipe::run(TheExecutionInputType input_value)
|
||||||
int rc = pipe(pipefd);
|
int rc = pipe(pipefd);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
dbg() << "Error: cannot pipe(): " << strerror(errno);
|
dbg() << "Error: cannot pipe(): " << strerror(errno);
|
||||||
return adopt(*new StringValue(""));
|
return create<StringValue>("");
|
||||||
}
|
}
|
||||||
auto left = m_left->run(input_value)->resolve_as_commands(input_value);
|
auto left = m_left->run(input_value)->resolve_as_commands(input_value);
|
||||||
auto right = m_right->run(input_value)->resolve_as_commands(input_value);
|
auto right = m_right->run(input_value)->resolve_as_commands(input_value);
|
||||||
|
@ -939,7 +951,7 @@ RefPtr<Value> Pipe::run(TheExecutionInputType input_value)
|
||||||
commands.append(first_in_right);
|
commands.append(first_in_right);
|
||||||
commands.append(right);
|
commands.append(right);
|
||||||
|
|
||||||
return adopt(*new CommandSequenceValue(move(commands)));
|
return create<CommandSequenceValue>(move(commands));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pipe::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void Pipe::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -1041,7 +1053,7 @@ RefPtr<Value> ReadRedirection::run(TheExecutionInputType input_value)
|
||||||
builder.join(" ", path_segments);
|
builder.join(" ", path_segments);
|
||||||
|
|
||||||
command.redirections.append(*new PathRedirection(builder.to_string(), m_fd, PathRedirection::Read));
|
command.redirections.append(*new PathRedirection(builder.to_string(), m_fd, PathRedirection::Read));
|
||||||
return adopt(*new CommandValue(move(command)));
|
return create<CommandValue>(move(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadRedirection::ReadRedirection(Position position, int fd, RefPtr<Node> path)
|
ReadRedirection::ReadRedirection(Position position, int fd, RefPtr<Node> path)
|
||||||
|
@ -1068,7 +1080,7 @@ RefPtr<Value> ReadWriteRedirection::run(TheExecutionInputType input_value)
|
||||||
builder.join(" ", path_segments);
|
builder.join(" ", path_segments);
|
||||||
|
|
||||||
command.redirections.append(*new PathRedirection(builder.to_string(), m_fd, PathRedirection::ReadWrite));
|
command.redirections.append(*new PathRedirection(builder.to_string(), m_fd, PathRedirection::ReadWrite));
|
||||||
return adopt(*new CommandValue(move(command)));
|
return create<CommandValue>(move(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadWriteRedirection::ReadWriteRedirection(Position position, int fd, RefPtr<Node> path)
|
ReadWriteRedirection::ReadWriteRedirection(Position position, int fd, RefPtr<Node> path)
|
||||||
|
@ -1096,7 +1108,7 @@ RefPtr<Value> Sequence::run(TheExecutionInputType input_value)
|
||||||
commands.append(left);
|
commands.append(left);
|
||||||
commands.append(right);
|
commands.append(right);
|
||||||
|
|
||||||
return adopt(*new CommandSequenceValue(move(commands)));
|
return create<CommandSequenceValue>(move(commands));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequence::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void Sequence::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -1135,7 +1147,7 @@ void SimpleVariable::dump(int level) const
|
||||||
|
|
||||||
RefPtr<Value> SimpleVariable::run(TheExecutionInputType)
|
RefPtr<Value> SimpleVariable::run(TheExecutionInputType)
|
||||||
{
|
{
|
||||||
return adopt(*new SimpleVariableValue(m_name));
|
return create<SimpleVariableValue>(m_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleVariable::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata metadata)
|
void SimpleVariable::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata metadata)
|
||||||
|
@ -1188,7 +1200,7 @@ void SpecialVariable::dump(int level) const
|
||||||
|
|
||||||
RefPtr<Value> SpecialVariable::run(TheExecutionInputType)
|
RefPtr<Value> SpecialVariable::run(TheExecutionInputType)
|
||||||
{
|
{
|
||||||
return adopt(*new SpecialVariableValue(m_name));
|
return create<SpecialVariableValue>(m_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpecialVariable::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata)
|
void SpecialVariable::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata)
|
||||||
|
@ -1219,26 +1231,54 @@ SpecialVariable::~SpecialVariable()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringConcatenate::dump(int level) const
|
void Juxtaposition::dump(int level) const
|
||||||
{
|
{
|
||||||
Node::dump(level);
|
Node::dump(level);
|
||||||
m_left->dump(level + 1);
|
m_left->dump(level + 1);
|
||||||
m_right->dump(level + 1);
|
m_right->dump(level + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Value> StringConcatenate::run(TheExecutionInputType input_value)
|
RefPtr<Value> Juxtaposition::run(TheExecutionInputType input_value)
|
||||||
{
|
{
|
||||||
auto left = m_left->run(input_value)->resolve_as_list(input_value);
|
auto left_value = m_left->run(input_value);
|
||||||
auto right = m_right->run(input_value)->resolve_as_list(input_value);
|
auto right_value = m_right->run(input_value);
|
||||||
|
|
||||||
|
auto left = left_value->resolve_as_list(input_value);
|
||||||
|
auto right = right_value->resolve_as_list(input_value);
|
||||||
|
|
||||||
|
if (left_value->is_string() && right_value->is_string()) {
|
||||||
|
|
||||||
|
ASSERT(left.size() == 1);
|
||||||
|
ASSERT(right.size() == 1);
|
||||||
|
|
||||||
|
StringBuilder builder;
|
||||||
|
builder.append(left[0]);
|
||||||
|
builder.append(right[0]);
|
||||||
|
|
||||||
|
return create<StringValue>(builder.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, treat them as lists and create a list product.
|
||||||
|
if (left.is_empty() || right.is_empty())
|
||||||
|
return create<ListValue>({});
|
||||||
|
|
||||||
|
Vector<String> result;
|
||||||
|
result.ensure_capacity(left.size() * right.size());
|
||||||
|
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
builder.join(" ", left);
|
for (auto& left_element : left) {
|
||||||
builder.join(" ", right);
|
for (auto& right_element : right) {
|
||||||
|
builder.append(left_element);
|
||||||
|
builder.append(right_element);
|
||||||
|
result.append(builder.to_string());
|
||||||
|
builder.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return adopt(*new StringValue(builder.to_string()));
|
return create<ListValue>(move(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringConcatenate::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void Juxtaposition::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
{
|
{
|
||||||
m_left->highlight_in_editor(editor, shell, metadata);
|
m_left->highlight_in_editor(editor, shell, metadata);
|
||||||
|
|
||||||
|
@ -1247,7 +1287,7 @@ void StringConcatenate::highlight_in_editor(Line::Editor& editor, Shell& shell,
|
||||||
m_right->highlight_in_editor(editor, shell, metadata);
|
m_right->highlight_in_editor(editor, shell, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
HitTestResult StringConcatenate::hit_test_position(size_t offset)
|
HitTestResult Juxtaposition::hit_test_position(size_t offset)
|
||||||
{
|
{
|
||||||
if (!position().contains(offset))
|
if (!position().contains(offset))
|
||||||
return {};
|
return {};
|
||||||
|
@ -1258,14 +1298,14 @@ HitTestResult StringConcatenate::hit_test_position(size_t offset)
|
||||||
return m_right->hit_test_position(offset);
|
return m_right->hit_test_position(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringConcatenate::StringConcatenate(Position position, RefPtr<Node> left, RefPtr<Node> right)
|
Juxtaposition::Juxtaposition(Position position, RefPtr<Node> left, RefPtr<Node> right)
|
||||||
: Node(move(position))
|
: Node(move(position))
|
||||||
, m_left(move(left))
|
, m_left(move(left))
|
||||||
, m_right(move(right))
|
, m_right(move(right))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
StringConcatenate::~StringConcatenate()
|
Juxtaposition::~Juxtaposition()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1277,7 +1317,7 @@ void StringLiteral::dump(int level) const
|
||||||
|
|
||||||
RefPtr<Value> StringLiteral::run(TheExecutionInputType)
|
RefPtr<Value> StringLiteral::run(TheExecutionInputType)
|
||||||
{
|
{
|
||||||
return adopt(*new StringValue(m_text));
|
return create<StringValue>(m_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringLiteral::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata metadata)
|
void StringLiteral::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata metadata)
|
||||||
|
@ -1314,7 +1354,7 @@ RefPtr<Value> StringPartCompose::run(TheExecutionInputType input_value)
|
||||||
builder.join(" ", left);
|
builder.join(" ", left);
|
||||||
builder.join(" ", right);
|
builder.join(" ", right);
|
||||||
|
|
||||||
return adopt(*new StringValue(builder.to_string()));
|
return create<StringValue>(builder.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringPartCompose::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void StringPartCompose::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -1353,7 +1393,7 @@ void SyntaxError::dump(int level) const
|
||||||
RefPtr<Value> SyntaxError::run(TheExecutionInputType)
|
RefPtr<Value> SyntaxError::run(TheExecutionInputType)
|
||||||
{
|
{
|
||||||
dbg() << "SYNTAX ERROR AAAA";
|
dbg() << "SYNTAX ERROR AAAA";
|
||||||
return adopt(*new StringValue(""));
|
return create<StringValue>("");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxError::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata)
|
void SyntaxError::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata)
|
||||||
|
@ -1378,7 +1418,7 @@ void Tilde::dump(int level) const
|
||||||
|
|
||||||
RefPtr<Value> Tilde::run(TheExecutionInputType)
|
RefPtr<Value> Tilde::run(TheExecutionInputType)
|
||||||
{
|
{
|
||||||
return adopt(*new TildeValue(m_username));
|
return create<TildeValue>(m_username);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tilde::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata)
|
void Tilde::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata)
|
||||||
|
@ -1432,7 +1472,7 @@ RefPtr<Value> WriteAppendRedirection::run(TheExecutionInputType input_value)
|
||||||
builder.join(" ", path_segments);
|
builder.join(" ", path_segments);
|
||||||
|
|
||||||
command.redirections.append(*new PathRedirection(builder.to_string(), m_fd, PathRedirection::WriteAppend));
|
command.redirections.append(*new PathRedirection(builder.to_string(), m_fd, PathRedirection::WriteAppend));
|
||||||
return adopt(*new CommandValue(move(command)));
|
return create<CommandValue>(move(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteAppendRedirection::WriteAppendRedirection(Position position, int fd, RefPtr<Node> path)
|
WriteAppendRedirection::WriteAppendRedirection(Position position, int fd, RefPtr<Node> path)
|
||||||
|
@ -1459,7 +1499,7 @@ RefPtr<Value> WriteRedirection::run(TheExecutionInputType input_value)
|
||||||
builder.join(" ", path_segments);
|
builder.join(" ", path_segments);
|
||||||
|
|
||||||
command.redirections.append(*new PathRedirection(builder.to_string(), m_fd, PathRedirection::Write));
|
command.redirections.append(*new PathRedirection(builder.to_string(), m_fd, PathRedirection::Write));
|
||||||
return adopt(*new CommandValue(move(command)));
|
return create<CommandValue>(move(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteRedirection::WriteRedirection(Position position, int fd, RefPtr<Node> path)
|
WriteRedirection::WriteRedirection(Position position, int fd, RefPtr<Node> path)
|
||||||
|
@ -1498,7 +1538,7 @@ RefPtr<Value> VariableDeclarations::run(TheExecutionInputType input_value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return adopt(*new ListValue(Vector<String> {}));
|
return create<ListValue>({});
|
||||||
}
|
}
|
||||||
|
|
||||||
void VariableDeclarations::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
void VariableDeclarations::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata)
|
||||||
|
@ -1546,10 +1586,6 @@ Vector<AST::Command> Value::resolve_as_commands(TheExecutionInputType input_valu
|
||||||
return { command };
|
return { command };
|
||||||
}
|
}
|
||||||
|
|
||||||
ListValue::~ListValue()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ListValue::ListValue(Vector<String> values)
|
ListValue::ListValue(Vector<String> values)
|
||||||
{
|
{
|
||||||
m_contained_values.ensure_capacity(values.size());
|
m_contained_values.ensure_capacity(values.size());
|
||||||
|
@ -1557,6 +1593,10 @@ ListValue::ListValue(Vector<String> values)
|
||||||
m_contained_values.append(adopt(*new StringValue(move(str))));
|
m_contained_values.append(adopt(*new StringValue(move(str))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ListValue::~ListValue()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Vector<String> ListValue::resolve_as_list(TheExecutionInputType input_value)
|
Vector<String> ListValue::resolve_as_list(TheExecutionInputType input_value)
|
||||||
{
|
{
|
||||||
Vector<String> values;
|
Vector<String> values;
|
||||||
|
|
|
@ -690,17 +690,17 @@ private:
|
||||||
char m_name { -1 };
|
char m_name { -1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringConcatenate final : public Node {
|
class Juxtaposition final : public Node {
|
||||||
public:
|
public:
|
||||||
StringConcatenate(Position, RefPtr<Node>, RefPtr<Node>);
|
Juxtaposition(Position, RefPtr<Node>, RefPtr<Node>);
|
||||||
virtual ~StringConcatenate();
|
virtual ~Juxtaposition();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void dump(int level) const override;
|
virtual void dump(int level) const override;
|
||||||
virtual RefPtr<Value> run(TheExecutionInputType) override;
|
virtual RefPtr<Value> run(TheExecutionInputType) override;
|
||||||
virtual void highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
|
virtual void highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
|
||||||
virtual HitTestResult hit_test_position(size_t) override;
|
virtual HitTestResult hit_test_position(size_t) override;
|
||||||
virtual String class_name() const override { return "StringConcatenate"; }
|
virtual String class_name() const override { return "Juxtaposition"; }
|
||||||
|
|
||||||
RefPtr<Node> m_left;
|
RefPtr<Node> m_left;
|
||||||
RefPtr<Node> m_right;
|
RefPtr<Node> m_right;
|
||||||
|
|
|
@ -262,8 +262,9 @@ RefPtr<AST::Node> Parser::parse_command()
|
||||||
if (!list_expr)
|
if (!list_expr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto next_command = parse_command();
|
|
||||||
auto cast = create<AST::CastToCommand>(move(list_expr)); // Cast List Command
|
auto cast = create<AST::CastToCommand>(move(list_expr)); // Cast List Command
|
||||||
|
|
||||||
|
auto next_command = parse_command();
|
||||||
if (!next_command)
|
if (!next_command)
|
||||||
return cast;
|
return cast;
|
||||||
|
|
||||||
|
@ -396,6 +397,16 @@ RefPtr<AST::Node> Parser::parse_expression()
|
||||||
auto rule_start = push_start();
|
auto rule_start = push_start();
|
||||||
auto starting_char = peek();
|
auto starting_char = peek();
|
||||||
|
|
||||||
|
auto read_concat = [&](auto expr) -> RefPtr<AST::Node> {
|
||||||
|
if (is_whitespace(peek()))
|
||||||
|
return expr;
|
||||||
|
|
||||||
|
if (auto next_expr = parse_expression())
|
||||||
|
return create<AST::Juxtaposition>(move(expr), move(next_expr));
|
||||||
|
|
||||||
|
return expr;
|
||||||
|
};
|
||||||
|
|
||||||
if (strchr("&|[]){} ;<>", starting_char) != nullptr)
|
if (strchr("&|[]){} ;<>", starting_char) != nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -409,10 +420,10 @@ RefPtr<AST::Node> Parser::parse_expression()
|
||||||
|
|
||||||
if (starting_char == '$') {
|
if (starting_char == '$') {
|
||||||
if (auto variable = parse_variable())
|
if (auto variable = parse_variable())
|
||||||
return variable;
|
return read_concat(variable);
|
||||||
|
|
||||||
if (auto inline_exec = parse_evaluate())
|
if (auto inline_exec = parse_evaluate())
|
||||||
return inline_exec;
|
return read_concat(inline_exec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (starting_char == '#')
|
if (starting_char == '#')
|
||||||
|
@ -424,11 +435,11 @@ RefPtr<AST::Node> Parser::parse_expression()
|
||||||
if (!list)
|
if (!list)
|
||||||
list = create<AST::SyntaxError>();
|
list = create<AST::SyntaxError>();
|
||||||
if (!expect(')'))
|
if (!expect(')'))
|
||||||
return create<AST::SyntaxError>();
|
return read_concat(create<AST::SyntaxError>());
|
||||||
return create<AST::CastToList>(move(list)); // Cast To List
|
return read_concat(create<AST::CastToList>(move(list))); // Cast To List
|
||||||
}
|
}
|
||||||
|
|
||||||
return parse_string_composite();
|
return read_concat(parse_string_composite());
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<AST::Node> Parser::parse_string_composite()
|
RefPtr<AST::Node> Parser::parse_string_composite()
|
||||||
|
@ -436,35 +447,35 @@ RefPtr<AST::Node> Parser::parse_string_composite()
|
||||||
auto rule_start = push_start();
|
auto rule_start = push_start();
|
||||||
if (auto string = parse_string()) {
|
if (auto string = parse_string()) {
|
||||||
if (auto next_part = parse_string_composite())
|
if (auto next_part = parse_string_composite())
|
||||||
return create<AST::StringConcatenate>(move(string), move(next_part)); // Concatenate String StringComposite
|
return create<AST::Juxtaposition>(move(string), move(next_part)); // Concatenate String StringComposite
|
||||||
|
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto variable = parse_variable()) {
|
if (auto variable = parse_variable()) {
|
||||||
if (auto next_part = parse_string_composite())
|
if (auto next_part = parse_string_composite())
|
||||||
return create<AST::StringConcatenate>(move(variable), move(next_part)); // Concatenate Variable StringComposite
|
return create<AST::Juxtaposition>(move(variable), move(next_part)); // Concatenate Variable StringComposite
|
||||||
|
|
||||||
return variable;
|
return variable;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto glob = parse_glob()) {
|
if (auto glob = parse_glob()) {
|
||||||
if (auto next_part = parse_string_composite())
|
if (auto next_part = parse_string_composite())
|
||||||
return create<AST::StringConcatenate>(move(glob), move(next_part)); // Concatenate Glob StringComposite
|
return create<AST::Juxtaposition>(move(glob), move(next_part)); // Concatenate Glob StringComposite
|
||||||
|
|
||||||
return glob;
|
return glob;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto bareword = parse_bareword()) {
|
if (auto bareword = parse_bareword()) {
|
||||||
if (auto next_part = parse_string_composite())
|
if (auto next_part = parse_string_composite())
|
||||||
return create<AST::StringConcatenate>(move(bareword), move(next_part)); // Concatenate Bareword StringComposite
|
return create<AST::Juxtaposition>(move(bareword), move(next_part)); // Concatenate Bareword StringComposite
|
||||||
|
|
||||||
return bareword;
|
return bareword;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto inline_command = parse_evaluate()) {
|
if (auto inline_command = parse_evaluate()) {
|
||||||
if (auto next_part = parse_string_composite())
|
if (auto next_part = parse_string_composite())
|
||||||
return create<AST::StringConcatenate>(move(inline_command), move(next_part)); // Concatenate Execute StringComposite
|
return create<AST::Juxtaposition>(move(inline_command), move(next_part)); // Concatenate Execute StringComposite
|
||||||
|
|
||||||
return inline_command;
|
return inline_command;
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,10 +120,10 @@ redirection :: number? '>'{1,2} ' '* string_composite
|
||||||
|
|
||||||
list_expression :: ' '* expression (' '+ list_expression)?
|
list_expression :: ' '* expression (' '+ list_expression)?
|
||||||
|
|
||||||
expression :: evaluate
|
expression :: evaluate expression?
|
||||||
| string_composite
|
| string_composite expression?
|
||||||
| comment
|
| comment expession?
|
||||||
| '(' list_expression ')'
|
| '(' list_expression ')' expression?
|
||||||
|
|
||||||
evaluate :: '$' expression {eval / dynamic resolve}
|
evaluate :: '$' expression {eval / dynamic resolve}
|
||||||
|
|
||||||
|
|
|
@ -324,7 +324,7 @@ int Shell::run_command(const StringView& cmd)
|
||||||
if (!command)
|
if (!command)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef SH_DEBUG
|
#ifndef SH_DEBUG
|
||||||
dbg() << "Command follows";
|
dbg() << "Command follows";
|
||||||
command->dump(0);
|
command->dump(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue