mirror of
https://github.com/neovim/neovim.git
synced 2025-09-13 06:48:17 +00:00
syntax, TUI: support "strikethrough"
fix #3436 Includes: vim-patch:8.0.1038: strike-through text not supported
This commit is contained in:

committed by
Justin M. Keyes

parent
35341b34b8
commit
3afb397407
@@ -8397,6 +8397,7 @@ synIDattr({synID}, {what} [, {mode}]) *synIDattr()*
|
|||||||
"standout" "1" if standout
|
"standout" "1" if standout
|
||||||
"underline" "1" if underlined
|
"underline" "1" if underlined
|
||||||
"undercurl" "1" if undercurled
|
"undercurl" "1" if undercurled
|
||||||
|
"strikethrough" "1" if struckthrough
|
||||||
|
|
||||||
Example (echoes the color of the syntax item under the
|
Example (echoes the color of the syntax item under the
|
||||||
cursor): >
|
cursor): >
|
||||||
|
@@ -4720,6 +4720,7 @@ the same syntax file on all UIs.
|
|||||||
|
|
||||||
*bold* *underline* *undercurl*
|
*bold* *underline* *undercurl*
|
||||||
*inverse* *italic* *standout*
|
*inverse* *italic* *standout*
|
||||||
|
*strikethrough*
|
||||||
cterm={attr-list} *attr-list* *highlight-cterm* *E418*
|
cterm={attr-list} *attr-list* *highlight-cterm* *E418*
|
||||||
attr-list is a comma separated list (without spaces) of the
|
attr-list is a comma separated list (without spaces) of the
|
||||||
following items (in any order):
|
following items (in any order):
|
||||||
@@ -4730,6 +4731,7 @@ cterm={attr-list} *attr-list* *highlight-cterm* *E418*
|
|||||||
inverse same as reverse
|
inverse same as reverse
|
||||||
italic
|
italic
|
||||||
standout
|
standout
|
||||||
|
strikethrough
|
||||||
NONE no attributes used (used to reset it)
|
NONE no attributes used (used to reset it)
|
||||||
|
|
||||||
Note that "bold" can be used here and by using a bold font. They
|
Note that "bold" can be used here and by using a bold font. They
|
||||||
|
@@ -290,6 +290,7 @@ numerical highlight ids to the actual attributes.
|
|||||||
switched.
|
switched.
|
||||||
`italic`: italic text.
|
`italic`: italic text.
|
||||||
`bold`: bold text.
|
`bold`: bold text.
|
||||||
|
`strikethrough`: struckthrough text.
|
||||||
`underline`: underlined text. The line has `special` color.
|
`underline`: underlined text. The line has `special` color.
|
||||||
`undercurl`: undercurled text. The curl has `special` color.
|
`undercurl`: undercurled text. The curl has `special` color.
|
||||||
`blend`: Blend level (0-100). Could be used by UIs to support
|
`blend`: Blend level (0-100). Could be used by UIs to support
|
||||||
@@ -447,6 +448,7 @@ is not active. New UIs should implement |ui-linegrid| instead.
|
|||||||
switched.
|
switched.
|
||||||
`italic`: italic text.
|
`italic`: italic text.
|
||||||
`bold`: bold text.
|
`bold`: bold text.
|
||||||
|
`strikethrough`: struckthrough text.
|
||||||
`underline`: underlined text. The line has `special` color.
|
`underline`: underlined text. The line has `special` color.
|
||||||
`undercurl`: undercurled text. The curl has `special` color.
|
`undercurl`: undercurled text. The curl has `special` color.
|
||||||
|
|
||||||
|
@@ -17584,6 +17584,9 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
case 's': {
|
case 's': {
|
||||||
if (TOLOWER_ASC(what[1]) == 'p') { // sp[#]
|
if (TOLOWER_ASC(what[1]) == 'p') { // sp[#]
|
||||||
p = highlight_color(id, what, modec);
|
p = highlight_color(id, what, modec);
|
||||||
|
} else if (TOLOWER_ASC(what[1]) == 't'
|
||||||
|
&& TOLOWER_ASC(what[2]) == 'r') { // strikethrough
|
||||||
|
p = highlight_has_attr(id, HL_STRIKETHROUGH, modec);
|
||||||
} else { // standout
|
} else { // standout
|
||||||
p = highlight_has_attr(id, HL_STANDOUT, modec);
|
p = highlight_has_attr(id, HL_STANDOUT, modec);
|
||||||
}
|
}
|
||||||
|
@@ -598,6 +598,10 @@ Dictionary hlattrs2dict(HlAttrs ae, bool use_rgb)
|
|||||||
PUT(hl, "reverse", BOOLEAN_OBJ(true));
|
PUT(hl, "reverse", BOOLEAN_OBJ(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mask & HL_STRIKETHROUGH) {
|
||||||
|
PUT(hl, "strikethrough", BOOLEAN_OBJ(true));
|
||||||
|
}
|
||||||
|
|
||||||
if (use_rgb) {
|
if (use_rgb) {
|
||||||
if (ae.rgb_fg_color != -1) {
|
if (ae.rgb_fg_color != -1) {
|
||||||
PUT(hl, "foreground", INTEGER_OBJ(ae.rgb_fg_color));
|
PUT(hl, "foreground", INTEGER_OBJ(ae.rgb_fg_color));
|
||||||
|
@@ -17,6 +17,7 @@ typedef enum {
|
|||||||
HL_UNDERLINE = 0x08,
|
HL_UNDERLINE = 0x08,
|
||||||
HL_UNDERCURL = 0x10,
|
HL_UNDERCURL = 0x10,
|
||||||
HL_STANDOUT = 0x20,
|
HL_STANDOUT = 0x20,
|
||||||
|
HL_STRIKETHROUGH = 0x40,
|
||||||
} HlAttrFlags;
|
} HlAttrFlags;
|
||||||
|
|
||||||
/// Stores a complete highlighting entry, including colors and attributes
|
/// Stores a complete highlighting entry, including colors and attributes
|
||||||
|
@@ -116,10 +116,10 @@ static int include_link = 0; /* when 2 include "nvim/link" and "clear" */
|
|||||||
/// following names, separated by commas (but no spaces!).
|
/// following names, separated by commas (but no spaces!).
|
||||||
static char *(hl_name_table[]) =
|
static char *(hl_name_table[]) =
|
||||||
{ "bold", "standout", "underline", "undercurl",
|
{ "bold", "standout", "underline", "undercurl",
|
||||||
"italic", "reverse", "inverse", "NONE"};
|
"italic", "reverse", "inverse", "strikethrough", "NONE" };
|
||||||
static int hl_attr_table[] =
|
static int hl_attr_table[] =
|
||||||
{ HL_BOLD, HL_STANDOUT, HL_UNDERLINE, HL_UNDERCURL, HL_ITALIC, HL_INVERSE,
|
{ HL_BOLD, HL_STANDOUT, HL_UNDERLINE, HL_UNDERCURL, HL_ITALIC, HL_INVERSE,
|
||||||
HL_INVERSE, 0};
|
HL_INVERSE, HL_STRIKETHROUGH, 0 };
|
||||||
|
|
||||||
// The patterns that are being searched for are stored in a syn_pattern.
|
// The patterns that are being searched for are stored in a syn_pattern.
|
||||||
// A match item consists of one pattern.
|
// A match item consists of one pattern.
|
||||||
|
@@ -605,7 +605,8 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr,
|
|||||||
int hl_attrs = (cell.attrs.bold ? HL_BOLD : 0)
|
int hl_attrs = (cell.attrs.bold ? HL_BOLD : 0)
|
||||||
| (cell.attrs.italic ? HL_ITALIC : 0)
|
| (cell.attrs.italic ? HL_ITALIC : 0)
|
||||||
| (cell.attrs.reverse ? HL_INVERSE : 0)
|
| (cell.attrs.reverse ? HL_INVERSE : 0)
|
||||||
| (cell.attrs.underline ? HL_UNDERLINE : 0);
|
| (cell.attrs.underline ? HL_UNDERLINE : 0)
|
||||||
|
| (cell.attrs.strike ? HL_STRIKETHROUGH: 0);
|
||||||
|
|
||||||
int attr_id = 0;
|
int attr_id = 0;
|
||||||
|
|
||||||
|
@@ -115,6 +115,7 @@ typedef struct {
|
|||||||
int enable_mouse, disable_mouse;
|
int enable_mouse, disable_mouse;
|
||||||
int enable_bracketed_paste, disable_bracketed_paste;
|
int enable_bracketed_paste, disable_bracketed_paste;
|
||||||
int enable_lr_margin, disable_lr_margin;
|
int enable_lr_margin, disable_lr_margin;
|
||||||
|
int enter_strikethrough_mode;
|
||||||
int set_rgb_foreground, set_rgb_background;
|
int set_rgb_foreground, set_rgb_background;
|
||||||
int set_cursor_color;
|
int set_cursor_color;
|
||||||
int reset_cursor_color;
|
int reset_cursor_color;
|
||||||
@@ -208,6 +209,7 @@ static void terminfo_start(UI *ui)
|
|||||||
data->unibi_ext.reset_cursor_color = -1;
|
data->unibi_ext.reset_cursor_color = -1;
|
||||||
data->unibi_ext.enable_bracketed_paste = -1;
|
data->unibi_ext.enable_bracketed_paste = -1;
|
||||||
data->unibi_ext.disable_bracketed_paste = -1;
|
data->unibi_ext.disable_bracketed_paste = -1;
|
||||||
|
data->unibi_ext.enter_strikethrough_mode = -1;
|
||||||
data->unibi_ext.enable_lr_margin = -1;
|
data->unibi_ext.enable_lr_margin = -1;
|
||||||
data->unibi_ext.disable_lr_margin = -1;
|
data->unibi_ext.disable_lr_margin = -1;
|
||||||
data->unibi_ext.enable_focus_reporting = -1;
|
data->unibi_ext.enable_focus_reporting = -1;
|
||||||
@@ -529,6 +531,7 @@ static void update_attrs(UI *ui, int attr_id)
|
|||||||
bool italic = attr & HL_ITALIC;
|
bool italic = attr & HL_ITALIC;
|
||||||
bool reverse = attr & HL_INVERSE;
|
bool reverse = attr & HL_INVERSE;
|
||||||
bool standout = attr & HL_STANDOUT;
|
bool standout = attr & HL_STANDOUT;
|
||||||
|
bool strikethrough = attr & HL_STRIKETHROUGH;
|
||||||
|
|
||||||
bool underline;
|
bool underline;
|
||||||
bool undercurl;
|
bool undercurl;
|
||||||
@@ -575,6 +578,9 @@ static void update_attrs(UI *ui, int attr_id)
|
|||||||
if (italic) {
|
if (italic) {
|
||||||
unibi_out(ui, unibi_enter_italics_mode);
|
unibi_out(ui, unibi_enter_italics_mode);
|
||||||
}
|
}
|
||||||
|
if (strikethrough && data->unibi_ext.enter_strikethrough_mode != -1) {
|
||||||
|
unibi_out_ext(ui, data->unibi_ext.enter_strikethrough_mode);
|
||||||
|
}
|
||||||
if (undercurl && data->unibi_ext.set_underline_style != -1) {
|
if (undercurl && data->unibi_ext.set_underline_style != -1) {
|
||||||
UNIBI_SET_NUM_VAR(data->params[0], 3);
|
UNIBI_SET_NUM_VAR(data->params[0], 3);
|
||||||
unibi_out_ext(ui, data->unibi_ext.set_underline_style);
|
unibi_out_ext(ui, data->unibi_ext.set_underline_style);
|
||||||
@@ -615,13 +621,14 @@ static void update_attrs(UI *ui, int attr_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
data->default_attr = fg == -1 && bg == -1
|
data->default_attr = fg == -1 && bg == -1
|
||||||
&& !bold && !italic && !underline && !undercurl && !reverse && !standout;
|
&& !bold && !italic && !underline && !undercurl && !reverse && !standout
|
||||||
|
&& !strikethrough;
|
||||||
|
|
||||||
// Non-BCE terminals can't clear with non-default background color. Some BCE
|
// Non-BCE terminals can't clear with non-default background color. Some BCE
|
||||||
// terminals don't support attributes either, so don't rely on it. But assume
|
// terminals don't support attributes either, so don't rely on it. But assume
|
||||||
// italic and bold has no effect if there is no text.
|
// italic and bold has no effect if there is no text.
|
||||||
data->can_clear_attr = !reverse && !standout && !underline && !undercurl
|
data->can_clear_attr = !reverse && !standout && !underline && !undercurl
|
||||||
&& (data->bce || bg == -1);
|
&& !strikethrough && (data->bce || bg == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void final_column_wrap(UI *ui)
|
static void final_column_wrap(UI *ui)
|
||||||
@@ -1826,6 +1833,11 @@ static void augment_terminfo(TUIData *data, const char *term,
|
|||||||
"\x1b[r");
|
"\x1b[r");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// terminfo describes strikethrough modes as rmxx/smxx with respect
|
||||||
|
// to the ECMA-48 strikeout/crossed-out attributes.
|
||||||
|
data->unibi_ext.enter_strikethrough_mode = (int)unibi_find_ext_str(
|
||||||
|
ut, "smxx");
|
||||||
|
|
||||||
// Dickey ncurses terminfo does not include the setrgbf and setrgbb
|
// Dickey ncurses terminfo does not include the setrgbf and setrgbb
|
||||||
// capabilities, proposed by Rüdiger Sonderfeld on 2013-10-15. Adding
|
// capabilities, proposed by Rüdiger Sonderfeld on 2013-10-15. Adding
|
||||||
// them here when terminfo lacks them is an augmentation, not a fixup.
|
// them here when terminfo lacks them is an augmentation, not a fixup.
|
||||||
|
@@ -25,6 +25,7 @@ describe('API: highlight',function()
|
|||||||
reverse = true,
|
reverse = true,
|
||||||
undercurl = true,
|
undercurl = true,
|
||||||
underline = true,
|
underline = true,
|
||||||
|
strikethrough = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
before_each(function()
|
before_each(function()
|
||||||
@@ -46,7 +47,7 @@ describe('API: highlight',function()
|
|||||||
eq('Invalid highlight id: 30000', string.match(emsg, 'Invalid.*'))
|
eq('Invalid highlight id: 30000', string.match(emsg, 'Invalid.*'))
|
||||||
|
|
||||||
-- Test all highlight properties.
|
-- Test all highlight properties.
|
||||||
command('hi NewHighlight gui=underline,bold,undercurl,italic,reverse')
|
command('hi NewHighlight gui=underline,bold,undercurl,italic,reverse,strikethrough')
|
||||||
eq(expected_rgb2, nvim("get_hl_by_id", hl_id, true))
|
eq(expected_rgb2, nvim("get_hl_by_id", hl_id, true))
|
||||||
|
|
||||||
-- Test nil argument.
|
-- Test nil argument.
|
||||||
|
@@ -29,6 +29,7 @@ local function set_bg(num) feed_termcode('[48;5;'..num..'m') end
|
|||||||
local function set_bold() feed_termcode('[1m') end
|
local function set_bold() feed_termcode('[1m') end
|
||||||
local function set_italic() feed_termcode('[3m') end
|
local function set_italic() feed_termcode('[3m') end
|
||||||
local function set_underline() feed_termcode('[4m') end
|
local function set_underline() feed_termcode('[4m') end
|
||||||
|
local function set_strikethrough() feed_termcode('[9m') end
|
||||||
local function clear_attrs() feed_termcode('[0;10m') end
|
local function clear_attrs() feed_termcode('[0;10m') end
|
||||||
-- mouse
|
-- mouse
|
||||||
local function enable_mouse() feed_termcode('[?1002h') end
|
local function enable_mouse() feed_termcode('[?1002h') end
|
||||||
@@ -113,6 +114,7 @@ return {
|
|||||||
set_bold = set_bold,
|
set_bold = set_bold,
|
||||||
set_italic = set_italic,
|
set_italic = set_italic,
|
||||||
set_underline = set_underline,
|
set_underline = set_underline,
|
||||||
|
set_strikethrough = set_strikethrough,
|
||||||
clear_attrs = clear_attrs,
|
clear_attrs = clear_attrs,
|
||||||
enable_mouse = enable_mouse,
|
enable_mouse = enable_mouse,
|
||||||
disable_mouse = disable_mouse,
|
disable_mouse = disable_mouse,
|
||||||
|
@@ -18,7 +18,7 @@ describe(':terminal highlight', function()
|
|||||||
[1] = {foreground = 45},
|
[1] = {foreground = 45},
|
||||||
[2] = {background = 46},
|
[2] = {background = 46},
|
||||||
[3] = {foreground = 45, background = 46},
|
[3] = {foreground = 45, background = 46},
|
||||||
[4] = {bold = true, italic = true, underline = true},
|
[4] = {bold = true, italic = true, underline = true, strikethrough = true},
|
||||||
[5] = {bold = true},
|
[5] = {bold = true},
|
||||||
[6] = {foreground = 12},
|
[6] = {foreground = 12},
|
||||||
[7] = {bold = true, reverse = true},
|
[7] = {bold = true, reverse = true},
|
||||||
@@ -108,10 +108,11 @@ describe(':terminal highlight', function()
|
|||||||
thelpers.set_fg(45)
|
thelpers.set_fg(45)
|
||||||
thelpers.set_bg(46)
|
thelpers.set_bg(46)
|
||||||
end)
|
end)
|
||||||
descr('bold, italics and underline', 4, function()
|
descr('bold, italics, underline and strikethrough', 4, function()
|
||||||
thelpers.set_bold()
|
thelpers.set_bold()
|
||||||
thelpers.set_italic()
|
thelpers.set_italic()
|
||||||
thelpers.set_underline()
|
thelpers.set_underline()
|
||||||
|
thelpers.set_strikethrough()
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -215,7 +216,7 @@ describe('synIDattr()', function()
|
|||||||
screen = Screen.new(50, 7)
|
screen = Screen.new(50, 7)
|
||||||
command('highlight Normal ctermfg=252 guifg=#ff0000 guibg=Black')
|
command('highlight Normal ctermfg=252 guifg=#ff0000 guibg=Black')
|
||||||
-- Salmon #fa8072 Maroon #800000
|
-- Salmon #fa8072 Maroon #800000
|
||||||
command('highlight Keyword ctermfg=79 guifg=Salmon guisp=Maroon')
|
command('highlight Keyword ctermfg=79 guifg=Salmon guisp=Maroon cterm=strikethrough gui=strikethrough')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('returns cterm-color if RGB-capable UI is _not_ attached', function()
|
it('returns cterm-color if RGB-capable UI is _not_ attached', function()
|
||||||
@@ -255,6 +256,12 @@ describe('synIDattr()', function()
|
|||||||
eq('252', eval('synIDattr(hlID("Normal"), "fg")'))
|
eq('252', eval('synIDattr(hlID("Normal"), "fg")'))
|
||||||
eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
|
eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('returns "1" if group has "strikethrough" attribute', function()
|
||||||
|
eq('', eval('synIDattr(hlID("Normal"), "strikethrough")'))
|
||||||
|
eq('1', eval('synIDattr(hlID("Keyword"), "strikethrough")'))
|
||||||
|
eq('1', eval('synIDattr(hlID("Keyword"), "strikethrough", "gui")'))
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('fg/bg special colors', function()
|
describe('fg/bg special colors', function()
|
||||||
|
@@ -412,6 +412,32 @@ describe('highlight', function()
|
|||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('strikethrough', function()
|
||||||
|
screen:detach()
|
||||||
|
screen = Screen.new(25,6)
|
||||||
|
screen:attach()
|
||||||
|
feed_command('syntax on')
|
||||||
|
feed_command('syn keyword TmpKeyword foo')
|
||||||
|
feed_command('hi! Awesome cterm=strikethrough gui=strikethrough')
|
||||||
|
feed_command('hi link TmpKeyword Awesome')
|
||||||
|
insert([[
|
||||||
|
foo
|
||||||
|
foo bar
|
||||||
|
foobarfoobar
|
||||||
|
]])
|
||||||
|
screen:expect([[
|
||||||
|
{1:foo} |
|
||||||
|
{1:foo} bar |
|
||||||
|
foobarfoobar |
|
||||||
|
^ |
|
||||||
|
{2:~ }|
|
||||||
|
|
|
||||||
|
]],{
|
||||||
|
[1] = {strikethrough = true},
|
||||||
|
[2] = {bold = true, foreground = Screen.colors.Blue1},
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
|
||||||
it('guisp (special/undercurl)', function()
|
it('guisp (special/undercurl)', function()
|
||||||
feed_command('syntax on')
|
feed_command('syntax on')
|
||||||
feed_command('syn keyword TmpKeyword neovim')
|
feed_command('syn keyword TmpKeyword neovim')
|
||||||
|
@@ -1509,7 +1509,8 @@ function Screen:_equal_attrs(a, b)
|
|||||||
a.underline == b.underline and a.undercurl == b.undercurl and
|
a.underline == b.underline and a.undercurl == b.undercurl and
|
||||||
a.italic == b.italic and a.reverse == b.reverse and
|
a.italic == b.italic and a.reverse == b.reverse and
|
||||||
a.foreground == b.foreground and a.background == b.background and
|
a.foreground == b.foreground and a.background == b.background and
|
||||||
a.special == b.special and a.blend == b.blend
|
a.special == b.special and a.blend == b.blend and
|
||||||
|
a.strikethrough == b.strikethrough
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:_equal_info(a, b)
|
function Screen:_equal_info(a, b)
|
||||||
|
Reference in New Issue
Block a user