pager history buffer: add config option, keep buffer on resize

This commit is contained in:
Dominique Martinet 2018-09-16 00:46:43 +09:00
parent d0104660c8
commit e08238d5a0
6 changed files with 44 additions and 17 deletions

View File

@ -323,6 +323,13 @@ def scrollback_lines(x):
return x return x
def size_mb(x):
x = int(x)
if x < 0 or x > 2 ** 12 - 1:
raise ValueError('Size {} is in MB (positive & <4GB)'.format(x))
return x
o('scrollback_lines', 2000, option_type=scrollback_lines, long_text=_(''' o('scrollback_lines', 2000, option_type=scrollback_lines, long_text=_('''
Number of lines of history to keep in memory for scrolling back. Memory is allocated Number of lines of history to keep in memory for scrolling back. Memory is allocated
on demand. Negative numbers are (effectively) infinite scrollback. Note that using on demand. Negative numbers are (effectively) infinite scrollback. Note that using
@ -336,6 +343,13 @@ use can handle ANSI escape sequences for colors and text formatting.
INPUT_LINE_NUMBER in the command line above will be replaced by an integer INPUT_LINE_NUMBER in the command line above will be replaced by an integer
representing which line should be at the top of the screen.''')) representing which line should be at the top of the screen.'''))
o('scrollback_pager_history_size', 10, option_type=size_mb, long_text=_('''
Separate scrollback history size, used only for pager, in MB.
This separate buffer is not available for interactive scrolling but will be
prepended to the pager program when viewing scrollback.
The current implementation stores one character in 4 bytes, so approximatively
2500 lines per megabyte at 100 chars per line'''))
o('wheel_scroll_multiplier', 5.0, long_text=_(''' o('wheel_scroll_multiplier', 5.0, long_text=_('''
Modify the amount scrolled by the mouse wheel. Note this is only used for low Modify the amount scrolled by the mouse wheel. Note this is only used for low
precision scrolling devices, not for high precision scrolling on platforms such precision scrolling devices, not for high precision scrolling on platforms such

View File

@ -185,7 +185,7 @@ typedef struct {
index_type xnum, ynum, num_segments; index_type xnum, ynum, num_segments;
HistoryBufSegment *segments; HistoryBufSegment *segments;
PagerHistoryBuf pagerhist; PagerHistoryBuf *pagerhist;
Line *line; Line *line;
index_type start_of_data, count; index_type start_of_data, count;
} HistoryBuf; } HistoryBuf;
@ -262,7 +262,7 @@ const char* base64_decode(const uint32_t *src, size_t src_sz, uint8_t *dest, siz
Line* alloc_line(); Line* alloc_line();
Cursor* alloc_cursor(); Cursor* alloc_cursor();
LineBuf* alloc_linebuf(unsigned int, unsigned int); LineBuf* alloc_linebuf(unsigned int, unsigned int);
HistoryBuf* alloc_historybuf(unsigned int, unsigned int); HistoryBuf* alloc_historybuf(unsigned int, unsigned int, unsigned int);
ColorProfile* alloc_color_profile(); ColorProfile* alloc_color_profile();
PyObject* create_256_color_table(); PyObject* create_256_color_table();
PyObject* parse_bytes_dump(PyObject UNUSED *, PyObject *); PyObject* parse_bytes_dump(PyObject UNUSED *, PyObject *);

View File

@ -54,12 +54,24 @@ attrptr(HistoryBuf *self, index_type y) {
seg_ptr(line_attrs, 1); seg_ptr(line_attrs, 1);
} }
static inline PagerHistoryBuf*
alloc_pagerhist(unsigned int pagerhist_sz) {
PagerHistoryBuf *ph;
if (!pagerhist_sz) return NULL;
pagerhist_sz *= 1024*1024;
ph = PyMem_Calloc(1, sizeof(PagerHistoryBuf));
ph->bufsize = pagerhist_sz / sizeof(Py_UCS4);
ph->buffer = PyMem_RawMalloc(pagerhist_sz);
if (!ph->buffer) { PyMem_Free(ph); return NULL; }
return ph;
}
static PyObject * static PyObject *
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
HistoryBuf *self; HistoryBuf *self;
unsigned int xnum = 1, ynum = 1; unsigned int xnum = 1, ynum = 1, pagerhist_sz = 0;
if (!PyArg_ParseTuple(args, "II", &ynum, &xnum)) return NULL; if (!PyArg_ParseTuple(args, "II|I", &ynum, &xnum, &pagerhist_sz)) return NULL;
if (xnum == 0 || ynum == 0) { if (xnum == 0 || ynum == 0) {
PyErr_SetString(PyExc_ValueError, "Cannot create an empty history buffer"); PyErr_SetString(PyExc_ValueError, "Cannot create an empty history buffer");
@ -74,10 +86,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
add_segment(self); add_segment(self);
self->line = alloc_line(); self->line = alloc_line();
self->line->xnum = xnum; self->line->xnum = xnum;
self->pagerhist.start = self->pagerhist.end = self->pagerhist.bufend = 0; self->pagerhist = alloc_pagerhist(pagerhist_sz);
self->pagerhist.buffer = PyMem_RawMalloc(1024*1024*10);
self->pagerhist.bufsize = 1024*1024*10 / sizeof(Py_UCS4);
// abort if allocation failed?
} }
return (PyObject*)self; return (PyObject*)self;
@ -92,7 +101,8 @@ dealloc(HistoryBuf* self) {
PyMem_Free(self->segments[i].line_attrs); PyMem_Free(self->segments[i].line_attrs);
} }
PyMem_Free(self->segments); PyMem_Free(self->segments);
PyMem_Free(self->pagerhist.buffer); if (self->pagerhist) PyMem_Free(self->pagerhist->buffer);
PyMem_Free(self->pagerhist);
Py_TYPE(self)->tp_free((PyObject*)self); Py_TYPE(self)->tp_free((PyObject*)self);
} }
@ -139,8 +149,8 @@ historybuf_clear(HistoryBuf *self) {
static inline void static inline void
pagerhist_push(HistoryBuf *self) { pagerhist_push(HistoryBuf *self) {
PagerHistoryBuf *ph = &self->pagerhist; PagerHistoryBuf *ph = self->pagerhist;
if (!ph->buffer) return; if (!ph) return;
Line l = {.xnum=self->xnum}; Line l = {.xnum=self->xnum};
init_line(self, self->start_of_data, &l); init_line(self, self->start_of_data, &l);
if (ph->start != ph->end && !l.continued) { if (ph->start != ph->end && !l.continued) {
@ -241,10 +251,10 @@ get_line(HistoryBuf *self, index_type y, Line *l) { init_line(self, index_of(sel
static PyObject * static PyObject *
pagerhist_as_text(HistoryBuf *self, PyObject *callback) { pagerhist_as_text(HistoryBuf *self, PyObject *callback) {
PagerHistoryBuf *ph = &self->pagerhist; PagerHistoryBuf *ph = self->pagerhist;
PyObject *ret = NULL, *t = NULL; PyObject *ret = NULL, *t = NULL;
Py_UCS4 *buf = NULL; Py_UCS4 *buf = NULL;
if (!ph->buffer) Py_RETURN_NONE; if (!ph) Py_RETURN_NONE;
index_type num = (ph->bufend ? ph->bufend : ph->end) - ph->start; index_type num = (ph->bufend ? ph->bufend : ph->end) - ph->start;
buf = ph->buffer + ph->start; buf = ph->buffer + ph->start;
@ -340,8 +350,8 @@ PyTypeObject HistoryBuf_Type = {
INIT_TYPE(HistoryBuf) INIT_TYPE(HistoryBuf)
HistoryBuf *alloc_historybuf(unsigned int lines, unsigned int columns) { HistoryBuf *alloc_historybuf(unsigned int lines, unsigned int columns, unsigned int pagerhist_sz) {
return (HistoryBuf*)new(&HistoryBuf_Type, Py_BuildValue("II", lines, columns), NULL); return (HistoryBuf*)new(&HistoryBuf_Type, Py_BuildValue("III", lines, columns, pagerhist_sz), NULL);
} }
// }}} // }}}

View File

@ -107,7 +107,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
self->color_profile = alloc_color_profile(); self->color_profile = alloc_color_profile();
self->main_linebuf = alloc_linebuf(lines, columns); self->alt_linebuf = alloc_linebuf(lines, columns); self->main_linebuf = alloc_linebuf(lines, columns); self->alt_linebuf = alloc_linebuf(lines, columns);
self->linebuf = self->main_linebuf; self->linebuf = self->main_linebuf;
self->historybuf = alloc_historybuf(MAX(scrollback, lines), columns); self->historybuf = alloc_historybuf(MAX(scrollback, lines), columns, OPT(scrollback_pager_history_size));
self->main_grman = grman_alloc(); self->main_grman = grman_alloc();
self->alt_grman = grman_alloc(); self->alt_grman = grman_alloc();
self->grman = self->main_grman; self->grman = self->main_grman;
@ -165,8 +165,9 @@ screen_dirty_sprite_positions(Screen *self) {
static inline HistoryBuf* static inline HistoryBuf*
realloc_hb(HistoryBuf *old, unsigned int lines, unsigned int columns) { realloc_hb(HistoryBuf *old, unsigned int lines, unsigned int columns) {
HistoryBuf *ans = alloc_historybuf(lines, columns); HistoryBuf *ans = alloc_historybuf(lines, columns, 0);
if (ans == NULL) { PyErr_NoMemory(); return NULL; } if (ans == NULL) { PyErr_NoMemory(); return NULL; }
ans->pagerhist = old->pagerhist; old->pagerhist = NULL;
historybuf_rewrap(old, ans); historybuf_rewrap(old, ans);
return ans; return ans;
} }

View File

@ -367,6 +367,7 @@ PYWRAP1(set_options) {
S(dynamic_background_opacity, PyObject_IsTrue); S(dynamic_background_opacity, PyObject_IsTrue);
S(inactive_text_alpha, PyFloat_AsDouble); S(inactive_text_alpha, PyFloat_AsDouble);
S(window_padding_width, PyFloat_AsDouble); S(window_padding_width, PyFloat_AsDouble);
S(scrollback_pager_history_size, PyLong_AsLong);
S(cursor_shape, PyLong_AsLong); S(cursor_shape, PyLong_AsLong);
S(url_style, PyLong_AsUnsignedLong); S(url_style, PyLong_AsUnsignedLong);
S(tab_bar_edge, PyLong_AsLong); S(tab_bar_edge, PyLong_AsLong);

View File

@ -19,6 +19,7 @@ typedef struct {
unsigned int open_url_modifiers; unsigned int open_url_modifiers;
unsigned int rectangle_select_modifiers; unsigned int rectangle_select_modifiers;
unsigned int url_style; unsigned int url_style;
unsigned int scrollback_pager_history_size;
char_type select_by_word_characters[256]; size_t select_by_word_characters_count; char_type select_by_word_characters[256]; size_t select_by_word_characters_count;
color_type url_color, background, active_border_color, inactive_border_color, bell_border_color; color_type url_color, background, active_border_color, inactive_border_color, bell_border_color;
double repaint_delay, input_delay; double repaint_delay, input_delay;