diff options
author | dundargoc <gocdundar@gmail.com> | 2025-01-03 15:40:46 +0100 |
---|---|---|
committer | dundargoc <33953936+dundargoc@users.noreply.github.com> | 2025-01-07 12:35:24 +0100 |
commit | d8bc08db7fd8d0efbf2e9ebf39fecb6f732f84e8 (patch) | |
tree | 3dd3eb1954d36db51a1eab82ea890d18cf085189 /test | |
parent | 4d9405991963a53ed31089ed456d9f4cfebc325d (diff) | |
download | rneovim-d8bc08db7fd8d0efbf2e9ebf39fecb6f732f84e8.tar.gz rneovim-d8bc08db7fd8d0efbf2e9ebf39fecb6f732f84e8.tar.bz2 rneovim-d8bc08db7fd8d0efbf2e9ebf39fecb6f732f84e8.zip |
refactor: adopt vterm
We have changed too much to consider it a mere bundled dependency (such
as unicode handling in e3bfcf2fd4a4ebf00b104b082cfe83c8144a842d), and
can consider it our own at this point.
Diffstat (limited to 'test')
-rw-r--r-- | test/unit/fixtures/vterm_test.c | 271 | ||||
-rw-r--r-- | test/unit/fixtures/vterm_test.h | 27 | ||||
-rw-r--r-- | test/unit/vterm_spec.lua | 14 |
3 files changed, 293 insertions, 19 deletions
diff --git a/test/unit/fixtures/vterm_test.c b/test/unit/fixtures/vterm_test.c index 8755e32e7a..7522962a05 100644 --- a/test/unit/fixtures/vterm_test.c +++ b/test/unit/fixtures/vterm_test.c @@ -1,7 +1,11 @@ #include <stdio.h> +#include <string.h> + #include "nvim/grid.h" #include "nvim/mbyte.h" - +#include "nvim/vterm/pen.h" +#include "nvim/vterm/screen.h" +#include "nvim/vterm/vterm_internal_defs.h" #include "vterm_test.h" int parser_text(const char bytes[], size_t len, void *user) @@ -204,7 +208,8 @@ int selection_query(VTermSelectionMask mask, void *user) return 1; } -static void print_schar(FILE *f, schar_T schar) { +static void print_schar(FILE *f, schar_T schar) +{ char buf[MAX_SCHAR_SIZE]; schar_get(buf, schar); StrCharInfo ci = utf_ptr2StrCharInfo(buf); @@ -319,6 +324,34 @@ void print_color(const VTermColor *col) fclose(f); } +static VTermValueType vterm_get_prop_type(VTermProp prop) +{ + switch (prop) { + case VTERM_PROP_CURSORVISIBLE: + return VTERM_VALUETYPE_BOOL; + case VTERM_PROP_CURSORBLINK: + return VTERM_VALUETYPE_BOOL; + case VTERM_PROP_ALTSCREEN: + return VTERM_VALUETYPE_BOOL; + case VTERM_PROP_TITLE: + return VTERM_VALUETYPE_STRING; + case VTERM_PROP_ICONNAME: + return VTERM_VALUETYPE_STRING; + case VTERM_PROP_REVERSE: + return VTERM_VALUETYPE_BOOL; + case VTERM_PROP_CURSORSHAPE: + return VTERM_VALUETYPE_INT; + case VTERM_PROP_MOUSE: + return VTERM_VALUETYPE_INT; + case VTERM_PROP_FOCUSREPORT: + return VTERM_VALUETYPE_BOOL; + + case VTERM_N_PROPS: + return 0; + } + return 0; // UNREACHABLE +} + bool want_state_settermprop; int state_settermprop(VTermProp prop, VTermValue *val, void *user) { @@ -463,14 +496,14 @@ int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user) } int eol = cols; - while (eol && !cells[eol-1].schar) { + while (eol && !cells[eol - 1].schar) { eol--; } FILE *f = fopen(VTERM_TEST_FILE, "a"); fprintf(f, "sb_pushline %d =", cols); for (int c = 0; c < eol; c++) { - fprintf(f, " "); + fprintf(f, " "); print_schar(f, cells[c].schar); } fprintf(f, "\n"); @@ -488,7 +521,7 @@ int screen_sb_popline(int cols, VTermScreenCell *cells, void *user) // All lines of scrollback contain "ABCDE" for (int col = 0; col < cols; col++) { - if(col < 5) { + if (col < 5) { cells[col].schar = schar_from_ascii((uint32_t)('A' + col)); } else { cells[col].schar = 0; @@ -524,3 +557,231 @@ void term_output(const char *s, size_t len, void *user) } fclose(f); } + +int vterm_state_get_penattr(const VTermState *state, VTermAttr attr, VTermValue *val) +{ + switch (attr) { + case VTERM_ATTR_BOLD: + val->boolean = state->pen.bold; + return 1; + + case VTERM_ATTR_UNDERLINE: + val->number = state->pen.underline; + return 1; + + case VTERM_ATTR_ITALIC: + val->boolean = state->pen.italic; + return 1; + + case VTERM_ATTR_BLINK: + val->boolean = state->pen.blink; + return 1; + + case VTERM_ATTR_REVERSE: + val->boolean = state->pen.reverse; + return 1; + + case VTERM_ATTR_CONCEAL: + val->boolean = state->pen.conceal; + return 1; + + case VTERM_ATTR_STRIKE: + val->boolean = state->pen.strike; + return 1; + + case VTERM_ATTR_FONT: + val->number = state->pen.font; + return 1; + + case VTERM_ATTR_FOREGROUND: + val->color = state->pen.fg; + return 1; + + case VTERM_ATTR_BACKGROUND: + val->color = state->pen.bg; + return 1; + + case VTERM_ATTR_SMALL: + val->boolean = state->pen.small; + return 1; + + case VTERM_ATTR_BASELINE: + val->number = state->pen.baseline; + return 1; + + case VTERM_ATTR_URI: + val->number = state->pen.uri; + return 1; + + case VTERM_N_ATTRS: + return 0; + } + + return 0; +} + +static int attrs_differ(VTermAttrMask attrs, ScreenCell *a, ScreenCell *b) +{ + if ((attrs & VTERM_ATTR_BOLD_MASK) && (a->pen.bold != b->pen.bold)) { + return 1; + } + if ((attrs & VTERM_ATTR_UNDERLINE_MASK) && (a->pen.underline != b->pen.underline)) { + return 1; + } + if ((attrs & VTERM_ATTR_ITALIC_MASK) && (a->pen.italic != b->pen.italic)) { + return 1; + } + if ((attrs & VTERM_ATTR_BLINK_MASK) && (a->pen.blink != b->pen.blink)) { + return 1; + } + if ((attrs & VTERM_ATTR_REVERSE_MASK) && (a->pen.reverse != b->pen.reverse)) { + return 1; + } + if ((attrs & VTERM_ATTR_CONCEAL_MASK) && (a->pen.conceal != b->pen.conceal)) { + return 1; + } + if ((attrs & VTERM_ATTR_STRIKE_MASK) && (a->pen.strike != b->pen.strike)) { + return 1; + } + if ((attrs & VTERM_ATTR_FONT_MASK) && (a->pen.font != b->pen.font)) { + return 1; + } + if ((attrs & VTERM_ATTR_FOREGROUND_MASK) && !vterm_color_is_equal(&a->pen.fg, &b->pen.fg)) { + return 1; + } + if ((attrs & VTERM_ATTR_BACKGROUND_MASK) && !vterm_color_is_equal(&a->pen.bg, &b->pen.bg)) { + return 1; + } + if ((attrs & VTERM_ATTR_SMALL_MASK) && (a->pen.small != b->pen.small)) { + return 1; + } + if ((attrs & VTERM_ATTR_BASELINE_MASK) && (a->pen.baseline != b->pen.baseline)) { + return 1; + } + if ((attrs & VTERM_ATTR_URI_MASK) && (a->pen.uri != b->pen.uri)) { + return 1; + } + + return 0; +} + +int vterm_screen_get_attrs_extent(const VTermScreen *screen, VTermRect *extent, VTermPos pos, + VTermAttrMask attrs) +{ + ScreenCell *target = getcell(screen, pos.row, pos.col); + + // TODO(vterm): bounds check + extent->start_row = pos.row; + extent->end_row = pos.row + 1; + + if (extent->start_col < 0) { + extent->start_col = 0; + } + if (extent->end_col < 0) { + extent->end_col = screen->cols; + } + + int col; + + for (col = pos.col - 1; col >= extent->start_col; col--) { + if (attrs_differ(attrs, target, getcell(screen, pos.row, col))) { + break; + } + } + extent->start_col = col + 1; + + for (col = pos.col + 1; col < extent->end_col; col++) { + if (attrs_differ(attrs, target, getcell(screen, pos.row, col))) { + break; + } + } + extent->end_col = col - 1; + + return 1; +} + +/// Does not NUL-terminate the buffer +size_t vterm_screen_get_text(const VTermScreen *screen, char *buffer, size_t len, + const VTermRect rect) +{ + size_t outpos = 0; + int padding = 0; + +#define PUT(bytes, thislen) \ + if (true) { \ + if (buffer && outpos + thislen <= len) \ + memcpy((char *)buffer + outpos, bytes, thislen); \ + outpos += thislen; \ + } \ + + for (int row = rect.start_row; row < rect.end_row; row++) { + for (int col = rect.start_col; col < rect.end_col; col++) { + ScreenCell *cell = getcell(screen, row, col); + + if (cell->schar == 0) { + // Erased cell, might need a space + padding++; + } else if (cell->schar == (uint32_t)-1) { + // Gap behind a double-width char, do nothing + } else { + while (padding) { + PUT(" ", 1); + padding--; + } + char buf[MAX_SCHAR_SIZE + 1]; + size_t thislen = schar_get(buf, cell->schar); + PUT(buf, thislen); + } + } + + if (row < rect.end_row - 1) { + PUT("\n", 1); + padding = 0; + } + } + + return outpos; +} + +int vterm_screen_is_eol(const VTermScreen *screen, VTermPos pos) +{ + // This cell is EOL if this and every cell to the right is black + for (; pos.col < screen->cols; pos.col++) { + ScreenCell *cell = getcell(screen, pos.row, pos.col); + if (cell->schar != 0) { + return 0; + } + } + + return 1; +} + +void vterm_state_get_cursorpos(const VTermState *state, VTermPos *cursorpos) +{ + *cursorpos = state->pos; +} + +void vterm_state_set_bold_highbright(VTermState *state, int bold_is_highbright) +{ + state->bold_is_highbright = bold_is_highbright; +} + +/// Compares two colours. Returns true if the colors are equal, false otherwise. +int vterm_color_is_equal(const VTermColor *a, const VTermColor *b) +{ + // First make sure that the two colours are of the same type (RGB/Indexed) + if (a->type != b->type) { + return false; + } + + // Depending on the type inspect the corresponding members + if (VTERM_COLOR_IS_INDEXED(a)) { + return a->indexed.idx == b->indexed.idx; + } else if (VTERM_COLOR_IS_RGB(a)) { + return (a->rgb.red == b->rgb.red) + && (a->rgb.green == b->rgb.green) + && (a->rgb.blue == b->rgb.blue); + } + + return 0; +} diff --git a/test/unit/fixtures/vterm_test.h b/test/unit/fixtures/vterm_test.h index a05e7d499e..ef6463af6d 100644 --- a/test/unit/fixtures/vterm_test.h +++ b/test/unit/fixtures/vterm_test.h @@ -2,8 +2,17 @@ #include <stdint.h> #include "nvim/macros_defs.h" -#include "vterm/vterm.h" +#include "nvim/vterm/vterm.h" +EXTERN VTermPos state_pos; +EXTERN bool want_state_putglyph INIT (=false); +EXTERN bool want_state_movecursor INIT(= false); +EXTERN bool want_state_erase INIT(= false); +EXTERN bool want_state_scrollrect INIT(= false); +EXTERN bool want_state_moverect INIT(= false); +EXTERN bool want_state_settermprop INIT(= false); +EXTERN bool want_state_scrollback INIT(= false); +EXTERN bool want_screen_scrollback INIT(= false); int parser_text(const char bytes[], size_t len, void *user); int parser_csi(const char *leader, const long args[], int argcount, const char *intermed, char command, void *user); @@ -27,12 +36,10 @@ int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user); int screen_sb_popline(int cols, VTermScreenCell *cells, void *user); int screen_sb_clear(void *user); void term_output(const char *s, size_t len, void *user); -EXTERN VTermPos state_pos; -EXTERN bool want_state_putglyph INIT (=false); -EXTERN bool want_state_movecursor INIT(= false); -EXTERN bool want_state_erase INIT(= false); -EXTERN bool want_state_scrollrect INIT(= false); -EXTERN bool want_state_moverect INIT(= false); -EXTERN bool want_state_settermprop INIT(= false); -EXTERN bool want_state_scrollback INIT(= false); -EXTERN bool want_screen_scrollback INIT(= false); +int vterm_state_get_penattr(const VTermState *state, VTermAttr attr, VTermValue *val); +int vterm_screen_get_attrs_extent(const VTermScreen *screen, VTermRect *extent, VTermPos pos, VTermAttrMask attrs); +size_t vterm_screen_get_text(const VTermScreen *screen, char *buffer, size_t len, VTermRect rect); +int vterm_screen_is_eol(const VTermScreen *screen, VTermPos pos); +void vterm_state_get_cursorpos(const VTermState *state, VTermPos *cursorpos); +void vterm_state_set_bold_highbright(VTermState *state, int bold_is_highbright); +int vterm_color_is_equal(const VTermColor *a, const VTermColor *b); diff --git a/test/unit/vterm_spec.lua b/test/unit/vterm_spec.lua index 2457525fb7..db0aa3c575 100644 --- a/test/unit/vterm_spec.lua +++ b/test/unit/vterm_spec.lua @@ -61,7 +61,6 @@ local bit = require('bit') --- @field vterm_screen_enable_reflow function --- @field vterm_screen_get_attrs_extent function --- @field vterm_screen_get_cell function ---- @field vterm_screen_get_chars fun(any, any, any, any):any --- @field vterm_screen_get_text fun(any, any, any, any):any --- @field vterm_screen_is_eol fun(any, any):any --- @field vterm_screen_reset function @@ -79,10 +78,17 @@ local bit = require('bit') --- @field vterm_state_set_selection_callbacks function --- @field vterm_state_set_unrecognised_fallbacks function local vterm = t.cimport( - './src/nvim/mbyte.h', './src/nvim/grid.h', - './src/vterm/vterm.h', - './src/vterm/vterm_internal.h', + './src/nvim/mbyte.h', + './src/nvim/vterm/encoding.h', + './src/nvim/vterm/keyboard.h', + './src/nvim/vterm/mouse.h', + './src/nvim/vterm/parser.h', + './src/nvim/vterm/pen.h', + './src/nvim/vterm/screen.h', + './src/nvim/vterm/state.h', + './src/nvim/vterm/vterm.h', + './src/nvim/vterm/vterm_internal.h', './test/unit/fixtures/vterm_test.h' ) |