2005-09-20 21:26:39 +08:00
|
|
|
/** \file history.h
|
|
|
|
Prototypes for history functions, part of the user interface.
|
|
|
|
*/
|
|
|
|
|
2005-10-04 23:11:39 +08:00
|
|
|
#ifndef FISH_HISTORY_H
|
|
|
|
#define FISH_HISTORY_H
|
|
|
|
|
|
|
|
#include <wchar.h>
|
2012-02-06 08:42:24 +08:00
|
|
|
#include "common.h"
|
|
|
|
#include "pthread.h"
|
|
|
|
#include <vector>
|
2012-02-06 14:30:42 +08:00
|
|
|
#include <deque>
|
|
|
|
#include <utility>
|
2012-02-16 03:33:41 +08:00
|
|
|
#include <list>
|
2012-02-06 08:42:24 +08:00
|
|
|
#include <tr1/memory>
|
2012-02-07 03:52:24 +08:00
|
|
|
#include <set>
|
2012-02-06 08:42:24 +08:00
|
|
|
using std::tr1::shared_ptr;
|
|
|
|
|
2012-02-16 03:33:41 +08:00
|
|
|
typedef std::list<wcstring> path_list_t;
|
|
|
|
|
2012-02-07 02:52:13 +08:00
|
|
|
enum history_search_type_t {
|
|
|
|
/** The history searches for strings containing the given string */
|
|
|
|
HISTORY_SEARCH_TYPE_CONTAINS,
|
|
|
|
|
|
|
|
/** The history searches for strings starting with the given string */
|
|
|
|
HISTORY_SEARCH_TYPE_PREFIX
|
|
|
|
};
|
|
|
|
|
2012-02-06 08:42:24 +08:00
|
|
|
class history_item_t {
|
|
|
|
friend class history_t;
|
|
|
|
|
|
|
|
private:
|
|
|
|
history_item_t(const wcstring &);
|
2012-02-16 03:33:41 +08:00
|
|
|
history_item_t(const wcstring &, time_t, const path_list_t &paths = path_list_t());
|
2012-02-06 08:42:24 +08:00
|
|
|
|
|
|
|
/** The actual contents of the entry */
|
|
|
|
wcstring contents;
|
|
|
|
|
|
|
|
/** Original creation time for the entry */
|
2012-02-06 12:54:41 +08:00
|
|
|
time_t creation_timestamp;
|
2012-02-06 08:42:24 +08:00
|
|
|
|
2012-02-16 03:33:41 +08:00
|
|
|
/** Paths that we require to be valid for this item to be autosuggested */
|
|
|
|
path_list_t required_paths;
|
|
|
|
|
2012-02-06 08:42:24 +08:00
|
|
|
public:
|
|
|
|
const wcstring &str() const { return contents; }
|
|
|
|
bool empty() const { return contents.empty(); }
|
2012-02-06 15:22:18 +08:00
|
|
|
|
2012-02-07 02:52:13 +08:00
|
|
|
/* Whether our contents matches a search term. */
|
|
|
|
bool matches_search(const wcstring &term, enum history_search_type_t type) const;
|
2012-02-06 15:22:18 +08:00
|
|
|
|
2012-02-06 12:54:41 +08:00
|
|
|
time_t timestamp() const { return creation_timestamp; }
|
|
|
|
|
|
|
|
bool write_to_file(FILE *f) const;
|
2012-02-06 08:42:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class history_t {
|
|
|
|
private:
|
|
|
|
/** No copying */
|
|
|
|
history_t(const history_t&);
|
|
|
|
history_t &operator=(const history_t&);
|
|
|
|
|
|
|
|
/** Private creator */
|
|
|
|
history_t(const wcstring &pname);
|
|
|
|
|
|
|
|
/** Destructor */
|
|
|
|
~history_t();
|
|
|
|
|
|
|
|
/** Lock for thread safety */
|
|
|
|
pthread_mutex_t lock;
|
|
|
|
|
|
|
|
/** The name of this list. Used for picking a suitable filename and for switching modes. */
|
|
|
|
const wcstring name;
|
|
|
|
|
|
|
|
/** New items. */
|
|
|
|
std::vector<history_item_t> new_items;
|
|
|
|
|
|
|
|
/** The mmaped region for the history file */
|
|
|
|
const char *mmap_start;
|
|
|
|
|
|
|
|
/** The size of the mmaped region */
|
|
|
|
size_t mmap_length;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Timestamp of last save
|
|
|
|
*/
|
|
|
|
time_t save_timestamp;
|
|
|
|
|
|
|
|
static history_item_t decode_item(const char *ptr, size_t len);
|
|
|
|
|
|
|
|
void populate_from_mmap(void);
|
|
|
|
|
|
|
|
/** List of old items, as offsets into out mmap data */
|
|
|
|
std::vector<size_t> old_item_offsets;
|
|
|
|
|
|
|
|
/** Whether we've loaded old items */
|
|
|
|
bool loaded_old;
|
|
|
|
|
|
|
|
/** Loads old if necessary */
|
|
|
|
void load_old_if_needed(void);
|
|
|
|
|
2012-02-06 12:54:41 +08:00
|
|
|
/** Saves history */
|
|
|
|
void save_internal();
|
|
|
|
|
2012-02-06 08:42:24 +08:00
|
|
|
public:
|
|
|
|
/** Returns history with the given name, creating it if necessary */
|
|
|
|
static history_t & history_with_name(const wcstring &name);
|
|
|
|
|
|
|
|
/** Add a new history item to the end */
|
2012-02-16 03:33:41 +08:00
|
|
|
void add(const wcstring &str, const path_list_t &valid_paths = path_list_t());
|
|
|
|
|
|
|
|
/** Add a new history item to the end */
|
|
|
|
void add_with_file_detection(const wcstring &str);
|
2012-02-06 08:42:24 +08:00
|
|
|
|
|
|
|
/** Saves history */
|
|
|
|
void save();
|
|
|
|
|
|
|
|
/** Return the specified history at the specified index. 0 is the index of the current commandline. */
|
|
|
|
history_item_t item_at_index(size_t idx);
|
|
|
|
};
|
|
|
|
|
|
|
|
class history_search_t {
|
|
|
|
|
|
|
|
/** The history in which we are searching */
|
|
|
|
history_t * history;
|
2012-02-06 14:30:42 +08:00
|
|
|
|
2012-02-07 02:52:13 +08:00
|
|
|
/** Our type */
|
|
|
|
enum history_search_type_t search_type;
|
|
|
|
|
2012-02-06 14:30:42 +08:00
|
|
|
/** Our list of previous matches as index, value. The end is the current match. */
|
|
|
|
typedef std::pair<size_t, wcstring> prev_match_t;
|
|
|
|
std::deque<prev_match_t> prev_matches;
|
|
|
|
|
|
|
|
/** Returns yes if a given term is in prev_matches. */
|
|
|
|
bool match_already_made(const wcstring &match) const;
|
2012-02-06 08:42:24 +08:00
|
|
|
|
|
|
|
/** The search term */
|
|
|
|
wcstring term;
|
2012-02-07 03:52:24 +08:00
|
|
|
|
|
|
|
/** Additional strings to skip (sorted) */
|
|
|
|
wcstring_list_t external_skips;
|
|
|
|
|
|
|
|
bool should_skip_match(const wcstring &str) const;
|
|
|
|
|
2012-02-06 14:30:42 +08:00
|
|
|
public:
|
2012-02-06 08:42:24 +08:00
|
|
|
|
2012-02-07 03:52:24 +08:00
|
|
|
/** Sets additional string matches to skip */
|
|
|
|
void skip_matches(const wcstring_list_t &skips);
|
|
|
|
|
2012-02-06 08:42:24 +08:00
|
|
|
/** Finds the next search term (forwards in time). Returns true if one was found. */
|
|
|
|
bool go_forwards(void);
|
|
|
|
|
|
|
|
/** Finds the previous search result (backwards in time). Returns true if one was found. */
|
|
|
|
bool go_backwards(void);
|
|
|
|
|
|
|
|
/** Goes to the end (forwards) */
|
|
|
|
void go_to_end(void);
|
|
|
|
|
2012-02-06 15:22:18 +08:00
|
|
|
/** Returns if we are at the end. We start out at the end. */
|
|
|
|
bool is_at_end(void) const;
|
|
|
|
|
2012-02-06 08:42:24 +08:00
|
|
|
/** Goes to the beginning (backwards) */
|
|
|
|
void go_to_beginning(void);
|
|
|
|
|
|
|
|
/** Returns the current search result. asserts if there is no current item. */
|
2012-02-06 14:30:42 +08:00
|
|
|
wcstring current_item(void) const;
|
2012-02-06 08:42:24 +08:00
|
|
|
|
|
|
|
/** Constructor */
|
2012-02-07 02:52:13 +08:00
|
|
|
history_search_t(history_t &hist, const wcstring &str, enum history_search_type_t type = HISTORY_SEARCH_TYPE_CONTAINS) :
|
2012-02-06 08:42:24 +08:00
|
|
|
history(&hist),
|
2012-02-07 02:52:13 +08:00
|
|
|
search_type(type),
|
2012-02-06 14:30:42 +08:00
|
|
|
term(str)
|
2012-02-06 12:54:41 +08:00
|
|
|
{}
|
2012-02-06 08:42:24 +08:00
|
|
|
|
|
|
|
/* Default constructor */
|
|
|
|
history_search_t() :
|
|
|
|
history(),
|
2012-02-07 02:52:13 +08:00
|
|
|
search_type(HISTORY_SEARCH_TYPE_CONTAINS),
|
2012-02-06 14:30:42 +08:00
|
|
|
term()
|
2012-02-06 12:54:41 +08:00
|
|
|
{}
|
2012-02-06 08:42:24 +08:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-10-04 23:11:39 +08:00
|
|
|
|
2005-09-20 21:26:39 +08:00
|
|
|
/**
|
2006-02-06 23:08:10 +08:00
|
|
|
Init history library. The history file won't actually be loaded
|
|
|
|
until the first time a history search is performed.
|
2005-09-20 21:26:39 +08:00
|
|
|
*/
|
|
|
|
void history_init();
|
|
|
|
|
|
|
|
/**
|
2012-02-06 08:42:24 +08:00
|
|
|
Saves the new history to disc.
|
2005-09-20 21:26:39 +08:00
|
|
|
*/
|
|
|
|
void history_destroy();
|
|
|
|
|
|
|
|
/**
|
|
|
|
Perform sanity checks
|
|
|
|
*/
|
|
|
|
void history_sanity_check();
|
|
|
|
|
2005-10-04 23:11:39 +08:00
|
|
|
#endif
|