mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-01-20 02:42:47 +08:00
Adopt tnode_t in autosuggest_parse_command()
This commit is contained in:
parent
55fc10ea6e
commit
baa0c73d81
|
@ -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<grammar::plain_statement>();
|
||||
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<grammar::argument>(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;
|
||||
|
|
|
@ -139,6 +139,9 @@ class parse_node_t {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
class tnode_t;
|
||||
|
||||
/// The parse tree itself.
|
||||
class parse_node_tree_t : public std::vector<parse_node_t> {
|
||||
public:
|
||||
|
@ -168,10 +171,10 @@ class parse_node_tree_t : public std::vector<parse_node_t> {
|
|||
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 <typename Type>
|
||||
tnode_t<Type> 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<parse_node_t> {
|
|||
|
||||
/// 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 <typename Type>
|
||||
tnode_t<Type> parse_node_tree_t::find_last_node(const parse_node_t *parent) const {
|
||||
return tnode_t<Type>(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,
|
||||
|
|
Loading…
Reference in New Issue
Block a user