diff options
author | ridiculousfish <corydoras@ridiculousfish.com> | 2013-10-07 03:56:09 -0700 |
---|---|---|
committer | ridiculousfish <corydoras@ridiculousfish.com> | 2013-10-07 03:56:09 -0700 |
commit | 4f718e83b343cd2cf49c801968dd36cbce84a772 (patch) | |
tree | c0162410d984db2881ef199e80b5c5ccdac9e448 /highlight.cpp | |
parent | 20ccda69f4319cadbfb242f139e48a84699b503d (diff) |
Syntax highlighting now correctly handles cd
Diffstat (limited to 'highlight.cpp')
-rw-r--r-- | highlight.cpp | 81 |
1 files changed, 59 insertions, 22 deletions
diff --git a/highlight.cpp b/highlight.cpp index a8e8326e..71dba3dc 100644 --- a/highlight.cpp +++ b/highlight.cpp @@ -1467,7 +1467,7 @@ static void color_node(const parse_node_t &node, int color, std::vector<int> &co std::fill(color_array.begin() + node.source_start, color_array.begin() + source_end, color); } -/* This function is a disaster badly in need of refactoring */ +/* This function is a disaster badly in need of refactoring. However, note that it does NOT do any I/O */ static void color_argument(const wcstring &buffstr, std::vector<int>::iterator colors, int normal_status) { const size_t buff_len = buffstr.size(); @@ -1772,10 +1772,45 @@ static bool node_is_potential_path(const wcstring &src, const parse_node_t &node return result; } +// Gets the expanded command from a plain statement node +static bool plain_statement_get_expanded_command(const wcstring &src, const parse_node_tree_t &tree, const parse_node_t &plain_statement, wcstring *out_cmd) +{ + assert(plain_statement.type == symbol_plain_statement); + bool result = false; + + // Get the command + const parse_node_t *cmd_node = tree.get_child(plain_statement, 0, parse_token_type_string); + if (cmd_node != NULL && cmd_node->has_source()) + { + wcstring cmd(src, cmd_node->source_start, cmd_node->source_length); + + /* Try expanding it. If we cannot, it's an error. */ + if (expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES | EXPAND_SKIP_JOBS)) + { + /* Success, return the expanded string by reference */ + std::swap(cmd, *out_cmd); + result = true; + } + } + return result; +} + // Color all of the arguments of the given command -static void color_arguments(const wcstring &src, const parse_node_tree_t &tree, const parse_node_t &parent, std::vector<int> &color_array) +static void color_arguments(const wcstring &src, const parse_node_tree_t &tree, const parse_node_t &list_node, const wcstring &working_directory, std::vector<int> &color_array) { - const parse_node_tree_t::parse_node_list_t nodes = tree.find_nodes(parent, symbol_argument); + /* Hack: determine whether the parent is the cd command. */ + bool cmd_is_cd = false; + const parse_node_t *parent = tree.get_parent(list_node, symbol_plain_statement); + if (parent != NULL) + { + wcstring cmd_str; + if (plain_statement_get_expanded_command(src, tree, *parent, &cmd_str)) + { + cmd_is_cd = (cmd_str == L"cd"); + } + } + + const parse_node_tree_t::parse_node_list_t nodes = tree.find_nodes(list_node, symbol_argument); wcstring param; for (node_offset_t i=0; i < nodes.size(); i++) @@ -1784,6 +1819,19 @@ static void color_arguments(const wcstring &src, const parse_node_tree_t &tree, assert(child != NULL && child->type == symbol_argument); param.assign(src, child->source_start, child->source_length); color_argument(param, color_array.begin() + child->source_start, HIGHLIGHT_PARAM); + + if (cmd_is_cd) + { + /* Mark this as an error if it's not 'help' and not a valid cd path */ + if (expand_one(param, EXPAND_SKIP_CMDSUBST)) + { + bool is_help = string_prefixes_string(param, L"--help") || string_prefixes_string(param, L"-h"); + if (!is_help && ! is_potential_cd_path(param, working_directory, PATH_EXPAND_TILDE, NULL)) + { + color_node(*child, HIGHLIGHT_ERROR, color_array); + } + } + } } } @@ -1893,20 +1941,10 @@ void highlight_shell_magic(const wcstring &buff, std::vector<int> &color, size_t case symbol_switch_statement: case symbol_boolean_statement: case symbol_decorated_statement: - color_children(parse_tree, node, parse_token_type_string, HIGHLIGHT_COMMAND, color); - break; - case symbol_if_statement: { // Color the 'end' color_children(parse_tree, node, parse_token_type_string, HIGHLIGHT_COMMAND, color); - - // Color arguments and redirections - const parse_node_t *arguments = parse_tree.get_child(node, 3, symbol_arguments_or_redirections_list); - if (arguments != NULL) - { - color_arguments(buff, parse_tree, *arguments, color); - } } break; @@ -1948,21 +1986,20 @@ void highlight_shell_magic(const wcstring &buff, std::vector<int> &color, size_t } color_node(*cmd_node, is_valid_cmd ? HIGHLIGHT_COMMAND : HIGHLIGHT_ERROR, color); } - - /* Color arguments */ - const parse_node_t *arguments = parse_tree.get_child(node, 1, symbol_arguments_or_redirections_list); - if (arguments != NULL) - { - color_arguments(buff, parse_tree, *arguments, color); - } } break; case symbol_arguments_or_redirections_list: case symbol_argument_list: - /* Nothing, these are handled by their parents */ - break; + { + /* Only work on root lists, so that we don't re-color child lists */ + if (parse_tree.argument_list_is_root(node)) + { + color_arguments(buff, parse_tree, node, working_directory, color); + } + } + break; case parse_special_type_parse_error: case parse_special_type_tokenizer_error: |