Skip to content

Commit 08cc374

Browse files
committed
patch 8.1.1838: there is :spellwrong and :spellgood but not :spellrare
Problem: There is :spellwrong and :spellgood but not :spellrare. Solution: Add :spellrare. (Martin Tournoij, closes #4291)
1 parent 4999a7f commit 08cc374

File tree

11 files changed

+226
-174
lines changed

11 files changed

+226
-174
lines changed

runtime/doc/spell.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,23 @@ zuG Undo |zW| and |zG|, remove the word from the internal
121121
:spellw[rong]! {word} Add {word} as a wrong (bad) word to the internal word
122122
list, like with |zW|.
123123

124+
*:spellr* *:spellrare*
125+
:[count]spellr[are] {word}
126+
Add {word} as a rare word to 'spellfile', similar to
127+
|zw|. Without count the first name is used, with
128+
a count of two the second entry, etc.
129+
130+
There are no normal mode commands to mark words as
131+
rare as this is a fairly uncommon command and all
132+
intuitive commands for this are already taken. If you
133+
want you can add mappings with e.g.: >
134+
nnoremap z? :exe ':spellrare ' . expand('<cWORD>')<CR>
135+
nnoremap z/ :exe ':spellrare! ' . expand('<cWORD>')<CR>
136+
< |:spellundo|, |zuw|, or |zuW| can be used to undo this.
137+
138+
:spellr[rare]! {word} Add {word} as a rare word to the internal word
139+
list, similar to |zW|.
140+
124141
:[count]spellu[ndo] {word} *:spellu* *:spellundo*
125142
Like |zuw|. [count] used as with |:spellgood|.
126143

src/ex_cmdidxs.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ static const unsigned short cmdidxs1[26] =
2424
/* q */ 358,
2525
/* r */ 361,
2626
/* s */ 381,
27-
/* t */ 449,
28-
/* u */ 494,
29-
/* v */ 505,
30-
/* w */ 523,
31-
/* x */ 537,
32-
/* y */ 547,
33-
/* z */ 548
27+
/* t */ 450,
28+
/* u */ 495,
29+
/* v */ 506,
30+
/* w */ 524,
31+
/* x */ 538,
32+
/* y */ 548,
33+
/* z */ 549
3434
};
3535

3636
/*
@@ -59,7 +59,7 @@ static const unsigned char cmdidxs2[26][26] =
5959
/* p */ { 1, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 0, 0, 16, 17, 26, 0, 27, 0, 28, 0 },
6060
/* q */ { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
6161
/* r */ { 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 19, 0, 0, 0, 0 },
62-
/* s */ { 2, 6, 15, 0, 19, 23, 0, 25, 26, 0, 0, 29, 31, 35, 39, 41, 0, 49, 0, 50, 0, 62, 63, 0, 64, 0 },
62+
/* s */ { 2, 6, 15, 0, 19, 23, 0, 25, 26, 0, 0, 29, 31, 35, 39, 41, 0, 50, 0, 51, 0, 63, 64, 0, 65, 0 },
6363
/* t */ { 2, 0, 19, 0, 24, 26, 0, 27, 0, 28, 0, 29, 33, 36, 38, 39, 0, 40, 42, 0, 43, 0, 0, 0, 0, 0 },
6464
/* u */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
6565
/* v */ { 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 9, 12, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0, 0, 0 },
@@ -69,4 +69,4 @@ static const unsigned char cmdidxs2[26][26] =
6969
/* z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
7070
};
7171

72-
static const int command_count = 561;
72+
static const int command_count = 562;

src/ex_cmds.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,9 @@ EXCMD(CMD_split, "split", ex_splitview,
13781378
EXCMD(CMD_spellgood, "spellgood", ex_spell,
13791379
EX_BANG|EX_RANGE|EX_NEEDARG|EX_EXTRA|EX_TRLBAR,
13801380
ADDR_OTHER),
1381+
EXCMD(CMD_spellrare, "spellrare", ex_spell,
1382+
EX_BANG|EX_RANGE|EX_NEEDARG|EX_EXTRA|EX_TRLBAR,
1383+
ADDR_OTHER),
13811384
EXCMD(CMD_spelldump, "spelldump", ex_spelldump,
13821385
EX_BANG|EX_TRLBAR,
13831386
ADDR_NONE),

src/normal.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5127,7 +5127,8 @@ nv_zet(cmdarg_T *cap)
51275127
if (ptr == NULL && (len = find_ident_under_cursor(&ptr,
51285128
FIND_IDENT)) == 0)
51295129
return;
5130-
spell_add_word(ptr, len, nchar == 'w' || nchar == 'W',
5130+
spell_add_word(ptr, len, nchar == 'w' || nchar == 'W'
5131+
? SPELL_ADD_BAD : SPELL_ADD_GOOD,
51315132
(nchar == 'G' || nchar == 'W')
51325133
? 0 : (int)cap->count1,
51335134
undo);

src/proto/spellfile.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ int spell_check_msm(void);
55
void ex_mkspell(exarg_T *eap);
66
void mkspell(int fcount, char_u **fnames, int ascii, int over_write, int added_word);
77
void ex_spell(exarg_T *eap);
8-
void spell_add_word(char_u *word, int len, int bad, int idx, int undo);
8+
void spell_add_word(char_u *word, int len, int what, int idx, int undo);
99
/* vim: set ft=c : */

src/spell.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,4 +298,8 @@ SPELL_EXTERN char e_format[] SPELL_INIT(= N_("E759: Format error in spell file")
298298
SPELL_EXTERN spelltab_T spelltab;
299299
SPELL_EXTERN int did_set_spelltab;
300300

301+
// Values for "what" argument of spell_add_word()
302+
#define SPELL_ADD_GOOD 0
303+
#define SPELL_ADD_BAD 1
304+
#define SPELL_ADD_RARE 2
301305
#endif

src/spellfile.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6125,28 +6125,31 @@ spell_message(spellinfo_T *spin, char_u *str)
61256125

61266126
/*
61276127
* ":[count]spellgood {word}"
6128-
* ":[count]spellwrong {word}"
6128+
* ":[count]spellwrong {word}"
61296129
* ":[count]spellundo {word}"
6130+
* ":[count]spellrare {word}"
61306131
*/
61316132
void
61326133
ex_spell(exarg_T *eap)
61336134
{
6134-
spell_add_word(eap->arg, (int)STRLEN(eap->arg), eap->cmdidx == CMD_spellwrong,
6135+
spell_add_word(eap->arg, (int)STRLEN(eap->arg),
6136+
eap->cmdidx == CMD_spellwrong ? SPELL_ADD_BAD :
6137+
eap->cmdidx == CMD_spellrare ? SPELL_ADD_RARE : SPELL_ADD_GOOD,
61356138
eap->forceit ? 0 : (int)eap->line2,
61366139
eap->cmdidx == CMD_spellundo);
61376140
}
61386141

61396142
/*
6140-
* Add "word[len]" to 'spellfile' as a good or bad word.
6143+
* Add "word[len]" to 'spellfile' as a good, rare or bad word.
61416144
*/
61426145
void
61436146
spell_add_word(
61446147
char_u *word,
61456148
int len,
6146-
int bad,
6147-
int idx, /* "zG" and "zW": zero, otherwise index in
6148-
'spellfile' */
6149-
int undo) /* TRUE for "zug", "zuG", "zuw" and "zuW" */
6149+
int what, // SPELL_ADD_ values
6150+
int idx, // "zG" and "zW": zero, otherwise index in
6151+
// 'spellfile'
6152+
int undo) // TRUE for "zug", "zuG", "zuw" and "zuW"
61506153
{
61516154
FILE *fd = NULL;
61526155
buf_T *buf = NULL;
@@ -6213,7 +6216,7 @@ spell_add_word(
62136216
fname = fnamebuf;
62146217
}
62156218

6216-
if (bad || undo)
6219+
if (what == SPELL_ADD_BAD || undo)
62176220
{
62186221
/* When the word appears as good word we need to remove that one,
62196222
* since its flags sort before the one with WF_BANNED. */
@@ -6280,8 +6283,10 @@ spell_add_word(
62806283
semsg(_(e_notopen), fname);
62816284
else
62826285
{
6283-
if (bad)
6286+
if (what == SPELL_ADD_BAD)
62846287
fprintf(fd, "%.*s/!\n", len, word);
6288+
else if (what == SPELL_ADD_RARE)
6289+
fprintf(fd, "%.*s/?\n", len, word);
62856290
else
62866291
fprintf(fd, "%.*s\n", len, word);
62876292
fclose(fd);

src/testdir/Make_all.mak

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ NEW_TESTS = \
236236
test_source \
237237
test_source_utf8 \
238238
test_spell \
239+
test_spellfile \
239240
test_startup \
240241
test_startup_utf8 \
241242
test_stat \
@@ -411,6 +412,7 @@ NEW_TESTS_RES = \
411412
test_sound.res \
412413
test_source.res \
413414
test_spell.res \
415+
test_spellfile.res \
414416
test_startup.res \
415417
test_stat.res \
416418
test_substitute.res \

src/testdir/test_normal.vim

Lines changed: 0 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,160 +1089,6 @@ func Test_normal18_z_fold()
10891089
bw!
10901090
endfunc
10911091

1092-
func Test_normal19_z_spell()
1093-
if !has("spell") || !has('syntax')
1094-
return
1095-
endif
1096-
new
1097-
call append(0, ['1 good', '2 goood', '3 goood'])
1098-
set spell spellfile=./Xspellfile.add spelllang=en
1099-
let oldlang=v:lang
1100-
lang C
1101-
1102-
" Test for zg
1103-
1
1104-
norm! ]s
1105-
call assert_equal('2 goood', getline('.'))
1106-
norm! zg
1107-
1
1108-
let a=execute('unsilent :norm! ]s')
1109-
call assert_equal('1 good', getline('.'))
1110-
call assert_equal('search hit BOTTOM, continuing at TOP', a[1:])
1111-
let cnt=readfile('./Xspellfile.add')
1112-
call assert_equal('goood', cnt[0])
1113-
1114-
" Test for zw
1115-
2
1116-
norm! $zw
1117-
1
1118-
norm! ]s
1119-
call assert_equal('2 goood', getline('.'))
1120-
let cnt=readfile('./Xspellfile.add')
1121-
call assert_equal('#oood', cnt[0])
1122-
call assert_equal('goood/!', cnt[1])
1123-
1124-
" Test for zg in visual mode
1125-
let a=execute('unsilent :norm! V$zg')
1126-
call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:])
1127-
1
1128-
norm! ]s
1129-
call assert_equal('3 goood', getline('.'))
1130-
let cnt=readfile('./Xspellfile.add')
1131-
call assert_equal('2 goood', cnt[2])
1132-
" Remove "2 good" from spellfile
1133-
2
1134-
let a=execute('unsilent norm! V$zw')
1135-
call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:])
1136-
let cnt=readfile('./Xspellfile.add')
1137-
call assert_equal('2 goood/!', cnt[3])
1138-
1139-
" Test for zG
1140-
let a=execute('unsilent norm! V$zG')
1141-
call assert_match("Word '2 goood' added to .*", a)
1142-
let fname=matchstr(a, 'to\s\+\zs\f\+$')
1143-
let cnt=readfile(fname)
1144-
call assert_equal('2 goood', cnt[0])
1145-
1146-
" Test for zW
1147-
let a=execute('unsilent norm! V$zW')
1148-
call assert_match("Word '2 goood' added to .*", a)
1149-
let cnt=readfile(fname)
1150-
call assert_equal('# goood', cnt[0])
1151-
call assert_equal('2 goood/!', cnt[1])
1152-
1153-
" Test for zuW
1154-
let a=execute('unsilent norm! V$zuW')
1155-
call assert_match("Word '2 goood' removed from .*", a)
1156-
let cnt=readfile(fname)
1157-
call assert_equal('# goood', cnt[0])
1158-
call assert_equal('# goood/!', cnt[1])
1159-
1160-
" Test for zuG
1161-
let a=execute('unsilent norm! $zG')
1162-
call assert_match("Word 'goood' added to .*", a)
1163-
let cnt=readfile(fname)
1164-
call assert_equal('# goood', cnt[0])
1165-
call assert_equal('# goood/!', cnt[1])
1166-
call assert_equal('goood', cnt[2])
1167-
let a=execute('unsilent norm! $zuG')
1168-
let cnt=readfile(fname)
1169-
call assert_match("Word 'goood' removed from .*", a)
1170-
call assert_equal('# goood', cnt[0])
1171-
call assert_equal('# goood/!', cnt[1])
1172-
call assert_equal('#oood', cnt[2])
1173-
" word not found in wordlist
1174-
let a=execute('unsilent norm! V$zuG')
1175-
let cnt=readfile(fname)
1176-
call assert_match("", a)
1177-
call assert_equal('# goood', cnt[0])
1178-
call assert_equal('# goood/!', cnt[1])
1179-
call assert_equal('#oood', cnt[2])
1180-
1181-
" Test for zug
1182-
call delete('./Xspellfile.add')
1183-
2
1184-
let a=execute('unsilent norm! $zg')
1185-
let cnt=readfile('./Xspellfile.add')
1186-
call assert_equal('goood', cnt[0])
1187-
let a=execute('unsilent norm! $zug')
1188-
call assert_match("Word 'goood' removed from \./Xspellfile.add", a)
1189-
let cnt=readfile('./Xspellfile.add')
1190-
call assert_equal('#oood', cnt[0])
1191-
" word not in wordlist
1192-
let a=execute('unsilent norm! V$zug')
1193-
call assert_match('', a)
1194-
let cnt=readfile('./Xspellfile.add')
1195-
call assert_equal('#oood', cnt[0])
1196-
1197-
" Test for zuw
1198-
call delete('./Xspellfile.add')
1199-
2
1200-
let a=execute('unsilent norm! Vzw')
1201-
let cnt=readfile('./Xspellfile.add')
1202-
call assert_equal('2 goood/!', cnt[0])
1203-
let a=execute('unsilent norm! Vzuw')
1204-
call assert_match("Word '2 goood' removed from \./Xspellfile.add", a)
1205-
let cnt=readfile('./Xspellfile.add')
1206-
call assert_equal('# goood/!', cnt[0])
1207-
" word not in wordlist
1208-
let a=execute('unsilent norm! $zug')
1209-
call assert_match('', a)
1210-
let cnt=readfile('./Xspellfile.add')
1211-
call assert_equal('# goood/!', cnt[0])
1212-
1213-
" add second entry to spellfile setting
1214-
set spellfile=./Xspellfile.add,./Xspellfile2.add
1215-
call delete('./Xspellfile.add')
1216-
2
1217-
let a=execute('unsilent norm! $2zg')
1218-
let cnt=readfile('./Xspellfile2.add')
1219-
call assert_match("Word 'goood' added to ./Xspellfile2.add", a)
1220-
call assert_equal('goood', cnt[0])
1221-
1222-
" Test for :spellgood!
1223-
let temp = execute(':spe!0/0')
1224-
call assert_match('Invalid region', temp)
1225-
let spellfile = matchstr(temp, 'Invalid region nr in \zs.*\ze line \d: 0')
1226-
call assert_equal(['# goood', '# goood/!', '#oood', '0/0'], readfile(spellfile))
1227-
call delete(spellfile)
1228-
1229-
" clean up
1230-
exe "lang" oldlang
1231-
call delete("./Xspellfile.add")
1232-
call delete("./Xspellfile2.add")
1233-
call delete("./Xspellfile.add.spl")
1234-
call delete("./Xspellfile2.add.spl")
1235-
1236-
" zux -> no-op
1237-
2
1238-
norm! $zux
1239-
call assert_equal([], glob('Xspellfile.add',0,1))
1240-
call assert_equal([], glob('Xspellfile2.add',0,1))
1241-
1242-
set spellfile=
1243-
bw!
1244-
endfunc
1245-
12461092
func Test_normal20_exmode()
12471093
if !has("unix")
12481094
" Reading from redirected file doesn't work on MS-Windows

0 commit comments

Comments
 (0)