forked from Bananymous/banan-os
Userspace: Shell now processes $ arguments
This commit is contained in:
parent
de88f60d1a
commit
54f89cba33
|
@ -1,6 +1,8 @@
|
|||
#include <BAN/Optional.h>
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <BAN/String.h>
|
||||
#include <BAN/Vector.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -10,6 +12,59 @@
|
|||
|
||||
struct termios old_termios, new_termios;
|
||||
|
||||
BAN::Optional<BAN::String> parse_dollar(BAN::StringView command, size_t& i)
|
||||
{
|
||||
ASSERT(command[i] == '$');
|
||||
|
||||
if (++i >= command.size())
|
||||
return "$"sv;
|
||||
|
||||
if (isalnum(command[i]))
|
||||
{
|
||||
size_t len = 1;
|
||||
for (; i + len < command.size(); len++)
|
||||
if (!isalnum(command[i + len]))
|
||||
break;
|
||||
BAN::String name = command.substring(i, len);
|
||||
i += len - 1;
|
||||
|
||||
if (const char* value = getenv(name.data()))
|
||||
return BAN::StringView(value);
|
||||
return ""sv;
|
||||
}
|
||||
else if (command[i] == '{')
|
||||
{
|
||||
size_t len = 1;
|
||||
for (; i + len < command.size(); len++)
|
||||
{
|
||||
if (command[i + len] == '}')
|
||||
break;
|
||||
if (!isalnum(command[i + len]))
|
||||
return {};
|
||||
}
|
||||
|
||||
if (i + len >= command.size())
|
||||
return {};
|
||||
|
||||
BAN::String name = command.substring(i + 1, len - 1);
|
||||
i += len;
|
||||
|
||||
if (const char* value = getenv(name.data()))
|
||||
return BAN::StringView(value);
|
||||
return ""sv;
|
||||
}
|
||||
else if (command[i] == '[')
|
||||
{
|
||||
return {};
|
||||
}
|
||||
else if (command[i] == '(')
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return "$"sv;
|
||||
}
|
||||
|
||||
BAN::Vector<BAN::String> parse_command(BAN::StringView command)
|
||||
{
|
||||
enum class State
|
||||
|
@ -23,8 +78,10 @@ BAN::Vector<BAN::String> parse_command(BAN::StringView command)
|
|||
|
||||
State state = State::Normal;
|
||||
BAN::String current;
|
||||
for (char c : command)
|
||||
for (size_t i = 0; i < command.size(); i++)
|
||||
{
|
||||
char c = command[i];
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case State::Normal:
|
||||
|
@ -32,6 +89,16 @@ BAN::Vector<BAN::String> parse_command(BAN::StringView command)
|
|||
state = State::SingleQuote;
|
||||
else if (c == '"')
|
||||
state = State::DoubleQuote;
|
||||
else if (c == '$')
|
||||
{
|
||||
auto expansion = parse_dollar(command, i);
|
||||
if (!expansion.has_value())
|
||||
{
|
||||
fprintf(stderr, "bad substitution\n");
|
||||
return {};
|
||||
}
|
||||
MUST(current.append(expansion.value()));
|
||||
}
|
||||
else if (!isspace(c))
|
||||
MUST(current.push_back(c));
|
||||
else
|
||||
|
@ -52,8 +119,18 @@ BAN::Vector<BAN::String> parse_command(BAN::StringView command)
|
|||
case State::DoubleQuote:
|
||||
if (c == '"')
|
||||
state = State::Normal;
|
||||
else
|
||||
else if (c != '$')
|
||||
MUST(current.push_back(c));
|
||||
else
|
||||
{
|
||||
auto expansion = parse_dollar(command, i);
|
||||
if (!expansion.has_value())
|
||||
{
|
||||
fprintf(stderr, "bad substitution\n");
|
||||
return {};
|
||||
}
|
||||
MUST(current.append(expansion.value()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +258,7 @@ BAN::String get_prompt()
|
|||
{
|
||||
const char* raw_prompt = getenv("PS1");
|
||||
if (raw_prompt == nullptr)
|
||||
raw_prompt = "\e[32muser@host\e[m:\e[34m\\~\e[m$ ";
|
||||
return ""sv;
|
||||
|
||||
BAN::String prompt;
|
||||
for (int i = 0; raw_prompt[i]; i++)
|
||||
|
@ -254,6 +331,7 @@ int main(int argc, char** argv)
|
|||
{
|
||||
if (argc >= 1)
|
||||
setenv("SHELL", argv[0], true);
|
||||
setenv("PS1", "\e[32muser@host\e[m:\e[34m\\~\e[m$ ", false);
|
||||
|
||||
tcgetattr(0, &old_termios);
|
||||
|
||||
|
|
Loading…
Reference in New Issue