1
Fork 0
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:
Ali Mohammad Pur 2023-10-13 03:10:31 +03:30 committed by Ali Mohammad Pur
parent 867f7da017
commit 5cb994d4dd
2 changed files with 90 additions and 19 deletions

View file

@ -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;

View file

@ -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;