aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-05-25 18:01:06 +0800
committerGitHub <noreply@github.com>2023-05-25 18:01:06 +0800
commitaa9d46b6724cf3454aca602e64350856827c3ab8 (patch)
tree1c95080c85ac0df1b6930aa82f8aeb9476ff7583
parentebb10d624825468c1f75bd14725cce500974b673 (diff)
parent50efdd6ccf1891392c048b92da5e5d123a30ff26 (diff)
downloadrneovim-aa9d46b6724cf3454aca602e64350856827c3ab8.tar.gz
rneovim-aa9d46b6724cf3454aca602e64350856827c3ab8.tar.bz2
rneovim-aa9d46b6724cf3454aca602e64350856827c3ab8.zip
Merge pull request #23744 from luukvbaal/spell
vim-patch:9.0.{0175,0590,0608,0664}
-rw-r--r--src/nvim/change.c10
-rw-r--r--src/nvim/drawline.c18
-rw-r--r--src/nvim/edit.c5
-rw-r--r--src/nvim/spell.c14
-rw-r--r--src/nvim/undo.c7
-rw-r--r--test/functional/ui/spell_spec.lua154
-rw-r--r--test/old/testdir/test_spell.vim64
7 files changed, 217 insertions, 55 deletions
diff --git a/src/nvim/change.c b/src/nvim/change.c
index f4969d0ca9..9e1767c2f3 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -43,6 +43,7 @@
#include "nvim/plines.h"
#include "nvim/pos.h"
#include "nvim/search.h"
+#include "nvim/spell.h"
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/textformat.h"
@@ -393,6 +394,15 @@ void changed_bytes(linenr_T lnum, colnr_T col)
{
changedOneline(curbuf, lnum);
changed_common(lnum, col, lnum + 1, 0);
+ // When text has been changed at the end of the line, possibly the start of
+ // the next line may have SpellCap that should be removed or it needs to be
+ // displayed. Schedule the next line for redrawing just in case.
+ // Don't do this when displaying '$' at the end of changed text.
+ if (spell_check_window(curwin)
+ && lnum < curbuf->b_ml.ml_line_count
+ && vim_strchr(p_cpo, CPO_DOLLAR) == NULL) {
+ redrawWinline(curwin, lnum + 1);
+ }
// notify any channels that are watching
buf_updates_send_changes(curbuf, lnum, 1, 1);
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index 927b1247be..54da38a6ff 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -1203,12 +1203,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
}
- if (wp->w_p_spell
- && !has_fold
- && !end_fill
- && *wp->w_s->b_p_spl != NUL
- && !GA_EMPTY(&wp->w_s->b_langp)
- && *(char **)(wp->w_s->b_langp.ga_data) != NULL) {
+ if (!has_fold && !end_fill && spell_check_window(wp)) {
// Prepare for spell checking.
has_spell = true;
extra_check = true;
@@ -2188,12 +2183,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
v = (ptr - line);
if (has_spell && v >= word_end && v > cur_checked_col) {
spell_attr = 0;
- if (c != 0 && ((!has_syntax && !no_plain_buffer) || can_spell)) {
- char *prev_ptr;
+ char *prev_ptr = ptr - mb_l;
+ // do not calculate cap_col at the end of the line or when
+ // only white space is following
+ if (c != 0 && (*skipwhite(prev_ptr) != NUL)
+ && ((!has_syntax && !no_plain_buffer) || can_spell)) {
char *p;
- int len;
hlf_T spell_hlf = HLF_COUNT;
- prev_ptr = ptr - mb_l;
v -= mb_l - 1;
// Use nextline[] if possible, it has the start of the
@@ -2206,7 +2202,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
cap_col -= (int)(prev_ptr - line);
size_t tmplen = spell_check(wp, p, &spell_hlf, &cap_col, nochange);
assert(tmplen <= INT_MAX);
- len = (int)tmplen;
+ int len = (int)tmplen;
word_end = (int)v + len;
// In Insert mode only highlight a word that
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index a25387f5a6..d6d5ff8ac7 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -53,6 +53,7 @@
#include "nvim/popupmenu.h"
#include "nvim/pos.h"
#include "nvim/search.h"
+#include "nvim/spell.h"
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
@@ -1526,8 +1527,8 @@ void edit_unputchar(void)
}
}
-// Called when p_dollar is set: display a '$' at the end of the changed text
-// Only works when cursor is in the line that changes.
+/// Called when "$" is in 'cpoptions': display a '$' at the end of the changed
+/// text. Only works when cursor is in the line that changes.
void display_dollar(colnr_T col_arg)
{
colnr_T col = col_arg < 0 ? 0 : col_arg;
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 84875261f1..498bd56b9e 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -1189,11 +1189,19 @@ bool spell_valid_case(int wordflags, int treeflags)
|| (wordflags & WF_ONECAP) != 0));
}
-// Returns true if spell checking is not enabled.
+/// Return true if spell checking is enabled for "wp".
+bool spell_check_window(win_T *wp)
+{
+ return wp->w_p_spell
+ && *wp->w_s->b_p_spl != NUL
+ && wp->w_s->b_langp.ga_len > 0
+ && *(char **)(wp->w_s->b_langp.ga_data) != NULL;
+}
+
+/// Return true and give an error if spell checking is not enabled.
bool no_spell_checking(win_T *wp)
{
- if (!wp->w_p_spell || *wp->w_s->b_p_spl == NUL
- || GA_EMPTY(&wp->w_s->b_langp)) {
+ if (!wp->w_p_spell || *wp->w_s->b_p_spl == NUL || GA_EMPTY(&wp->w_s->b_langp)) {
emsg(_(e_no_spell));
return true;
}
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 00a3922a5b..1eb73d85d7 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -120,6 +120,7 @@
#include "nvim/path.h"
#include "nvim/pos.h"
#include "nvim/sha256.h"
+#include "nvim/spell.h"
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/types.h"
@@ -2372,6 +2373,12 @@ static void u_undoredo(int undo, bool do_buf_event)
}
changed_lines(top + 1, 0, bot, newsize - oldsize, do_buf_event);
+ // When text has been changed, possibly the start of the next line
+ // may have SpellCap that should be removed or it needs to be
+ // displayed. Schedule the next line for redrawing just in case.
+ if (spell_check_window(curwin) && bot <= curbuf->b_ml.ml_line_count) {
+ redrawWinline(curwin, bot);
+ }
// Set the '[ mark.
if (top + 1 < curbuf->b_op_start.lnum) {
diff --git a/test/functional/ui/spell_spec.lua b/test/functional/ui/spell_spec.lua
index 0f553d4a9b..7f11b06f78 100644
--- a/test/functional/ui/spell_spec.lua
+++ b/test/functional/ui/spell_spec.lua
@@ -3,9 +3,9 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
+local exec = helpers.exec
local feed = helpers.feed
local insert = helpers.insert
-local command = helpers.command
local meths = helpers.meths
local curbufmeths = helpers.curbufmeths
local is_os = helpers.is_os
@@ -27,12 +27,13 @@ describe("'spell'", function()
[6] = {foreground = Screen.colors.Red},
[7] = {foreground = Screen.colors.Blue},
[8] = {foreground = Screen.colors.Blue, special = Screen.colors.Red, undercurl = true},
+ [9] = {bold = true},
})
end)
it('joins long lines #7937', function()
if is_os('openbsd') then pending('FIXME #12104', function() end) return end
- command('set spell')
+ exec('set spell')
insert([[
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
@@ -57,31 +58,128 @@ describe("'spell'", function()
-- oldtest: Test_spell_screendump()
it('has correct highlight at start of line', function()
- insert([[
- "This is some text without any spell errors. Everything",
- "should just be black, nothing wrong here.",
- "",
- "This line has a sepll error. and missing caps.",
- "And and this is the the duplication.",
- "with missing caps here.",
+ exec([=[
+ call setline(1, [
+ \"This is some text without any spell errors. Everything",
+ \"should just be black, nothing wrong here.",
+ \"",
+ \"This line has a sepll error. and missing caps.",
+ \"And and this is the the duplication.",
+ \"with missing caps here.",
+ \])
+ set spell spelllang=en_nz
+ ]=])
+ screen:expect([[
+ ^This is some text without any spell errors. Everything |
+ should just be black, nothing wrong here. |
+ |
+ This line has a {1:sepll} error. {2:and} missing caps. |
+ {1:And and} this is {1:the the} duplication. |
+ {2:with} missing caps here. |
+ {0:~ }|
+ |
]])
- command('set spell spelllang=en_nz')
+ end)
+
+ -- oldtest: Test_spell_screendump_spellcap()
+ it('has correct highlight at start of line with trailing space', function()
+ exec([=[
+ call setline(1, [
+ \" This line has a sepll error. and missing caps and trailing spaces. ",
+ \"another missing cap here.",
+ \"",
+ \"and here.",
+ \" ",
+ \"and here."
+ \])
+ set spell spelllang=en
+ ]=])
screen:expect([[
- "This is some text without any spell errors. Everything", |
- "should just be black, nothing wrong here.", |
- "", |
- "This line has a {1:sepll} error. {2:and} missing caps.", |
- "{1:And and} this is {1:the the} duplication.", |
- "with missing caps here.", |
- ^ |
- |
+ ^ This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. |
+ {2:another} missing cap here. |
+ |
+ {2:and} here. |
+ |
+ {2:and} here. |
+ {0:~ }|
+ |
+ ]])
+ -- After adding word missing Cap in next line is updated
+ feed('3GANot<Esc>')
+ screen:expect([[
+ This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. |
+ {2:another} missing cap here. |
+ No^t |
+ and here. |
+ |
+ {2:and} here. |
+ {0:~ }|
+ |
+ ]])
+ -- Deleting a full stop removes missing Cap in next line
+ feed('5Gddk$x')
+ screen:expect([[
+ This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. |
+ {2:another} missing cap here. |
+ Not |
+ and her^e |
+ and here. |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ -- Undo also updates the next line (go to command line to remove message)
+ feed('u:<Esc>')
+ screen:expect([[
+ This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. |
+ {2:another} missing cap here. |
+ Not |
+ and here^. |
+ {2:and} here. |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end)
+
+ -- oldtest: Test_spell_compatible()
+ it([[redraws properly when using "C" and "$" is in 'cpo']], function()
+ exec([=[
+ call setline(1, [
+ \ "test "->repeat(20),
+ \ "",
+ \ "end",
+ \ ])
+ set spell cpo+=$
+ ]=])
+ feed('51|C')
+ screen:expect([[
+ {2:test} test test test test test test test test test ^test test test test test test |
+ test test test test$ |
+ |
+ {2:end} |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {9:-- INSERT --} |
+ ]])
+ feed('x')
+ screen:expect([[
+ {2:test} test test test test test test test test test x^est test test test test test |
+ test test test test$ |
+ |
+ {2:end} |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {9:-- INSERT --} |
]])
end)
it('extmarks, "noplainbuffer" and syntax #20385 #23398', function()
- command('set filetype=c')
- command('syntax on')
- command('set spell')
+ exec('set filetype=c')
+ exec('syntax on')
+ exec('set spell')
insert([[
#include <stdbool.h>
bool func(void);
@@ -119,7 +217,7 @@ describe("'spell'", function()
{0:~ }|
{6:search hit BOTTOM, continuing at TOP} |
]])
- command('echo ""')
+ exec('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 })
@@ -168,7 +266,7 @@ describe("'spell'", function()
{0:~ }|
{6:search hit TOP, continuing at BOTTOM} |
]])
- command('echo ""')
+ exec('echo ""')
curbufmeths.del_extmark(ns, id)
screen:expect([[
{3:#include }{4:<stdbool.h>} |
@@ -192,7 +290,7 @@ describe("'spell'", function()
|
]])
-- "noplainbuffer" shouldn't change spellchecking behavior with syntax enabled
- command('set spelloptions+=noplainbuffer')
+ exec('set spelloptions+=noplainbuffer')
screen:expect_unchanged()
feed('[s')
screen:expect([[
@@ -206,7 +304,7 @@ describe("'spell'", function()
|
]])
-- no spellchecking with "noplainbuffer" and syntax disabled
- command('syntax off')
+ exec('syntax off')
screen:expect([[
#include <stdbool.h> |
bool func(void); |
@@ -228,9 +326,9 @@ describe("'spell'", function()
{0:~ }|
{6:search hit BOTTOM, continuing at TOP} |
]])
- command('echo ""')
+ exec('echo ""')
-- everything is spellchecked without "noplainbuffer" with syntax disabled
- command('set spelloptions&')
+ exec('set spelloptions&')
screen:expect([[
#include <{1:stdbool}.h> |
{1:bool} {1:func}(void); |
@@ -256,7 +354,7 @@ describe("'spell'", function()
it('and syntax does not clear extmark highlighting at the start of a word', function()
screen:try_resize(43, 3)
- command([[
+ exec([[
set spell
syntax match Constant "^.*$"
call setline(1, "This is some text without any spell errors.")
diff --git a/test/old/testdir/test_spell.vim b/test/old/testdir/test_spell.vim
index c840e834b9..14d6ce30c4 100644
--- a/test/old/testdir/test_spell.vim
+++ b/test/old/testdir/test_spell.vim
@@ -972,28 +972,70 @@ func Test_spell_screendump()
\ ])
set spell spelllang=en_nz
END
- call writefile(lines, 'XtestSpell')
+ call writefile(lines, 'XtestSpell', 'D')
let buf = RunVimInTerminal('-S XtestSpell', {'rows': 8})
call VerifyScreenDump(buf, 'Test_spell_1', {})
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
+func Test_spell_screendump_spellcap()
+ CheckScreendump
+
let lines =<< trim END
call setline(1, [
- \ "This is some text without any spell errors. Everything",
- \ "should just be black, nothing wrong here.",
+ \ " This line has a sepll error. and missing caps and trailing spaces. ",
+ \ "another missing cap here.",
\ "",
- \ "This line has a sepll error. and missing caps.",
- \ "And and this is the the duplication.",
- \ "with missing caps here.",
+ \ "and here.",
+ \ " ",
+ \ "and here."
\ ])
- set spell spelllang=en_nz
+ set spell spelllang=en
END
- call writefile(lines, 'XtestSpell')
- let buf = RunVimInTerminal('-S XtestSpell', {'rows': 8})
- call VerifyScreenDump(buf, 'Test_spell_1', {})
+ call writefile(lines, 'XtestSpellCap', 'D')
+ let buf = RunVimInTerminal('-S XtestSpellCap', {'rows': 8})
+ call VerifyScreenDump(buf, 'Test_spell_2', {})
+
+ " After adding word missing Cap in next line is updated
+ call term_sendkeys(buf, "3GANot\<Esc>")
+ call VerifyScreenDump(buf, 'Test_spell_3', {})
+
+ " Deleting a full stop removes missing Cap in next line
+ call term_sendkeys(buf, "5Gddk$x")
+ call VerifyScreenDump(buf, 'Test_spell_4', {})
+
+ " Undo also updates the next line (go to command line to remove message)
+ call term_sendkeys(buf, "u:\<Esc>")
+ call VerifyScreenDump(buf, 'Test_spell_5', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
+func Test_spell_compatible()
+ CheckScreendump
+
+ let lines =<< trim END
+ call setline(1, [
+ \ "test "->repeat(20),
+ \ "",
+ \ "end",
+ \ ])
+ set spell cpo+=$
+ END
+ call writefile(lines, 'XtestSpellComp', 'D')
+ let buf = RunVimInTerminal('-S XtestSpellComp', {'rows': 8})
+
+ call term_sendkeys(buf, "51|C")
+ call VerifyScreenDump(buf, 'Test_spell_compatible_1', {})
+
+ call term_sendkeys(buf, "x")
+ call VerifyScreenDump(buf, 'Test_spell_compatible_2', {})
" clean up
call StopVimInTerminal(buf)
- call delete('XtestSpell')
endfunc
let g:test_data_aff1 = [