From 2915dcfcc314deb4b41efdf14768e527614dc3fc Mon Sep 17 00:00:00 2001 From: AnotherTest Date: Wed, 17 Jun 2020 18:51:44 +0430 Subject: [PATCH] Shell: Add the alias builtin and resolve aliases This follows the other shells in alias resolution, and resolves the alias only once. --- Shell/AST.cpp | 25 ++++++++++++++++++++++++- Shell/Builtin.cpp | 34 ++++++++++++++++++++++++++++++++++ Shell/Shell.cpp | 5 +++++ Shell/Shell.h | 3 +++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/Shell/AST.cpp b/Shell/AST.cpp index 9f6340e913..6674dd5185 100644 --- a/Shell/AST.cpp +++ b/Shell/AST.cpp @@ -617,7 +617,30 @@ RefPtr Execute::run(TheExecutionInputType input_value) RefPtr job; auto shell = input_value; - auto commands = m_command->run(input_value)->resolve_as_commands(input_value); + auto initial_commands = m_command->run(input_value)->resolve_as_commands(input_value); + decltype(initial_commands) commands; + + for (auto& command : initial_commands) { + if (!command.argv.is_empty()) { + auto alias = shell->resolve_alias(command.argv[0]); + if (!alias.is_null()) { + auto argv0 = command.argv.take_first(); + auto subcommand_ast = Parser { alias }.parse(); + if (subcommand_ast) { + while (subcommand_ast->is_execute()) { + auto* ast = static_cast(subcommand_ast.ptr()); + subcommand_ast = ast->command(); + } + RefPtr substitute = adopt(*new Join(position(), move(subcommand_ast), adopt(*new CommandLiteral(position(), command)))); + commands.append(substitute->run(input_value)->resolve_as_commands(input_value)); + } else { + commands.append(command); + } + } else { + commands.append(command); + } + } + } Vector> jobs_to_wait_for; auto run_commands = [&](auto& commands) { diff --git a/Shell/Builtin.cpp b/Shell/Builtin.cpp index 14d7aece5c..4be6e4ff4f 100644 --- a/Shell/Builtin.cpp +++ b/Shell/Builtin.cpp @@ -33,6 +33,40 @@ extern RefPtr editor; +int Shell::builtin_alias(int argc, const char** argv) +{ + Vector arguments; + + Core::ArgsParser parser; + parser.add_positional_argument(arguments, "List of name[=values]'s", "name[=value]", Core::ArgsParser::Required::No); + + if (!parser.parse(argc, const_cast(argv), false)) + return 1; + + if (arguments.is_empty()) { + for (auto& alias : m_aliases) + printf("%s=%s\n", escape_token(alias.key).characters(), escape_token(alias.value).characters()); + return 0; + } + + bool fail = false; + for (auto& argument : arguments) { + auto parts = String { argument }.split_limit('=', 2, true); + if (parts.size() == 1) { + auto alias = m_aliases.get(parts[0]); + if (alias.has_value()) { + printf("%s=%s\n", escape_token(parts[0]).characters(), escape_token(alias.value()).characters()); + } else { + fail = true; + } + } else { + m_aliases.set(parts[0], parts[1]); + } + } + + return fail ? 1 : 0; +} + int Shell::builtin_bg(int argc, const char** argv) { int job_id = -1; diff --git a/Shell/Shell.cpp b/Shell/Shell.cpp index 9ae3b6bc80..b6ce3d8437 100644 --- a/Shell/Shell.cpp +++ b/Shell/Shell.cpp @@ -306,6 +306,11 @@ void Shell::unset_local_variable(const String& name) m_local_variables.remove(name); } +String Shell::resolve_alias(const String& name) const +{ + return m_aliases.get(name).value_or({}); +} + int Shell::run_command(const StringView& cmd) { if (cmd.is_empty()) diff --git a/Shell/Shell.h b/Shell/Shell.h index cfdf06a860..e052428c15 100644 --- a/Shell/Shell.h +++ b/Shell/Shell.h @@ -40,6 +40,7 @@ #include #define ENUMERATE_SHELL_BUILTINS() \ + __ENUMERATE_SHELL_BUILTIN(alias) \ __ENUMERATE_SHELL_BUILTIN(cd) \ __ENUMERATE_SHELL_BUILTIN(cdh) \ __ENUMERATE_SHELL_BUILTIN(pwd) \ @@ -73,6 +74,7 @@ public: static Vector expand_globs(const StringView& path, StringView base); static Vector expand_globs(Vector path_segments, const StringView& base); String resolve_path(String) const; + String resolve_alias(const String&) const; RefPtr lookup_local_variable(const String&); String local_variable_or(const String&, const String&); @@ -161,6 +163,7 @@ private: pid_t m_pid { 0 }; HashMap> m_local_variables; + HashMap m_aliases; }; static constexpr bool is_word_character(char c)