1 /// Prototypes for functions related to tab-completion. 2 /// 3 /// These functions are used for storing and retrieving tab-completion data, as well as for 4 /// performing tab-completion. 5 #ifndef FISH_COMPLETE_H 6 #define FISH_COMPLETE_H 7 8 #include <stdint.h> 9 10 #include <functional> 11 #include <vector> 12 13 #include "common.h" 14 #include "enum_set.h" 15 #include "wcstringutil.h" 16 17 struct completion_mode_t { 18 /// If set, skip file completions. 19 bool no_files{false}; 20 bool force_files{false}; 21 22 /// If set, require a parameter after completion. 23 bool requires_param{false}; 24 }; 25 26 /// Character that separates the completion and description on programmable completions. 27 #define PROG_COMPLETE_SEP L'\t' 28 29 class environment_t; 30 31 enum { 32 /// Do not insert space afterwards if this is the only completion. (The default is to try insert 33 /// a space). 34 COMPLETE_NO_SPACE = 1 << 0, 35 /// This is not the suffix of a token, but replaces it entirely. 36 COMPLETE_REPLACES_TOKEN = 1 << 2, 37 /// This completion may or may not want a space at the end - guess by checking the last 38 /// character of the completion. 39 COMPLETE_AUTO_SPACE = 1 << 3, 40 /// This completion should be inserted as-is, without escaping. 41 COMPLETE_DONT_ESCAPE = 1 << 4, 42 /// If you do escape, don't escape tildes. 43 COMPLETE_DONT_ESCAPE_TILDES = 1 << 5, 44 /// Do not sort supplied completions 45 COMPLETE_DONT_SORT = 1 << 6, 46 /// This completion looks to have the same string as an existing argument. 47 COMPLETE_DUPLICATES_ARGUMENT = 1 << 7 48 }; 49 typedef int complete_flags_t; 50 51 /// std::function which accepts a completion string and returns its description. 52 using description_func_t = std::function<wcstring(const wcstring &)>; 53 54 /// Helper to return a description_func_t for a constant string. 55 description_func_t const_desc(const wcstring &s); 56 57 class completion_t { 58 private: 59 // No public default constructor. 60 completion_t(); 61 62 public: 63 // Destructor. Not inlining it saves code size. 64 ~completion_t(); 65 66 /// The completion string. 67 wcstring completion; 68 /// The description for this completion. 69 wcstring description; 70 /// The type of fuzzy match. 71 string_fuzzy_match_t match; 72 /// Flags determining the completion behavior. 73 /// 74 /// Determines whether a space should be inserted after this completion if it is the only 75 /// possible completion using the COMPLETE_NO_SPACE flag. The COMPLETE_NO_CASE can be used to 76 /// signal that this completion is case insensitive. 77 complete_flags_t flags; 78 79 // Construction. 80 explicit completion_t(wcstring comp, wcstring desc = wcstring(), 81 string_fuzzy_match_t match = string_fuzzy_match_t::exact_match(), 82 complete_flags_t flags_val = 0); 83 completion_t(const completion_t &); 84 completion_t &operator=(const completion_t &); 85 86 // noexcepts are required for push_back to use the move ctor. 87 completion_t(completion_t &&) noexcept; 88 completion_t &operator=(completion_t &&) noexcept; 89 90 // Compare two completions. No operating overlaoding to make this always explicit (there's 91 // potentially multiple ways to compare completions). 92 // 93 // "Naturally less than" means in a natural ordering, where digits are treated as numbers. For 94 // example, foo10 is naturally greater than foo2 (but alphabetically less than it). 95 static bool is_naturally_less_than(const completion_t &a, const completion_t &b); 96 97 /// \return the completion's match rank. Lower ranks are better completions. rank()98 uint32_t rank() const { return match.rank(); } 99 100 // If this completion replaces the entire token, prepend a prefix. Otherwise do nothing. 101 void prepend_token_prefix(const wcstring &prefix); 102 }; 103 104 using completion_list_t = std::vector<completion_t>; 105 106 enum class completion_request_t { 107 autosuggestion, // indicates the completion is for an autosuggestion 108 descriptions, // indicates that we want descriptions 109 fuzzy_match, // indicates that we don't require a prefix match 110 COUNT 111 }; 112 113 template <> 114 struct enum_info_t<completion_request_t> { 115 static constexpr auto count = completion_request_t::COUNT; 116 }; 117 118 using completion_request_flags_t = enum_set_t<completion_request_t>; 119 120 class completion_t; 121 using completion_list_t = std::vector<completion_t>; 122 123 /// A completion receiver accepts completions. It is essentially a wrapper around std::vector with 124 /// some conveniences. 125 class completion_receiver_t { 126 public: 127 /// Construct as empty, with a limit. 128 explicit completion_receiver_t(size_t limit) : limit_(limit) {} 129 130 /// Acquire an existing list, with a limit. 131 explicit completion_receiver_t(completion_list_t &&v, size_t limit) 132 : completions_(std::move(v)), limit_(limit) {} 133 134 /// Add a completion. 135 /// \return true on success, false if this would overflow the limit. 136 __warn_unused bool add(completion_t &&comp); 137 138 /// Add a completion with the given string, and default other properties. 139 /// \return true on success, false if this would overflow the limit. 140 __warn_unused bool add(wcstring &&comp); 141 142 /// Add a completion with the given string, description, flags, and fuzzy match. 143 /// \return true on success, false if this would overflow the limit. 144 /// The 'desc' parameter is not && because if gettext is not enabled, then we end 145 /// up passing a 'const wcstring &' here. 146 __warn_unused bool add(wcstring &&comp, wcstring desc, complete_flags_t flags = 0, 147 string_fuzzy_match_t match = string_fuzzy_match_t::exact_match()); 148 149 /// Add a list of completions. 150 /// \return true on success, false if this would overflow the limit. 151 __warn_unused bool add_list(completion_list_t &&lst); 152 153 /// Swap our completions with a new list. 154 void swap(completion_list_t &lst) { std::swap(completions_, lst); } 155 156 /// Clear the list of completions. This retains the storage inside completions_ which can be 157 /// useful to prevent allocations. 158 void clear() { completions_.clear(); } 159 160 /// \return whether our completion list is empty. 161 bool empty() const { return completions_.empty(); } 162 163 /// \return how many completions we have stored. 164 size_t size() const { return completions_.size(); } 165 166 /// \return a completion at an index. 167 completion_t &at(size_t idx) { return completions_.at(idx); } 168 const completion_t &at(size_t idx) const { return completions_.at(idx); } 169 170 /// \return the list of completions. Do not modify the size of the list via this function, as it 171 /// may exceed our completion limit. 172 const completion_list_t &get_list() const { return completions_; } 173 completion_list_t &get_list() { return completions_; } 174 175 /// \return the list of completions, clearing it. 176 completion_list_t take(); 177 178 /// \return a new, empty receiver whose limit is our remaining capacity. 179 /// This is useful for e.g. recursive calls when you want to act on the result before adding it. 180 completion_receiver_t subreceiver() const; 181 182 private: 183 // Our list of completions. 184 completion_list_t completions_; 185 186 // The maximum number of completions to add. If our list length exceeds this, then new 187 // completions are not added. Note 0 has no special significance here - use 188 // numeric_limits<size_t>::max() instead. 189 const size_t limit_; 190 }; 191 192 enum complete_option_type_t { 193 option_type_args_only, // no option 194 option_type_short, // -x 195 option_type_single_long, // -foo 196 option_type_double_long // --foo 197 }; 198 199 /// Sorts and remove any duplicate completions in the completion list, then puts them in priority 200 /// order. 201 void completions_sort_and_prioritize(completion_list_t *comps, 202 completion_request_flags_t flags = {}); 203 204 /// Add a completion. 205 /// 206 /// All supplied values are copied, they should be freed by or otherwise disposed by the caller. 207 /// 208 /// Examples: 209 /// 210 /// The command 'gcc -o' requires that a file follows it, so the NO_COMMON option is suitable. This 211 /// can be done using the following line: 212 /// 213 /// complete -c gcc -s o -r 214 /// 215 /// The command 'grep -d' required that one of the strings 'read', 'skip' or 'recurse' is used. As 216 /// such, it is suitable to specify that a completion requires one of them. This can be done using 217 /// the following line: 218 /// 219 /// complete -c grep -s d -x -a "read skip recurse" 220 /// 221 /// \param cmd Command to complete. 222 /// \param cmd_is_path If cmd_is_path is true, cmd will be interpreted as the absolute 223 /// path of the program (optionally containing wildcards), otherwise it 224 /// will be interpreted as the command name. 225 /// \param option The name of an option. 226 /// \param option_type The type of option: can be option_type_short (-x), 227 /// option_type_single_long (-foo), option_type_double_long (--bar). 228 /// \param result_mode Controls how to search further completions when this completion has been 229 /// successfully matched. 230 /// \param comp A space separated list of completions which may contain subshells. 231 /// \param desc A description of the completion. 232 /// \param condition a command to be run to check it this completion should be used. If \c condition 233 /// is empty, the completion is always used. 234 /// \param flags A set of completion flags 235 void complete_add(const wchar_t *cmd, bool cmd_is_path, const wcstring &option, 236 complete_option_type_t option_type, completion_mode_t result_mode, 237 const wchar_t *condition, const wchar_t *comp, const wchar_t *desc, int flags); 238 239 /// Remove a previously defined completion. 240 void complete_remove(const wcstring &cmd, bool cmd_is_path, const wcstring &option, 241 complete_option_type_t type); 242 243 /// Removes all completions for a given command. 244 void complete_remove_all(const wcstring &cmd, bool cmd_is_path); 245 246 /// \return all completions of the command cmd. 247 class operation_context_t; 248 completion_list_t complete(const wcstring &cmd, completion_request_flags_t flags, 249 const operation_context_t &ctx); 250 251 /// Return a list of all current completions. 252 wcstring complete_print(const wcstring &cmd = L""); 253 254 /// Tests if the specified option is defined for the specified command. 255 int complete_is_valid_option(const wcstring &str, const wcstring &opt, 256 wcstring_list_t *inErrorsOrNull, bool allow_autoload); 257 258 /// Tests if the specified argument is valid for the specified option and command. 259 bool complete_is_valid_argument(const wcstring &str, const wcstring &opt, const wcstring &arg); 260 261 /// Create a new completion entry. 262 /// 263 /// \param completions The array of completions to append to 264 /// \param comp The completion string 265 /// \param desc The description of the completion 266 /// \param flags completion flags 267 void append_completion(completion_list_t *completions, wcstring comp, wcstring desc = wcstring(), 268 int flags = 0, 269 string_fuzzy_match_t match = string_fuzzy_match_t::exact_match()); 270 271 /// Support for "wrap targets." A wrap target is a command that completes like another command. 272 bool complete_add_wrapper(const wcstring &command, const wcstring &new_target); 273 bool complete_remove_wrapper(const wcstring &command, const wcstring &target_to_remove); 274 275 /// Returns a list of wrap targets for a given command. 276 wcstring_list_t complete_get_wrap_targets(const wcstring &command); 277 278 // Observes that fish_complete_path has changed. 279 void complete_invalidate_path(); 280 281 #endif 282