diff --git a/src/history.h b/src/history.h index 2877f273b..5073bce1b 100644 --- a/src/history.h +++ b/src/history.h @@ -26,42 +26,43 @@ class env_stack_t; class environment_t; class operation_context_t; -// Fish supports multiple shells writing to history at once. Here is its strategy: -// -// 1. All history files are append-only. Data, once written, is never modified. -// -// 2. A history file may be re-written ("vacuumed"). This involves reading in the file and writing a -// new one, while performing maintenance tasks: discarding items in an LRU fashion until we reach -// the desired maximum count, removing duplicates, and sorting them by timestamp (eventually, not -// implemented yet). The new file is atomically moved into place via rename(). -// -// 3. History files are mapped in via mmap(). Before the file is mapped, the file takes a fcntl read -// lock. The purpose of this lock is to avoid seeing a transient state where partial data has been -// written to the file. -// -// 4. History is appended to under a fcntl write lock. -// -// 5. The chaos_mode boolean can be set to true to do things like lower buffer sizes which can -// trigger race conditions. This is useful for testing. +/** +Fish supports multiple shells writing to history at once. Here is its strategy: -typedef std::vector path_list_t; +1. All history files are append-only. Data, once written, is never modified. + +2. A history file may be re-written ("vacuumed"). This involves reading in the file and writing a +new one, while performing maintenance tasks: discarding items in an LRU fashion until we reach +the desired maximum count, removing duplicates, and sorting them by timestamp (eventually, not +implemented yet). The new file is atomically moved into place via rename(). + +3. History files are mapped in via mmap(). Before the file is mapped, the file takes a fcntl read +lock. The purpose of this lock is to avoid seeing a transient state where partial data has been +written to the file. + +4. History is appended to under a fcntl write lock. + +5. The chaos_mode boolean can be set to true to do things like lower buffer sizes which can +trigger race conditions. This is useful for testing. +*/ +using path_list_t = std::vector; enum class history_search_type_t { - // Search for commands exactly matching the given string. + /// Search for commands exactly matching the given string. exact, - // Search for commands containing the given string. + /// Search for commands containing the given string. contains, - // Search for commands starting with the given string. + /// Search for commands starting with the given string. prefix, - // Search for commands containing the given glob pattern. + /// Search for commands containing the given glob pattern. contains_glob, - // Search for commands starting with the given glob pattern. + /// Search for commands starting with the given glob pattern. prefix_glob, - // Matches everything. + /// Matches everything. match_everything, }; -typedef uint64_t history_identifier_t; +using history_identifier_t = uint64_t; /// Ways that a history item may be written to disk (or omitted). enum class history_persistence_mode_t : uint8_t { @@ -73,7 +74,7 @@ enum class history_persistence_mode_t : uint8_t { class history_item_t { public: /// Construct from a text, timestamp, and optional identifier. - /// If \p no_persist is set, then do not write this item to disk. + /// If \p persist_mode is ::ephemeral, then do not write this item to disk. explicit history_item_t( wcstring str = {}, time_t when = 0, history_identifier_t ident = 0, history_persistence_mode_t persist_mode = history_persistence_mode_t::disk); @@ -84,7 +85,7 @@ class history_item_t { /// \return whether the text is empty. bool empty() const { return contents.empty(); } - // \return wehther our contents matches a search term. + /// \return wehther our contents matches a search term. bool matches_search(const wcstring &term, enum history_search_type_t type, bool case_sensitive) const; @@ -100,22 +101,22 @@ class history_item_t { void set_required_paths(path_list_t paths) { required_paths = std::move(paths); } private: - // Attempts to merge two compatible history items together. + /// Attempts to merge two compatible history items together. bool merge(const history_item_t &item); - // The actual contents of the entry. + /// The actual contents of the entry. wcstring contents; - // Original creation time for the entry. + /// Original creation time for the entry. time_t creation_timestamp; - // Paths that we require to be valid for this item to be autosuggested. + /// Paths that we require to be valid for this item to be autosuggested. path_list_t required_paths; - // Sometimes unique identifier used for hinting. + /// Sometimes unique identifier used for hinting. history_identifier_t identifier; - // If set, do not write this item to disk. + /// If set, do not write this item to disk. history_persistence_mode_t persist_mode; friend class history_t; @@ -124,7 +125,7 @@ class history_item_t { friend class history_tests_t; }; -typedef std::deque history_item_list_t; +using history_item_list_t = std::deque; struct history_impl_t; @@ -136,98 +137,98 @@ class history_t : noncopyable_t, nonmovable_t { acquired_lock impl(); acquired_lock impl() const; - // Privately add an item. If pending, the item will not be returned by history searches until a - // call to resolve_pending. Any trailing ephemeral items are dropped. + /// Privately add an item. If pending, the item will not be returned by history searches until a + /// call to resolve_pending. Any trailing ephemeral items are dropped. void add(history_item_t &&item, bool pending = false); - // Add a new history item with text \p str to the end of history. + /// Add a new history item with text \p str to the end of history. void add(wcstring str); public: explicit history_t(wcstring name); ~history_t(); - // Whether we're in maximum chaos mode, useful for testing. - // This causes things like locks to fail. + /// Whether we're in maximum chaos mode, useful for testing. + /// This causes things like locks to fail. static bool chaos_mode; - // Whether to force the read path instead of mmap. This is useful for testing. + /// Whether to force the read path instead of mmap. This is useful for testing. static bool never_mmap; - // Returns history with the given name, creating it if necessary. + /// Returns history with the given name, creating it if necessary. static std::shared_ptr with_name(const wcstring &name); /// Returns whether this is using the default name. bool is_default() const; - // Determines whether the history is empty. Unfortunately this cannot be const, since it may - // require populating the history. + /// Determines whether the history is empty. Unfortunately this cannot be const, since it may + /// require populating the history. bool is_empty(); - // Remove a history item. + /// Remove a history item. void remove(const wcstring &str); /// Remove any trailing ephemeral items. void remove_ephemeral_items(); - // Add a new pending history item to the end, and then begin file detection on the items to - // determine which arguments are paths. Arguments may be expanded (e.g. with PWD and variables) - // using the given \p vars. The item has the given \p persist_mode. + /// Add a new pending history item to the end, and then begin file detection on the items to + /// determine which arguments are paths. Arguments may be expanded (e.g. with PWD and variables) + /// using the given \p vars. The item has the given \p persist_mode. static void add_pending_with_file_detection( const std::shared_ptr &self, const wcstring &str, const std::shared_ptr &vars, history_persistence_mode_t persist_mode = history_persistence_mode_t::disk); - // Resolves any pending history items, so that they may be returned in history searches. + /// Resolves any pending history items, so that they may be returned in history searches. void resolve_pending(); - // Saves history. + /// Saves history. void save(); - // Searches history. + /// Searches history. bool search(history_search_type_t search_type, const wcstring_list_t &search_args, const wchar_t *show_time_format, size_t max_items, bool case_sensitive, bool null_terminate, bool reverse, const cancel_checker_t &cancel_check, io_streams_t &streams); - // Irreversibly clears history. + /// Irreversibly clears history. void clear(); - // Irreversibly clears history for the current session. + /// Irreversibly clears history for the current session. void clear_session(); - // Populates from older location (in config path, rather than data path). + /// Populates from older location (in config path, rather than data path). void populate_from_config_path(); - // Populates from a bash history file. + /// Populates from a bash history file. void populate_from_bash(FILE *f); - // Incorporates the history of other shells into this history. + /// Incorporates the history of other shells into this history. void incorporate_external_changes(); - // Gets all the history into a list. This is intended for the $history environment variable. - // This may be long! + /// Gets all the history into a list. This is intended for the $history environment variable. + /// This may be long! void get_history(wcstring_list_t &result); - // Let indexes be a list of one-based indexes into the history, matching the interpretation of - // $history. That is, $history[1] is the most recently executed command. Values less than one - // are skipped. Return a mapping from index to history item text. + /// Let indexes be a list of one-based indexes into the history, matching the interpretation of + /// $history. That is, $history[1] is the most recently executed command. Values less than one + /// are skipped. Return a mapping from index to history item text. std::unordered_map items_at_indexes(const std::vector &idxs); - // Return the specified history at the specified index. 0 is the index of the current - // commandline. (So the most recent item is at index 1.) + /// Return the specified history at the specified index. 0 is the index of the current + /// commandline. (So the most recent item is at index 1.) history_item_t item_at_index(size_t idx); - // Return the number of history entries. + /// Return the number of history entries. size_t size(); }; /// Flags for history searching. enum { - // If set, ignore case. + /// If set, ignore case. history_search_ignore_case = 1 << 0, - // If set, do not deduplicate, which can help performance. + /// If set, do not deduplicate, which can help performance. history_search_no_dedup = 1 << 1 }; using history_search_flags_t = uint32_t; @@ -236,52 +237,52 @@ using history_search_flags_t = uint32_t; /// Note this does NOT de-duplicate; it is the caller's responsibility to do so. class history_search_t { private: - // The history in which we are searching. - // TODO: this should be a shared_ptr. + /// The history in which we are searching. + /// TODO: this should be a shared_ptr. history_t *history_; - // The original search term. + /// The original search term. wcstring orig_term_; - // The (possibly lowercased) search term. + /// The (possibly lowercased) search term. wcstring canon_term_; - // Our search type. + /// Our search type. enum history_search_type_t search_type_ { history_search_type_t::contains }; - // Our flags. + /// Our flags. history_search_flags_t flags_{0}; - // The current history item. + /// The current history item. maybe_t current_item_; - // Index of the current history item. + /// Index of the current history item. size_t current_index_{0}; - // If deduping, the items we've seen. + /// If deduping, the items we've seen. std::unordered_set deduper_; - // return whether we are case insensitive. + /// return whether we are case insensitive. bool ignores_case() const { return flags_ & history_search_ignore_case; } - // return whether we deduplicate items. + /// return whether we deduplicate items. bool dedup() const { return !(flags_ & history_search_no_dedup); } public: - // Gets the original search term. + /// Gets the original search term. const wcstring &original_term() const { return orig_term_; } - // Finds the previous search result (backwards in time). Returns true if one was found. + /// Finds the previous search result (backwards in time). Returns true if one was found. bool go_backwards(); - // Returns the current search result item. asserts if there is no current item. + /// Returns the current search result item. asserts if there is no current item. const history_item_t ¤t_item() const; - // Returns the current search result item contents. asserts if there is no current item. + /// Returns the current search result item contents. asserts if there is no current item. const wcstring ¤t_string() const; - // Construct from a history pointer; the caller is responsible for ensuring the history stays - // alive. + /// Construct from a history pointer; the caller is responsible for ensuring the history stays + /// alive. history_search_t(history_t *hist, const wcstring &str, enum history_search_type_t type = history_search_type_t::contains, history_search_flags_t flags = 0) @@ -291,39 +292,43 @@ class history_search_t { } } - // Construct from a shared_ptr. TODO: this should be the only constructor. + /// Construct from a shared_ptr. TODO: this should be the only constructor. history_search_t(const std::shared_ptr &hist, const wcstring &str, enum history_search_type_t type = history_search_type_t::contains, history_search_flags_t flags = 0) : history_search_t(hist.get(), str, type, flags) {} - // Default constructor. + /** Default constructor. */ history_search_t() = default; }; -/// Saves the new history to disk. +/** Saves the new history to disk. */ void history_save_all(); -/// Return the prefix for the files to be used for command and read history. +/** Return the prefix for the files to be used for command and read history. */ wcstring history_session_id(const environment_t &vars); -/// Given a list of proposed paths and a context, perform variable and home directory expansion, -/// and detect if the result expands to a value which is also the path to a file. -/// Wildcard expansions are suppressed - see implementation comments for why. -/// This is used for autosuggestion hinting. If we add an item to history, and one of its arguments -/// refers to a file, then we only want to suggest it if there is a valid file there. -/// This does disk I/O and may only be called in a background thread. +/** + Given a list of proposed paths and a context, perform variable and home directory expansion, + and detect if the result expands to a value which is also the path to a file. + Wildcard expansions are suppressed - see implementation comments for why. + This is used for autosuggestion hinting. If we add an item to history, and one of its arguments + refers to a file, then we only want to suggest it if there is a valid file there. + This does disk I/O and may only be called in a background thread. +*/ path_list_t expand_and_detect_paths(const path_list_t &paths, const environment_t &vars); -/// Given a list of proposed paths and a context, expand each one and see if it refers to a file. -/// Wildcard expansions are suppressed. -/// \return true if \p paths is empty or every path is valid. +/** + Given a list of proposed paths and a context, expand each one and see if it refers to a file. + Wildcard expansions are suppressed. + \return true if \p paths is empty or every path is valid. +*/ bool all_paths_are_valid(const path_list_t &paths, const operation_context_t &ctx); -/// Sets private mode on. Once in private mode, it cannot be turned off. +/** Sets private mode on. Once in private mode, it cannot be turned off. */ void start_private_mode(env_stack_t &vars); -/// Queries private mode status. +/** Queries private mode status. */ bool in_private_mode(const environment_t &vars); #endif