mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 11:15:14 -07:00
Merge pull request #14785 from janlazo/vim-8.1.1838
vim-patch:8.1.{1838,1865},8.2.{38,39,46,945,948,2896}
This commit is contained in:
commit
12d8ff7ccd
@ -8230,9 +8230,8 @@ spellbadword([{sentence}])
|
||||
echo spellbadword("the quik brown fox")
|
||||
< ['quik', 'bad'] ~
|
||||
|
||||
The spelling information for the current window is used. The
|
||||
'spell' option must be set and the value of 'spelllang' is
|
||||
used.
|
||||
The spelling information for the current window and the value
|
||||
of 'spelllang' are used.
|
||||
|
||||
*spellsuggest()*
|
||||
spellsuggest({word} [, {max} [, {capital}]])
|
||||
@ -8254,8 +8253,7 @@ spellsuggest({word} [, {max} [, {capital}]])
|
||||
although it may appear capitalized.
|
||||
|
||||
The spelling information for the current window is used. The
|
||||
'spell' option must be set and the values of 'spelllang' and
|
||||
'spellsuggest' are used.
|
||||
values of 'spelllang' and 'spellsuggest' are used.
|
||||
|
||||
|
||||
split({expr} [, {pattern} [, {keepempty}]]) *split()*
|
||||
|
@ -110,6 +110,23 @@ zuG Undo |zW| and |zG|, remove the word from the internal
|
||||
:spellw[rong]! {word} Add {word} as a wrong (bad) word to the internal word
|
||||
list, like with |zW|.
|
||||
|
||||
*:spellra* *:spellrare*
|
||||
:[count]spellr[are] {word}
|
||||
Add {word} as a rare word to 'spellfile', similar to
|
||||
|zw|. Without count the first name is used, with
|
||||
a count of two the second entry, etc.
|
||||
|
||||
There are no normal mode commands to mark words as
|
||||
rare as this is a fairly uncommon command and all
|
||||
intuitive commands for this are already taken. If you
|
||||
want you can add mappings with e.g.: >
|
||||
nnoremap z? :exe ':spellrare ' . expand('<cWORD>')<CR>
|
||||
nnoremap z/ :exe ':spellrare! ' . expand('<cWORD>')<CR>
|
||||
< |:spellundo|, |zuw|, or |zuW| can be used to undo this.
|
||||
|
||||
:spellr[rare]! {word} Add {word} as a rare word to the internal word
|
||||
list, similar to |zW|.
|
||||
|
||||
:[count]spellu[ndo] {word} *:spellu* *:spellundo*
|
||||
Like |zuw|. [count] used as with |:spellgood|.
|
||||
|
||||
|
Binary file not shown.
@ -9661,6 +9661,18 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
const char *word = "";
|
||||
hlf_T attr = HLF_COUNT;
|
||||
size_t len = 0;
|
||||
const int wo_spell_save = curwin->w_p_spell;
|
||||
|
||||
if (!curwin->w_p_spell) {
|
||||
did_set_spelllang(curwin);
|
||||
curwin->w_p_spell = true;
|
||||
}
|
||||
|
||||
if (*curwin->w_s->b_p_spl == NUL) {
|
||||
EMSG(_(e_no_spell));
|
||||
curwin->w_p_spell = wo_spell_save;
|
||||
return;
|
||||
}
|
||||
|
||||
if (argvars[0].v_type == VAR_UNKNOWN) {
|
||||
// Find the start and length of the badly spelled word.
|
||||
@ -9669,7 +9681,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
word = (char *)get_cursor_pos_ptr();
|
||||
curwin->w_set_curswant = true;
|
||||
}
|
||||
} else if (curwin->w_p_spell && *curbuf->b_s.b_p_spl != NUL) {
|
||||
} else if (*curbuf->b_s.b_p_spl != NUL) {
|
||||
const char *str = tv_get_string_chk(&argvars[0]);
|
||||
int capcol = -1;
|
||||
|
||||
@ -9687,6 +9699,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
curwin->w_p_spell = wo_spell_save;
|
||||
|
||||
assert(len <= INT_MAX);
|
||||
tv_list_alloc_ret(rettv, 2);
|
||||
@ -9708,8 +9721,20 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
int maxcount;
|
||||
garray_T ga = GA_EMPTY_INIT_VALUE;
|
||||
bool need_capital = false;
|
||||
const int wo_spell_save = curwin->w_p_spell;
|
||||
|
||||
if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) {
|
||||
if (!curwin->w_p_spell) {
|
||||
did_set_spelllang(curwin);
|
||||
curwin->w_p_spell = true;
|
||||
}
|
||||
|
||||
if (*curwin->w_s->b_p_spl == NUL) {
|
||||
EMSG(_(e_no_spell));
|
||||
curwin->w_p_spell = wo_spell_save;
|
||||
return;
|
||||
}
|
||||
|
||||
if (*curwin->w_s->b_p_spl != NUL) {
|
||||
const char *const str = tv_get_string(&argvars[0]);
|
||||
if (argvars[1].v_type != VAR_UNKNOWN) {
|
||||
maxcount = tv_get_number_chk(&argvars[1], &typeerr);
|
||||
@ -9736,6 +9761,7 @@ f_spellsuggest_return:
|
||||
tv_list_append_allocated_string(rettv->vval.v_list, p);
|
||||
}
|
||||
ga_clear(&ga);
|
||||
curwin->w_p_spell = wo_spell_save;
|
||||
}
|
||||
|
||||
static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
|
@ -2567,6 +2567,12 @@ module.cmds = {
|
||||
addr_type='ADDR_NONE',
|
||||
func='ex_spellrepall',
|
||||
},
|
||||
{
|
||||
command='spellrare',
|
||||
flags=bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
|
||||
addr_type='ADDR_OTHER',
|
||||
func='ex_spell',
|
||||
},
|
||||
{
|
||||
command='spellundo',
|
||||
flags=bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
|
||||
|
@ -878,6 +878,7 @@ EXTERN char_u e_invexpr2[] INIT(= N_("E15: Invalid expression: %s"));
|
||||
EXTERN char_u e_invrange[] INIT(= N_("E16: Invalid range"));
|
||||
EXTERN char_u e_invcmd[] INIT(= N_("E476: Invalid command"));
|
||||
EXTERN char_u e_isadir2[] INIT(= N_("E17: \"%s\" is a directory"));
|
||||
EXTERN char_u e_no_spell[] INIT(= N_("E756: Spell checking is not possible"));
|
||||
EXTERN char_u e_invchan[] INIT(= N_("E900: Invalid channel id"));
|
||||
EXTERN char_u e_invchanjob[] INIT(= N_("E900: Invalid channel id: not a job"));
|
||||
EXTERN char_u e_jobtblfull[] INIT(= N_("E901: Job table is full"));
|
||||
|
@ -4604,7 +4604,9 @@ dozet:
|
||||
if (ptr == NULL && (len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0)
|
||||
return;
|
||||
assert(len <= INT_MAX);
|
||||
spell_add_word(ptr, (int)len, nchar == 'w' || nchar == 'W',
|
||||
spell_add_word(ptr, (int)len,
|
||||
nchar == 'w' || nchar == 'W'
|
||||
? SPELL_ADD_BAD : SPELL_ADD_GOOD,
|
||||
(nchar == 'G' || nchar == 'W') ? 0 : (int)cap->count1,
|
||||
undo);
|
||||
}
|
||||
|
@ -1343,7 +1343,7 @@ static 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)) {
|
||||
EMSG(_("E756: Spell checking is not enabled"));
|
||||
EMSG(_(e_no_spell));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -2771,9 +2771,17 @@ void spell_suggest(int count)
|
||||
int selected = count;
|
||||
int badlen = 0;
|
||||
int msg_scroll_save = msg_scroll;
|
||||
const int wo_spell_save = curwin->w_p_spell;
|
||||
|
||||
if (no_spell_checking(curwin))
|
||||
if (!curwin->w_p_spell) {
|
||||
did_set_spelllang(curwin);
|
||||
curwin->w_p_spell = true;
|
||||
}
|
||||
|
||||
if (*curwin->w_s->b_p_spl == NUL) {
|
||||
EMSG(_(e_no_spell));
|
||||
return;
|
||||
}
|
||||
|
||||
if (VIsual_active) {
|
||||
// Use the Visually selected text as the bad word. But reject
|
||||
@ -2966,6 +2974,7 @@ void spell_suggest(int count)
|
||||
|
||||
spell_find_cleanup(&sug);
|
||||
xfree(line);
|
||||
curwin->w_p_spell = wo_spell_save;
|
||||
}
|
||||
|
||||
// Check if the word at line "lnum" column "col" is required to start with a
|
||||
@ -5761,7 +5770,9 @@ cleanup_suggestions (
|
||||
xfree(stp[i].st_word);
|
||||
}
|
||||
gap->ga_len = keep;
|
||||
return stp[keep - 1].st_score;
|
||||
if (keep >= 1) {
|
||||
return stp[keep - 1].st_score;
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxscore;
|
||||
|
@ -284,4 +284,11 @@ extern int did_set_spelltab;
|
||||
|
||||
extern char *e_format;
|
||||
|
||||
// Values for "what" argument of spell_add_word()
|
||||
typedef enum {
|
||||
SPELL_ADD_GOOD = 0,
|
||||
SPELL_ADD_BAD = 1,
|
||||
SPELL_ADD_RARE = 2,
|
||||
} SpellAddType;
|
||||
|
||||
#endif // NVIM_SPELL_DEFS_H
|
||||
|
@ -5290,13 +5290,16 @@ static void spell_message(const spellinfo_T *spin, char_u *str)
|
||||
}
|
||||
|
||||
// ":[count]spellgood {word}"
|
||||
// ":[count]spellwrong {word}"
|
||||
// ":[count]spellwrong {word}"
|
||||
// ":[count]spellundo {word}"
|
||||
// ":[count]spellrare {word}"
|
||||
void ex_spell(exarg_T *eap)
|
||||
{
|
||||
spell_add_word(eap->arg, (int)STRLEN(eap->arg), eap->cmdidx == CMD_spellwrong,
|
||||
eap->forceit ? 0 : (int)eap->line2,
|
||||
eap->cmdidx == CMD_spellundo);
|
||||
spell_add_word(eap->arg, (int)STRLEN(eap->arg),
|
||||
eap->cmdidx == CMD_spellwrong ? SPELL_ADD_BAD :
|
||||
eap->cmdidx == CMD_spellrare ? SPELL_ADD_RARE : SPELL_ADD_GOOD,
|
||||
eap->forceit ? 0 : (int)eap->line2,
|
||||
eap->cmdidx == CMD_spellundo);
|
||||
}
|
||||
|
||||
// Add "word[len]" to 'spellfile' as a good or bad word.
|
||||
@ -5304,10 +5307,10 @@ void
|
||||
spell_add_word (
|
||||
char_u *word,
|
||||
int len,
|
||||
int bad,
|
||||
int idx, // "zG" and "zW": zero, otherwise index in
|
||||
// 'spellfile'
|
||||
bool undo // true for "zug", "zuG", "zuw" and "zuW"
|
||||
SpellAddType what, // SPELL_ADD_ values
|
||||
int idx, // "zG" and "zW": zero, otherwise index in
|
||||
// 'spellfile'
|
||||
bool undo // true for "zug", "zuG", "zuw" and "zuW"
|
||||
)
|
||||
{
|
||||
FILE *fd = NULL;
|
||||
@ -5364,7 +5367,7 @@ spell_add_word (
|
||||
fname = fnamebuf;
|
||||
}
|
||||
|
||||
if (bad || undo) {
|
||||
if (what == SPELL_ADD_BAD || undo) {
|
||||
// When the word appears as good word we need to remove that one,
|
||||
// since its flags sort before the one with WF_BANNED.
|
||||
fd = os_fopen((char *)fname, "r");
|
||||
@ -5422,13 +5425,16 @@ spell_add_word (
|
||||
}
|
||||
}
|
||||
|
||||
if (fd == NULL)
|
||||
if (fd == NULL) {
|
||||
EMSG2(_(e_notopen), fname);
|
||||
else {
|
||||
if (bad)
|
||||
} else {
|
||||
if (what == SPELL_ADD_BAD) {
|
||||
fprintf(fd, "%.*s/!\n", len, word);
|
||||
else
|
||||
} else if (what == SPELL_ADD_RARE) {
|
||||
fprintf(fd, "%.*s/?\n", len, word);
|
||||
} else {
|
||||
fprintf(fd, "%.*s\n", len, word);
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE);
|
||||
|
@ -1111,161 +1111,6 @@ func Test_normal18_z_fold()
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_normal19_z_spell()
|
||||
if !has("spell") || !has('syntax')
|
||||
return
|
||||
endif
|
||||
new
|
||||
call append(0, ['1 good', '2 goood', '3 goood'])
|
||||
set spell spellfile=./Xspellfile.add spelllang=en
|
||||
let oldlang=v:lang
|
||||
lang C
|
||||
|
||||
" Test for zg
|
||||
1
|
||||
norm! ]s
|
||||
call assert_equal('2 goood', getline('.'))
|
||||
norm! zg
|
||||
1
|
||||
let a=execute('unsilent :norm! ]s')
|
||||
call assert_equal('1 good', getline('.'))
|
||||
call assert_equal('search hit BOTTOM, continuing at TOP', a[1:])
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('goood', cnt[0])
|
||||
|
||||
" Test for zw
|
||||
2
|
||||
norm! $zw
|
||||
1
|
||||
norm! ]s
|
||||
call assert_equal('2 goood', getline('.'))
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('#oood', cnt[0])
|
||||
call assert_equal('goood/!', cnt[1])
|
||||
|
||||
" Test for zg in visual mode
|
||||
let a=execute('unsilent :norm! V$zg')
|
||||
call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:])
|
||||
1
|
||||
norm! ]s
|
||||
call assert_equal('3 goood', getline('.'))
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('2 goood', cnt[2])
|
||||
" Remove "2 good" from spellfile
|
||||
2
|
||||
let a=execute('unsilent norm! V$zw')
|
||||
call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:])
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('2 goood/!', cnt[3])
|
||||
|
||||
" Test for zG
|
||||
let a=execute('unsilent norm! V$zG')
|
||||
call assert_match("Word '2 goood' added to .*", a)
|
||||
let fname=matchstr(a, 'to\s\+\zs\f\+$')
|
||||
let fname=Fix_truncated_tmpfile(fname)
|
||||
let cnt=readfile(fname)
|
||||
call assert_equal('2 goood', cnt[0])
|
||||
|
||||
" Test for zW
|
||||
let a=execute('unsilent norm! V$zW')
|
||||
call assert_match("Word '2 goood' added to .*", a)
|
||||
let cnt=readfile(fname)
|
||||
call assert_equal('# goood', cnt[0])
|
||||
call assert_equal('2 goood/!', cnt[1])
|
||||
|
||||
" Test for zuW
|
||||
let a=execute('unsilent norm! V$zuW')
|
||||
call assert_match("Word '2 goood' removed from .*", a)
|
||||
let cnt=readfile(fname)
|
||||
call assert_equal('# goood', cnt[0])
|
||||
call assert_equal('# goood/!', cnt[1])
|
||||
|
||||
" Test for zuG
|
||||
let a=execute('unsilent norm! $zG')
|
||||
call assert_match("Word 'goood' added to .*", a)
|
||||
let cnt=readfile(fname)
|
||||
call assert_equal('# goood', cnt[0])
|
||||
call assert_equal('# goood/!', cnt[1])
|
||||
call assert_equal('goood', cnt[2])
|
||||
let a=execute('unsilent norm! $zuG')
|
||||
let cnt=readfile(fname)
|
||||
call assert_match("Word 'goood' removed from .*", a)
|
||||
call assert_equal('# goood', cnt[0])
|
||||
call assert_equal('# goood/!', cnt[1])
|
||||
call assert_equal('#oood', cnt[2])
|
||||
" word not found in wordlist
|
||||
let a=execute('unsilent norm! V$zuG')
|
||||
let cnt=readfile(fname)
|
||||
call assert_match("", a)
|
||||
call assert_equal('# goood', cnt[0])
|
||||
call assert_equal('# goood/!', cnt[1])
|
||||
call assert_equal('#oood', cnt[2])
|
||||
|
||||
" Test for zug
|
||||
call delete('./Xspellfile.add')
|
||||
2
|
||||
let a=execute('unsilent norm! $zg')
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('goood', cnt[0])
|
||||
let a=execute('unsilent norm! $zug')
|
||||
call assert_match("Word 'goood' removed from \./Xspellfile.add", a)
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('#oood', cnt[0])
|
||||
" word not in wordlist
|
||||
let a=execute('unsilent norm! V$zug')
|
||||
call assert_match('', a)
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('#oood', cnt[0])
|
||||
|
||||
" Test for zuw
|
||||
call delete('./Xspellfile.add')
|
||||
2
|
||||
let a=execute('unsilent norm! Vzw')
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('2 goood/!', cnt[0])
|
||||
let a=execute('unsilent norm! Vzuw')
|
||||
call assert_match("Word '2 goood' removed from \./Xspellfile.add", a)
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('# goood/!', cnt[0])
|
||||
" word not in wordlist
|
||||
let a=execute('unsilent norm! $zug')
|
||||
call assert_match('', a)
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('# goood/!', cnt[0])
|
||||
|
||||
" add second entry to spellfile setting
|
||||
set spellfile=./Xspellfile.add,./Xspellfile2.add
|
||||
call delete('./Xspellfile.add')
|
||||
2
|
||||
let a=execute('unsilent norm! $2zg')
|
||||
let cnt=readfile('./Xspellfile2.add')
|
||||
call assert_match("Word 'goood' added to ./Xspellfile2.add", a)
|
||||
call assert_equal('goood', cnt[0])
|
||||
|
||||
" Test for :spellgood!
|
||||
let temp = execute(':spe!0/0')
|
||||
call assert_match('Invalid region', temp)
|
||||
let spellfile = matchstr(temp, 'Invalid region nr in \zs.*\ze line \d: 0')
|
||||
call assert_equal(['# goood', '# goood/!', '#oood', '0/0'], readfile(spellfile))
|
||||
call delete(spellfile)
|
||||
|
||||
" clean up
|
||||
exe "lang" oldlang
|
||||
call delete("./Xspellfile.add")
|
||||
call delete("./Xspellfile2.add")
|
||||
call delete("./Xspellfile.add.spl")
|
||||
call delete("./Xspellfile2.add.spl")
|
||||
|
||||
" zux -> no-op
|
||||
2
|
||||
norm! $zux
|
||||
call assert_equal([], glob('Xspellfile.add',0,1))
|
||||
call assert_equal([], glob('Xspellfile2.add',0,1))
|
||||
|
||||
set spellfile=
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_normal20_exmode()
|
||||
if !has("unix")
|
||||
" Reading from redirected file doesn't work on MS-Windows
|
||||
|
@ -106,11 +106,14 @@ foobar/?
|
||||
set spelllang=Xwords.spl
|
||||
call assert_equal(['foobar', 'rare'], spellbadword('foo foobar'))
|
||||
|
||||
" Typo should not be detected without the 'spell' option.
|
||||
" Typo should be detected even without the 'spell' option.
|
||||
set spelllang=en_gb nospell
|
||||
call assert_equal(['', ''], spellbadword('centre'))
|
||||
call assert_equal(['', ''], spellbadword('My bycycle.'))
|
||||
call assert_equal(['', ''], spellbadword('A sentence. another sentence'))
|
||||
call assert_equal(['bycycle', 'bad'], spellbadword('My bycycle.'))
|
||||
call assert_equal(['another', 'caps'], spellbadword('A sentence. another sentence'))
|
||||
|
||||
set spelllang=
|
||||
call assert_fails("call spellbadword('maxch')", 'E756:')
|
||||
|
||||
call delete('Xwords.spl')
|
||||
call delete('Xwords')
|
||||
@ -172,6 +175,183 @@ func Test_spellreall()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" Test spellsuggest({word} [, {max} [, {capital}]])
|
||||
func Test_spellsuggest()
|
||||
" Verify suggestions are given even when spell checking is not enabled.
|
||||
set nospell
|
||||
call assert_equal(['march', 'March'], spellsuggest('marrch', 2))
|
||||
|
||||
set spell
|
||||
|
||||
" With 1 argument.
|
||||
call assert_equal(['march', 'March'], spellsuggest('marrch')[0:1])
|
||||
|
||||
" With 2 arguments.
|
||||
call assert_equal(['march', 'March'], spellsuggest('marrch', 2))
|
||||
|
||||
" With 3 arguments.
|
||||
call assert_equal(['march'], spellsuggest('marrch', 1, 0))
|
||||
call assert_equal(['March'], spellsuggest('marrch', 1, 1))
|
||||
|
||||
" Test with digits and hyphen.
|
||||
call assert_equal('Carbon-14', spellsuggest('Carbon-15')[0])
|
||||
|
||||
" Comment taken from spellsuggest.c explains the following test cases:
|
||||
"
|
||||
" If there are more UPPER than lower case letters suggest an
|
||||
" ALLCAP word. Otherwise, if the first letter is UPPER then
|
||||
" suggest ONECAP. Exception: "ALl" most likely should be "All",
|
||||
" require three upper case letters.
|
||||
call assert_equal(['THIRD', 'third'], spellsuggest('thIRD', 2))
|
||||
call assert_equal(['third', 'THIRD'], spellsuggest('tHIrd', 2))
|
||||
call assert_equal(['Third'], spellsuggest('THird', 1))
|
||||
call assert_equal(['All'], spellsuggest('ALl', 1))
|
||||
|
||||
call assert_fails("call spellsuggest('maxch', [])", 'E745:')
|
||||
call assert_fails("call spellsuggest('maxch', 2, [])", 'E745:')
|
||||
|
||||
set spelllang=
|
||||
call assert_fails("call spellsuggest('maxch')", 'E756:')
|
||||
set spelllang&
|
||||
|
||||
set spell&
|
||||
endfunc
|
||||
|
||||
" Test 'spellsuggest' option with methods fast, best and double.
|
||||
func Test_spellsuggest_option_methods()
|
||||
set spell
|
||||
|
||||
for e in ['utf-8']
|
||||
exe 'set encoding=' .. e
|
||||
|
||||
set spellsuggest=fast
|
||||
call assert_equal(['Stick', 'Stitch'], spellsuggest('Stich', 2), e)
|
||||
|
||||
" With best or double option, "Stitch" should become the top suggestion
|
||||
" because of better phonetic matching.
|
||||
set spellsuggest=best
|
||||
call assert_equal(['Stitch', 'Stick'], spellsuggest('Stich', 2), e)
|
||||
|
||||
set spellsuggest=double
|
||||
call assert_equal(['Stitch', 'Stick'], spellsuggest('Stich', 2), e)
|
||||
endfor
|
||||
|
||||
set spell& spellsuggest& encoding&
|
||||
endfunc
|
||||
|
||||
" Test 'spellsuggest' option with value file:{filename}
|
||||
func Test_spellsuggest_option_file()
|
||||
set spell spellsuggest=file:Xspellsuggest
|
||||
call writefile(['emacs/vim',
|
||||
\ 'theribal/terrible',
|
||||
\ 'teribal/terrrible',
|
||||
\ 'terribal'],
|
||||
\ 'Xspellsuggest')
|
||||
|
||||
call assert_equal(['vim'], spellsuggest('emacs', 2))
|
||||
call assert_equal(['terrible'], spellsuggest('theribal',2))
|
||||
|
||||
" If the suggestion is misspelled (*terrrible* with 3 r),
|
||||
" it should not be proposed.
|
||||
" The entry for "terribal" should be ignored because of missing slash.
|
||||
call assert_equal([], spellsuggest('teribal', 2))
|
||||
call assert_equal([], spellsuggest('terribal', 2))
|
||||
|
||||
set spell spellsuggest=best,file:Xspellsuggest
|
||||
call assert_equal(['vim', 'Emacs'], spellsuggest('emacs', 2))
|
||||
call assert_equal(['terrible', 'tribal'], spellsuggest('theribal', 2))
|
||||
call assert_equal(['tribal'], spellsuggest('teribal', 1))
|
||||
call assert_equal(['tribal'], spellsuggest('terribal', 1))
|
||||
|
||||
call delete('Xspellsuggest')
|
||||
call assert_fails("call spellsuggest('vim')", "E484: Can't open file Xspellsuggest")
|
||||
|
||||
set spellsuggest& spell&
|
||||
endfunc
|
||||
|
||||
" Test 'spellsuggest' option with value {number}
|
||||
" to limit the number of suggestions
|
||||
func Test_spellsuggest_option_number()
|
||||
set spell spellsuggest=2,best
|
||||
new
|
||||
|
||||
" We limited the number of suggestions to 2, so selecting
|
||||
" the 1st and 2nd suggestion should correct the word, but
|
||||
" selecting a 3rd suggestion should do nothing.
|
||||
call setline(1, 'A baord')
|
||||
norm $1z=
|
||||
call assert_equal('A board', getline(1))
|
||||
|
||||
call setline(1, 'A baord')
|
||||
norm $2z=
|
||||
call assert_equal('A bard', getline(1))
|
||||
|
||||
call setline(1, 'A baord')
|
||||
norm $3z=
|
||||
call assert_equal('A baord', getline(1))
|
||||
|
||||
let a = execute('norm $z=')
|
||||
call assert_equal(
|
||||
\ "\n"
|
||||
\ .. "Change \"baord\" to:\n"
|
||||
\ .. " 1 \"board\"\n"
|
||||
\ .. " 2 \"bard\"\n"
|
||||
\ .. "Type number and <Enter> or click with the mouse (q or empty cancels): ", a)
|
||||
|
||||
set spell spellsuggest=0
|
||||
call assert_equal("\nSorry, no suggestions", execute('norm $z='))
|
||||
|
||||
" Unlike z=, function spellsuggest(...) should not be affected by the
|
||||
" max number of suggestions (2) set by the 'spellsuggest' option.
|
||||
call assert_equal(['board', 'bard', 'broad'], spellsuggest('baord', 3))
|
||||
|
||||
set spellsuggest& spell&
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" Test 'spellsuggest' option with value expr:{expr}
|
||||
func Test_spellsuggest_option_expr()
|
||||
" A silly 'spellsuggest' function which makes suggestions all uppercase
|
||||
" and makes the score of each suggestion the length of the suggested word.
|
||||
" So shorter suggestions are preferred.
|
||||
func MySuggest()
|
||||
let spellsuggest_save = &spellsuggest
|
||||
set spellsuggest=3,best
|
||||
let result = map(spellsuggest(v:val, 3), "[toupper(v:val), len(v:val)]")
|
||||
let &spellsuggest = spellsuggest_save
|
||||
return result
|
||||
endfunc
|
||||
|
||||
set spell spellsuggest=expr:MySuggest()
|
||||
call assert_equal(['BARD', 'BOARD', 'BROAD'], spellsuggest('baord', 3))
|
||||
|
||||
new
|
||||
call setline(1, 'baord')
|
||||
let a = execute('norm z=')
|
||||
call assert_equal(
|
||||
\ "\n"
|
||||
\ .. "Change \"baord\" to:\n"
|
||||
\ .. " 1 \"BARD\"\n"
|
||||
\ .. " 2 \"BOARD\"\n"
|
||||
\ .. " 3 \"BROAD\"\n"
|
||||
\ .. "Type number and <Enter> or click with the mouse (q or empty cancels): ", a)
|
||||
|
||||
" With verbose, z= should show the score i.e. word length with
|
||||
" our SpellSuggest() function.
|
||||
set verbose=1
|
||||
let a = execute('norm z=')
|
||||
call assert_equal(
|
||||
\ "\n"
|
||||
\ .. "Change \"baord\" to:\n"
|
||||
\ .. " 1 \"BARD\" (4 - 0)\n"
|
||||
\ .. " 2 \"BOARD\" (5 - 0)\n"
|
||||
\ .. " 3 \"BROAD\" (5 - 0)\n"
|
||||
\ .. "Type number and <Enter> or click with the mouse (q or empty cancels): ", a)
|
||||
|
||||
set spell& spellsuggest& verbose&
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_spellinfo()
|
||||
throw 'skipped: Nvim does not support enc=latin1'
|
||||
new
|
||||
@ -227,7 +407,7 @@ func Test_zz_basic()
|
||||
\ )
|
||||
|
||||
call assert_equal("gebletegek", soundfold('goobledygoook'))
|
||||
call assert_equal("kepereneven", soundfold('kóopërÿnôven'))
|
||||
call assert_equal("kepereneven", soundfold('kóopërÿnôven'))
|
||||
call assert_equal("everles gesvets etele", soundfold('oeverloos gezwets edale'))
|
||||
endfunc
|
||||
|
||||
@ -408,7 +588,7 @@ func Test_zz_sal_and_addition()
|
||||
mkspell! Xtest Xtest
|
||||
set spl=Xtest.latin1.spl spell
|
||||
call assert_equal('kbltykk', soundfold('goobledygoook'))
|
||||
call assert_equal('kprnfn', soundfold('kóopërÿnôven'))
|
||||
call assert_equal('kprnfn', soundfold('kóopërÿnôven'))
|
||||
call assert_equal('*fls kswts tl', soundfold('oeverloos gezwets edale'))
|
||||
|
||||
"also use an addition file
|
||||
@ -461,6 +641,34 @@ func Test_zeq_crash()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" Check that z= works even when 'nospell' is set. This test uses one of the
|
||||
" tests in Test_spellsuggest_option_number() just to verify that z= basically
|
||||
" works and that "E756: Spell checking is not enabled" is not generated.
|
||||
func Test_zeq_nospell()
|
||||
new
|
||||
set nospell spellsuggest=1,best
|
||||
call setline(1, 'A baord')
|
||||
try
|
||||
norm $1z=
|
||||
call assert_equal('A board', getline(1))
|
||||
catch
|
||||
call assert_report("Caught exception: " . v:exception)
|
||||
endtry
|
||||
set spell& spellsuggest&
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" Check that "E756: Spell checking is not possible" is reported when z= is
|
||||
" executed and 'spelllang' is empty.
|
||||
func Test_zeq_no_spelllang()
|
||||
new
|
||||
set spelllang= spellsuggest=1,best
|
||||
call setline(1, 'A baord')
|
||||
call assert_fails('normal $1z=', 'E756:')
|
||||
set spelllang& spellsuggest&
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" Check handling a word longer than MAXWLEN.
|
||||
func Test_spell_long_word()
|
||||
set enc=utf-8
|
||||
|
240
src/nvim/testdir/test_spellfile.vim
Normal file
240
src/nvim/testdir/test_spellfile.vim
Normal file
@ -0,0 +1,240 @@
|
||||
" Test for commands that operate on the spellfile.
|
||||
|
||||
source shared.vim
|
||||
source check.vim
|
||||
|
||||
CheckFeature spell
|
||||
CheckFeature syntax
|
||||
|
||||
func Test_spell_normal()
|
||||
new
|
||||
call append(0, ['1 good', '2 goood', '3 goood'])
|
||||
set spell spellfile=./Xspellfile.add spelllang=en
|
||||
let oldlang=v:lang
|
||||
lang C
|
||||
|
||||
" Test for zg
|
||||
1
|
||||
norm! ]s
|
||||
call assert_equal('2 goood', getline('.'))
|
||||
norm! zg
|
||||
1
|
||||
let a=execute('unsilent :norm! ]s')
|
||||
call assert_equal('1 good', getline('.'))
|
||||
call assert_equal('search hit BOTTOM, continuing at TOP', a[1:])
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('goood', cnt[0])
|
||||
|
||||
" Test for zw
|
||||
2
|
||||
norm! $zw
|
||||
1
|
||||
norm! ]s
|
||||
call assert_equal('2 goood', getline('.'))
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('#oood', cnt[0])
|
||||
call assert_equal('goood/!', cnt[1])
|
||||
|
||||
" Test for :spellrare
|
||||
spellrare rare
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal(['#oood', 'goood/!', 'rare/?'], cnt)
|
||||
|
||||
" Make sure :spellundo works for rare words.
|
||||
spellundo rare
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal(['#oood', 'goood/!', '#are/?'], cnt)
|
||||
|
||||
" Test for zg in visual mode
|
||||
let a=execute('unsilent :norm! V$zg')
|
||||
call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:])
|
||||
1
|
||||
norm! ]s
|
||||
call assert_equal('3 goood', getline('.'))
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('2 goood', cnt[3])
|
||||
" Remove "2 good" from spellfile
|
||||
2
|
||||
let a=execute('unsilent norm! V$zw')
|
||||
call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:])
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('2 goood/!', cnt[4])
|
||||
|
||||
" Test for zG
|
||||
let a=execute('unsilent norm! V$zG')
|
||||
call assert_match("Word '2 goood' added to .*", a)
|
||||
let fname=matchstr(a, 'to\s\+\zs\f\+$')
|
||||
let cnt=readfile(fname)
|
||||
call assert_equal('2 goood', cnt[0])
|
||||
|
||||
" Test for zW
|
||||
let a=execute('unsilent norm! V$zW')
|
||||
call assert_match("Word '2 goood' added to .*", a)
|
||||
let cnt=readfile(fname)
|
||||
call assert_equal('# goood', cnt[0])
|
||||
call assert_equal('2 goood/!', cnt[1])
|
||||
|
||||
" Test for zuW
|
||||
let a=execute('unsilent norm! V$zuW')
|
||||
call assert_match("Word '2 goood' removed from .*", a)
|
||||
let cnt=readfile(fname)
|
||||
call assert_equal('# goood', cnt[0])
|
||||
call assert_equal('# goood/!', cnt[1])
|
||||
|
||||
" Test for zuG
|
||||
let a=execute('unsilent norm! $zG')
|
||||
call assert_match("Word 'goood' added to .*", a)
|
||||
let cnt=readfile(fname)
|
||||
call assert_equal('# goood', cnt[0])
|
||||
call assert_equal('# goood/!', cnt[1])
|
||||
call assert_equal('goood', cnt[2])
|
||||
let a=execute('unsilent norm! $zuG')
|
||||
let cnt=readfile(fname)
|
||||
call assert_match("Word 'goood' removed from .*", a)
|
||||
call assert_equal('# goood', cnt[0])
|
||||
call assert_equal('# goood/!', cnt[1])
|
||||
call assert_equal('#oood', cnt[2])
|
||||
" word not found in wordlist
|
||||
let a=execute('unsilent norm! V$zuG')
|
||||
let cnt=readfile(fname)
|
||||
call assert_match("", a)
|
||||
call assert_equal('# goood', cnt[0])
|
||||
call assert_equal('# goood/!', cnt[1])
|
||||
call assert_equal('#oood', cnt[2])
|
||||
|
||||
" Test for zug
|
||||
call delete('./Xspellfile.add')
|
||||
2
|
||||
let a=execute('unsilent norm! $zg')
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('goood', cnt[0])
|
||||
let a=execute('unsilent norm! $zug')
|
||||
call assert_match("Word 'goood' removed from \./Xspellfile.add", a)
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('#oood', cnt[0])
|
||||
" word not in wordlist
|
||||
let a=execute('unsilent norm! V$zug')
|
||||
call assert_match('', a)
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('#oood', cnt[0])
|
||||
|
||||
" Test for zuw
|
||||
call delete('./Xspellfile.add')
|
||||
2
|
||||
let a=execute('unsilent norm! Vzw')
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('2 goood/!', cnt[0])
|
||||
let a=execute('unsilent norm! Vzuw')
|
||||
call assert_match("Word '2 goood' removed from \./Xspellfile.add", a)
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('# goood/!', cnt[0])
|
||||
" word not in wordlist
|
||||
let a=execute('unsilent norm! $zug')
|
||||
call assert_match('', a)
|
||||
let cnt=readfile('./Xspellfile.add')
|
||||
call assert_equal('# goood/!', cnt[0])
|
||||
|
||||
" add second entry to spellfile setting
|
||||
set spellfile=./Xspellfile.add,./Xspellfile2.add
|
||||
call delete('./Xspellfile.add')
|
||||
2
|
||||
let a=execute('unsilent norm! $2zg')
|
||||
let cnt=readfile('./Xspellfile2.add')
|
||||
call assert_match("Word 'goood' added to ./Xspellfile2.add", a)
|
||||
call assert_equal('goood', cnt[0])
|
||||
|
||||
" Test for :spellgood!
|
||||
let temp = execute(':spe!0/0')
|
||||
call assert_match('Invalid region', temp)
|
||||
let spellfile = matchstr(temp, 'Invalid region nr in \zs.*\ze line \d: 0')
|
||||
call assert_equal(['# goood', '# goood/!', '#oood', '0/0'], readfile(spellfile))
|
||||
|
||||
" Test for :spellrare!
|
||||
:spellrare! raare
|
||||
call assert_equal(['# goood', '# goood/!', '#oood', '0/0', 'raare/?'], readfile(spellfile))
|
||||
call delete(spellfile)
|
||||
|
||||
" clean up
|
||||
exe "lang" oldlang
|
||||
call delete("./Xspellfile.add")
|
||||
call delete("./Xspellfile2.add")
|
||||
call delete("./Xspellfile.add.spl")
|
||||
call delete("./Xspellfile2.add.spl")
|
||||
|
||||
" zux -> no-op
|
||||
2
|
||||
norm! $zux
|
||||
call assert_equal([], glob('Xspellfile.add',0,1))
|
||||
call assert_equal([], glob('Xspellfile2.add',0,1))
|
||||
|
||||
set spellfile=
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
" Test CHECKCOMPOUNDPATTERN (see :help spell-CHECKCOMPOUNDPATTERN)
|
||||
func Test_spellfile_CHECKCOMPOUNDPATTERN()
|
||||
call writefile(['4',
|
||||
\ 'one/c',
|
||||
\ 'two/c',
|
||||
\ 'three/c',
|
||||
\ 'four'], 'XtestCHECKCOMPOUNDPATTERN.dic')
|
||||
" Forbid compound words where first word ends with 'wo' and second starts with 'on'.
|
||||
call writefile(['CHECKCOMPOUNDPATTERN 1',
|
||||
\ 'CHECKCOMPOUNDPATTERN wo on',
|
||||
\ 'COMPOUNDFLAG c'], 'XtestCHECKCOMPOUNDPATTERN.aff')
|
||||
|
||||
let output = execute('mkspell! XtestCHECKCOMPOUNDPATTERN-utf8.spl XtestCHECKCOMPOUNDPATTERN')
|
||||
set spell spelllang=XtestCHECKCOMPOUNDPATTERN-utf8.spl
|
||||
|
||||
" Check valid words with and without valid compounds.
|
||||
for goodword in ['one', 'two', 'three', 'four',
|
||||
\ 'oneone', 'onetwo', 'onethree',
|
||||
\ 'twotwo', 'twothree',
|
||||
\ 'threeone', 'threetwo', 'threethree',
|
||||
\ 'onetwothree', 'onethreetwo', 'twothreeone', 'oneoneone']
|
||||
call assert_equal(['', ''], spellbadword(goodword), goodword)
|
||||
endfor
|
||||
|
||||
" Compounds 'twoone' or 'threetwoone' should be forbidden by CHECKCOMPOUNPATTERN.
|
||||
" 'four' does not have the 'c' flag in *.aff file so no compound.
|
||||
" 'five' is not in the *.dic file.
|
||||
for badword in ['five', 'onetwox',
|
||||
\ 'twoone', 'threetwoone',
|
||||
\ 'fourone', 'onefour']
|
||||
call assert_equal([badword, 'bad'], spellbadword(badword))
|
||||
endfor
|
||||
|
||||
set spell& spelllang&
|
||||
call delete('XtestCHECKCOMPOUNDPATTERN.dic')
|
||||
call delete('XtestCHECKCOMPOUNDPATTERN.aff')
|
||||
call delete('XtestCHECKCOMPOUNDPATTERN-utf8.spl')
|
||||
endfunc
|
||||
|
||||
" Test COMMON (better suggestions with common words, see :help spell-COMMON)
|
||||
func Test_spellfile_COMMON()
|
||||
call writefile(['7',
|
||||
\ 'and',
|
||||
\ 'ant',
|
||||
\ 'end',
|
||||
\ 'any',
|
||||
\ 'tee',
|
||||
\ 'the',
|
||||
\ 'ted'], 'XtestCOMMON.dic')
|
||||
call writefile(['COMMON the and'], 'XtestCOMMON.aff')
|
||||
|
||||
let output = execute('mkspell! XtestCOMMON-utf8.spl XtestCOMMON')
|
||||
set spell spelllang=XtestCOMMON-utf8.spl
|
||||
|
||||
" COMMON words 'and' and 'the' should be the top suggestions.
|
||||
call assert_equal(['and', 'ant'], spellsuggest('anr', 2))
|
||||
call assert_equal(['and', 'end'], spellsuggest('ond', 2))
|
||||
call assert_equal(['the', 'ted'], spellsuggest('tha', 2))
|
||||
call assert_equal(['the', 'tee'], spellsuggest('dhe', 2))
|
||||
|
||||
set spell& spelllang&
|
||||
call delete('XtestCOMMON.dic')
|
||||
call delete('XtestCOMMON.aff')
|
||||
call delete('XtestCOMMON-utf8.spl')
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
@ -811,7 +811,7 @@ describe('ui/ext_messages', function()
|
||||
{1:~ }|
|
||||
{1:^~ }|
|
||||
]], messages={
|
||||
{content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Helli"\nType number and <Enter> or click with the mouse (q or empty cancels): ' } }, kind = ""}
|
||||
{content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\nType number and <Enter> or click with the mouse (q or empty cancels): ' } }, kind = ""}
|
||||
}}
|
||||
|
||||
feed('1')
|
||||
@ -822,7 +822,7 @@ describe('ui/ext_messages', function()
|
||||
{1:~ }|
|
||||
{1:^~ }|
|
||||
]], messages={
|
||||
{content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Helli"\nType number and <Enter> or click with the mouse (q or empty cancels): ' } }, kind = ""},
|
||||
{content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\nType number and <Enter> or click with the mouse (q or empty cancels): ' } }, kind = ""},
|
||||
{ content = { { "1" } }, kind = "" }
|
||||
}}
|
||||
|
||||
|
@ -36,7 +36,7 @@ describe("'spell'", function()
|
||||
feed('ggJJJJJJ0')
|
||||
screen:expect([[
|
||||
{1:^Lorem} {1:ipsum} dolor sit {1:amet}, {1:consectetur} {1:adipiscing} {1:elit}, {1:sed} do {1:eiusmod} {1:tempor} {1:i}|
|
||||
{1:ncididunt} {1:ut} {1:labore} {1:et} {1:dolore} {1:magna} {1:aliqua}. {1:Ut} {1:enim} ad minim {1:veniam}, {1:quis} {1:nostru}|
|
||||
{1:ncididunt} {1:ut} {1:labore} et {1:dolore} {1:magna} {1:aliqua}. {1:Ut} {1:enim} ad minim {1:veniam}, {1:quis} {1:nostru}|
|
||||
{1:d} {1:exercitation} {1:ullamco} {1:laboris} {1:nisi} {1:ut} {1:aliquip} ex ea {1:commodo} {1:consequat}. {1:Duis} {1:aut}|
|
||||
{1:e} {1:irure} dolor in {1:reprehenderit} in {1:voluptate} {1:velit} {1:esse} {1:cillum} {1:dolore} {1:eu} {1:fugiat} {1:n}|
|
||||
{1:ulla} {1:pariatur}. {1:Excepteur} {1:sint} {1:occaecat} {1:cupidatat} non {1:proident}, {1:sunt} in culpa {1:qui}|
|
||||
@ -44,6 +44,7 @@ describe("'spell'", function()
|
||||
{0:~ }|
|
||||
|
|
||||
]])
|
||||
|
||||
end)
|
||||
|
||||
it('has correct highlight at start of line', function()
|
||||
|
Loading…
Reference in New Issue
Block a user