fix(spell): extmark with spell=false should disable spell (#23400)

This commit is contained in:
zeertzjq 2023-05-01 12:30:55 +08:00 committed by GitHub
parent 9f9cef1b56
commit a803bff89c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 216 additions and 89 deletions

View File

@ -1206,8 +1206,8 @@ static void decor_spell_nav_start(win_T *wp)
decor_redraw_reset(wp, &decor_state); decor_redraw_reset(wp, &decor_state);
} }
static bool decor_spell_nav_col(win_T *wp, linenr_T lnum, linenr_T *decor_lnum, int col, static TriState decor_spell_nav_col(win_T *wp, linenr_T lnum, linenr_T *decor_lnum, int col,
char **decor_error) char **decor_error)
{ {
if (*decor_lnum != lnum) { if (*decor_lnum != lnum) {
decor_providers_invoke_spell(wp, lnum - 1, col, lnum - 1, -1, decor_error); decor_providers_invoke_spell(wp, lnum - 1, col, lnum - 1, -1, decor_error);
@ -1215,7 +1215,7 @@ static bool decor_spell_nav_col(win_T *wp, linenr_T lnum, linenr_T *decor_lnum,
*decor_lnum = lnum; *decor_lnum = lnum;
} }
decor_redraw_col(wp, col, col, false, &decor_state); decor_redraw_col(wp, col, col, false, &decor_state);
return decor_state.spell == kTrue; return decor_state.spell;
} }
static inline bool can_syn_spell(win_T *wp, linenr_T lnum, int col) static inline bool can_syn_spell(win_T *wp, linenr_T lnum, int col)
@ -1352,9 +1352,18 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
: p - buf) > wp->w_cursor.col)) { : p - buf) > wp->w_cursor.col)) {
col = (colnr_T)(p - buf); col = (colnr_T)(p - buf);
bool can_spell = (!has_syntax && (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) == 0) bool no_plain_buffer = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) != 0;
|| decor_spell_nav_col(wp, lnum, &decor_lnum, col, &decor_error) bool can_spell = !no_plain_buffer;
|| (has_syntax && can_syn_spell(wp, lnum, col)); switch (decor_spell_nav_col(wp, lnum, &decor_lnum, col, &decor_error)) {
case kTrue:
can_spell = true; break;
case kFalse:
can_spell = false; break;
case kNone:
if (has_syntax) {
can_spell = can_syn_spell(wp, lnum, col);
}
}
if (!can_spell) { if (!can_spell) {
attr = HLF_COUNT; attr = HLF_COUNT;

View File

@ -8,6 +8,7 @@ local exec_lua = helpers.exec_lua
local exec = helpers.exec local exec = helpers.exec
local expect_events = helpers.expect_events local expect_events = helpers.expect_events
local meths = helpers.meths local meths = helpers.meths
local curbufmeths = helpers.curbufmeths
local command = helpers.command local command = helpers.command
describe('decorations providers', function() describe('decorations providers', function()
@ -31,8 +32,9 @@ describe('decorations providers', function()
[12] = {foreground = tonumber('0x990000')}; [12] = {foreground = tonumber('0x990000')};
[13] = {background = Screen.colors.LightBlue}; [13] = {background = Screen.colors.LightBlue};
[14] = {background = Screen.colors.WebGray, foreground = Screen.colors.DarkBlue}; [14] = {background = Screen.colors.WebGray, foreground = Screen.colors.DarkBlue};
[15] = {special = Screen.colors.Blue1, undercurl = true}, [15] = {special = Screen.colors.Blue, undercurl = true},
[16] = {special = Screen.colors.Red, undercurl = true}, [16] = {special = Screen.colors.Red, undercurl = true},
[17] = {foreground = Screen.colors.Red},
} }
end) end)
@ -201,14 +203,14 @@ describe('decorations providers', function()
feed "gg0" feed "gg0"
screen:expect{grid=[[ screen:expect{grid=[[
^I am well written text. | ^I am well written text. |
{15:i} am not capitalized. | {15:i} am not capitalized. |
I am a {16:speling} {16:mistakke}. | I am a {16:speling} {16:mistakke}. |
| |
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
| |
]]} ]]}
feed "]s" feed "]s"
@ -216,14 +218,14 @@ describe('decorations providers', function()
{ "spell", 1000, 1, 1, 0, 1, -1 }; { "spell", 1000, 1, 1, 0, 1, -1 };
} }
screen:expect{grid=[[ screen:expect{grid=[[
I am well written text. | I am well written text. |
{15:^i} am not capitalized. | {15:^i} am not capitalized. |
I am a {16:speling} {16:mistakke}. | I am a {16:speling} {16:mistakke}. |
| |
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
| |
]]} ]]}
feed "]s" feed "]s"
@ -231,43 +233,68 @@ describe('decorations providers', function()
{ "spell", 1000, 1, 2, 7, 2, -1 }; { "spell", 1000, 1, 2, 7, 2, -1 };
} }
screen:expect{grid=[[ screen:expect{grid=[[
I am well written text. | I am well written text. |
{15:i} am not capitalized. | {15:i} am not capitalized. |
I am a {16:^speling} {16:mistakke}. | I am a {16:^speling} {16:mistakke}. |
| |
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
| |
]]}
-- spell=false with lower priority doesn't disable spell
local ns = meths.create_namespace "spell"
local id = helpers.curbufmeths.set_extmark(ns, 0, 0, { priority = 30, end_row = 2, end_col = 23, spell = false })
screen:expect{grid=[[
I am well written text. |
i am not capitalized. |
I am a ^speling mistakke. |
|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]} ]]}
-- spell=false with higher priority does disable spell -- spell=false with higher priority does disable spell
helpers.curbufmeths.set_extmark(ns, 0, 0, { id = id, priority = 10, end_row = 2, end_col = 23, spell = false }) local ns = meths.create_namespace "spell"
local id = curbufmeths.set_extmark(ns, 0, 0, { priority = 30, end_row = 2, end_col = 23, spell = false })
screen:expect{grid=[[ screen:expect{grid=[[
I am well written text. | I am well written text. |
{15:i} am not capitalized. | i am not capitalized. |
I am a {16:^speling} {16:mistakke}. | I am a ^speling mistakke. |
| |
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
| |
]]}
feed "]s"
screen:expect{grid=[[
I am well written text. |
i am not capitalized. |
I am a ^speling mistakke. |
|
{1:~ }|
{1:~ }|
{1:~ }|
{17:search hit BOTTOM, continuing at TOP} |
]]}
command('echo ""')
-- spell=false with lower priority doesn't disable spell
curbufmeths.set_extmark(ns, 0, 0, { id = id, priority = 10, end_row = 2, end_col = 23, spell = false })
screen:expect{grid=[[
I am well written text. |
{15:i} am not capitalized. |
I am a {16:^speling} {16:mistakke}. |
|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
feed "]s"
screen:expect{grid=[[
I am well written text. |
{15:i} am not capitalized. |
I am a {16:speling} {16:^mistakke}. |
|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]} ]]}
end) end)

View File

@ -6,6 +6,8 @@ local clear = helpers.clear
local feed = helpers.feed local feed = helpers.feed
local insert = helpers.insert local insert = helpers.insert
local command = helpers.command local command = helpers.command
local meths = helpers.meths
local curbufmeths = helpers.curbufmeths
local is_os = helpers.is_os local is_os = helpers.is_os
describe("'spell'", function() describe("'spell'", function()
@ -18,11 +20,13 @@ describe("'spell'", function()
screen:set_default_attr_ids( { screen:set_default_attr_ids( {
[0] = {bold=true, foreground=Screen.colors.Blue}, [0] = {bold=true, foreground=Screen.colors.Blue},
[1] = {special = Screen.colors.Red, undercurl = true}, [1] = {special = Screen.colors.Red, undercurl = true},
[2] = {special = Screen.colors.Blue1, undercurl = true}, [2] = {special = Screen.colors.Blue, undercurl = true},
[3] = {foreground = tonumber('0x6a0dad')}, [3] = {foreground = tonumber('0x6a0dad')},
[4] = {foreground = Screen.colors.Magenta}, [4] = {foreground = Screen.colors.Magenta},
[5] = {bold = true, foreground = Screen.colors.SeaGreen}, [5] = {bold = true, foreground = Screen.colors.SeaGreen},
[6] = {foreground = Screen.colors.Red}, [6] = {foreground = Screen.colors.Red},
[7] = {foreground = Screen.colors.Blue},
[8] = {foreground = Screen.colors.Blue, special = Screen.colors.Red, undercurl = true},
}) })
end) end)
@ -74,19 +78,57 @@ describe("'spell'", function()
]]) ]])
end) end)
it('"noplainbuffer" and syntax #20385', function() it('extmarks, "noplainbuffer" and syntax #20385 #23398', function()
command('set filetype=c') command('set filetype=c')
command('syntax on') command('syntax on')
command('set spell') command('set spell')
insert([[ insert([[
#include <stdbool.h> #include <stdbool.h>
bool func(void);]]) bool func(void);
// I am a speling mistakke]])
feed('ge')
screen:expect([[ screen:expect([[
{3:#include }{4:<stdbool.h>} | {3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void})^; | {5:bool} func({5:void}); |
{7:// I am a }{8:spelin^g}{7: }{8:mistakke} |
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
{0:~ }|
|
]])
feed(']s')
screen:expect([[
{3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void}); |
{7:// I am a }{8:speling}{7: }{8:^mistakke} |
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
|
]])
feed(']s')
screen:expect([[
{3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void}); |
{7:// I am a }{8:^speling}{7: }{8:mistakke} |
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{6:search hit BOTTOM, continuing at TOP} |
]])
command('echo ""')
local ns = meths.create_namespace("spell")
-- extmark with spell=true enables spell
local id = curbufmeths.set_extmark(ns, 1, 4, { end_row = 1, end_col = 10, spell = true })
screen:expect([[
{3:#include }{4:<stdbool.h>} |
{5:bool} {1:func}({5:void}); |
{7:// I am a }{8:^speling}{7: }{8:mistakke} |
{0:~ }|
{0:~ }|
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
| |
@ -94,73 +136,122 @@ describe("'spell'", function()
feed('[s') feed('[s')
screen:expect([[ screen:expect([[
{3:#include }{4:<stdbool.h>} | {3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void})^; | {5:bool} {1:^func}({5:void}); |
{7:// I am a }{8:speling}{7: }{8:mistakke} |
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
{0:~ }|
|
]])
curbufmeths.del_extmark(ns, id)
-- extmark with spell=false disables spell
id = curbufmeths.set_extmark(ns, 2, 18, { end_row = 2, end_col = 26, spell = false })
screen:expect([[
{3:#include }{4:<stdbool.h>} |
{5:bool} ^func({5:void}); |
{7:// I am a }{8:speling}{7: mistakke} |
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
|
]])
feed('[s')
screen:expect([[
{3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void}); |
{7:// I am a }{8:^speling}{7: mistakke} |
{0:~ }|
{0:~ }|
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
{6:search hit TOP, continuing at BOTTOM} | {6:search hit TOP, continuing at BOTTOM} |
]]) ]])
-- "noplainbuffer" shouldn't change spellchecking behavior with syntax enabled command('echo ""')
command('set spelloptions+=noplainbuffer') curbufmeths.del_extmark(ns, id)
screen:expect_unchanged() screen:expect([[
{3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void}); |
{7:// I am a }{8:^speling}{7: }{8:mistakke} |
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
|
]])
feed(']s') feed(']s')
screen:expect([[ screen:expect([[
{3:#include }{4:<stdbool.h>} | {3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void})^; | {5:bool} func({5:void}); |
{7:// I am a }{8:speling}{7: }{8:^mistakke} |
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
|
]])
-- "noplainbuffer" shouldn't change spellchecking behavior with syntax enabled
command('set spelloptions+=noplainbuffer')
screen:expect_unchanged()
feed('[s')
screen:expect([[
{3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void}); |
{7:// I am a }{8:^speling}{7: }{8:mistakke} |
{0:~ }| {0:~ }|
{6:search hit BOTTOM, continuing at TOP} | {0:~ }|
{0:~ }|
{0:~ }|
|
]]) ]])
-- no spellchecking with "noplainbuffer" and syntax disabled -- no spellchecking with "noplainbuffer" and syntax disabled
command('syntax off') command('syntax off')
screen:expect([[ screen:expect([[
#include <stdbool.h> | #include <stdbool.h> |
bool func(void)^; | bool func(void); |
// I am a ^speling mistakke |
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
{0:~ }|
|
]])
feed(']s')
screen:expect([[
#include <stdbool.h> |
bool func(void); |
// I am a ^speling mistakke |
{0:~ }|
{0:~ }|
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
{6:search hit BOTTOM, continuing at TOP} | {6:search hit BOTTOM, continuing at TOP} |
]]) ]])
feed('[s') command('echo ""')
screen:expect([[
#include <stdbool.h> |
bool func(void)^; |
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{6:search hit TOP, continuing at BOTTOM} |
]])
-- everything is spellchecked without "noplainbuffer" with syntax disabled -- everything is spellchecked without "noplainbuffer" with syntax disabled
command('set spelloptions&') command('set spelloptions&')
screen:expect([[ screen:expect([[
#include <{1:stdbool}.h> | #include <{1:stdbool}.h> |
{1:bool} {1:func}(void)^; |
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{6:search hit TOP, continuing at BOTTOM} |
]])
feed(']s')
screen:expect([[
#include <{1:^stdbool}.h> |
{1:bool} {1:func}(void); | {1:bool} {1:func}(void); |
// I am a {1:^speling} {1:mistakke} |
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
{0:~ }| {0:~ }|
|
]])
feed('[s')
screen:expect([[
#include <{1:stdbool}.h> |
{1:bool} {1:^func}(void); |
// I am a {1:speling} {1:mistakke} |
{0:~ }| {0:~ }|
{6:search hit BOTTOM, continuing at TOP} | {0:~ }|
{0:~ }|
{0:~ }|
|
]]) ]])
end) end)
end) end)