aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/spell.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/spell.c')
-rw-r--r--src/nvim/spell.c127
1 files changed, 113 insertions, 14 deletions
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 84906a3548..610fb660e7 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -2317,16 +2317,14 @@ static void spell_load_lang(char_u *lang)
for (round = 1; round <= 2; ++round) {
// Find the first spell file for "lang" in 'runtimepath' and load it.
vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
- "spell/%s.%s.spl",
- lang, spell_enc());
- r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl);
+ "spell/%s.%s.spl", lang, spell_enc());
+ r = do_in_runtimepath(fname_enc, 0, spell_load_cb, &sl);
if (r == FAIL && *sl.sl_lang != NUL) {
// Try loading the ASCII version.
vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
- "spell/%s.ascii.spl",
- lang);
- r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl);
+ "spell/%s.ascii.spl", lang);
+ r = do_in_runtimepath(fname_enc, 0, spell_load_cb, &sl);
if (r == FAIL && *sl.sl_lang != NUL && round == 1
&& apply_autocmds(EVENT_SPELLFILEMISSING, lang,
@@ -2354,7 +2352,7 @@ static void spell_load_lang(char_u *lang)
} else if (sl.sl_slang != NULL) {
// At least one file was loaded, now load ALL the additions.
STRCPY(fname_enc + STRLEN(fname_enc) - 3, "add.spl");
- do_in_runtimepath(fname_enc, TRUE, spell_load_cb, &sl);
+ do_in_runtimepath(fname_enc, DIP_ALL, spell_load_cb, &sl);
}
}
@@ -7630,7 +7628,7 @@ mkspell (
else {
// Check for overwriting before doing things that may take a lot of
// time.
- if (!over_write && os_file_exists(wfname)) {
+ if (!over_write && os_path_exists(wfname)) {
EMSG(_(e_exists));
goto theend;
}
@@ -7686,7 +7684,7 @@ mkspell (
spin.si_region = 1 << i;
vim_snprintf((char *)fname, MAXPATHL, "%s.aff", innames[i]);
- if (os_file_exists(fname)) {
+ if (os_path_exists(fname)) {
// Read the .aff file. Will init "spin->si_conv" based on the
// "SET" line.
afile[i] = spell_read_aff(&spin, fname);
@@ -9319,7 +9317,56 @@ static void suggest_try_special(suginfo_T *su)
}
}
+// Measure how much time is spent in each state.
+// Output is dumped in "suggestprof".
+
+#ifdef SUGGEST_PROFILE
+proftime_T current;
+proftime_T total;
+proftime_T times[STATE_FINAL + 1];
+long counts[STATE_FINAL + 1];
+
+ static void
+prof_init(void)
+{
+ for (int i = 0; i <= STATE_FINAL; i++) {
+ profile_zero(&times[i]);
+ counts[i] = 0;
+ }
+ profile_start(&current);
+ profile_start(&total);
+}
+
+// call before changing state
+ static void
+prof_store(state_T state)
+{
+ profile_end(&current);
+ profile_add(&times[state], &current);
+ counts[state]++;
+ profile_start(&current);
+}
+# define PROF_STORE(state) prof_store(state);
+
+ static void
+prof_report(char *name)
+{
+ FILE *fd = fopen("suggestprof", "a");
+
+ profile_end(&total);
+ fprintf(fd, "-----------------------\n");
+ fprintf(fd, "%s: %s\n", name, profile_msg(&total));
+ for (int i = 0; i <= STATE_FINAL; i++) {
+ fprintf(fd, "%d: %s ("%" PRId64)\n", i, profile_msg(&times[i]), counts[i]);
+ }
+ fclose(fd);
+}
+#else
+# define PROF_STORE(state)
+#endif
+
// Try finding suggestions by adding/removing/swapping letters.
+
static void suggest_try_change(suginfo_T *su)
{
char_u fword[MAXWLEN]; // copy of the bad word, case-folded
@@ -9344,7 +9391,14 @@ static void suggest_try_change(suginfo_T *su)
continue;
// Try it for this language. Will add possible suggestions.
+ //
+#ifdef SUGGEST_PROFILE
+ prof_init();
+#endif
suggest_trie_walk(su, lp, fword, false);
+#ifdef SUGGEST_PROFILE
+ prof_report("try_change");
+#endif
}
}
@@ -9478,6 +9532,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// Always past NUL bytes now.
n = (int)sp->ts_state;
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_ENDNUL;
sp->ts_save_badflags = su->su_badflags;
@@ -9517,6 +9572,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
if (sp->ts_curi > len || byts[arridx] != 0) {
// Past bytes in node and/or past NUL bytes.
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_ENDNUL;
sp->ts_save_badflags = su->su_badflags;
break;
@@ -9870,6 +9926,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
#endif
// Save things to be restored at STATE_SPLITUNDO.
sp->ts_save_badflags = su->su_badflags;
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_SPLITUNDO;
++depth;
@@ -9936,6 +9993,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
byts = pbyts;
idxs = pidxs;
sp->ts_prefixdepth = PFD_PREFIXTREE;
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_NOPREFIX;
}
}
@@ -9948,6 +10006,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
su->su_badflags = sp->ts_save_badflags;
// Continue looking for NUL bytes.
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_START;
// In case we went into the prefix tree.
@@ -9962,9 +10021,11 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
&& sp->ts_tcharlen == 0
) {
// The badword ends, can't use STATE_PLAIN.
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_DEL;
break;
}
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_PLAIN;
// FALLTHROUGH
@@ -9975,10 +10036,12 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
if (sp->ts_curi > byts[arridx]) {
// Done all bytes at this node, do next state. When still at
// already changed bytes skip the other tricks.
- if (sp->ts_fidx >= sp->ts_fidxtry)
+ PROF_STORE(sp->ts_state)
+ if (sp->ts_fidx >= sp->ts_fidxtry) {
sp->ts_state = STATE_DEL;
- else
+ } else {
sp->ts_state = STATE_FINAL;
+ }
} else {
arridx += sp->ts_curi++;
c = byts[arridx];
@@ -10110,10 +10173,12 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// When past the first byte of a multi-byte char don't try
// delete/insert/swap a character.
if (has_mbyte && sp->ts_tcharlen > 0) {
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_FINAL;
break;
}
// Try skipping one character in the bad word (delete it).
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_INS_PREP;
sp->ts_curi = 1;
if (soundfold && sp->ts_fidx == 0 && fword[sp->ts_fidx] == '*')
@@ -10161,6 +10226,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
if (sp->ts_flags & TSF_DIDDEL) {
// If we just deleted a byte then inserting won't make sense,
// a substitute is always cheaper.
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_SWAP;
break;
}
@@ -10170,11 +10236,13 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
for (;; ) {
if (sp->ts_curi > byts[n]) {
// Only NUL bytes at this node, go to next state.
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_SWAP;
break;
}
if (byts[n + sp->ts_curi] != NUL) {
// Found a byte to insert.
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_INS;
break;
}
@@ -10190,6 +10258,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
n = sp->ts_arridx;
if (sp->ts_curi > byts[n]) {
// Done all bytes at this node, go to next state.
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_SWAP;
break;
}
@@ -10250,6 +10319,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
c = *p;
if (c == NUL) {
// End of word, can't swap or replace.
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_FINAL;
break;
}
@@ -10257,6 +10327,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// Don't swap if the first character is not a word character.
// SWAP3 etc. also don't make sense then.
if (!soundfold && !spell_iswordp(p, curwin)) {
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_INI;
break;
}
@@ -10281,6 +10352,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// When the second character is NUL we can't swap.
if (c2 == NUL) {
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_INI;
break;
}
@@ -10288,6 +10360,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// When characters are identical, swap won't do anything.
// Also get here if the second char is not a word character.
if (c == c2) {
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_SWAP3;
break;
}
@@ -10298,6 +10371,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
sp->ts_twordlen, tword, fword + sp->ts_fidx,
c, c2);
#endif
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_UNSWAP;
++depth;
if (has_mbyte) {
@@ -10312,6 +10386,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
}
} else
// If this swap doesn't work then SWAP3 won't either.
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_INI;
break;
@@ -10359,6 +10434,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// Also get here when the third character is not a word character.
// Second character may any char: "a.b" -> "b.a"
if (c == c3 || c3 == NUL) {
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_INI;
break;
}
@@ -10369,6 +10445,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
sp->ts_twordlen, tword, fword + sp->ts_fidx,
c, c3);
#endif
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_UNSWAP3;
++depth;
if (has_mbyte) {
@@ -10382,8 +10459,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
p[2] = c;
stack[depth].ts_fidxtry = sp->ts_fidx + 3;
}
- } else
+ } else {
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_INI;
+ }
break;
case STATE_UNSWAP3:
@@ -10409,6 +10488,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
if (!soundfold && !spell_iswordp(p, curwin)) {
// Middle char is not a word char, skip the rotate. First and
// third char were already checked at swap and swap3.
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_INI;
break;
}
@@ -10423,6 +10503,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
sp->ts_twordlen, tword, fword + sp->ts_fidx,
p[0], p[1], p[2]);
#endif
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_UNROT3L;
++depth;
p = fword + sp->ts_fidx;
@@ -10441,8 +10522,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
p[2] = c;
stack[depth].ts_fidxtry = sp->ts_fidx + 3;
}
- } else
+ } else {
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_INI;
+ }
break;
case STATE_UNROT3L:
@@ -10472,6 +10555,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
sp->ts_twordlen, tword, fword + sp->ts_fidx,
p[0], p[1], p[2]);
#endif
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_UNROT3R;
++depth;
p = fword + sp->ts_fidx;
@@ -10490,8 +10574,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
*p = c;
stack[depth].ts_fidxtry = sp->ts_fidx + 3;
}
- } else
+ } else {
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_INI;
+ }
break;
case STATE_UNROT3R:
@@ -10521,6 +10607,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
if ((lp->lp_replang == NULL && !soundfold)
|| sp->ts_score + SCORE_REP >= su->su_maxscore
|| sp->ts_fidx < sp->ts_fidxtry) {
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_FINAL;
break;
}
@@ -10533,10 +10620,12 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
sp->ts_curi = lp->lp_replang->sl_rep_first[fword[sp->ts_fidx]];
if (sp->ts_curi < 0) {
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_FINAL;
break;
}
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP;
// FALLTHROUGH
@@ -10566,6 +10655,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
ftp->ft_from, ftp->ft_to);
#endif
// Need to undo this afterwards.
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_UNDO;
// Change the "from" to the "to" string.
@@ -10585,6 +10675,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
if (sp->ts_curi >= gap->ga_len && sp->ts_state == STATE_REP)
// No (more) matches.
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_FINAL;
break;
@@ -10604,6 +10695,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
repextra -= tl - fl;
}
memmove(p, ftp->ft_from, fl);
+ PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP;
break;
@@ -11014,7 +11106,13 @@ static void suggest_try_soundalike(suginfo_T *su)
// try all kinds of inserts/deletes/swaps/etc.
// TODO: also soundfold the next words, so that we can try joining
// and splitting
+#ifdef SUGGEST_PROFILE
+ prof_init();
+#endif
suggest_trie_walk(su, lp, salword, true);
+#ifdef SUGGEST_PROFILE
+ prof_report("soundalike");
+#endif
}
}
}
@@ -13364,3 +13462,4 @@ int expand_spelling(linenr_T lnum, char_u *pat, char_u ***matchp)
return ga.ga_len;
}
+