Implement rewrp for pagerhist using the streaming wcswidth
This commit is contained in:
150
kitty/history.c
150
kitty/history.c
@@ -5,7 +5,7 @@
|
|||||||
* Distributed under terms of the GPL3 license.
|
* Distributed under terms of the GPL3 license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "data-types.h"
|
#include "wcswidth.h"
|
||||||
#include "lineops.h"
|
#include "lineops.h"
|
||||||
#include "charsets.h"
|
#include "charsets.h"
|
||||||
#include <structmember.h>
|
#include <structmember.h>
|
||||||
@@ -187,7 +187,7 @@ historybuf_clear(HistoryBuf *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
pagerhist_write(PagerHistoryBuf *ph, const uint8_t *buf, size_t sz) {
|
pagerhist_write_bytes(PagerHistoryBuf *ph, const uint8_t *buf, size_t sz) {
|
||||||
if (sz > ph->max_sz) return false;
|
if (sz > ph->max_sz) return false;
|
||||||
if (!sz) return true;
|
if (!sz) return true;
|
||||||
if (sz > ph->buffer_size - ph->length) pagerhist_extend(ph, sz);
|
if (sz > ph->buffer_size - ph->length) pagerhist_extend(ph, sz);
|
||||||
@@ -220,7 +220,7 @@ pagerhist_write_ucs4(PagerHistoryBuf *ph, const Py_UCS4 *buf, size_t sz) {
|
|||||||
uint8_t scratch[4];
|
uint8_t scratch[4];
|
||||||
for (size_t i = 0; i < sz; i++) {
|
for (size_t i = 0; i < sz; i++) {
|
||||||
unsigned int num = encode_utf8(buf[i], (char*)scratch);
|
unsigned int num = encode_utf8(buf[i], (char*)scratch);
|
||||||
if (!pagerhist_write(ph, scratch, num)) return false;
|
if (!pagerhist_write_bytes(ph, scratch, num)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -233,9 +233,9 @@ pagerhist_push(HistoryBuf *self, ANSIBuf *as_ansi_buf) {
|
|||||||
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);
|
||||||
line_as_ansi(&l, as_ansi_buf, &prev_cell);
|
line_as_ansi(&l, as_ansi_buf, &prev_cell);
|
||||||
if (ph->length != 0 && !l.continued) pagerhist_write(ph, (const uint8_t*)"\n", 1);
|
if (ph->length != 0 && !l.continued) pagerhist_write_bytes(ph, (const uint8_t*)"\n", 1);
|
||||||
pagerhist_write(ph, (const uint8_t*)"\x1b[m", 3);
|
pagerhist_write_bytes(ph, (const uint8_t*)"\x1b[m", 3);
|
||||||
if (pagerhist_write_ucs4(ph, as_ansi_buf->buf, as_ansi_buf->len)) pagerhist_write(ph, (const uint8_t*)"\r", 1);
|
if (pagerhist_write_ucs4(ph, as_ansi_buf->buf, as_ansi_buf->len)) pagerhist_write_bytes(ph, (const uint8_t*)"\r", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline index_type
|
static inline index_type
|
||||||
@@ -326,55 +326,85 @@ end:
|
|||||||
static inline Line*
|
static inline Line*
|
||||||
get_line(HistoryBuf *self, index_type y, Line *l) { init_line(self, index_of(self, self->count - y - 1), l); return l; }
|
get_line(HistoryBuf *self, index_type y, Line *l) { init_line(self, index_of(self, self->count - y - 1), l); return l; }
|
||||||
|
|
||||||
|
static inline char_type
|
||||||
|
pagerhist_read_char(PagerHistoryBuf *ph, size_t pos, unsigned *count, uint8_t record[8]) {
|
||||||
|
uint32_t codep, state = UTF8_ACCEPT;
|
||||||
|
*count = 0;
|
||||||
|
while (true) {
|
||||||
|
decode_utf8(&state, &codep, ph->buffer[pos]);
|
||||||
|
record[(*count)++] = ph->buffer[pos];
|
||||||
|
if (state == UTF8_REJECT) { codep = 0; break; }
|
||||||
|
if (state == UTF8_ACCEPT) break;
|
||||||
|
pos = pos == ph->buffer_size - 1 ? 0 : (pos + 1);
|
||||||
|
}
|
||||||
|
return codep;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pagerhist_rewrap(PagerHistoryBuf *ph, index_type xnum) {
|
pagerhist_rewrap_to(HistoryBuf *self, index_type cells_in_line) {
|
||||||
(void)ph; (void)xnum;
|
PagerHistoryBuf *ph = self->pagerhist;
|
||||||
return; // TODO: Implement this
|
if (!ph->length) return;
|
||||||
/* Py_UCS4 *buf = PyMem_RawMalloc(ph->bufsize * sizeof(Py_UCS4)); */
|
PagerHistoryBuf *nph = PyMem_Calloc(sizeof(PagerHistoryBuf), 1);
|
||||||
/* if (!buf) return; */
|
if (!nph) return;
|
||||||
/* index_type s = ph->start, i = s, dest = 0, dest_bufend = 0, x = 0; */
|
nph->buffer_size = ph->buffer_size;
|
||||||
/* index_type end = ph->bufend ? ph->bufend : ph->end; */
|
nph->max_sz = ph->max_sz;
|
||||||
/* index_type lastmod_s = 0, lastmod_len = 0; */
|
nph->buffer = PyMem_Malloc(nph->buffer_size);
|
||||||
/* #define CPY(_s, _l) { if (dest + (_l) >= ph->bufsize - 1) { dest_bufend = dest; dest = 0; } \ */
|
if (!nph->buffer) { PyMem_Free(nph); return ; }
|
||||||
/* memcpy(buf + dest, ph->buffer + (_s), (_l) * sizeof(Py_UCS4)); dest += (_l); } */
|
size_t i = 0, pos;
|
||||||
/* while (i < end) { */
|
ssize_t ch_width = 0;
|
||||||
/* switch (ph->buffer[i]) { */
|
unsigned count;
|
||||||
/* case '\n': */
|
uint8_t record[8];
|
||||||
/* CPY(s, i - s + 1); */
|
index_type num_in_current_line = 0;
|
||||||
/* x = 0; s = i + 1; lastmod_len = 0; */
|
char_type ch;
|
||||||
/* break; */
|
WCSState wcs_state;
|
||||||
/* case '\r': */
|
initialize_wcs_state(&wcs_state);
|
||||||
/* CPY(s, i - s); */
|
|
||||||
/* if (!memcmp(ph->buffer + lastmod_s, ph->buffer + i + 1, lastmod_len * sizeof(Py_UCS4))) */
|
#define READ_CHAR(ch) { \
|
||||||
/* i += lastmod_len; */
|
ch = pagerhist_read_char(ph, pos, &count, record); \
|
||||||
/* s = i + 1; */
|
i += count; pos += count; \
|
||||||
/* break; */
|
if (pos >= ph->buffer_size) pos = pos - ph->buffer_size; \
|
||||||
/* case '\x1b': */
|
}
|
||||||
/* if (ph->buffer[i+1] != '[') break; */
|
#define WRITE_CHAR() { \
|
||||||
/* lastmod_s = i; */
|
if (num_in_current_line + ch_width > cells_in_line) { \
|
||||||
/* while (ph->buffer[++i] != 'm'); */
|
pagerhist_write_bytes(nph, (const uint8_t*)"\r", 1); \
|
||||||
/* lastmod_len = i - lastmod_s + 1; */
|
num_in_current_line = 0; \
|
||||||
/* break; */
|
}\
|
||||||
/* default: */
|
if (ch_width >= 0 || num_in_current_line >= -ch_width) num_in_current_line += ch_width; \
|
||||||
/* x++; break; */
|
pagerhist_write_bytes(nph, record, count); \
|
||||||
/* } */
|
}
|
||||||
/* i++; */
|
|
||||||
/* if (ph->bufend && i == ph->bufend) { */
|
for (i = 0; i < ph->length;) {
|
||||||
/* if (s != i) CPY(s, i - s); */
|
pos = ph->start + i;
|
||||||
/* end = ph->end; i = s = 0; */
|
if (pos >= ph->buffer_size) pos = pos - ph->buffer_size;
|
||||||
/* } */
|
READ_CHAR(ch);
|
||||||
/* if (x == xnum) { */
|
if (ch == '\n') {
|
||||||
/* CPY(s, i - s); buf[dest++] = '\r'; s = i; x = 0; */
|
initialize_wcs_state(&wcs_state);
|
||||||
/* if (!(ph->buffer[i] == '\x1b' && ph->buffer[i+1] == '[') && lastmod_len) */
|
ch_width = 1;
|
||||||
/* CPY(lastmod_s, lastmod_len); */
|
WRITE_CHAR();
|
||||||
/* } */
|
num_in_current_line = 0;
|
||||||
/* } */
|
} else if (ch != '\r') {
|
||||||
/* #undef CPY */
|
ch_width = wcswidth_step(&wcs_state, ch);
|
||||||
/* PyMem_Free(ph->buffer); */
|
WRITE_CHAR();
|
||||||
/* ph->buffer = buf; */
|
}
|
||||||
/* ph->end = dest; ph->bufend = dest_bufend; */
|
}
|
||||||
/* ph->start = dest_bufend ? dest + 1 : 0; */
|
free_pagerhist(self);
|
||||||
/* ph->rewrap_needed = false; */
|
self->pagerhist = nph;
|
||||||
|
#undef READ_CHAR
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
pagerhist_write(HistoryBuf *self, PyObject *what) {
|
||||||
|
if (self->pagerhist && self->pagerhist->max_sz) {
|
||||||
|
if (PyBytes_Check(what)) pagerhist_write_bytes(self->pagerhist, (const uint8_t*)PyBytes_AS_STRING(what), PyBytes_GET_SIZE(what));
|
||||||
|
else if (PyUnicode_Check(what) && PyUnicode_READY(what) == 0) {
|
||||||
|
Py_UCS4 *buf = PyUnicode_AsUCS4Copy(what);
|
||||||
|
if (buf) {
|
||||||
|
pagerhist_write_ucs4(self->pagerhist, buf, PyUnicode_GET_LENGTH(what));
|
||||||
|
PyMem_Free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
@@ -383,7 +413,7 @@ pagerhist_as_text(HistoryBuf *self, PyObject *args UNUSED) {
|
|||||||
if (!ph || !ph->length) return PyUnicode_FromString("");
|
if (!ph || !ph->length) return PyUnicode_FromString("");
|
||||||
pagerhist_ensure_start_is_valid_utf8(ph);
|
pagerhist_ensure_start_is_valid_utf8(ph);
|
||||||
|
|
||||||
if (ph->rewrap_needed) pagerhist_rewrap(ph, self->xnum);
|
if (ph->rewrap_needed) pagerhist_rewrap_to(self, self->xnum);
|
||||||
|
|
||||||
Line l = {.xnum=self->xnum}; get_line(self, 0, &l);
|
Line l = {.xnum=self->xnum}; get_line(self, 0, &l);
|
||||||
size_t sz = ph->length;
|
size_t sz = ph->length;
|
||||||
@@ -434,6 +464,14 @@ dirty_lines(HistoryBuf *self, PyObject *a UNUSED) {
|
|||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
pagerhist_rewrap(HistoryBuf *self, PyObject *xnum) {
|
||||||
|
if (self->pagerhist) {
|
||||||
|
pagerhist_rewrap_to(self, PyLong_AsUnsignedLong(xnum));
|
||||||
|
}
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Boilerplate {{{
|
// Boilerplate {{{
|
||||||
static PyObject* rewrap(HistoryBuf *self, PyObject *args);
|
static PyObject* rewrap(HistoryBuf *self, PyObject *args);
|
||||||
@@ -442,6 +480,8 @@ static PyObject* rewrap(HistoryBuf *self, PyObject *args);
|
|||||||
static PyMethodDef methods[] = {
|
static PyMethodDef methods[] = {
|
||||||
METHOD(line, METH_O)
|
METHOD(line, METH_O)
|
||||||
METHOD(as_ansi, METH_O)
|
METHOD(as_ansi, METH_O)
|
||||||
|
METHODB(pagerhist_write, METH_O),
|
||||||
|
METHODB(pagerhist_rewrap, METH_O),
|
||||||
METHODB(pagerhist_as_text, METH_NOARGS),
|
METHODB(pagerhist_as_text, METH_NOARGS),
|
||||||
METHODB(as_text, METH_VARARGS),
|
METHODB(as_text, METH_VARARGS),
|
||||||
METHOD(dirty_lines, METH_NOARGS)
|
METHOD(dirty_lines, METH_NOARGS)
|
||||||
|
|||||||
Reference in New Issue
Block a user