mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 05:37:34 +00:00
Shell: Minimally implement the 'set' builtin
This only implements the printing and argv setting behaviours.
This commit is contained in:
parent
867f7da017
commit
5cb994d4dd
2 changed files with 90 additions and 19 deletions
|
@ -332,6 +332,26 @@ ErrorOr<int> Shell::builtin_bg(Main::Arguments arguments)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<String> Shell::serialize_function_definition(ShellFunction const& fn) const
|
||||||
|
{
|
||||||
|
StringBuilder builder;
|
||||||
|
builder.append(fn.name);
|
||||||
|
builder.append('(');
|
||||||
|
for (size_t i = 0; i < fn.arguments.size(); i++) {
|
||||||
|
builder.append(fn.arguments[i]);
|
||||||
|
if (i != fn.arguments.size() - 1)
|
||||||
|
builder.append(' ');
|
||||||
|
}
|
||||||
|
builder.append(") {\n"sv);
|
||||||
|
if (fn.body) {
|
||||||
|
auto formatter = Formatter(*fn.body);
|
||||||
|
builder.append(formatter.format());
|
||||||
|
}
|
||||||
|
builder.append("\n}"sv);
|
||||||
|
|
||||||
|
return builder.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<int> Shell::builtin_type(Main::Arguments arguments)
|
ErrorOr<int> Shell::builtin_type(Main::Arguments arguments)
|
||||||
{
|
{
|
||||||
Vector<DeprecatedString> commands;
|
Vector<DeprecatedString> commands;
|
||||||
|
@ -359,22 +379,8 @@ ErrorOr<int> Shell::builtin_type(Main::Arguments arguments)
|
||||||
auto fn = function.value();
|
auto fn = function.value();
|
||||||
printf("%s is a function\n", command.characters());
|
printf("%s is a function\n", command.characters());
|
||||||
if (!dont_show_function_source) {
|
if (!dont_show_function_source) {
|
||||||
StringBuilder builder;
|
auto source = TRY(serialize_function_definition(fn));
|
||||||
builder.append(fn.name);
|
outln("{}", source);
|
||||||
builder.append('(');
|
|
||||||
for (size_t i = 0; i < fn.arguments.size(); i++) {
|
|
||||||
builder.append(fn.arguments[i]);
|
|
||||||
if (!(i == fn.arguments.size() - 1))
|
|
||||||
builder.append(' ');
|
|
||||||
}
|
|
||||||
builder.append(") {\n"sv);
|
|
||||||
if (fn.body) {
|
|
||||||
auto formatter = Formatter(*fn.body);
|
|
||||||
builder.append(formatter.format());
|
|
||||||
printf("%s\n}\n", builder.to_deprecated_string().characters());
|
|
||||||
} else {
|
|
||||||
printf("%s\n}\n", builder.to_deprecated_string().characters());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1289,6 +1295,68 @@ ErrorOr<int> Shell::builtin_unset(Main::Arguments arguments)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<int> Shell::builtin_set(Main::Arguments arguments)
|
||||||
|
{
|
||||||
|
if (arguments.strings.size() == 1) {
|
||||||
|
HashMap<String, String> vars;
|
||||||
|
|
||||||
|
StringBuilder builder;
|
||||||
|
for (auto& frame : m_local_frames) {
|
||||||
|
for (auto& var : frame->local_variables) {
|
||||||
|
builder.join(" "sv, TRY(var.value->resolve_as_list(*this)));
|
||||||
|
vars.set(TRY(String::from_deprecated_string(var.key)), TRY(builder.to_string()));
|
||||||
|
builder.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Variable {
|
||||||
|
StringView name;
|
||||||
|
String value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<Variable> variables;
|
||||||
|
variables.ensure_capacity(vars.size());
|
||||||
|
|
||||||
|
for (auto& var : vars)
|
||||||
|
variables.unchecked_append({ var.key, var.value });
|
||||||
|
|
||||||
|
Vector<String> functions;
|
||||||
|
functions.ensure_capacity(m_functions.size());
|
||||||
|
for (auto& function : m_functions)
|
||||||
|
functions.unchecked_append(TRY(serialize_function_definition(function.value)));
|
||||||
|
|
||||||
|
quick_sort(variables, [](auto& a, auto& b) { return a.name < b.name; });
|
||||||
|
quick_sort(functions, [](auto& a, auto& b) { return a < b; });
|
||||||
|
|
||||||
|
for (auto& var : variables)
|
||||||
|
outln("{}={}", var.name, escape_token(var.value));
|
||||||
|
|
||||||
|
for (auto& fn : functions)
|
||||||
|
outln("{}", fn);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<StringView> argv_to_set;
|
||||||
|
|
||||||
|
Core::ArgsParser parser;
|
||||||
|
parser.set_stop_on_first_non_option(true);
|
||||||
|
parser.add_positional_argument(argv_to_set, "List of arguments", "arg", Core::ArgsParser::Required::No);
|
||||||
|
|
||||||
|
if (!parser.parse(arguments, Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!argv_to_set.is_empty() || arguments.strings.last() == "--"sv) {
|
||||||
|
Vector<String> argv;
|
||||||
|
argv.ensure_capacity(argv_to_set.size());
|
||||||
|
for (auto& arg : argv_to_set)
|
||||||
|
argv.unchecked_append(TRY(String::from_utf8(arg)));
|
||||||
|
set_local_variable("ARGV", AST::make_ref_counted<AST::ListValue>(move(argv)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<int> Shell::builtin_not(Main::Arguments arguments)
|
ErrorOr<int> Shell::builtin_not(Main::Arguments arguments)
|
||||||
{
|
{
|
||||||
Vector<StringView> args;
|
Vector<StringView> args;
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
__ENUMERATE_SHELL_BUILTIN(glob, InAllModes) \
|
__ENUMERATE_SHELL_BUILTIN(glob, InAllModes) \
|
||||||
__ENUMERATE_SHELL_BUILTIN(unalias, InAllModes) \
|
__ENUMERATE_SHELL_BUILTIN(unalias, InAllModes) \
|
||||||
__ENUMERATE_SHELL_BUILTIN(unset, InAllModes) \
|
__ENUMERATE_SHELL_BUILTIN(unset, InAllModes) \
|
||||||
|
__ENUMERATE_SHELL_BUILTIN(set, InAllModes) \
|
||||||
__ENUMERATE_SHELL_BUILTIN(history, InAllModes) \
|
__ENUMERATE_SHELL_BUILTIN(history, InAllModes) \
|
||||||
__ENUMERATE_SHELL_BUILTIN(umask, InAllModes) \
|
__ENUMERATE_SHELL_BUILTIN(umask, InAllModes) \
|
||||||
__ENUMERATE_SHELL_BUILTIN(not, InAllModes) \
|
__ENUMERATE_SHELL_BUILTIN(not, InAllModes) \
|
||||||
|
@ -479,15 +480,17 @@ private:
|
||||||
// clang-format on
|
// clang-format on
|
||||||
};
|
};
|
||||||
|
|
||||||
bool m_should_ignore_jobs_on_next_exit { false };
|
|
||||||
pid_t m_pid { 0 };
|
|
||||||
|
|
||||||
struct ShellFunction {
|
struct ShellFunction {
|
||||||
DeprecatedString name;
|
DeprecatedString name;
|
||||||
Vector<DeprecatedString> arguments;
|
Vector<DeprecatedString> arguments;
|
||||||
RefPtr<AST::Node> body;
|
RefPtr<AST::Node> body;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ErrorOr<String> serialize_function_definition(ShellFunction const&) const;
|
||||||
|
|
||||||
|
bool m_should_ignore_jobs_on_next_exit { false };
|
||||||
|
pid_t m_pid { 0 };
|
||||||
|
|
||||||
HashMap<DeprecatedString, ShellFunction> m_functions;
|
HashMap<DeprecatedString, ShellFunction> m_functions;
|
||||||
Vector<NonnullOwnPtr<LocalFrame>> m_local_frames;
|
Vector<NonnullOwnPtr<LocalFrame>> m_local_frames;
|
||||||
Promise::List m_active_promises;
|
Promise::List m_active_promises;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue