__eq__ for Line

This commit is contained in:
Kovid Goyal 2016-11-04 14:56:31 +05:30
parent 8324ec1c2b
commit d324baf979
5 changed files with 44 additions and 20 deletions

View File

@ -42,7 +42,7 @@ dealloc(Cursor* self) {
#define EQ(x) (a->x == b->x)
#define PEQ(x) (PyObject_RichCompareBool(a->x, b->x, Py_EQ) == 1)
int is_eq(Cursor *a, Cursor *b) {
static int __eq__(Cursor *a, Cursor *b) {
return EQ(bold) && EQ(italic) && EQ(strikethrough) && EQ(reverse) && EQ(decoration) && EQ(fg) && EQ(bg) && EQ(decoration_fg) && PEQ(x) && PEQ(y) && PEQ(shape) && PEQ(blink) && PEQ(color) && PEQ(hidden);
}
@ -103,25 +103,10 @@ PyTypeObject Cursor_Type = {
.tp_new = new,
};
RICHCMP(Cursor)
// }}}
static PyObject *
richcmp(PyObject *obj1, PyObject *obj2, int op)
{
PyObject *result = NULL;
int eq;
if (op != Py_EQ && op != Py_NE) { Py_RETURN_NOTIMPLEMENTED; }
if (!PyObject_TypeCheck(obj1, &Cursor_Type)) { Py_RETURN_FALSE; }
if (!PyObject_TypeCheck(obj2, &Cursor_Type)) { Py_RETURN_FALSE; }
eq = is_eq((Cursor*)obj1, (Cursor*)obj2);
if (op == Py_NE) result = eq ? Py_False : Py_True;
else result = eq ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
static PyObject*
copy(Cursor *self, PyObject UNUSED *args) {
#define CPY(x) ans->x = self->x; Py_XINCREF(self->x);

View File

@ -69,6 +69,22 @@ typedef unsigned int index_type;
return 1; \
}
#define RICHCMP(type) \
static PyObject * richcmp(PyObject *obj1, PyObject *obj2, int op) { \
PyObject *result = NULL; \
int eq; \
if (op != Py_EQ && op != Py_NE) { Py_RETURN_NOTIMPLEMENTED; } \
if (!PyObject_TypeCheck(obj1, &type##_Type)) { Py_RETURN_FALSE; } \
if (!PyObject_TypeCheck(obj2, &type##_Type)) { Py_RETURN_FALSE; } \
eq = __eq__((type*)obj1, (type*)obj2); \
if (op == Py_NE) result = eq ? Py_False : Py_True; \
else result = eq ? Py_True : Py_False; \
Py_INCREF(result); \
return result; \
}
typedef struct {
PyObject_HEAD

View File

@ -250,11 +250,22 @@ __len__(PyObject *self) {
return (Py_ssize_t)(((Line*)self)->ynum);
}
static int __eq__(Line *a, Line *b) {
return a->xnum == b->xnum && \
memcmp(a->chars, b->chars, sizeof(char_type) * a->xnum) == 0 && \
memcmp(a->colors, b->colors, sizeof(color_type) * a->xnum) == 0 && \
memcmp(a->decoration_fg, b->decoration_fg, sizeof(decoration_type) * a->xnum) == 0 && \
memcmp(a->combining_chars, b->combining_chars, sizeof(combining_type) * a->xnum) == 0;
}
// Boilerplate {{{
static PyObject*
copy_char(Line* self, PyObject *args);
#define copy_char_doc "copy_char(src, to, dest) -> Copy the character at src to to the character dest in the line `to`"
static PyObject *
richcmp(PyObject *obj1, PyObject *obj2, int op);
static PySequenceMethods sequence_methods = {
.sq_length = __len__,
@ -282,6 +293,7 @@ static PyTypeObject Line_Type = {
.tp_repr = (reprfunc)as_unicode,
.tp_as_sequence = &sequence_methods,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_richcompare = richcmp,
.tp_doc = "Lines",
.tp_methods = methods,
.tp_new = new
@ -290,6 +302,8 @@ static PyTypeObject Line_Type = {
Line *alloc_line() {
return (Line*)PyType_GenericAlloc(&Line_Type, 0);
}
RICHCMP(Line)
// }}
static PyObject*

View File

@ -20,6 +20,15 @@ def filled_line_buf(ynum=5, xnum=5, cursor=Cursor()):
return ans
def filled_cursor():
ans = Cursor()
ans.bold = ans.italic = ans.reverse = ans.strikethrough = True
ans.fg = 0x101
ans.bg = 0x201
ans.decoration_fg = 0x301
return ans
class BaseTest(TestCase):
ae = TestCase.assertEqual

View File

@ -4,7 +4,7 @@
import codecs
from . import BaseTest, filled_line_buf
from . import BaseTest, filled_line_buf, filled_cursor
from kitty.utils import is_simple_string, wcwidth, sanitize_title
from kitty.fast_data_types import LineBuf, Cursor as C
@ -13,10 +13,10 @@ from kitty.fast_data_types import LineBuf, Cursor as C
class TestDataTypes(BaseTest):
def test_linebuf(self):
old = filled_line_buf(2, 3)
old = filled_line_buf(2, 3, filled_cursor())
new = LineBuf(1, 3)
new.copy_old(old)
self.ae(str(new.line(0)), str(old.line(1)))
self.ae(new.line(0), old.line(1))
def test_line(self):
lb = LineBuf(2, 3)