From d2a27d9892a9418eaae12e1c7fe6c4acf89fa539 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 12 Nov 2016 08:29:48 +0530 Subject: [PATCH] Use the native tracker implementation --- kitty/screen.py | 6 ++-- kitty/tracker.c | 20 +++++++----- kitty/tracker.py | 68 ----------------------------------------- kitty_tests/__init__.py | 7 +++-- 4 files changed, 19 insertions(+), 82 deletions(-) delete mode 100644 kitty/tracker.py diff --git a/kitty/screen.py b/kitty/screen.py index e3db249a0..7c4e02af0 100644 --- a/kitty/screen.py +++ b/kitty/screen.py @@ -11,8 +11,7 @@ from typing import Sequence from pyte import charsets as cs, graphics as g, modes as mo from .utils import wcwidth, is_simple_string, sanitize_title from .unicode import ignore_pat -from .tracker import ChangeTracker -from .fast_data_types import LineBuf, REVERSE, Cursor +from .fast_data_types import LineBuf, REVERSE, Cursor, ChangeTracker #: A container for screen's scroll margins. @@ -63,7 +62,7 @@ class Screen: self.savepoints = self.main_savepoints self.columns = columns self.lines = lines - self.tracker = ChangeTracker() + self.tracker = ChangeTracker(self.lines, self.columns) for attr in self.tracker_callbacks: setattr(self, attr, getattr(self.tracker, attr)) self.consolidate_changes = self.tracker.consolidate_changes @@ -159,6 +158,7 @@ class Screen: """ self.lines, self.columns = lines, columns + self.tracker.resize(self.lines, self.columns) # TODO: Implement rewrap for history buf self.tophistorybuf.clear() is_main = self.linebuf is self.main_linebuf diff --git a/kitty/tracker.c b/kitty/tracker.c index 2ce006d0b..a8855bd16 100644 --- a/kitty/tracker.c +++ b/kitty/tracker.c @@ -48,15 +48,19 @@ dealloc(ChangeTracker* self) { Py_TYPE(self)->tp_free((PyObject*)self); } -static PyObject* -reset(ChangeTracker *self) { -#define reset_doc "Reset all changes" +static inline void reset_inner(ChangeTracker *self) { self->screen_changed = false; self->cursor_changed = false; self->dirty = false; self->history_line_added_count = 0; memset(self->changed_lines, 0, self->ynum * sizeof(bool)); memset(self->changed_cells, 0, self->ynum * self->xnum * sizeof(bool)); memset(self->lines_with_changed_cells, 0, self->ynum * sizeof(bool)); RESET_STATE_VARS(self); +} + +static PyObject* +reset(ChangeTracker *self) { +#define reset_doc "Reset all changes" + reset_inner(self); Py_RETURN_NONE; } @@ -146,16 +150,16 @@ consolidate_changes(ChangeTracker *self) { // Changed lines Py_ssize_t num = 0; if (!self->screen_changed) { - for (unsigned int i = 0; i < self->ynum; i++) { if (self->changed_lines[i]) num++; } + for (unsigned int i = 0; i < self->ynum; i++) { num += self->changed_lines[i]; } } t = PyTuple_New(num); if (t == NULL) { Py_CLEAR(ans); return NULL; } - if (!self->screen_changed) { - for (unsigned int i = 0, j=0; i < self->ynum; i++, j++) { + if (num > 0) { + for (unsigned int i = 0, j=0; i < self->ynum; i++) { if (self->changed_lines[i]) { PyObject *n = PyLong_FromUnsignedLong(i); if (n == NULL) { Py_CLEAR(t); Py_CLEAR(ans); return NULL; } - PyTuple_SET_ITEM(t, j, n); + PyTuple_SET_ITEM(t, j++, n); } } } @@ -181,7 +185,7 @@ consolidate_changes(ChangeTracker *self) { if (PyDict_SetItemString(ans, "cells", t) != 0) { Py_CLEAR(t); Py_CLEAR(ans); return NULL; } Py_CLEAR(t); - + reset_inner(self); return ans; } diff --git a/kitty/tracker.py b/kitty/tracker.py deleted file mode 100644 index 24c0ef88c..000000000 --- a/kitty/tracker.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python -# vim:fileencoding=utf-8 -# License: GPL v3 Copyright: 2016, Kovid Goyal - -from collections import defaultdict -from operator import itemgetter -from typing import Set, Tuple, Iterator - - -def merge_ranges(ranges: Set[Tuple[int]]) -> Iterator[Tuple[int]]: - if ranges: - sorted_intervals = sorted(ranges, key=itemgetter(0)) - # low and high represent the bounds of the current run of merges - low, high = sorted_intervals[0] - - for iv in sorted_intervals[1:]: - if iv[0] <= high + 1: # new interval overlaps current run or borders it - high = max(high, iv[1]) # merge with the current run - else: # current run is over - yield low, high # yield accumulated interval - low, high = iv # start new run - - yield low, high # end the final run - - -class ChangeTracker: - - def __init__(self): - self.reset() - - def reset(self): - self.dirty = False - self.changed_cursor = False - self.changed_cells = defaultdict(set) - self.changed_lines = set() - self.screen_changed = False - self.history_line_added_count = 0 - - def cursor_changed(self) -> None: - self.changed_cursor = True - self.dirty = True - - def update_screen(self): - self.screen_changed = True - self.dirty = True - - def update_line_range(self, first_line, last_line): - self.changed_lines |= set(range(first_line, last_line + 1)) - self.dirty = True - - def update_cell_range(self, y, first_cell, last_cell): - self.changed_cells[y].add((first_cell, last_cell)) - self.dirty = True - - def line_added_to_history(self): - self.history_line_added_count += 1 - self.dirty = True - - def consolidate_changes(self): - if self.screen_changed: - self.changed_lines.clear() - cc = {} - else: - cc = {y: tuple(merge_ranges(cell_ranges)) for y, cell_ranges in self.changed_cells.items() if y not in self.changed_lines} - changes = {'screen': self.screen_changed, 'cursor': self.changed_cursor, 'lines': self.changed_lines, - 'cells': cc, 'history_line_added_count': self.history_line_added_count} - self.reset() - return changes diff --git a/kitty_tests/__init__.py b/kitty_tests/__init__.py index 0bceb910e..e1c135150 100644 --- a/kitty_tests/__init__.py +++ b/kitty_tests/__init__.py @@ -2,7 +2,6 @@ # vim:fileencoding=utf-8 # License: GPL v3 Copyright: 2016, Kovid Goyal -from collections import defaultdict from unittest import TestCase from kitty.screen import Screen @@ -49,9 +48,11 @@ class BaseTest(TestCase): actual_changes = s.consolidate_changes() ignore = frozenset(ignore.split()) for k, v in actual_changes.items(): - if isinstance(v, defaultdict): - v = dict(v) if k not in ignore: + if isinstance(v, dict): + v = {ky: tuple(vy) for ky, vy in v.items()} + if k == 'lines': + v = set(v) if k in expected_changes: self.ae(expected_changes[k], v) else: