diff options
| author | Maxime Coste <frrrwww@gmail.com> | 2012-08-01 14:27:34 +0200 |
|---|---|---|
| committer | Maxime Coste <frrrwww@gmail.com> | 2012-08-01 14:27:34 +0200 |
| commit | 2071db355895f68d26f906549112e2e0f514bc98 (patch) | |
| tree | ff509ca88ee969784d8c6dd06462d8e879d9693a /src/command_manager.cc | |
| parent | 36070dd429af69f1042f4ee56488a960c4d8e7ef (diff) | |
Tokens are CommandManager implementation details
CommandParameters go back to memoryview<String>
Diffstat (limited to 'src/command_manager.cc')
| -rw-r--r-- | src/command_manager.cc | 109 |
1 files changed, 68 insertions, 41 deletions
diff --git a/src/command_manager.cc b/src/command_manager.cc index e4cde2ba..494b9317 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -30,10 +30,29 @@ void CommandManager::register_commands(const memoryview<String>& command_names, register_command(command_name, command, completer); } -static bool is_horizontal_blank(char c) +struct Token { - return c == ' ' or c == '\t'; -} + enum class Type + { + Raw, + ShellExpand, + CommandSeparator + }; + Token() : m_type(Type::Raw) {} + + explicit Token(const String& string) : m_content(string), m_type(Type::Raw) {} + explicit Token(Type type) : m_type(type) {} + Token(Type type, String str) : m_content(str), m_type(type) {} + + Type type() const { return m_type; } + + const String& content() const { return m_content; } + +private: + Type m_type; + String m_content; +}; + using TokenList = std::vector<Token>; using TokenPosList = std::vector<std::pair<size_t, size_t>>; @@ -43,6 +62,11 @@ static bool is_command_separator(Character c) return c == ';' or c == '\n'; } +static bool is_horizontal_blank(char c) +{ + return c == ' ' or c == '\t'; +} + static TokenList parse(const String& line, TokenPosList* opt_token_pos_info = NULL) { @@ -139,21 +163,10 @@ static TokenList parse(const String& line, ++pos; } - return result; -} - -struct command_not_found : runtime_error -{ - command_not_found(const String& command) - : runtime_error(command + " : no such command") {} -}; + if (not result.empty() and result.back().type() == Token::Type::CommandSeparator) + result.pop_back(); -void CommandManager::execute(const String& command_line, - const Context& context, - const EnvVarMap& env_vars) -{ - TokenList tokens = parse(command_line); - execute(tokens, context, env_vars); + return result; } static void shell_eval(TokenList& params, @@ -161,48 +174,62 @@ static void shell_eval(TokenList& params, const Context& context, const EnvVarMap& env_vars) { - String output = ShellManager::instance().eval(cmdline, context, env_vars); - TokenList tokens = parse(output); + String output = ShellManager::instance().eval(cmdline, context, env_vars); + TokenList tokens = parse(output); - for (auto& token : tokens) - params.push_back(std::move(token)); + for (auto& token : tokens) + params.push_back(std::move(token)); } -void CommandManager::execute(const CommandParameters& params, +struct command_not_found : runtime_error +{ + command_not_found(const String& command) + : runtime_error(command + " : no such command") {} +}; + +void CommandManager::execute(const String& command_line, const Context& context, const EnvVarMap& env_vars) { - if (params.empty()) + TokenList tokens = parse(command_line); + if (tokens.empty()) return; - auto begin = params.begin(); + TokenList expanded_tokens; + for (auto& token : tokens) + { + if (token.type() == Token::Type::ShellExpand) + shell_eval(expanded_tokens, token.content(), + context, env_vars); + else + expanded_tokens.push_back(token); + } + + auto begin = expanded_tokens.begin(); auto end = begin; + while (true) { - while (end != params.end() and end->type() != Token::Type::CommandSeparator) + while (end != expanded_tokens.end() and + end->type() != Token::Type::CommandSeparator) ++end; if (end != begin) { - if (begin->type() != Token::Type::Raw) - throw command_not_found("unable to parse command name"); auto command_it = m_commands.find(begin->content()); if (command_it == m_commands.end()) throw command_not_found(begin->content()); - TokenList expanded_tokens; - for (auto param = begin+1; param != end; ++param) + std::vector<String> params; + for (auto token_it = begin+1; token_it != end; ++token_it) { - if (param->type() == Token::Type::ShellExpand) - shell_eval(expanded_tokens, param->content(), - context, env_vars); - else - expanded_tokens.push_back(*param); + assert(token_it->type() == Token::Type::Raw); + params.push_back(token_it->content()); } - command_it->second.command(expanded_tokens, context); + command_it->second.command(params, context); } - if (end == params.end()) + if (end == expanded_tokens.end()) break; begin = end+1; @@ -257,7 +284,9 @@ Completions CommandManager::complete(const String& command_line, size_t cursor_p Completions result(start , cursor_pos); size_t cursor_pos_in_token = cursor_pos - start; - CommandParameters params(tokens.begin()+1, tokens.end()); + std::vector<String> params; + for (auto token_it = tokens.begin()+1; token_it != tokens.end(); ++token_it) + params.push_back(token_it->content()); result.candidates = command_it->second.completer(params, token_to_complete - 1, cursor_pos_in_token); @@ -268,16 +297,14 @@ CandidateList PerArgumentCommandCompleter::operator()(const CommandParameters& p size_t token_to_complete, size_t pos_in_token) const { - if (token_to_complete >= m_completers.size() or - (token_to_complete < params.size() and - params[token_to_complete].type() != Token::Type::Raw)) + if (token_to_complete >= m_completers.size()) return CandidateList(); // it is possible to try to complete a new argument assert(token_to_complete <= params.size()); const String& argument = token_to_complete < params.size() ? - params[token_to_complete].content() : String(); + params[token_to_complete] : String(); return m_completers[token_to_complete](argument, pos_in_token); } |
