mirror of
https://github.com/neovim/neovim.git
synced 2026-03-31 12:52:13 +00:00
feat(terminal): support SGR dim, overline attributes #37997
Problem: libvterm doesn't support parsing the dim and overline attributes, so when a program running in the embedded terminal emits one of these escape codes, we ignore it and don't surface it to the outer terminal. Solution: tweak libvterm to add support for both attributes.
This commit is contained in:
committed by
GitHub
parent
5cbb9d613b
commit
2368a9edbd
@@ -1405,8 +1405,10 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *te
|
||||
bool bg_set = vt_bg_idx && vt_bg_idx <= 16 && term->color_set[vt_bg_idx - 1];
|
||||
|
||||
int hl_attrs = (cell.attrs.bold ? HL_BOLD : 0)
|
||||
| (cell.attrs.dim ? HL_DIM : 0)
|
||||
| (cell.attrs.blink ? HL_BLINK : 0)
|
||||
| (cell.attrs.conceal ? HL_CONCEALED : 0)
|
||||
| (cell.attrs.overline ? HL_OVERLINE : 0)
|
||||
| (cell.attrs.italic ? HL_ITALIC : 0)
|
||||
| (cell.attrs.reverse ? HL_INVERSE : 0)
|
||||
| get_underline_hl_flag(cell.attrs)
|
||||
|
||||
@@ -182,6 +182,8 @@ void vterm_state_resetpen(VTermState *state)
|
||||
state->pen.font = 0; setpenattr_int(state, VTERM_ATTR_FONT, 0);
|
||||
state->pen.small = 0; setpenattr_bool(state, VTERM_ATTR_SMALL, 0);
|
||||
state->pen.baseline = 0; setpenattr_int(state, VTERM_ATTR_BASELINE, 0);
|
||||
state->pen.dim = 0; setpenattr_bool(state, VTERM_ATTR_DIM, 0);
|
||||
state->pen.overline = 0; setpenattr_bool(state, VTERM_ATTR_OVERLINE, 0);
|
||||
|
||||
state->pen.fg = state->default_fg;
|
||||
setpenattr_col(state, VTERM_ATTR_FOREGROUND, state->default_fg);
|
||||
@@ -208,6 +210,8 @@ void vterm_state_savepen(VTermState *state, int save)
|
||||
setpenattr_int(state, VTERM_ATTR_FONT, state->pen.font);
|
||||
setpenattr_bool(state, VTERM_ATTR_SMALL, state->pen.small);
|
||||
setpenattr_int(state, VTERM_ATTR_BASELINE, state->pen.baseline);
|
||||
setpenattr_bool(state, VTERM_ATTR_DIM, state->pen.dim);
|
||||
setpenattr_bool(state, VTERM_ATTR_OVERLINE, state->pen.overline);
|
||||
|
||||
setpenattr_col(state, VTERM_ATTR_FOREGROUND, state->pen.fg);
|
||||
setpenattr_col(state, VTERM_ATTR_BACKGROUND, state->pen.bg);
|
||||
@@ -285,6 +289,11 @@ void vterm_state_setpen(VTermState *state, const long args[], int argcount)
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: // Dim/faint on
|
||||
state->pen.dim = 1;
|
||||
setpenattr_bool(state, VTERM_ATTR_DIM, 1);
|
||||
break;
|
||||
|
||||
case 3: // Italic on
|
||||
state->pen.italic = 1;
|
||||
setpenattr_bool(state, VTERM_ATTR_ITALIC, 1);
|
||||
@@ -351,9 +360,11 @@ void vterm_state_setpen(VTermState *state, const long args[], int argcount)
|
||||
setpenattr_int(state, VTERM_ATTR_UNDERLINE, state->pen.underline);
|
||||
break;
|
||||
|
||||
case 22: // Bold off
|
||||
case 22: // Normal intensity (bold and dim off)
|
||||
state->pen.bold = 0;
|
||||
setpenattr_bool(state, VTERM_ATTR_BOLD, 0);
|
||||
state->pen.dim = 0;
|
||||
setpenattr_bool(state, VTERM_ATTR_DIM, 0);
|
||||
break;
|
||||
|
||||
case 23: // Italic and Gothic (currently unsupported) off
|
||||
@@ -441,6 +452,16 @@ void vterm_state_setpen(VTermState *state, const long args[], int argcount)
|
||||
setpenattr_col(state, VTERM_ATTR_BACKGROUND, state->pen.bg);
|
||||
break;
|
||||
|
||||
case 53: // Overline on
|
||||
state->pen.overline = 1;
|
||||
setpenattr_bool(state, VTERM_ATTR_OVERLINE, 1);
|
||||
break;
|
||||
|
||||
case 55: // Overline off
|
||||
state->pen.overline = 0;
|
||||
setpenattr_bool(state, VTERM_ATTR_OVERLINE, 0);
|
||||
break;
|
||||
|
||||
case 73: // Superscript
|
||||
case 74: // Subscript
|
||||
case 75: // Superscript/subscript off
|
||||
@@ -528,6 +549,10 @@ int vterm_state_getpen(VTermState *state, long args[], int argcount)
|
||||
args[argi++] = 1;
|
||||
}
|
||||
|
||||
if (state->pen.dim) {
|
||||
args[argi++] = 2;
|
||||
}
|
||||
|
||||
if (state->pen.italic) {
|
||||
args[argi++] = 3;
|
||||
}
|
||||
@@ -567,6 +592,10 @@ int vterm_state_getpen(VTermState *state, long args[], int argcount)
|
||||
|
||||
argi = vterm_state_getpen_color(&state->pen.bg, argi, args, false);
|
||||
|
||||
if (state->pen.overline) {
|
||||
args[argi++] = 53;
|
||||
}
|
||||
|
||||
if (state->pen.small) {
|
||||
if (state->pen.baseline == VTERM_BASELINE_RAISE) {
|
||||
args[argi++] = 73;
|
||||
@@ -630,6 +659,12 @@ int vterm_state_set_penattr(VTermState *state, VTermAttr attr, VTermValueType ty
|
||||
case VTERM_ATTR_URI:
|
||||
state->pen.uri = val->number;
|
||||
break;
|
||||
case VTERM_ATTR_DIM:
|
||||
state->pen.dim = (unsigned)val->boolean;
|
||||
break;
|
||||
case VTERM_ATTR_OVERLINE:
|
||||
state->pen.overline = (unsigned)val->boolean;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -399,6 +399,12 @@ static int setpenattr(VTermAttr attr, VTermValue *val, void *user)
|
||||
case VTERM_ATTR_URI:
|
||||
screen->pen.uri = val->number;
|
||||
return 1;
|
||||
case VTERM_ATTR_DIM:
|
||||
screen->pen.dim = (unsigned)val->boolean;
|
||||
return 1;
|
||||
case VTERM_ATTR_OVERLINE:
|
||||
screen->pen.overline = (unsigned)val->boolean;
|
||||
return 1;
|
||||
|
||||
case VTERM_N_ATTRS:
|
||||
return 0;
|
||||
@@ -670,6 +676,8 @@ static void resize_buffer(VTermScreen *screen, int bufidx, int new_rows, int new
|
||||
dst->pen.font = src->attrs.font;
|
||||
dst->pen.small = src->attrs.small;
|
||||
dst->pen.baseline = src->attrs.baseline;
|
||||
dst->pen.dim = src->attrs.dim;
|
||||
dst->pen.overline = src->attrs.overline;
|
||||
|
||||
dst->pen.fg = src->fg;
|
||||
dst->pen.bg = src->bg;
|
||||
@@ -931,6 +939,8 @@ int vterm_screen_get_cell(const VTermScreen *screen, VTermPos pos, VTermScreenCe
|
||||
cell->attrs.font = intcell->pen.font;
|
||||
cell->attrs.small = intcell->pen.small;
|
||||
cell->attrs.baseline = intcell->pen.baseline;
|
||||
cell->attrs.dim = intcell->pen.dim;
|
||||
cell->attrs.overline = intcell->pen.overline;
|
||||
|
||||
cell->attrs.dwl = intcell->pen.dwl;
|
||||
cell->attrs.dhl = intcell->pen.dhl;
|
||||
|
||||
@@ -260,6 +260,10 @@ VTermValueType vterm_get_attr_type(VTermAttr attr)
|
||||
return VTERM_VALUETYPE_INT;
|
||||
case VTERM_ATTR_URI:
|
||||
return VTERM_VALUETYPE_INT;
|
||||
case VTERM_ATTR_DIM:
|
||||
return VTERM_VALUETYPE_BOOL;
|
||||
case VTERM_ATTR_OVERLINE:
|
||||
return VTERM_VALUETYPE_BOOL;
|
||||
|
||||
case VTERM_N_ATTRS:
|
||||
return 0;
|
||||
|
||||
@@ -65,6 +65,8 @@ typedef struct {
|
||||
unsigned dhl : 2; // On a DECDHL line (1=top 2=bottom)
|
||||
unsigned small : 1;
|
||||
unsigned baseline : 2;
|
||||
unsigned dim : 1;
|
||||
unsigned overline : 1;
|
||||
} VTermScreenCellAttrs;
|
||||
|
||||
typedef struct {
|
||||
@@ -158,8 +160,10 @@ typedef enum {
|
||||
VTERM_ATTR_SMALL_MASK = 1 << 10,
|
||||
VTERM_ATTR_BASELINE_MASK = 1 << 11,
|
||||
VTERM_ATTR_URI_MASK = 1 << 12,
|
||||
VTERM_ATTR_DIM_MASK = 1 << 13,
|
||||
VTERM_ATTR_OVERLINE_MASK = 1 << 14,
|
||||
|
||||
VTERM_ALL_ATTRS_MASK = (1 << 13) - 1,
|
||||
VTERM_ALL_ATTRS_MASK = (1 << 15) - 1,
|
||||
} VTermAttrMask;
|
||||
|
||||
typedef enum {
|
||||
@@ -187,6 +191,8 @@ typedef enum {
|
||||
VTERM_ATTR_SMALL, // bool: 73, 74, 75
|
||||
VTERM_ATTR_BASELINE, // number: 73, 74, 75
|
||||
VTERM_ATTR_URI, // number
|
||||
VTERM_ATTR_DIM, // bool: 2, 22
|
||||
VTERM_ATTR_OVERLINE, // bool: 53, 55
|
||||
|
||||
VTERM_N_ATTRS,
|
||||
} VTermAttr;
|
||||
@@ -314,6 +320,8 @@ typedef struct {
|
||||
unsigned font : 4; // 0 to 9
|
||||
unsigned small : 1;
|
||||
unsigned baseline : 2;
|
||||
unsigned dim : 1;
|
||||
unsigned overline : 1;
|
||||
|
||||
// Extra state storage that isn't strictly pen-related
|
||||
unsigned protected_cell : 1;
|
||||
|
||||
@@ -51,6 +51,8 @@ struct VTermPen {
|
||||
unsigned font:4; // To store 0-9
|
||||
unsigned small:1;
|
||||
unsigned baseline:2;
|
||||
unsigned dim:1;
|
||||
unsigned overline:1;
|
||||
};
|
||||
|
||||
// https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement
|
||||
|
||||
@@ -423,6 +423,8 @@ struct {
|
||||
int font;
|
||||
int small;
|
||||
int baseline;
|
||||
int dim;
|
||||
int overline;
|
||||
VTermColor foreground;
|
||||
VTermColor background;
|
||||
} state_pen;
|
||||
@@ -460,6 +462,12 @@ int state_setpenattr(VTermAttr attr, VTermValue *val, void *user)
|
||||
case VTERM_ATTR_BASELINE:
|
||||
state_pen.baseline = val->number;
|
||||
break;
|
||||
case VTERM_ATTR_DIM:
|
||||
state_pen.dim = val->boolean;
|
||||
break;
|
||||
case VTERM_ATTR_OVERLINE:
|
||||
state_pen.overline = val->boolean;
|
||||
break;
|
||||
case VTERM_ATTR_FOREGROUND:
|
||||
state_pen.foreground = val->color;
|
||||
break;
|
||||
@@ -615,6 +623,14 @@ int vterm_state_get_penattr(const VTermState *state, VTermAttr attr, VTermValue
|
||||
val->number = state->pen.uri;
|
||||
return 1;
|
||||
|
||||
case VTERM_ATTR_DIM:
|
||||
val->boolean = state->pen.dim;
|
||||
return 1;
|
||||
|
||||
case VTERM_ATTR_OVERLINE:
|
||||
val->boolean = state->pen.overline;
|
||||
return 1;
|
||||
|
||||
case VTERM_N_ATTRS:
|
||||
return 0;
|
||||
}
|
||||
@@ -663,6 +679,12 @@ static int attrs_differ(VTermAttrMask attrs, ScreenCell *a, ScreenCell *b)
|
||||
if ((attrs & VTERM_ATTR_URI_MASK) && (a->pen.uri != b->pen.uri)) {
|
||||
return 1;
|
||||
}
|
||||
if ((attrs & VTERM_ATTR_DIM_MASK) && (a->pen.dim != b->pen.dim)) {
|
||||
return 1;
|
||||
}
|
||||
if ((attrs & VTERM_ATTR_OVERLINE_MASK) && (a->pen.overline != b->pen.overline)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -285,7 +285,8 @@ local function lineinfo(row, expected, state)
|
||||
end
|
||||
|
||||
local function pen(attribute, expected, state)
|
||||
local is_bool = { bold = true, italic = true, blink = true, reverse = true }
|
||||
local is_bool =
|
||||
{ bold = true, italic = true, blink = true, reverse = true, dim = true, overline = true }
|
||||
local vterm_attribute = {
|
||||
bold = vterm.VTERM_ATTR_BOLD,
|
||||
underline = vterm.VTERM_ATTR_UNDERLINE,
|
||||
@@ -293,6 +294,8 @@ local function pen(attribute, expected, state)
|
||||
blink = vterm.VTERM_ATTR_BLINK,
|
||||
reverse = vterm.VTERM_ATTR_REVERSE,
|
||||
font = vterm.VTERM_ATTR_FONT,
|
||||
dim = vterm.VTERM_ATTR_DIM,
|
||||
overline = vterm.VTERM_ATTR_OVERLINE,
|
||||
}
|
||||
|
||||
local val = t.ffi.new('VTermValue') --- @type {boolean: integer}
|
||||
@@ -386,11 +389,13 @@ local function screen_cell(row, col, expected, screen)
|
||||
end
|
||||
actual = string.format('%s} width=%d attrs={', actual, cell['width'])
|
||||
actual = actual .. (cell['attrs'].bold ~= 0 and 'B' or '')
|
||||
actual = actual .. (cell['attrs'].dim ~= 0 and 'D' or '')
|
||||
actual = actual
|
||||
.. (cell['attrs'].underline ~= 0 and string.format('U%d', cell['attrs'].underline) or '')
|
||||
actual = actual .. (cell['attrs'].italic ~= 0 and 'I' or '')
|
||||
actual = actual .. (cell['attrs'].blink ~= 0 and 'K' or '')
|
||||
actual = actual .. (cell['attrs'].reverse ~= 0 and 'R' or '')
|
||||
actual = actual .. (cell['attrs'].overline ~= 0 and 'O' or '')
|
||||
actual = actual .. (cell['attrs'].font ~= 0 and string.format('F%d', cell['attrs'].font) or '')
|
||||
actual = actual .. (cell['attrs'].small ~= 0 and 'S' or '')
|
||||
if cell['attrs'].baseline ~= 0 then
|
||||
@@ -2950,6 +2955,30 @@ putglyph 1f3f4,200d,2620,fe0f 2 0,4]])
|
||||
push('\x1b[11m\x1b[m', vt)
|
||||
pen('font', 0, state)
|
||||
|
||||
-- Dim
|
||||
push('\x1b[2m', vt)
|
||||
pen('dim', true, state)
|
||||
push('\x1b[22m', vt)
|
||||
pen('dim', false, state)
|
||||
push('\x1b[2m\x1b[m', vt)
|
||||
pen('dim', false, state)
|
||||
|
||||
-- Bold and Dim interaction (SGR 22 turns off both)
|
||||
push('\x1b[1;2m', vt)
|
||||
pen('bold', true, state)
|
||||
pen('dim', true, state)
|
||||
push('\x1b[22m', vt)
|
||||
pen('bold', false, state)
|
||||
pen('dim', false, state)
|
||||
|
||||
-- Overline
|
||||
push('\x1b[53m', vt)
|
||||
pen('overline', true, state)
|
||||
push('\x1b[55m', vt)
|
||||
pen('overline', false, state)
|
||||
push('\x1b[53m\x1b[m', vt)
|
||||
pen('overline', false, state)
|
||||
|
||||
-- TODO(dundargoc): fix
|
||||
-- Foreground
|
||||
-- push "\x1b[31m"
|
||||
@@ -3485,6 +3514,14 @@ putglyph 1f3f4,200d,2620,fe0f 2 0,4]])
|
||||
screen_cell(0, 9, '{30} width=1 attrs={S_} fg=rgb(240,240,240) bg=rgb(0,0,0)', screen)
|
||||
screen_cell(0, 10, '{32} width=1 attrs={S^} fg=rgb(240,240,240) bg=rgb(0,0,0)', screen)
|
||||
|
||||
-- Dim
|
||||
push('\x1b[2mI\x1b[m', vt)
|
||||
screen_cell(0, 11, '{49} width=1 attrs={D} fg=rgb(240,240,240) bg=rgb(0,0,0)', screen)
|
||||
|
||||
-- Overline
|
||||
push('\x1b[53mJ\x1b[m', vt)
|
||||
screen_cell(0, 12, '{4a} width=1 attrs={O} fg=rgb(240,240,240) bg=rgb(0,0,0)', screen)
|
||||
|
||||
-- EL sets only colours to end of line, not other attrs
|
||||
push('\x1b[H\x1b[7;33;44m\x1b[K', vt)
|
||||
screen_cell(0, 0, '{} width=1 attrs={} fg=rgb(224,224,0) bg=rgb(0,0,224)', screen)
|
||||
|
||||
Reference in New Issue
Block a user