Преглед на файлове

Shell: Add the alias builtin and resolve aliases

This follows the other shells in alias resolution, and resolves the
alias only once.
AnotherTest преди 5 години
родител
ревизия
2915dcfcc3
променени са 4 файла, в които са добавени 66 реда и са изтрити 1 реда
  1. 24 1
      Shell/AST.cpp
  2. 34 0
      Shell/Builtin.cpp
  3. 5 0
      Shell/Shell.cpp
  4. 3 0
      Shell/Shell.h

+ 24 - 1
Shell/AST.cpp

@@ -617,7 +617,30 @@ RefPtr<Value> Execute::run(TheExecutionInputType input_value)
     RefPtr<Job> 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<Execute*>(subcommand_ast.ptr());
+                        subcommand_ast = ast->command();
+                    }
+                    RefPtr<Node> 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<RefPtr<Job>> jobs_to_wait_for;
 
     auto run_commands = [&](auto& commands) {

+ 34 - 0
Shell/Builtin.cpp

@@ -33,6 +33,40 @@
 
 extern RefPtr<Line::Editor> editor;
 
+int Shell::builtin_alias(int argc, const char** argv)
+{
+    Vector<const char*> 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<char**>(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;

+ 5 - 0
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())

+ 3 - 0
Shell/Shell.h

@@ -40,6 +40,7 @@
 #include <termios.h>
 
 #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<String> expand_globs(const StringView& path, StringView base);
     static Vector<String> expand_globs(Vector<StringView> path_segments, const StringView& base);
     String resolve_path(String) const;
+    String resolve_alias(const String&) const;
 
     RefPtr<AST::Value> lookup_local_variable(const String&);
     String local_variable_or(const String&, const String&);
@@ -161,6 +163,7 @@ private:
     pid_t m_pid { 0 };
 
     HashMap<String, RefPtr<AST::Value>> m_local_variables;
+    HashMap<String, String> m_aliases;
 };
 
 static constexpr bool is_word_character(char c)