2016-05-04 07:23:30 +08:00
|
|
|
/// Prototypes for functions related to tab-completion.
|
|
|
|
///
|
|
|
|
/// These functions are used for storing and retrieving tab-completion data, as well as for
|
|
|
|
/// performing tab-completion.
|
2005-10-04 23:11:39 +08:00
|
|
|
#ifndef FISH_COMPLETE_H
|
|
|
|
#define FISH_COMPLETE_H
|
|
|
|
|
2016-05-04 07:23:30 +08:00
|
|
|
#include <stdint.h>
|
2017-02-14 12:37:27 +08:00
|
|
|
|
2018-10-17 09:38:41 +08:00
|
|
|
#include <functional>
|
2016-05-04 07:23:30 +08:00
|
|
|
#include <vector>
|
2005-10-04 23:11:39 +08:00
|
|
|
|
2012-01-17 00:56:47 +08:00
|
|
|
#include "common.h"
|
2019-05-05 08:55:57 +08:00
|
|
|
#include "enum_set.h"
|
2020-11-28 07:43:07 +08:00
|
|
|
#include "wcstringutil.h"
|
2019-05-05 08:55:57 +08:00
|
|
|
|
2019-04-26 05:21:06 +08:00
|
|
|
struct completion_mode_t {
|
|
|
|
/// If set, skip file completions.
|
|
|
|
bool no_files{false};
|
2019-05-31 01:12:49 +08:00
|
|
|
bool force_files{false};
|
2019-04-26 05:21:06 +08:00
|
|
|
|
|
|
|
/// If set, require a parameter after completion.
|
|
|
|
bool requires_param{false};
|
|
|
|
};
|
2019-04-26 04:25:36 +08:00
|
|
|
|
2016-05-04 07:23:30 +08:00
|
|
|
/// Character that separates the completion and description on programmable completions.
|
2005-09-20 21:26:39 +08:00
|
|
|
#define PROG_COMPLETE_SEP L'\t'
|
|
|
|
|
2018-09-11 00:58:02 +08:00
|
|
|
class environment_t;
|
|
|
|
|
2016-05-04 07:23:30 +08:00
|
|
|
enum {
|
|
|
|
/// Do not insert space afterwards if this is the only completion. (The default is to try insert
|
|
|
|
/// a space).
|
2012-02-26 10:54:49 +08:00
|
|
|
COMPLETE_NO_SPACE = 1 << 0,
|
2016-05-04 07:23:30 +08:00
|
|
|
/// This is not the suffix of a token, but replaces it entirely.
|
2013-03-06 12:54:16 +08:00
|
|
|
COMPLETE_REPLACES_TOKEN = 1 << 2,
|
2016-05-04 07:23:30 +08:00
|
|
|
/// This completion may or may not want a space at the end - guess by checking the last
|
|
|
|
/// character of the completion.
|
2013-03-06 12:54:16 +08:00
|
|
|
COMPLETE_AUTO_SPACE = 1 << 3,
|
2016-05-04 07:23:30 +08:00
|
|
|
/// This completion should be inserted as-is, without escaping.
|
2013-04-08 14:54:43 +08:00
|
|
|
COMPLETE_DONT_ESCAPE = 1 << 4,
|
2016-05-04 07:23:30 +08:00
|
|
|
/// If you do escape, don't escape tildes.
|
2017-07-25 06:54:54 +08:00
|
|
|
COMPLETE_DONT_ESCAPE_TILDES = 1 << 5,
|
|
|
|
/// Do not sort supplied completions
|
2018-08-07 17:01:19 +08:00
|
|
|
COMPLETE_DONT_SORT = 1 << 6,
|
|
|
|
/// This completion looks to have the same string as an existing argument.
|
|
|
|
COMPLETE_DUPLICATES_ARGUMENT = 1 << 7
|
2012-02-26 10:54:49 +08:00
|
|
|
};
|
2021-09-22 08:57:25 +08:00
|
|
|
using complete_flags_t = int;
|
2008-01-14 03:32:21 +08:00
|
|
|
|
2018-10-16 13:30:13 +08:00
|
|
|
/// std::function which accepts a completion string and returns its description.
|
|
|
|
using description_func_t = std::function<wcstring(const wcstring &)>;
|
|
|
|
|
|
|
|
/// Helper to return a description_func_t for a constant string.
|
|
|
|
description_func_t const_desc(const wcstring &s);
|
|
|
|
|
2016-05-04 07:23:30 +08:00
|
|
|
class completion_t {
|
|
|
|
private:
|
|
|
|
// No public default constructor.
|
2012-11-19 08:30:30 +08:00
|
|
|
completion_t();
|
2012-02-02 08:27:14 +08:00
|
|
|
|
2016-05-04 07:23:30 +08:00
|
|
|
public:
|
|
|
|
// Destructor. Not inlining it saves code size.
|
2013-04-17 06:01:24 +08:00
|
|
|
~completion_t();
|
|
|
|
|
2016-05-04 07:23:30 +08:00
|
|
|
/// The completion string.
|
2012-11-19 08:30:30 +08:00
|
|
|
wcstring completion;
|
2016-05-04 07:23:30 +08:00
|
|
|
/// The description for this completion.
|
2012-11-19 08:30:30 +08:00
|
|
|
wcstring description;
|
2016-05-04 07:23:30 +08:00
|
|
|
/// The type of fuzzy match.
|
2013-05-26 06:41:18 +08:00
|
|
|
string_fuzzy_match_t match;
|
2019-03-28 19:27:45 +08:00
|
|
|
/// Flags determining the completion behavior.
|
2016-05-04 07:23:30 +08:00
|
|
|
///
|
|
|
|
/// Determines whether a space should be inserted after this completion if it is the only
|
|
|
|
/// possible completion using the COMPLETE_NO_SPACE flag. The COMPLETE_NO_CASE can be used to
|
|
|
|
/// signal that this completion is case insensitive.
|
2014-01-15 06:28:06 +08:00
|
|
|
complete_flags_t flags;
|
2013-06-02 16:14:26 +08:00
|
|
|
|
2018-02-17 13:26:15 +08:00
|
|
|
// Construction.
|
|
|
|
explicit completion_t(wcstring comp, wcstring desc = wcstring(),
|
2020-11-29 05:39:36 +08:00
|
|
|
string_fuzzy_match_t match = string_fuzzy_match_t::exact_match(),
|
2016-05-04 07:23:30 +08:00
|
|
|
complete_flags_t flags_val = 0);
|
2012-07-18 03:47:01 +08:00
|
|
|
completion_t(const completion_t &);
|
|
|
|
completion_t &operator=(const completion_t &);
|
2013-10-27 06:27:39 +08:00
|
|
|
|
2018-10-11 08:41:17 +08:00
|
|
|
// noexcepts are required for push_back to use the move ctor.
|
|
|
|
completion_t(completion_t &&) noexcept;
|
|
|
|
completion_t &operator=(completion_t &&) noexcept;
|
2018-02-17 13:26:15 +08:00
|
|
|
|
2021-11-28 10:42:25 +08:00
|
|
|
/// \return whether this replaces its token.
|
|
|
|
bool replaces_token() const { return flags & COMPLETE_REPLACES_TOKEN; }
|
|
|
|
|
2020-11-29 05:39:36 +08:00
|
|
|
/// \return the completion's match rank. Lower ranks are better completions.
|
|
|
|
uint32_t rank() const { return match.rank(); }
|
2016-05-04 07:23:30 +08:00
|
|
|
|
|
|
|
// If this completion replaces the entire token, prepend a prefix. Otherwise do nothing.
|
2015-08-03 08:58:37 +08:00
|
|
|
void prepend_token_prefix(const wcstring &prefix);
|
2012-02-03 04:04:04 +08:00
|
|
|
};
|
2007-02-09 17:33:50 +08:00
|
|
|
|
2020-01-16 08:13:41 +08:00
|
|
|
using completion_list_t = std::vector<completion_t>;
|
|
|
|
|
2019-05-05 08:55:57 +08:00
|
|
|
enum class completion_request_t {
|
|
|
|
autosuggestion, // indicates the completion is for an autosuggestion
|
|
|
|
descriptions, // indicates that we want descriptions
|
|
|
|
fuzzy_match, // indicates that we don't require a prefix match
|
|
|
|
COUNT
|
2012-02-25 04:13:35 +08:00
|
|
|
};
|
2019-05-05 08:55:57 +08:00
|
|
|
|
|
|
|
template <>
|
|
|
|
struct enum_info_t<completion_request_t> {
|
|
|
|
static constexpr auto count = completion_request_t::COUNT;
|
|
|
|
};
|
|
|
|
|
|
|
|
using completion_request_flags_t = enum_set_t<completion_request_t>;
|
2007-02-09 17:33:50 +08:00
|
|
|
|
2020-01-16 09:14:47 +08:00
|
|
|
class completion_t;
|
|
|
|
using completion_list_t = std::vector<completion_t>;
|
|
|
|
|
2020-12-02 03:36:38 +08:00
|
|
|
/// A completion receiver accepts completions. It is essentially a wrapper around std::vector with
|
|
|
|
/// some conveniences.
|
|
|
|
class completion_receiver_t {
|
|
|
|
public:
|
2020-12-06 05:07:19 +08:00
|
|
|
/// Construct as empty, with a limit.
|
2020-12-21 03:58:26 +08:00
|
|
|
explicit completion_receiver_t(size_t limit) : limit_(limit) {}
|
2020-12-04 04:04:17 +08:00
|
|
|
|
2020-12-06 05:07:19 +08:00
|
|
|
/// Acquire an existing list, with a limit.
|
2020-12-21 03:58:26 +08:00
|
|
|
explicit completion_receiver_t(completion_list_t &&v, size_t limit)
|
2020-12-04 04:04:17 +08:00
|
|
|
: completions_(std::move(v)), limit_(limit) {}
|
2020-12-02 05:19:34 +08:00
|
|
|
|
2020-12-02 03:36:38 +08:00
|
|
|
/// Add a completion.
|
2020-12-04 04:04:17 +08:00
|
|
|
/// \return true on success, false if this would overflow the limit.
|
|
|
|
__warn_unused bool add(completion_t &&comp);
|
2020-12-02 03:36:38 +08:00
|
|
|
|
|
|
|
/// Add a completion with the given string, and default other properties.
|
2020-12-04 04:04:17 +08:00
|
|
|
/// \return true on success, false if this would overflow the limit.
|
|
|
|
__warn_unused bool add(wcstring &&comp);
|
2020-12-02 03:36:38 +08:00
|
|
|
|
|
|
|
/// Add a completion with the given string, description, flags, and fuzzy match.
|
2020-12-04 04:04:17 +08:00
|
|
|
/// \return true on success, false if this would overflow the limit.
|
2020-12-06 06:26:07 +08:00
|
|
|
/// The 'desc' parameter is not && because if gettext is not enabled, then we end
|
|
|
|
/// up passing a 'const wcstring &' here.
|
|
|
|
__warn_unused bool add(wcstring &&comp, wcstring desc, complete_flags_t flags = 0,
|
|
|
|
string_fuzzy_match_t match = string_fuzzy_match_t::exact_match());
|
2020-12-02 03:36:38 +08:00
|
|
|
|
|
|
|
/// Add a list of completions.
|
2020-12-04 04:04:17 +08:00
|
|
|
/// \return true on success, false if this would overflow the limit.
|
|
|
|
__warn_unused bool add_list(completion_list_t &&lst);
|
2020-12-02 03:36:38 +08:00
|
|
|
|
|
|
|
/// Swap our completions with a new list.
|
|
|
|
void swap(completion_list_t &lst) { std::swap(completions_, lst); }
|
|
|
|
|
|
|
|
/// Clear the list of completions. This retains the storage inside completions_ which can be
|
|
|
|
/// useful to prevent allocations.
|
|
|
|
void clear() { completions_.clear(); }
|
|
|
|
|
2020-12-02 05:19:34 +08:00
|
|
|
/// \return whether our completion list is empty.
|
|
|
|
bool empty() const { return completions_.empty(); }
|
|
|
|
|
|
|
|
/// \return how many completions we have stored.
|
|
|
|
size_t size() const { return completions_.size(); }
|
|
|
|
|
|
|
|
/// \return a completion at an index.
|
|
|
|
completion_t &at(size_t idx) { return completions_.at(idx); }
|
|
|
|
const completion_t &at(size_t idx) const { return completions_.at(idx); }
|
|
|
|
|
|
|
|
/// \return the list of completions. Do not modify the size of the list via this function, as it
|
|
|
|
/// may exceed our completion limit.
|
|
|
|
const completion_list_t &get_list() const { return completions_; }
|
|
|
|
completion_list_t &get_list() { return completions_; }
|
|
|
|
|
2020-12-04 04:04:17 +08:00
|
|
|
/// \return the list of completions, clearing it.
|
2020-12-02 03:36:38 +08:00
|
|
|
completion_list_t take();
|
|
|
|
|
2020-12-04 04:04:17 +08:00
|
|
|
/// \return a new, empty receiver whose limit is our remaining capacity.
|
|
|
|
/// This is useful for e.g. recursive calls when you want to act on the result before adding it.
|
|
|
|
completion_receiver_t subreceiver() const;
|
|
|
|
|
2020-12-02 03:36:38 +08:00
|
|
|
private:
|
2020-12-04 04:04:17 +08:00
|
|
|
// Our list of completions.
|
2020-12-02 03:36:38 +08:00
|
|
|
completion_list_t completions_;
|
2020-12-04 04:04:17 +08:00
|
|
|
|
|
|
|
// The maximum number of completions to add. If our list length exceeds this, then new
|
|
|
|
// completions are not added. Note 0 has no special significance here - use
|
|
|
|
// numeric_limits<size_t>::max() instead.
|
|
|
|
const size_t limit_;
|
2020-12-02 03:36:38 +08:00
|
|
|
};
|
|
|
|
|
2016-06-06 09:46:04 +08:00
|
|
|
enum complete_option_type_t {
|
|
|
|
option_type_args_only, // no option
|
|
|
|
option_type_short, // -x
|
|
|
|
option_type_single_long, // -foo
|
|
|
|
option_type_double_long // --foo
|
|
|
|
};
|
|
|
|
|
2018-08-07 17:01:19 +08:00
|
|
|
/// Sorts and remove any duplicate completions in the completion list, then puts them in priority
|
|
|
|
/// order.
|
2020-01-16 08:13:41 +08:00
|
|
|
void completions_sort_and_prioritize(completion_list_t *comps,
|
2019-05-05 08:55:57 +08:00
|
|
|
completion_request_flags_t flags = {});
|
2018-08-07 17:01:19 +08:00
|
|
|
|
2016-05-04 07:23:30 +08:00
|
|
|
/// Add a completion.
|
|
|
|
///
|
|
|
|
/// All supplied values are copied, they should be freed by or otherwise disposed by the caller.
|
|
|
|
///
|
|
|
|
/// Examples:
|
|
|
|
///
|
|
|
|
/// The command 'gcc -o' requires that a file follows it, so the NO_COMMON option is suitable. This
|
|
|
|
/// can be done using the following line:
|
|
|
|
///
|
|
|
|
/// complete -c gcc -s o -r
|
|
|
|
///
|
|
|
|
/// The command 'grep -d' required that one of the strings 'read', 'skip' or 'recurse' is used. As
|
|
|
|
/// such, it is suitable to specify that a completion requires one of them. This can be done using
|
|
|
|
/// the following line:
|
|
|
|
///
|
|
|
|
/// complete -c grep -s d -x -a "read skip recurse"
|
|
|
|
///
|
|
|
|
/// \param cmd Command to complete.
|
2016-06-06 09:46:04 +08:00
|
|
|
/// \param cmd_is_path If cmd_is_path is true, cmd will be interpreted as the absolute
|
2016-05-04 07:23:30 +08:00
|
|
|
/// path of the program (optionally containing wildcards), otherwise it
|
|
|
|
/// will be interpreted as the command name.
|
2016-06-06 09:46:04 +08:00
|
|
|
/// \param option The name of an option.
|
|
|
|
/// \param option_type The type of option: can be option_type_short (-x),
|
|
|
|
/// option_type_single_long (-foo), option_type_double_long (--bar).
|
2019-04-26 05:21:06 +08:00
|
|
|
/// \param result_mode Controls how to search further completions when this completion has been
|
2019-11-25 19:03:25 +08:00
|
|
|
/// successfully matched.
|
2016-05-04 07:23:30 +08:00
|
|
|
/// \param comp A space separated list of completions which may contain subshells.
|
|
|
|
/// \param desc A description of the completion.
|
|
|
|
/// \param condition a command to be run to check it this completion should be used. If \c condition
|
|
|
|
/// is empty, the completion is always used.
|
|
|
|
/// \param flags A set of completion flags
|
|
|
|
void complete_add(const wchar_t *cmd, bool cmd_is_path, const wcstring &option,
|
2019-04-26 05:21:06 +08:00
|
|
|
complete_option_type_t option_type, completion_mode_t result_mode,
|
2022-05-21 01:02:42 +08:00
|
|
|
wcstring_list_t condition, const wchar_t *comp, const wchar_t *desc, int flags);
|
2016-05-04 07:23:30 +08:00
|
|
|
|
|
|
|
/// Remove a previously defined completion.
|
|
|
|
void complete_remove(const wcstring &cmd, bool cmd_is_path, const wcstring &option,
|
2016-01-17 14:42:14 +08:00
|
|
|
complete_option_type_t type);
|
2005-09-20 21:26:39 +08:00
|
|
|
|
2016-05-04 07:23:30 +08:00
|
|
|
/// Removes all completions for a given command.
|
2016-01-17 14:42:14 +08:00
|
|
|
void complete_remove_all(const wcstring &cmd, bool cmd_is_path);
|
2012-02-25 04:13:35 +08:00
|
|
|
|
2020-01-16 08:41:30 +08:00
|
|
|
/// \return all completions of the command cmd.
|
2020-01-16 09:14:47 +08:00
|
|
|
class operation_context_t;
|
2020-01-16 08:41:30 +08:00
|
|
|
completion_list_t complete(const wcstring &cmd, completion_request_flags_t flags,
|
2020-01-16 09:14:47 +08:00
|
|
|
const operation_context_t &ctx);
|
2005-09-20 21:26:39 +08:00
|
|
|
|
2016-05-04 07:23:30 +08:00
|
|
|
/// Return a list of all current completions.
|
2020-09-26 20:24:27 +08:00
|
|
|
wcstring complete_print(const wcstring &cmd = L"");
|
2005-09-20 21:26:39 +08:00
|
|
|
|
2016-05-04 07:23:30 +08:00
|
|
|
/// Tests if the specified option is defined for the specified command.
|
|
|
|
int complete_is_valid_option(const wcstring &str, const wcstring &opt,
|
|
|
|
wcstring_list_t *inErrorsOrNull, bool allow_autoload);
|
2007-02-19 07:25:20 +08:00
|
|
|
|
2016-05-04 07:23:30 +08:00
|
|
|
/// Tests if the specified argument is valid for the specified option and command.
|
|
|
|
bool complete_is_valid_argument(const wcstring &str, const wcstring &opt, const wcstring &arg);
|
2012-02-02 08:27:14 +08:00
|
|
|
|
2016-05-04 07:23:30 +08:00
|
|
|
/// Create a new completion entry.
|
|
|
|
///
|
|
|
|
/// \param completions The array of completions to append to
|
|
|
|
/// \param comp The completion string
|
|
|
|
/// \param desc The description of the completion
|
|
|
|
/// \param flags completion flags
|
2020-01-16 08:13:41 +08:00
|
|
|
void append_completion(completion_list_t *completions, wcstring comp, wcstring desc = wcstring(),
|
|
|
|
int flags = 0,
|
2020-11-29 05:39:36 +08:00
|
|
|
string_fuzzy_match_t match = string_fuzzy_match_t::exact_match());
|
2007-02-19 07:25:20 +08:00
|
|
|
|
2018-02-27 11:21:46 +08:00
|
|
|
/// Support for "wrap targets." A wrap target is a command that completes like another command.
|
2019-11-19 08:54:36 +08:00
|
|
|
bool complete_add_wrapper(const wcstring &command, const wcstring &new_target);
|
|
|
|
bool complete_remove_wrapper(const wcstring &command, const wcstring &target_to_remove);
|
2018-02-27 11:21:46 +08:00
|
|
|
|
|
|
|
/// Returns a list of wrap targets for a given command.
|
|
|
|
wcstring_list_t complete_get_wrap_targets(const wcstring &command);
|
2014-08-16 09:14:36 +08:00
|
|
|
|
2018-02-16 13:58:02 +08:00
|
|
|
// Observes that fish_complete_path has changed.
|
|
|
|
void complete_invalidate_path();
|
|
|
|
|
2005-10-04 23:11:39 +08:00
|
|
|
#endif
|