Merge pull request #21042 from neovim/backport-20178-to-release-0.8

[Backport release-0.8] feat(extmarks): allow preventing spellchecking with spell = false
This commit is contained in:
bfredl
2022-11-13 11:16:36 +01:00
committed by GitHub
10 changed files with 88 additions and 29 deletions

View File

@@ -432,6 +432,9 @@ capture marks comments as to be checked: >
(comment) @spell
<
There is also `@nospell` which disables spellchecking regions with `@spell`.
*treesitter-highlight-conceal*
Treesitter highlighting supports |conceal| via the `conceal` metadata. By
convention, nodes to be concealed are captured as `@conceal`, but any capture

View File

@@ -164,7 +164,7 @@ function TSHighlighter:get_query(lang)
end
---@private
local function on_line_impl(self, buf, line, spell)
local function on_line_impl(self, buf, line, is_spell_nav)
self.tree:for_each_tree(function(tstree, tree)
if not tstree then
return
@@ -201,17 +201,26 @@ local function on_line_impl(self, buf, line, spell)
local start_row, start_col, end_row, end_col = node:range()
local hl = highlighter_query.hl_cache[capture]
local is_spell = highlighter_query:query().captures[capture] == 'spell'
local capture_name = highlighter_query:query().captures[capture]
local spell = nil
if capture_name == 'spell' then
spell = true
elseif capture_name == 'nospell' then
spell = false
end
if hl and end_row >= line and (not spell or is_spell) then
-- Give nospell a higher priority so it always overrides spell captures.
local spell_pri_offset = capture_name == 'nospell' and 1 or 0
if hl and end_row >= line and (not is_spell_nav or spell ~= nil) then
a.nvim_buf_set_extmark(buf, ns, start_row, start_col, {
end_line = end_row,
end_col = end_col,
hl_group = hl,
ephemeral = true,
priority = tonumber(metadata.priority) or 100, -- Low but leaves room below
priority = (tonumber(metadata.priority) or 100) + spell_pri_offset, -- Low but leaves room below
conceal = metadata.conceal,
spell = is_spell,
spell = spell,
})
end
if start_row > line then

View File

@@ -721,8 +721,12 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
bool ephemeral = false;
OPTION_TO_BOOL(ephemeral, ephemeral, false);
OPTION_TO_BOOL(decor.spell, spell, false);
if (decor.spell) {
if (opts->spell.type == kObjectTypeNil) {
decor.spell = kNone;
} else {
bool spell = false;
OPTION_TO_BOOL(spell, spell, false);
decor.spell = spell ? kTrue : kFalse;
has_decor = true;
}

View File

@@ -69,7 +69,11 @@ void bufhl_add_hl_pos_offset(buf_T *buf, int src_id, int hl_id, lpos_T pos_start
void decor_redraw(buf_T *buf, int row1, int row2, Decoration *decor)
{
if (row2 >= row1) {
if (!decor || decor->hl_id || decor_has_sign(decor) || decor->conceal || decor->spell) {
if (!decor
|| decor->hl_id
|| decor_has_sign(decor)
|| decor->conceal
|| decor->spell != kNone) {
redraw_buf_range_later(buf, row1 + 1, row2 + 1);
}
}
@@ -310,7 +314,7 @@ next_mark:
bool conceal = 0;
int conceal_char = 0;
int conceal_attr = 0;
bool spell = false;
TriState spell = kNone;
for (size_t i = 0; i < kv_size(state->active); i++) {
DecorRange item = kv_A(state->active, i);
@@ -344,8 +348,8 @@ next_mark:
conceal_attr = item.attr_id;
}
}
if (active && item.decor.spell) {
spell = true;
if (active && item.decor.spell != kNone) {
spell = item.decor.spell;
}
if ((item.start_row == state->row && item.start_col <= col)
&& decor_virt_pos(item.decor)

View File

@@ -46,7 +46,7 @@ struct Decoration {
bool hl_eol;
bool virt_lines_above;
bool conceal;
bool spell;
TriState spell;
// TODO(bfredl): style, etc
DecorPriority priority;
int col; // fixed col value, like win_col
@@ -62,7 +62,7 @@ struct Decoration {
bool ui_watched; // watched for win_extmark
};
#define DECORATION_INIT { KV_INITIAL_VALUE, KV_INITIAL_VALUE, 0, kVTEndOfLine, \
kHlModeUnknown, false, false, false, false, false, \
kHlModeUnknown, false, false, false, false, kNone, \
DECOR_PRIORITY_BASE, 0, 0, NULL, 0, 0, 0, 0, 0, false }
typedef struct {
@@ -92,7 +92,7 @@ typedef struct {
int conceal_char;
int conceal_attr;
bool spell;
TriState spell;
} DecorState;
EXTERN DecorState decor_state INIT(= { 0 });

View File

@@ -33,6 +33,7 @@
#include "nvim/spell.h"
#include "nvim/state.h"
#include "nvim/syntax.h"
#include "nvim/types.h"
#include "nvim/undo.h"
#include "nvim/window.h"
@@ -1719,9 +1720,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
decor_conceal = 2; // really??
}
if (decor_state.spell) {
can_spell = true;
}
can_spell = TRISTATE_TO_BOOL(decor_state.spell, can_spell);
}
// Check spelling (unless at the end of the line).

View File

@@ -71,7 +71,7 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
|| decor->conceal
|| decor_has_sign(decor)
|| decor->ui_watched
|| decor->spell) {
|| decor->spell != kNone) {
decor_full = true;
decor = xmemdup(decor, sizeof *decor);
}

View File

@@ -1214,7 +1214,14 @@ static bool decor_spell_nav_col(win_T *wp, linenr_T lnum, linenr_T *decor_lnum,
*decor_lnum = lnum;
}
decor_redraw_col(wp->w_buffer, col, col, false, &decor_state);
return decor_state.spell;
return decor_state.spell == kTrue;
}
static inline bool can_syn_spell(win_T *wp, linenr_T lnum, int col)
{
bool can_spell;
(void)syn_get_id(wp, lnum, col, false, &can_spell, false);
return can_spell;
}
/// Moves to the next spell error.
@@ -1344,15 +1351,9 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
: p - buf) > wp->w_cursor.col)) {
col = (colnr_T)(p - buf);
bool can_spell = decor_spell_nav_col(wp, lnum, &decor_lnum, col, &decor_error);
if (!can_spell) {
if (has_syntax) {
(void)syn_get_id(wp, lnum, col, false, &can_spell, false);
} else {
can_spell = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) == 0;
}
}
bool can_spell = (!has_syntax && (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) == 0)
|| decor_spell_nav_col(wp, lnum, &decor_lnum, col, &decor_error)
|| (has_syntax && can_syn_spell(wp, lnum, col));
if (!can_spell) {
attr = HLF_COUNT;

View File

@@ -45,6 +45,9 @@ typedef enum {
kTrue = 1,
} TriState;
#define TRISTATE_TO_BOOL(val, \
default) ((val) == kTrue ? true : ((val) == kFalse ? false : (default)))
typedef struct Decoration Decoration;
#endif // NVIM_TYPES_H

View File

@@ -176,7 +176,13 @@ describe('decorations providers', function()
beamtrace = {}
local function on_do(kind, ...)
if kind == 'win' or kind == 'spell' then
a.nvim_buf_set_extmark(0, ns, 0, 0, { end_row = 2, end_col = 23, spell = true, ephemeral = true })
a.nvim_buf_set_extmark(0, ns, 0, 0, {
end_row = 2,
end_col = 23,
spell = true,
priority = 20,
ephemeral = true
})
end
table.insert(beamtrace, {kind, ...})
end
@@ -234,6 +240,36 @@ describe('decorations providers', function()
{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
helpers.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:~ }|
|
]]}
end)
it('can predefine highlights', function()