mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +00:00
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:
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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 });
|
||||
|
@@ -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).
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
|
Reference in New Issue
Block a user