mirror of
https://github.com/neovim/neovim.git
synced 2025-09-11 13:58:18 +00:00
feat(extmarks,ts,spell): full support for spelling
- Added 'spell' option to extmarks: Extmarks with this set will have the region spellchecked. - Added 'noplainbuffer' option to 'spelloptions': This is used to tell Neovim not to spellcheck the buffer. The old behaviour was to spell check the whole buffer unless :syntax was set. - Added spelling support to the treesitter highlighter: @spell captures in highlights.scm are used to define regions which should be spell checked. - Added support for navigating spell errors for extmarks: Works for both ephemeral and static extmarks - Added '_on_spell_nav' callback for decoration providers: Since ephemeral callbacks are only drawn for the visible screen, providers must implement this callback to instruct Neovim which regions in the buffer need can be spell checked. The callback takes a start position and an end position. Note: this callback is subject to change hence the _ prefix. - Added spell captures for built-in support languages Co-authored-by: Lewis Russell <lewis6991@gmail.com> Co-authored-by: Björn Linse <bjorn.linse@gmail.com>
This commit is contained in:

committed by
Lewis Russell

parent
05893aea39
commit
75adfefc85
@@ -473,6 +473,8 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
|
||||
/// When a character is supplied it is used as |:syn-cchar|.
|
||||
/// "hl_group" is used as highlight for the cchar if provided,
|
||||
/// otherwise it defaults to |hl-Conceal|.
|
||||
/// - spell: boolean indicating that spell checking should be
|
||||
/// performed within this extmark
|
||||
/// - ui_watched: boolean that indicates the mark should be drawn
|
||||
/// by a UI. When set, the UI will receive win_extmark events.
|
||||
/// Note: the mark is positioned by virt_text attributes. Can be
|
||||
@@ -719,6 +721,11 @@ 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) {
|
||||
has_decor = true;
|
||||
}
|
||||
|
||||
OPTION_TO_BOOL(decor.ui_watched, ui_watched, false);
|
||||
if (decor.ui_watched) {
|
||||
has_decor = true;
|
||||
@@ -972,20 +979,21 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
|
||||
/// for the moment.
|
||||
///
|
||||
/// @param ns_id Namespace id from |nvim_create_namespace()|
|
||||
/// @param opts Callbacks invoked during redraw:
|
||||
/// @param opts Table of callbacks:
|
||||
/// - on_start: called first on each screen redraw
|
||||
/// ["start", tick]
|
||||
/// - on_buf: called for each buffer being redrawn (before window
|
||||
/// callbacks)
|
||||
/// - on_buf: called for each buffer being redrawn (before
|
||||
/// window callbacks)
|
||||
/// ["buf", bufnr, tick]
|
||||
/// - on_win: called when starting to redraw a specific window.
|
||||
/// - on_win: called when starting to redraw a
|
||||
/// specific window.
|
||||
/// ["win", winid, bufnr, topline, botline_guess]
|
||||
/// - on_line: called for each buffer line being redrawn. (The
|
||||
/// interaction with fold lines is subject to change)
|
||||
/// - on_line: called for each buffer line being redrawn.
|
||||
/// (The interaction with fold lines is subject to change)
|
||||
/// ["win", winid, bufnr, row]
|
||||
/// - on_end: called at the end of a redraw cycle
|
||||
/// ["end", tick]
|
||||
void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, Error *err)
|
||||
void nvim_set_decoration_provider(Integer ns_id, Dict(set_decoration_provider) *opts, Error *err)
|
||||
FUNC_API_SINCE(7) FUNC_API_LUA_ONLY
|
||||
{
|
||||
DecorProvider *p = get_decor_provider((NS)ns_id, true);
|
||||
@@ -997,37 +1005,32 @@ void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, Erro
|
||||
|
||||
struct {
|
||||
const char *name;
|
||||
Object *source;
|
||||
LuaRef *dest;
|
||||
} cbs[] = {
|
||||
{ "on_start", &p->redraw_start },
|
||||
{ "on_buf", &p->redraw_buf },
|
||||
{ "on_win", &p->redraw_win },
|
||||
{ "on_line", &p->redraw_line },
|
||||
{ "on_end", &p->redraw_end },
|
||||
{ "_on_hl_def", &p->hl_def },
|
||||
{ NULL, NULL },
|
||||
{ "on_start", &opts->on_start, &p->redraw_start },
|
||||
{ "on_buf", &opts->on_buf, &p->redraw_buf },
|
||||
{ "on_win", &opts->on_win, &p->redraw_win },
|
||||
{ "on_line", &opts->on_line, &p->redraw_line },
|
||||
{ "on_end", &opts->on_end, &p->redraw_end },
|
||||
{ "_on_hl_def", &opts->_on_hl_def, &p->hl_def },
|
||||
{ "_on_spell_nav", &opts->_on_spell_nav, &p->spell_nav },
|
||||
{ NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < opts.size; i++) {
|
||||
String k = opts.items[i].key;
|
||||
Object *v = &opts.items[i].value;
|
||||
size_t j;
|
||||
for (j = 0; cbs[j].name && cbs[j].dest; j++) {
|
||||
if (strequal(cbs[j].name, k.data)) {
|
||||
if (v->type != kObjectTypeLuaRef) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"%s is not a function", cbs[j].name);
|
||||
goto error;
|
||||
}
|
||||
*(cbs[j].dest) = v->data.luaref;
|
||||
v->data.luaref = LUA_NOREF;
|
||||
break;
|
||||
}
|
||||
for (size_t i = 0; cbs[i].source && cbs[i].dest && cbs[i].name; i++) {
|
||||
Object *v = cbs[i].source;
|
||||
if (v->type == kObjectTypeNil) {
|
||||
continue;
|
||||
}
|
||||
if (!cbs[j].name) {
|
||||
api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
|
||||
|
||||
if (v->type != kObjectTypeLuaRef) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"%s is not a function", cbs[i].name);
|
||||
goto error;
|
||||
}
|
||||
*(cbs[i].dest) = v->data.luaref;
|
||||
v->data.luaref = LUA_NOREF;
|
||||
}
|
||||
|
||||
p->active = true;
|
||||
|
Reference in New Issue
Block a user