[view_curses] fix color pair allocation

fixes #839
This commit is contained in:
Timothy Stack 2021-02-16 22:15:14 -08:00
parent bbba9ff732
commit 9575f9c7d7
6 changed files with 130 additions and 66 deletions

View File

@ -411,6 +411,7 @@ add_library(diag STATIC
logfile.hh
logfile_fwd.hh
logfile_stats.hh
base/lrucache.hpp
base/math_util.hh
optional.hpp
papertrail_proc.hh

View File

@ -26,6 +26,7 @@ noinst_HEADERS = \
is_utf8.hh \
isc.hh \
lnav_log.hh \
lrucache.hpp \
math_util.hh \
opt_util.hh \
result.h \

83
src/base/lrucache.hpp Normal file
View File

@ -0,0 +1,83 @@
/*
* File: lrucache.hpp
* Author: Alexander Ponomarev
*
* Created on June 20, 2013, 5:09 PM
*/
#ifndef _LRUCACHE_HPP_INCLUDED_
#define _LRUCACHE_HPP_INCLUDED_
#include <map>
#include <list>
#include <cstddef>
#include <stdexcept>
#include "optional.hpp"
namespace cache {
template<typename key_t, typename value_t>
class lru_cache {
public:
typedef typename std::pair<key_t, value_t> key_value_pair_t;
typedef typename std::list<key_value_pair_t>::iterator list_iterator_t;
lru_cache(size_t max_size) :
_max_size(max_size) {
}
void put(const key_t& key, const value_t& value) {
auto it = _cache_items_map.find(key);
_cache_items_list.push_front(key_value_pair_t(key, value));
if (it != _cache_items_map.end()) {
_cache_items_list.erase(it->second);
_cache_items_map.erase(it);
}
_cache_items_map[key] = _cache_items_list.begin();
if (_cache_items_map.size() > _max_size) {
auto last = _cache_items_list.end();
last--;
_cache_items_map.erase(last->first);
_cache_items_list.pop_back();
}
}
nonstd::optional<value_t> get(const key_t& key) {
auto it = _cache_items_map.find(key);
if (it == _cache_items_map.end()) {
return nonstd::nullopt;
}
_cache_items_list.splice(_cache_items_list.begin(), _cache_items_list, it->second);
return it->second->second;
}
bool exists(const key_t& key) const {
return _cache_items_map.find(key) != _cache_items_map.end();
}
size_t size() const {
return _cache_items_map.size();
}
void set_max_size(size_t max_size) {
this->_max_size = max_size;
}
void clear() {
this->_cache_items_map.clear();
this->_cache_items_list.clear();
}
private:
std::list<key_value_pair_t> _cache_items_list;
std::map<key_t, list_iterator_t> _cache_items_map;
size_t _max_size;
};
} // namespace cache
#endif /* _LRUCACHE_HPP_INCLUDED_ */

View File

@ -400,14 +400,8 @@ void readline_command_highlighter(attr_line_t &al, int x)
if (COLOR_RE.match(pc, pi)) {
pcre_context::capture_t *cap = pc[0];
string hash_color = pi.get_substr(cap);
string errmsg;
attr_t color_hint_attrs = vc.attrs_for_role(view_colors::VCR_COLOR_HINT);
int pnum = PAIR_NUMBER(color_hint_attrs);
styling::color_unit::from_str(hash_color).then([&](const auto& rgb_fg) {
pnum -= 1;
vc.ensure_color_pair(pnum, rgb_fg, styling::color_unit::make_empty());
al.get_attrs().emplace_back(
line_range{cap->c_begin, cap->c_begin + 1},
&view_curses::VC_ROLE,

View File

@ -334,6 +334,7 @@ void view_curses::mvwattrline(WINDOW *window,
iter->sa_range.length());
}
color_pair = vc.ensure_color_pair(pair_fg, pair_bg);
attrs &= ~(A_LEFT|A_RIGHT);
}
@ -410,17 +411,6 @@ void view_curses::mvwattrline(WINDOW *window,
#endif
}
attr_t view_colors::BASIC_HL_PAIRS[view_colors::BASIC_COLOR_COUNT] = {
ansi_color_pair(COLOR_BLUE, COLOR_BLACK),
ansi_color_pair(COLOR_CYAN, COLOR_BLACK),
ansi_color_pair(COLOR_GREEN, COLOR_BLACK),
ansi_color_pair(COLOR_MAGENTA, COLOR_BLACK),
ansi_color_pair(COLOR_BLACK, COLOR_WHITE),
ansi_color_pair(COLOR_CYAN, COLOR_BLACK),
ansi_color_pair(COLOR_YELLOW, COLOR_MAGENTA) | A_BOLD,
ansi_color_pair(COLOR_MAGENTA, COLOR_CYAN) | A_BOLD,
};
view_colors &view_colors::singleton()
{
static view_colors s_vc;
@ -429,8 +419,18 @@ view_colors &view_colors::singleton()
}
view_colors::view_colors()
: vc_color_pair_end(0)
: vc_dyn_pairs(0)
{
size_t color_index = 0;
for (int z = 0; z < 6; z++) {
for (int x = 1; x < 6; x += 2) {
for (int y = 1; y < 6; y += 2) {
short fg = 16 + x + (y * 6) + (z * 6 * 6);
this->vc_highlight_colors[color_index++] = fg;
}
}
}
}
bool view_colors::initialized = false;
@ -525,6 +525,9 @@ void view_colors::init()
}
}
log_debug("COLOR_PAIRS = %d", COLOR_PAIRS);
singleton().vc_dyn_pairs.set_max_size(COLOR_PAIRS);
initialized = true;
{
@ -559,7 +562,8 @@ inline attr_t attr_for_colors(int &pair_base, short fg, short bg)
require(pair_base < COLOR_PAIRS);
int pair = ++pair_base;
int pair = pair_base;
pair_base += 1;
if (view_colors::initialized) {
init_pair(pair, fg, bg);
@ -624,7 +628,7 @@ pair<attr_t, attr_t> view_colors::to_attrs(
void view_colors::init_roles(const lnav_theme &lt,
lnav_config_listener::error_reporter &reporter)
{
int color_pair_base = VC_ANSI_END;
int color_pair_base = VC_ANSI_END + 1;
rgb_color fg, bg;
string err;
@ -643,16 +647,6 @@ void view_colors::init_roles(const lnav_theme &lt,
});
ident_bg = vc_active_palette->match_color(lab_color(rgb_bg));
}
for (int z = 0; z < 6; z++) {
for (int x = 1; x < 6; x += 2) {
for (int y = 1; y < 6; y += 2) {
int fg = 16 + x + (y * 6) + (z * 6 * 6);
init_pair(color_pair_base, fg, ident_bg);
color_pair_base += 1;
}
}
}
} else {
color_pair_base = VC_ANSI_END + HI_COLOR_COUNT;
}
@ -916,16 +910,18 @@ void view_colors::init_roles(const lnav_theme &lt,
this->vc_dyn_pairs.clear();
}
int view_colors::ensure_color_pair(int &pair_base, short fg, short bg)
int view_colors::ensure_color_pair(short fg, short bg)
{
require(fg >= -100);
require(bg >= -100);
auto index_pair = make_pair(fg, bg);
auto existing = this->vc_dyn_pairs.find(index_pair);
auto existing = this->vc_dyn_pairs.get(index_pair);
if (existing != this->vc_dyn_pairs.end()) {
return existing->second;
if (existing) {
auto retval = existing.value().dp_color_pair;
return retval;
}
short def_pair = PAIR_NUMBER(this->attrs_for_role(VCR_TEXT));
@ -933,26 +929,27 @@ int view_colors::ensure_color_pair(int &pair_base, short fg, short bg)
pair_content(def_pair, &def_fg, &def_bg);
int retval = PAIR_NUMBER(attr_for_colors(
pair_base,
fg == -1 ? def_fg : fg,
bg == -1 ? def_bg : bg));
int new_pair = this->vc_color_pair_end + this->vc_dyn_pairs.size();
auto retval = PAIR_NUMBER(attr_for_colors(new_pair,
fg == -1 ? def_fg : fg,
bg == -1 ? def_bg : bg));
if (initialized) {
this->vc_dyn_pairs[index_pair] = retval;
struct dyn_pair dp = { (int) retval };
this->vc_dyn_pairs.put(index_pair, dp);
}
return retval;
}
int view_colors::ensure_color_pair(int &pair_base,
const styling::color_unit &rgb_fg,
int view_colors::ensure_color_pair(const styling::color_unit &rgb_fg,
const styling::color_unit &rgb_bg)
{
auto fg = this->match_color(rgb_fg);
auto bg = this->match_color(rgb_bg);
return this->ensure_color_pair(pair_base, fg, bg);
return this->ensure_color_pair(fg, bg);
}
short view_colors::match_color(const styling::color_unit &color) const
@ -985,12 +982,7 @@ int view_colors::color_for_ident(const char *str, size_t len) const
}
unsigned long offset = index % HI_COLOR_COUNT;
auto cpair = COLOR_PAIR(VC_ANSI_END + offset);
short fg, bg;
auto pnum = PAIR_NUMBER(cpair);
pair_content(pnum, &fg, &bg);
retval = fg;
retval = this->vc_highlight_colors[offset];
}
else {
retval = -1;

View File

@ -60,6 +60,7 @@
#include <functional>
#include "base/lnav_log.hh"
#include "base/lrucache.hpp"
#include "attr_line.hh"
#include "optional.hpp"
#include "styling.hh"
@ -179,10 +180,7 @@ private:
*/
class view_colors {
public:
static const unsigned long BASIC_COLOR_COUNT = 8;
static const unsigned long HI_COLOR_COUNT = 6 * 3 * 3;
static attr_t BASIC_HL_PAIRS[BASIC_COLOR_COUNT];
static constexpr unsigned long HI_COLOR_COUNT = 6 * 3 * 3;
/** Roles that can be mapped to curses attributes using attrs_for_role() */
typedef enum {
@ -296,20 +294,10 @@ public:
return this->attrs_for_ident(str.c_str(), str.length());
};
int ensure_color_pair(int &pair_base, short fg, short bg);
int ensure_color_pair(short fg, short bg) {
return this->ensure_color_pair(this->vc_color_pair_end, fg, bg);
}
int ensure_color_pair(int &pair_base,
const styling::color_unit &fg,
const styling::color_unit &bg);
int ensure_color_pair(short fg, short bg);
int ensure_color_pair(const styling::color_unit &fg,
const styling::color_unit &bg) {
return this->ensure_color_pair(this->vc_color_pair_end, fg, bg);
}
const styling::color_unit &bg);
static constexpr short MATCH_COLOR_DEFAULT = -1;
static constexpr short MATCH_COLOR_SEMANTIC = -10;
@ -348,13 +336,18 @@ private:
/** Private constructor that initializes the member fields. */
view_colors();
struct dyn_pair {
int dp_color_pair;
};
/** Map of role IDs to attribute values. */
std::pair<attr_t, attr_t> vc_role_colors[VCR__MAX];
/** Map of role IDs to reverse-video attribute values. */
attr_t vc_role_reverse_colors[VCR__MAX];
short vc_ansi_to_theme[8];
int vc_color_pair_end;
std::map<std::pair<short, short>, int> vc_dyn_pairs;
short vc_highlight_colors[HI_COLOR_COUNT];
int vc_color_pair_end{0};
cache::lru_cache<std::pair<short, short>, dyn_pair> vc_dyn_pairs;
};
enum class mouse_button_t {