mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-25 09:39:52 +08:00
restyle pager & lru module to match project style
Reduces lint errors from 65 to 25 (-63%). Line count from 1439 to 1218 (-15%). Another step in resolving issue #2902.
This commit is contained in:
parent
ed8d1040ba
commit
13d7432368
239
src/lru.h
239
src/lru.h
|
@ -1,257 +1,198 @@
|
|||
/** \file lru.h
|
||||
|
||||
Least-recently-used cache implementation
|
||||
*/
|
||||
// Least-recently-used cache implementation.
|
||||
#ifndef FISH_LRU_H
|
||||
#define FISH_LRU_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <wchar.h>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <list>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/** A predicate to compare dereferenced pointers */
|
||||
struct dereference_less_t
|
||||
{
|
||||
/// A predicate to compare dereferenced pointers.
|
||||
struct dereference_less_t {
|
||||
template <typename ptr_t>
|
||||
bool operator()(ptr_t p1, ptr_t p2) const
|
||||
{
|
||||
bool operator()(ptr_t p1, ptr_t p2) const {
|
||||
return *p1 < *p2;
|
||||
}
|
||||
};
|
||||
|
||||
class lru_node_t
|
||||
{
|
||||
template<class T> friend class lru_cache_t;
|
||||
class lru_node_t {
|
||||
template <class T>
|
||||
friend class lru_cache_t;
|
||||
|
||||
/** Our linked list pointer */
|
||||
/// Our linked list pointer.
|
||||
lru_node_t *prev, *next;
|
||||
|
||||
public:
|
||||
/** The key used to look up in the cache */
|
||||
public:
|
||||
/// The key used to look up in the cache.
|
||||
const wcstring key;
|
||||
|
||||
/** Constructor */
|
||||
explicit lru_node_t(const wcstring &pkey) : prev(NULL), next(NULL), key(pkey) { }
|
||||
/// Constructor.
|
||||
explicit lru_node_t(const wcstring &pkey) : prev(NULL), next(NULL), key(pkey) {}
|
||||
|
||||
/** Virtual destructor that does nothing for classes that inherit lru_node_t */
|
||||
/// Virtual destructor that does nothing for classes that inherit lru_node_t.
|
||||
virtual ~lru_node_t() {}
|
||||
|
||||
/** operator< for std::set */
|
||||
bool operator<(const lru_node_t &other) const
|
||||
{
|
||||
return key < other.key;
|
||||
}
|
||||
/// operator< for std::set
|
||||
bool operator<(const lru_node_t &other) const { return key < other.key; }
|
||||
};
|
||||
|
||||
template<class node_type_t>
|
||||
class lru_cache_t
|
||||
{
|
||||
private:
|
||||
|
||||
/** Max node count. This may be (transiently) exceeded by add_node_without_eviction, which is used from background threads. */
|
||||
template <class node_type_t>
|
||||
class lru_cache_t {
|
||||
private:
|
||||
/// Max node count. This may be (transiently) exceeded by add_node_without_eviction, which is
|
||||
/// used from background threads.
|
||||
const size_t max_node_count;
|
||||
|
||||
/** Count of nodes */
|
||||
/// Count of nodes.
|
||||
size_t node_count;
|
||||
|
||||
/** The set of nodes */
|
||||
/// The set of nodes.
|
||||
typedef std::set<lru_node_t *, dereference_less_t> node_set_t;
|
||||
node_set_t node_set;
|
||||
|
||||
void promote_node(node_type_t *node)
|
||||
{
|
||||
/* We should never promote the mouth */
|
||||
void promote_node(node_type_t *node) {
|
||||
// We should never promote the mouth.
|
||||
assert(node != &mouth);
|
||||
|
||||
/* First unhook us */
|
||||
// First unhook us.
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
|
||||
/* Put us after the mouth */
|
||||
// Put us after the mouth.
|
||||
node->next = mouth.next;
|
||||
node->next->prev = node;
|
||||
node->prev = &mouth;
|
||||
mouth.next = node;
|
||||
}
|
||||
|
||||
void evict_node(node_type_t *condemned_node)
|
||||
{
|
||||
/* We should never evict the mouth */
|
||||
void evict_node(node_type_t *condemned_node) {
|
||||
// We should never evict the mouth.
|
||||
assert(condemned_node != NULL && condemned_node != &mouth);
|
||||
|
||||
/* Remove it from the linked list */
|
||||
// Remove it from the linked list.
|
||||
condemned_node->prev->next = condemned_node->next;
|
||||
condemned_node->next->prev = condemned_node->prev;
|
||||
|
||||
/* Remove us from the set */
|
||||
// Remove us from the set.
|
||||
node_set.erase(condemned_node);
|
||||
node_count--;
|
||||
|
||||
/* Tell ourselves */
|
||||
// Tell ourselves.
|
||||
this->node_was_evicted(condemned_node);
|
||||
}
|
||||
|
||||
void evict_last_node(void)
|
||||
{
|
||||
/* Simple */
|
||||
evict_node((node_type_t *)mouth.prev);
|
||||
}
|
||||
void evict_last_node(void) { evict_node((node_type_t *)mouth.prev); }
|
||||
|
||||
static lru_node_t *get_previous(lru_node_t *node)
|
||||
{
|
||||
return node->prev;
|
||||
}
|
||||
static lru_node_t *get_previous(lru_node_t *node) { return node->prev; }
|
||||
|
||||
protected:
|
||||
|
||||
/** Head of the linked list */
|
||||
protected:
|
||||
/// Head of the linked list.
|
||||
lru_node_t mouth;
|
||||
|
||||
/** Overridable callback for when a node is evicted */
|
||||
virtual void node_was_evicted(node_type_t *node) { }
|
||||
/// Overridable callback for when a node is evicted.
|
||||
virtual void node_was_evicted(node_type_t *node) {}
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor */
|
||||
explicit lru_cache_t(size_t max_size = 1024) : max_node_count(max_size), node_count(0), mouth(wcstring())
|
||||
{
|
||||
/* Hook up the mouth to itself: a one node circularly linked list! */
|
||||
public:
|
||||
/// Constructor
|
||||
explicit lru_cache_t(size_t max_size = 1024)
|
||||
: max_node_count(max_size), node_count(0), mouth(wcstring()) {
|
||||
// Hook up the mouth to itself: a one node circularly linked list!
|
||||
mouth.prev = mouth.next = &mouth;
|
||||
}
|
||||
|
||||
/** Note that we do not evict nodes in our destructor (even though they typically need to be deleted by their creator). */
|
||||
virtual ~lru_cache_t() { }
|
||||
/// Note that we do not evict nodes in our destructor (even though they typically need to be
|
||||
/// deleted by their creator).
|
||||
virtual ~lru_cache_t() {}
|
||||
|
||||
|
||||
/** Returns the node for a given key, or NULL */
|
||||
node_type_t *get_node(const wcstring &key)
|
||||
{
|
||||
/// Returns the node for a given key, or NULL.
|
||||
node_type_t *get_node(const wcstring &key) {
|
||||
node_type_t *result = NULL;
|
||||
|
||||
/* Construct a fake node as our key */
|
||||
// Construct a fake node as our key.
|
||||
lru_node_t node_key(key);
|
||||
|
||||
/* Look for it in the set */
|
||||
// Look for it in the set.
|
||||
node_set_t::iterator iter = node_set.find(&node_key);
|
||||
|
||||
/* If we found a node, promote and return it */
|
||||
if (iter != node_set.end())
|
||||
{
|
||||
result = static_cast<node_type_t*>(*iter);
|
||||
// If we found a node, promote and return it.
|
||||
if (iter != node_set.end()) {
|
||||
result = static_cast<node_type_t *>(*iter);
|
||||
promote_node(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Evicts the node for a given key, returning true if a node was evicted. */
|
||||
bool evict_node(const wcstring &key)
|
||||
{
|
||||
/* Construct a fake node as our key */
|
||||
/// Evicts the node for a given key, returning true if a node was evicted.
|
||||
bool evict_node(const wcstring &key) {
|
||||
// Construct a fake node as our key.
|
||||
lru_node_t node_key(key);
|
||||
|
||||
/* Look for it in the set */
|
||||
// Look for it in the set.
|
||||
node_set_t::iterator iter = node_set.find(&node_key);
|
||||
if (iter == node_set.end())
|
||||
return false;
|
||||
if (iter == node_set.end()) return false;
|
||||
|
||||
/* Evict the given node */
|
||||
evict_node(static_cast<node_type_t*>(*iter));
|
||||
// Evict the given node.
|
||||
evict_node(static_cast<node_type_t *>(*iter));
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Adds a node under the given key. Returns true if the node was added, false if the node was not because a node with that key is already in the set. */
|
||||
bool add_node(node_type_t *node)
|
||||
{
|
||||
/* Add our node without eviction */
|
||||
if (! this->add_node_without_eviction(node))
|
||||
return false;
|
||||
/// Adds a node under the given key. Returns true if the node was added, false if the node was
|
||||
/// not because a node with that key is already in the set.
|
||||
bool add_node(node_type_t *node) {
|
||||
// Add our node without eviction.
|
||||
if (!this->add_node_without_eviction(node)) return false;
|
||||
|
||||
/* Evict */
|
||||
while (node_count > max_node_count)
|
||||
evict_last_node();
|
||||
|
||||
/* Success */
|
||||
while (node_count > max_node_count) evict_last_node(); // evict
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Adds a node under the given key without triggering eviction. Returns true if the node was added, false if the node was not because a node with that key is already in the set. */
|
||||
bool add_node_without_eviction(node_type_t *node)
|
||||
{
|
||||
/// Adds a node under the given key without triggering eviction. Returns true if the node was
|
||||
/// added, false if the node was not because a node with that key is already in the set.
|
||||
bool add_node_without_eviction(node_type_t *node) {
|
||||
assert(node != NULL && node != &mouth);
|
||||
|
||||
/* Try inserting; return false if it was already in the set */
|
||||
if (! node_set.insert(node).second)
|
||||
return false;
|
||||
// Try inserting; return false if it was already in the set.
|
||||
if (!node_set.insert(node).second) return false;
|
||||
|
||||
/* Add the node after the mouth */
|
||||
// Add the node after the mouth.
|
||||
node->next = mouth.next;
|
||||
node->next->prev = node;
|
||||
node->prev = &mouth;
|
||||
mouth.next = node;
|
||||
|
||||
/* Update the count. This may push us over the maximum node count. */
|
||||
// Update the count. This may push us over the maximum node count.
|
||||
node_count++;
|
||||
|
||||
/* Success */
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Counts nodes */
|
||||
size_t size(void)
|
||||
{
|
||||
return node_count;
|
||||
}
|
||||
/// Counts nodes.
|
||||
size_t size(void) { return node_count; }
|
||||
|
||||
/** Evicts all nodes */
|
||||
void evict_all_nodes(void)
|
||||
{
|
||||
while (node_count > 0)
|
||||
{
|
||||
/// Evicts all nodes.
|
||||
void evict_all_nodes(void) {
|
||||
while (node_count > 0) {
|
||||
evict_last_node();
|
||||
}
|
||||
}
|
||||
|
||||
/** Iterator for walking nodes, from least recently used to most */
|
||||
class iterator
|
||||
{
|
||||
/// Iterator for walking nodes, from least recently used to most.
|
||||
class iterator {
|
||||
lru_node_t *node;
|
||||
public:
|
||||
explicit iterator(lru_node_t *val) : node(val) { }
|
||||
void operator++()
|
||||
{
|
||||
node = lru_cache_t::get_previous(node);
|
||||
}
|
||||
void operator++(int x)
|
||||
{
|
||||
node = lru_cache_t::get_previous(node);
|
||||
}
|
||||
bool operator==(const iterator &other)
|
||||
{
|
||||
return node == other.node;
|
||||
}
|
||||
bool operator!=(const iterator &other)
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
node_type_t *operator*()
|
||||
{
|
||||
return static_cast<node_type_t *>(node);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit iterator(lru_node_t *val) : node(val) {}
|
||||
void operator++() { node = lru_cache_t::get_previous(node); }
|
||||
void operator++(int x) { node = lru_cache_t::get_previous(node); }
|
||||
bool operator==(const iterator &other) { return node == other.node; }
|
||||
bool operator!=(const iterator &other) { return !(*this == other); }
|
||||
node_type_t *operator*() { return static_cast<node_type_t *>(node); }
|
||||
};
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(mouth.prev);
|
||||
}
|
||||
iterator end()
|
||||
{
|
||||
return iterator(&mouth);
|
||||
}
|
||||
iterator begin() { return iterator(mouth.prev); }
|
||||
iterator end() { return iterator(&mouth); }
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
927
src/pager.cpp
927
src/pager.cpp
File diff suppressed because it is too large
Load Diff
137
src/pager.h
137
src/pager.h
|
@ -1,26 +1,23 @@
|
|||
/** \file pager.h
|
||||
Pager support
|
||||
*/
|
||||
// Pager support.
|
||||
#ifndef FISH_PAGER_H
|
||||
#define FISH_PAGER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "complete.h"
|
||||
#include "screen.h"
|
||||
#include "reader.h"
|
||||
#include "screen.h"
|
||||
|
||||
#define PAGER_SELECTION_NONE ((size_t)(-1))
|
||||
|
||||
/* Represents rendering from the pager */
|
||||
class page_rendering_t
|
||||
{
|
||||
public:
|
||||
/// Represents rendering from the pager.
|
||||
class page_rendering_t {
|
||||
public:
|
||||
int term_width;
|
||||
int term_height;
|
||||
size_t rows;
|
||||
|
@ -35,144 +32,148 @@ public:
|
|||
bool search_field_shown;
|
||||
editable_line_t search_field_line;
|
||||
|
||||
/* Returns a rendering with invalid data, useful to indicate "no rendering" */
|
||||
// Returns a rendering with invalid data, useful to indicate "no rendering".
|
||||
page_rendering_t();
|
||||
};
|
||||
|
||||
/* The space between adjacent completions */
|
||||
// The space between adjacent completions.
|
||||
#define PAGER_SPACER_STRING L" "
|
||||
#define PAGER_SPACER_STRING_WIDTH 2
|
||||
|
||||
/* How many rows we will show in the "initial" pager */
|
||||
// How many rows we will show in the "initial" pager.
|
||||
#define PAGER_UNDISCLOSED_MAX_ROWS 4
|
||||
|
||||
typedef std::vector<completion_t> completion_list_t;
|
||||
page_rendering_t render_completions(const completion_list_t &raw_completions, const wcstring &prefix);
|
||||
page_rendering_t render_completions(const completion_list_t &raw_completions,
|
||||
const wcstring &prefix);
|
||||
|
||||
class pager_t
|
||||
{
|
||||
class pager_t {
|
||||
int available_term_width;
|
||||
int available_term_height;
|
||||
|
||||
size_t selected_completion_idx;
|
||||
size_t suggested_row_start;
|
||||
|
||||
/* Fully disclosed means that we show all completions */
|
||||
// Fully disclosed means that we show all completions.
|
||||
bool fully_disclosed;
|
||||
|
||||
/* Whether we show the search field */
|
||||
// Whether we show the search field.
|
||||
bool search_field_shown;
|
||||
|
||||
/* Returns the index of the completion that should draw selected, using the given number of columns */
|
||||
// Returns the index of the completion that should draw selected, using the given number of
|
||||
// columns.
|
||||
size_t visual_selected_completion_index(size_t rows, size_t cols) const;
|
||||
|
||||
/** Data structure describing one or a group of related completions */
|
||||
public:
|
||||
struct comp_t
|
||||
{
|
||||
/** The list of all completin strings this entry applies to */
|
||||
public:
|
||||
/// Data structure describing one or a group of related completions.
|
||||
struct comp_t {
|
||||
/// The list of all completin strings this entry applies to.
|
||||
wcstring_list_t comp;
|
||||
|
||||
/** The description */
|
||||
/// The description.
|
||||
wcstring desc;
|
||||
|
||||
/** The representative completion */
|
||||
/// The representative completion.
|
||||
completion_t representative;
|
||||
|
||||
/** On-screen width of the completion string */
|
||||
/// On-screen width of the completion string.
|
||||
int comp_width;
|
||||
|
||||
/** On-screen width of the description information */
|
||||
/// On-screen width of the description information.
|
||||
int desc_width;
|
||||
|
||||
/** Preferred total width */
|
||||
/// Preferred total width.
|
||||
int pref_width;
|
||||
|
||||
/** Minimum acceptable width */
|
||||
/// Minimum acceptable width.
|
||||
int min_width;
|
||||
|
||||
comp_t() : comp(), desc(), representative(L""), comp_width(0), desc_width(0), pref_width(0), min_width(0)
|
||||
{
|
||||
}
|
||||
comp_t()
|
||||
: comp(),
|
||||
desc(),
|
||||
representative(L""),
|
||||
comp_width(0),
|
||||
desc_width(0),
|
||||
pref_width(0),
|
||||
min_width(0) {}
|
||||
};
|
||||
|
||||
private:
|
||||
private:
|
||||
typedef std::vector<comp_t> comp_info_list_t;
|
||||
|
||||
/* The filtered list of completion infos */
|
||||
// The filtered list of completion infos.
|
||||
comp_info_list_t completion_infos;
|
||||
|
||||
/* The unfiltered list. Note there's a lot of duplication here. */
|
||||
// The unfiltered list. Note there's a lot of duplication here.
|
||||
comp_info_list_t unfiltered_completion_infos;
|
||||
|
||||
wcstring prefix;
|
||||
|
||||
bool completion_try_print(size_t cols, const wcstring &prefix, const comp_info_list_t &lst, page_rendering_t *rendering, size_t suggested_start_row) const;
|
||||
bool completion_try_print(size_t cols, const wcstring &prefix, const comp_info_list_t &lst,
|
||||
page_rendering_t *rendering, size_t suggested_start_row) const;
|
||||
|
||||
void recalc_min_widths(comp_info_list_t * lst) const;
|
||||
void recalc_min_widths(comp_info_list_t *lst) const;
|
||||
void measure_completion_infos(std::vector<comp_t> *infos, const wcstring &prefix) const;
|
||||
|
||||
bool completion_info_passes_filter(const comp_t &info) const;
|
||||
|
||||
void completion_print(size_t cols, int *width_per_column, size_t row_start, size_t row_stop, const wcstring &prefix, const comp_info_list_t &lst, page_rendering_t *rendering) const;
|
||||
line_t completion_print_item(const wcstring &prefix, const comp_t *c, size_t row, size_t column, int width, bool secondary, bool selected, page_rendering_t *rendering) const;
|
||||
void completion_print(size_t cols, int *width_per_column, size_t row_start, size_t row_stop,
|
||||
const wcstring &prefix, const comp_info_list_t &lst,
|
||||
page_rendering_t *rendering) const;
|
||||
line_t completion_print_item(const wcstring &prefix, const comp_t *c, size_t row, size_t column,
|
||||
int width, bool secondary, bool selected,
|
||||
page_rendering_t *rendering) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/* The text of the search field */
|
||||
public:
|
||||
// The text of the search field.
|
||||
editable_line_t search_field_line;
|
||||
|
||||
/* Sets the set of completions */
|
||||
// Sets the set of completions.
|
||||
void set_completions(const completion_list_t &comp);
|
||||
|
||||
/* Sets the prefix */
|
||||
// Sets the prefix.
|
||||
void set_prefix(const wcstring &pref);
|
||||
|
||||
/* Sets the terminal width and height */
|
||||
// Sets the terminal width and height.
|
||||
void set_term_size(int w, int h);
|
||||
|
||||
/* Changes the selected completion in the given direction according to the layout of the given rendering. Returns true if the selection changed. */
|
||||
bool select_next_completion_in_direction(selection_direction_t direction, const page_rendering_t &rendering);
|
||||
// Changes the selected completion in the given direction according to the layout of the given
|
||||
// rendering. Returns true if the selection changed.
|
||||
bool select_next_completion_in_direction(selection_direction_t direction,
|
||||
const page_rendering_t &rendering);
|
||||
|
||||
/* Returns the currently selected completion for the given rendering */
|
||||
// Returns the currently selected completion for the given rendering.
|
||||
const completion_t *selected_completion(const page_rendering_t &rendering) const;
|
||||
|
||||
/* Indicates the row and column for the given rendering. Returns -1 if no selection. */
|
||||
// Indicates the row and column for the given rendering. Returns -1 if no selection.
|
||||
size_t get_selected_row(const page_rendering_t &rendering) const;
|
||||
size_t get_selected_column(const page_rendering_t &rendering) const;
|
||||
|
||||
/* Produces a rendering of the completions, at the given term size */
|
||||
// Produces a rendering of the completions, at the given term size.
|
||||
page_rendering_t render() const;
|
||||
|
||||
/* Updates the rendering if it's stale */
|
||||
// Updates the rendering if it's stale.
|
||||
void update_rendering(page_rendering_t *rendering) const;
|
||||
|
||||
/* Indicates if there are no completions, and therefore nothing to render */
|
||||
// Indicates if there are no completions, and therefore nothing to render.
|
||||
bool empty() const;
|
||||
|
||||
/* Clears all completions and the prefix */
|
||||
// Clears all completions and the prefix.
|
||||
void clear();
|
||||
|
||||
/* Updates the completions list per the filter */
|
||||
// Updates the completions list per the filter.
|
||||
void refilter_completions();
|
||||
|
||||
/* Sets whether the search field is shown */
|
||||
// Sets whether the search field is shown.
|
||||
void set_search_field_shown(bool flag);
|
||||
|
||||
/* Gets whether the search field shown */
|
||||
// Gets whether the search field shown.
|
||||
bool is_search_field_shown() const;
|
||||
|
||||
/* Indicates if we are navigating our contents */
|
||||
// Indicates if we are navigating our contents.
|
||||
bool is_navigating_contents() const;
|
||||
|
||||
/* Become fully disclosed */
|
||||
// Become fully disclosed.
|
||||
void set_fully_disclosed(bool flag);
|
||||
|
||||
/* Position of the cursor */
|
||||
// Position of the cursor.
|
||||
size_t cursor_position() const;
|
||||
|
||||
/* Constructor */
|
||||
// Constructor
|
||||
pager_t();
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user