Shell: add type builtin

This commit is contained in:
jacob gw 2021-04-10 23:25:49 -04:00 committed by Andreas Kling
parent 1d7a0ab5ea
commit cb22a6642d
Notes: sideshowbarker 2024-07-18 20:26:44 +09:00
3 changed files with 96 additions and 0 deletions

View file

@ -26,6 +26,7 @@
#include "AST.h"
#include "Shell.h"
#include "Shell/Formatter.h"
#include <AK/LexicalPath.h>
#include <AK/ScopeGuard.h>
#include <LibCore/ArgsParser.h>
@ -127,6 +128,76 @@ int Shell::builtin_bg(int argc, const char** argv)
return 0;
}
int Shell::builtin_type(int argc, const char** argv)
{
Vector<const char*> commands;
bool dont_show_function_source = false;
Core::ArgsParser parser;
parser.set_general_help("Display information about commands.");
parser.add_positional_argument(commands, "Command(s) to list info about", "command");
parser.add_option(dont_show_function_source, "Do not show functions source.", "no-fn-source", 'f');
if (!parser.parse(argc, const_cast<char**>(argv), false))
return 1;
bool something_not_found = false;
for (auto& command : commands) {
// check if it is an alias
if (auto alias = m_aliases.get(command); alias.has_value()) {
printf("%s is aliased to `%s`\n", escape_token(command).characters(), escape_token(alias.value()).characters());
continue;
}
// check if it is a function
if (auto function = m_functions.get(command); function.has_value()) {
auto fn = function.value();
printf("%s is a function\n", command);
if (!dont_show_function_source) {
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");
if (fn.body) {
auto formatter = Formatter(*fn.body);
builder.append(formatter.format());
printf("%s\n}\n", builder.build().characters());
} else {
printf("%s\n}\n", builder.build().characters());
}
}
continue;
}
// check if its a builtin
if (has_builtin(command)) {
printf("%s is a shell builtin\n", command);
continue;
}
// check if its an executable in PATH
auto fullpath = Core::find_executable_in_path(command);
if (!fullpath.is_null()) {
printf("%s is %s\n", command, escape_token(fullpath).characters());
continue;
}
something_not_found = true;
printf("type: %s not found\n", command);
}
if (something_not_found)
return 1;
else
return 0;
}
int Shell::builtin_cd(int argc, const char** argv)
{
const char* arg_path = nullptr;

View file

@ -45,6 +45,7 @@
__ENUMERATE_SHELL_BUILTIN(cd) \
__ENUMERATE_SHELL_BUILTIN(cdh) \
__ENUMERATE_SHELL_BUILTIN(pwd) \
__ENUMERATE_SHELL_BUILTIN(type) \
__ENUMERATE_SHELL_BUILTIN(exec) \
__ENUMERATE_SHELL_BUILTIN(exit) \
__ENUMERATE_SHELL_BUILTIN(export) \

View file

@ -0,0 +1,24 @@
#!/bin/sh
source $(dirname "$0")/test-commons.inc
if not [ "$(type ls)" = "ls is $(which ls)" ] { fail "'type' on a binary not working" }
if not [ "$(type pwd)" = "pwd is a shell builtin" ] { fail "'type' on a builtin not working" }
f() { ls }
if not [ "$(type f)" = "f is a function f() { ls }" ] { fail "'type' on a function not working" }
if not [ "$(type f -f)" = "f is a function" ] { fail "'type' on a function not working with -f" }
alias l=ls
if not [ "$(type l)" = "l is aliased to `ls`" ] { fail "'type' on a alias not working" }
if not [ "$(type l ls)" = "l is aliased to `ls` ls is $(which ls)" ] { fail "'type' on multiple commands not working" }
echo PASS