LineBuf.set_attribute

This commit is contained in:
Kovid Goyal 2016-11-04 22:32:50 +05:30
parent e3fdd3089d
commit 7687e75de4
6 changed files with 48 additions and 10 deletions

View File

@ -37,6 +37,11 @@ PyInit_fast_data_types(void) {
if (!init_Line(m)) return NULL; if (!init_Line(m)) return NULL;
if (!init_Cursor(m)) return NULL; if (!init_Cursor(m)) return NULL;
if (!add_module_gl_constants(m)) return NULL; if (!add_module_gl_constants(m)) return NULL;
PyModule_AddIntConstant(m, "BOLD", BOLD_SHIFT);
PyModule_AddIntConstant(m, "ITALIC", ITALIC_SHIFT);
PyModule_AddIntConstant(m, "REVERSE", REVERSE_SHIFT);
PyModule_AddIntConstant(m, "STRIKETHROUGH", STRIKE_SHIFT);
PyModule_AddIntConstant(m, "DECORATION", DECORATION_SHIFT);
} }
return m; return m;

View File

@ -44,6 +44,12 @@ typedef unsigned int index_type;
c->decoration = (a >> DECORATION_SHIFT) & 3; c->bold = (a >> BOLD_SHIFT) & 1; c->italic = (a >> ITALIC_SHIFT) & 1; \ c->decoration = (a >> DECORATION_SHIFT) & 3; c->bold = (a >> BOLD_SHIFT) & 1; c->italic = (a >> ITALIC_SHIFT) & 1; \
c->reverse = (a >> REVERSE_SHIFT) & 1; c->strikethrough = (a >> STRIKE_SHIFT) & 1; c->reverse = (a >> REVERSE_SHIFT) & 1; c->strikethrough = (a >> STRIKE_SHIFT) & 1;
#define SET_ATTRIBUTE(chars, shift, val) \
mask = shift == DECORATION_SHIFT ? 3 : 1; \
val = (val & mask) << (ATTRS_SHIFT + shift); \
mask = ~(mask << (ATTRS_SHIFT + shift)); \
for (index_type i = 0; i < self->xnum; i++) (chars)[i] = ((chars)[i] & mask) | val;
#define COPY_CELL(src, s, dest, d) \ #define COPY_CELL(src, s, dest, d) \
(dest)->chars[d] = (self)->chars[s]; \ (dest)->chars[d] = (self)->chars[s]; \
(dest)->colors[d] = (self)->colors[s]; \ (dest)->colors[d] = (self)->colors[s]; \

View File

@ -101,6 +101,19 @@ line(LineBuf *self, PyObject *y) {
return (PyObject*)self->line; return (PyObject*)self->line;
} }
static PyObject*
set_attribute(LineBuf *self, PyObject *args) {
#define set_attribute_doc "set_attribute(which, val) -> Set the attribute on all cells in the line."
unsigned int shift, val;
char_type mask;
if (!PyArg_ParseTuple(args, "II", &shift, &val)) return NULL;
if (shift < DECORATION_SHIFT || shift > STRIKE_SHIFT) { PyErr_SetString(PyExc_ValueError, "Unknown attribute"); return NULL; }
for (index_type y = 0; y < self->ynum; y++) {
SET_ATTRIBUTE(self->chars + y * self->xnum, shift, val);
}
Py_RETURN_NONE;
}
// Boilerplate {{{ // Boilerplate {{{
static PyObject* static PyObject*
@ -111,6 +124,7 @@ static PyMethodDef methods[] = {
METHOD(line, METH_O) METHOD(line, METH_O)
METHOD(copy_old, METH_O) METHOD(copy_old, METH_O)
METHOD(clear, METH_NOARGS) METHOD(clear, METH_NOARGS)
METHOD(set_attribute, METH_VARARGS)
{NULL, NULL, 0, NULL} /* Sentinel */ {NULL, NULL, 0, NULL} /* Sentinel */
}; };

View File

@ -245,6 +245,17 @@ set_char(Line *self, PyObject *args) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject*
set_attribute(Line *self, PyObject *args) {
#define set_attribute_doc "set_attribute(which, val) -> Set the attribute on all cells in the line."
unsigned int shift, val;
char_type mask;
if (!PyArg_ParseTuple(args, "II", &shift, &val)) return NULL;
if (shift < DECORATION_SHIFT || shift > STRIKE_SHIFT) { PyErr_SetString(PyExc_ValueError, "Unknown attribute"); return NULL; }
SET_ATTRIBUTE(self->chars, shift, val);
Py_RETURN_NONE;
}
static Py_ssize_t static Py_ssize_t
__len__(PyObject *self) { __len__(PyObject *self) {
return (Py_ssize_t)(((Line*)self)->ynum); return (Py_ssize_t)(((Line*)self)->ynum);
@ -281,6 +292,7 @@ static PyMethodDef methods[] = {
METHOD(right_shift, METH_VARARGS) METHOD(right_shift, METH_VARARGS)
METHOD(left_shift, METH_VARARGS) METHOD(left_shift, METH_VARARGS)
METHOD(set_char, METH_VARARGS) METHOD(set_char, METH_VARARGS)
METHOD(set_attribute, METH_VARARGS)
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };

View File

@ -12,7 +12,7 @@ from pyte import charsets as cs, graphics as g, modes as mo
from .data_types import Line, Cursor, rewrap_lines from .data_types import Line, Cursor, rewrap_lines
from .utils import wcwidth, is_simple_string, sanitize_title from .utils import wcwidth, is_simple_string, sanitize_title
from .unicode import ignore_pat from .unicode import ignore_pat
from .fast_data_types import LineBuf from .fast_data_types import LineBuf, REVERSE
#: A container for screen's scroll margins. #: A container for screen's scroll margins.
@ -79,7 +79,7 @@ class Screen:
self.tophistorybuf.copy_old(previous) self.tophistorybuf.copy_old(previous)
def line(self, i): def line(self, i):
return self.linebuf[i] return self.linebuf.line(i)
def __repr__(self): def __repr__(self):
return ("{0}({1}, {2})".format(self.__class__.__name__, return ("{0}({1}, {2})".format(self.__class__.__name__,
@ -121,7 +121,6 @@ class Screen:
if self.linebuf is self.alt_linebuf: if self.linebuf is self.alt_linebuf:
self.toggle_screen_buffer() self.toggle_screen_buffer()
self.linebuf.clear() self.linebuf.clear()
self.linebuf[:] = (Line(self.columns) for i in range(self.lines))
self.mode = {mo.DECAWM, mo.DECTCEM} self.mode = {mo.DECAWM, mo.DECTCEM}
self.margins = Margins(0, self.lines - 1) self.margins = Margins(0, self.lines - 1)
@ -236,9 +235,7 @@ class Screen:
# Mark all displayed characters as reverse. # Mark all displayed characters as reverse.
if mo.DECSCNM in modes: if mo.DECSCNM in modes:
for line in self.linebuf: self.linebuf.set_attribute(REVERSE, True)
for i in range(len(line)):
line.set_reverse(i, True)
self.update_screen() self.update_screen()
self.select_graphic_rendition(7) # +reverse. self.select_graphic_rendition(7) # +reverse.
@ -282,9 +279,7 @@ class Screen:
self.cursor_position() self.cursor_position()
if mo.DECSCNM in modes: if mo.DECSCNM in modes:
for line in self.linebuf: self.linebuf.set_attribute(REVERSE, False)
for i in range(len(line)):
line.set_reverse(i, False)
self.update_screen() self.update_screen()
self.select_graphic_rendition(27) # -reverse. self.select_graphic_rendition(27) # -reverse.

View File

@ -7,7 +7,7 @@ import codecs
from . import BaseTest, filled_line_buf, filled_cursor from . import BaseTest, filled_line_buf, filled_cursor
from kitty.utils import is_simple_string, wcwidth, sanitize_title from kitty.utils import is_simple_string, wcwidth, sanitize_title
from kitty.fast_data_types import LineBuf, Cursor as C from kitty.fast_data_types import LineBuf, Cursor as C, REVERSE
class TestDataTypes(BaseTest): class TestDataTypes(BaseTest):
@ -19,6 +19,12 @@ class TestDataTypes(BaseTest):
self.ae(new.line(0), old.line(1)) self.ae(new.line(0), old.line(1))
new.clear() new.clear()
self.ae(str(new.line(0)), ' ' * new.xnum) self.ae(str(new.line(0)), ' ' * new.xnum)
old.set_attribute(REVERSE, False)
for y in range(old.ynum):
for x in range(old.xnum):
c = old.line(y).cursor_from(x)
self.assertFalse(c.reverse)
self.assertTrue(c.bold)
def test_line(self): def test_line(self):
lb = LineBuf(2, 3) lb = LineBuf(2, 3)