From baa0c73d814b20d0cb99f3966ca5acf18b4f7fe7 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 13 Jan 2018 14:25:39 -0800 Subject: [PATCH] Adopt tnode_t in autosuggest_parse_command() --- src/highlight.cpp | 31 +++++++++++++------------------ src/parse_tree.h | 22 ++++++++++++++++++---- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/highlight.cpp b/src/highlight.cpp index 0d0b08e0a..5883ae0e6 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -313,9 +313,9 @@ static bool has_expand_reserved(const wcstring &str) { } // Parse a command line. Return by reference the last command, and the last argument to that command -// (as a copied node), if any. This is used by autosuggestions. +// (as a string), if any. This is used by autosuggestions. static bool autosuggest_parse_command(const wcstring &buff, wcstring *out_expanded_command, - parse_node_t *out_last_arg) { + wcstring *out_last_arg) { // Parse the buffer. parse_node_tree_t parse_tree; parse_tree_from_string(buff, @@ -323,15 +323,12 @@ static bool autosuggest_parse_command(const wcstring &buff, wcstring *out_expand &parse_tree, NULL); // Find the last statement. - const parse_node_t *last_statement = - parse_tree.find_last_node_of_type(symbol_plain_statement, NULL); - if (last_statement != NULL && plain_statement_get_expanded_command( - buff, parse_tree, *last_statement, out_expanded_command)) { + auto last_statement = parse_tree.find_last_node(); + if (last_statement && plain_statement_get_expanded_command(buff, parse_tree, *last_statement, + out_expanded_command)) { // Find the last argument. If we don't get one, return an invalid node. - const parse_node_t *last_arg = - parse_tree.find_last_node_of_type(symbol_argument, last_statement); - if (last_arg != NULL) { - *out_last_arg = *last_arg; + if (auto last_arg = parse_tree.find_last_node(last_statement)) { + *out_last_arg = last_arg.get_source(buff); } return true; } @@ -347,20 +344,18 @@ bool autosuggest_validate_from_history(const history_item_t &item, // Parse the string. wcstring parsed_command; - parse_node_t last_arg_node(token_type_invalid); - if (!autosuggest_parse_command(item.str(), &parsed_command, &last_arg_node)) return false; + wcstring cd_dir; + if (!autosuggest_parse_command(item.str(), &parsed_command, &cd_dir)) return false; - if (parsed_command == L"cd" && last_arg_node.type == symbol_argument && - last_arg_node.has_source()) { + if (parsed_command == L"cd" && !cd_dir.empty()) { // We can possibly handle this specially. - wcstring dir = last_arg_node.get_source(item.str()); - if (expand_one(dir, EXPAND_SKIP_CMDSUBST)) { + if (expand_one(cd_dir, EXPAND_SKIP_CMDSUBST)) { handled = true; bool is_help = - string_prefixes_string(dir, L"--help") || string_prefixes_string(dir, L"-h"); + string_prefixes_string(cd_dir, L"--help") || string_prefixes_string(cd_dir, L"-h"); if (!is_help) { wcstring path; - env_var_t dir_var(L"n/a", dir); + env_var_t dir_var(L"n/a", cd_dir); bool can_cd = path_get_cdpath(dir_var, &path, working_directory.c_str(), vars); if (can_cd && !paths_are_same_file(working_directory, path)) { suggestionOK = true; diff --git a/src/parse_tree.h b/src/parse_tree.h index 51b37fc86..11f110572 100644 --- a/src/parse_tree.h +++ b/src/parse_tree.h @@ -139,6 +139,9 @@ class parse_node_t { } }; +template +class tnode_t; + /// The parse tree itself. class parse_node_tree_t : public std::vector { public: @@ -168,10 +171,10 @@ class parse_node_tree_t : public std::vector { parse_node_list_t find_nodes(const parse_node_t &parent, parse_token_type_t type, size_t max_count = size_t(-1)) const; - // Finds the last node of a given type underneath a given node, or NULL if it could not be - // found. If parent is NULL, this finds the last node in the tree of that type. - const parse_node_t *find_last_node_of_type(parse_token_type_t type, - const parse_node_t *parent = NULL) const; + // Finds the last node of a given type, or empty if it could not be found. If parent is NULL, + // this finds the last node in the tree of that type. + template + tnode_t find_last_node(const parse_node_t *parent = NULL) const; // Finds a node containing the given source location. If 'parent' is not NULL, it must be an // ancestor. @@ -227,6 +230,12 @@ class parse_node_tree_t : public std::vector { /// Given a job, return whether it should be backgrounded, because it has a & specifier. bool job_should_be_backgrounded(const parse_node_t &job) const; + + private: + // Finds the last node of a given type underneath a given node, or NULL if it could not be + // found. If parent is NULL, this finds the last node in the tree of that type. + const parse_node_t *find_last_node_of_type(parse_token_type_t type, + const parse_node_t *parent) const; }; struct source_range_t { @@ -350,6 +359,11 @@ class tnode_t { } }; +template +tnode_t parse_node_tree_t::find_last_node(const parse_node_t *parent) const { + return tnode_t(this, this->find_last_node_of_type(Type::token, parent)); +} + /// The big entry point. Parse a string, attempting to produce a tree for the given goal type. bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t flags, parse_node_tree_t *output, parse_error_list_t *errors,