Add way to remove items from document dictionary

This commit is contained in:
Juergen Spitzmueller 2021-03-07 18:23:07 +01:00
parent 07122f066b
commit c8feef2e23
11 changed files with 85 additions and 20 deletions

View File

@ -119,6 +119,9 @@
* spelling-add-local adds words for a given language to the document's local spelling * spelling-add-local adds words for a given language to the document's local spelling
dictionary. dictionary.
* spelling-remove-local removes words for a given language from the document's local
spelling dictionary.
* inset-split is a new convenience function that splits an inset into two at the given * inset-split is a new convenience function that splits an inset into two at the given
cursor position. This is only implemented for text insets currently. cursor position. This is only implemented for text insets currently.

View File

@ -92,7 +92,7 @@ SpellChecker::Result AppleSpellChecker::check(WordLangTuple const & word,
if (it->lang()->code() != word.lang()->code()) if (it->lang()->code() != word.lang()->code())
continue; continue;
if (it->word() == word.word()) if (it->word() == word.word())
return LEARNED_WORD; return DOCUMENT_LEARNED_WORD;
} }
SpellCheckResult result = SpellCheckResult result =

View File

@ -445,7 +445,7 @@ SpellChecker::Result AspellChecker::check(WordLangTuple const & word,
if (it->lang()->code() != word.lang()->code()) if (it->lang()->code() != word.lang()->code())
continue; continue;
if (it->word() == word.word()) if (it->word() == word.word())
return LEARNED_WORD; return DOCUMENT_LEARNED_WORD;
} }
SpellChecker::Result rc = d->check(m, word); SpellChecker::Result rc = d->check(m, word);
return (rc == WORD_OK && d->learned(word)) ? LEARNED_WORD : rc; return (rc == WORD_OK && d->learned(word)) ? LEARNED_WORD : rc;

View File

@ -139,7 +139,7 @@ SpellChecker::Result EnchantChecker::check(WordLangTuple const & word,
if (it->lang()->code() != word.lang()->code()) if (it->lang()->code() != word.lang()->code())
continue; continue;
if (it->word() == word.word()) if (it->word() == word.word())
return LEARNED_WORD; return DOCUMENT_LEARNED_WORD;
} }
return UNKNOWN_WORD; return UNKNOWN_WORD;

View File

@ -499,6 +499,7 @@ enum FuncCode
LFUN_FONT_NO_SPELLCHECK, // jspitzm 20210305 LFUN_FONT_NO_SPELLCHECK, // jspitzm 20210305
LFUN_SPELLING_ADD_LOCAL, // jspitzm 20210306 LFUN_SPELLING_ADD_LOCAL, // jspitzm 20210306
// 390 // 390
LFUN_SPELLING_REMOVE_LOCAL, // jspitzm 20210307
LFUN_LASTACTION // end of the table LFUN_LASTACTION // end of the table
}; };

View File

@ -70,8 +70,7 @@ struct HunspellChecker::Private
Hunspell * speller(Language const * lang); Hunspell * speller(Language const * lang);
Hunspell * lookup(Language const * lang); Hunspell * lookup(Language const * lang);
/// ignored words /// ignored words
bool isIgnored(WordLangTuple const & wl, bool isIgnored(WordLangTuple const & wl) const;
std::vector<WordLangTuple> const & docdict) const;
/// personal word list interface /// personal word list interface
void remove(WordLangTuple const & wl); void remove(WordLangTuple const & wl);
void insert(WordLangTuple const & wl); void insert(WordLangTuple const & wl);
@ -282,8 +281,7 @@ int HunspellChecker::Private::numDictionaries() const
} }
bool HunspellChecker::Private::isIgnored(WordLangTuple const & wl, bool HunspellChecker::Private::isIgnored(WordLangTuple const & wl) const
vector<WordLangTuple> const & docdict) const
{ {
IgnoreList::const_iterator it = ignored_.begin(); IgnoreList::const_iterator it = ignored_.begin();
for (; it != ignored_.end(); ++it) { for (; it != ignored_.end(); ++it) {
@ -292,13 +290,6 @@ bool HunspellChecker::Private::isIgnored(WordLangTuple const & wl,
if (it->word() == wl.word()) if (it->word() == wl.word())
return true; return true;
} }
it = docdict.begin();
for (; it != docdict.end(); ++it) {
if (it->lang()->code() != wl.lang()->code())
continue;
if (it->word() == wl.word())
return true;
}
return false; return false;
} }
@ -356,9 +347,17 @@ HunspellChecker::~HunspellChecker()
SpellChecker::Result HunspellChecker::check(WordLangTuple const & wl, SpellChecker::Result HunspellChecker::check(WordLangTuple const & wl,
vector<WordLangTuple> const & docdict) vector<WordLangTuple> const & docdict)
{ {
if (d->isIgnored(wl, docdict)) if (d->isIgnored(wl))
return WORD_OK; return WORD_OK;
IgnoreList::const_iterator it = docdict.begin();
for (; it != docdict.end(); ++it) {
if (it->lang()->code() != wl.lang()->code())
continue;
if (it->word() == wl.word())
return DOCUMENT_LEARNED_WORD;
}
Hunspell * h = d->speller(wl.lang()); Hunspell * h = d->speller(wl.lang());
if (!h) if (!h)
return NO_DICTIONARY; return NO_DICTIONARY;

View File

@ -3806,6 +3806,19 @@ void LyXAction::init()
*/ */
{ LFUN_SPELLING_ADD_LOCAL, "spelling-add-local", Noop, Edit }, { LFUN_SPELLING_ADD_LOCAL, "spelling-add-local", Noop, Edit },
/*!
* \var lyx::FuncCode lyx::LFUN_SPELLING_REMOVE_LOCAL
* \li Action: Remove the word under the cursor from the document's local
* spell checker dictionary.
* The default for the language is retrieved from the cursor position.
* \li Syntax: spelling-remove-local [<STRING>] [<LANG>]
* \li Params: <WORD>: word to remove
<LANG>: language name (see file languages)
* \li Origin: spitz, 7 Mar 2021
* \endvar
*/
{ LFUN_SPELLING_REMOVE_LOCAL, "spelling-remove-local", Noop, Edit },
/*! /*!
* \var lyx::FuncCode lyx::LFUN_SPELLING_CONTINUOUSLY * \var lyx::FuncCode lyx::LFUN_SPELLING_CONTINUOUSLY
* \li Action: Toggle continuous spell checking. * \li Action: Toggle continuous spell checking.

View File

@ -4961,11 +4961,11 @@ void Paragraph::Private::markMisspelledWords(
WordLangTuple const candidate(word.substr(wstart, wlen), lang); WordLangTuple const candidate(word.substr(wstart, wlen), lang);
SpellChecker::Result actresult = result; SpellChecker::Result actresult = result;
if (inset_owner_->buffer().params().spellignored(candidate)) if (inset_owner_->buffer().params().spellignored(candidate))
actresult = SpellChecker::WORD_OK; actresult = SpellChecker::DOCUMENT_LEARNED_WORD;
numskipped += countSkips(it, et, snext); numskipped += countSkips(it, et, snext);
/// mark the range of misspelling /// mark the range of misspelling
setMisspelled(wstart, snext, actresult); setMisspelled(wstart, snext, actresult);
if (actresult == SpellChecker::WORD_OK) if (actresult == SpellChecker::DOCUMENT_LEARNED_WORD)
LYXERR(Debug::GUI, "local dictionary word: \"" << LYXERR(Debug::GUI, "local dictionary word: \"" <<
candidate.word() << "\" [" << candidate.word() << "\" [" <<
wstart << ".." << (snext-1) << "]"); wstart << ".." << (snext-1) << "]");

View File

@ -44,6 +44,8 @@ public:
IGNORED_WORD, IGNORED_WORD,
/// number of personal dictionary "word" /// number of personal dictionary "word"
LEARNED_WORD, LEARNED_WORD,
/// number of document dictionary "word"
DOCUMENT_LEARNED_WORD,
/// missing dictionary for language /// missing dictionary for language
NO_DICTIONARY NO_DICTIONARY
}; };
@ -57,7 +59,8 @@ public:
return res != WORD_OK return res != WORD_OK
&& res != IGNORED_WORD && res != IGNORED_WORD
&& res != NO_DICTIONARY && res != NO_DICTIONARY
&& res != LEARNED_WORD; } && res != LEARNED_WORD
&& res != DOCUMENT_LEARNED_WORD; }
/// check the given word of the given lang code and return the result /// check the given word of the given lang code and return the result
virtual enum Result check(WordLangTuple const &, virtual enum Result check(WordLangTuple const &,

View File

@ -2745,8 +2745,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
} }
} }
WordLangTuple wl(word, language); WordLangTuple wl(word, language);
bool const has_item = bv->buffer().params().spellignored(wl); if (!bv->buffer().params().spellignored(wl)) {
if (!has_item) {
cur.recordUndoBufferParams(); cur.recordUndoBufferParams();
bv->buffer().params().spellignore().push_back(wl); bv->buffer().params().spellignore().push_back(wl);
cur.recordUndo(); cur.recordUndo();
@ -2761,6 +2760,45 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
break; break;
} }
case LFUN_SPELLING_REMOVE_LOCAL: {
Language const * language = getLanguage(cur, cmd.getArg(1));
docstring word = from_utf8(cmd.getArg(0));
if (word.empty()) {
word = cur.selectionAsString(false);
if (word.size() > 100)
break;
if (word.empty()) {
// Get word or selection
selectWordWhenUnderCursor(cur, WHOLE_WORD);
word = cur.selectionAsString(false);
}
}
WordLangTuple wl(word, language);
bool has_item = false;
vector<WordLangTuple>::const_iterator it = bv->buffer().params().spellignore().begin();
for (; it != bv->buffer().params().spellignore().end(); ++it) {
if (it->lang()->code() != wl.lang()->code())
continue;
if (it->word() == wl.word()) {
has_item = true;
break;
}
}
if (has_item) {
cur.recordUndoBufferParams();
bv->buffer().params().spellignore().erase(it);
cur.recordUndo();
// trigger re-check
WordLangTuple wl;
docstring_list suggestions;
Paragraph const & par = cur.paragraph();
pos_type from = cur.pos();
pos_type to = from;
par.spellCheck(from, to, wl, suggestions, true, true);
}
break;
}
case LFUN_SPELLING_IGNORE: { case LFUN_SPELLING_IGNORE: {
Language const * language = getLanguage(cur, cmd.getArg(1)); Language const * language = getLanguage(cur, cmd.getArg(1));
@ -3492,6 +3530,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
case LFUN_SPELLING_ADD: case LFUN_SPELLING_ADD:
case LFUN_SPELLING_ADD_LOCAL: case LFUN_SPELLING_ADD_LOCAL:
case LFUN_SPELLING_REMOVE_LOCAL:
case LFUN_SPELLING_IGNORE: case LFUN_SPELLING_IGNORE:
case LFUN_SPELLING_REMOVE: case LFUN_SPELLING_REMOVE:
enable = theSpellChecker() != nullptr; enable = theSpellChecker() != nullptr;

View File

@ -878,6 +878,13 @@ void MenuDefinition::expandSpellingSuggestions(BufferView const * bv)
FuncRequest(LFUN_SPELLING_REMOVE, arg))); FuncRequest(LFUN_SPELLING_REMOVE, arg)));
} }
break; break;
case SpellChecker::DOCUMENT_LEARNED_WORD: {
LYXERR(Debug::GUI, "Document-Learned Word.");
docstring const arg = wl.word() + " " + from_ascii(wl.lang()->lang());
add(MenuItem(MenuItem::Command, qt_("Remove from document dictionary|r"),
FuncRequest(LFUN_SPELLING_REMOVE_LOCAL, arg)));
}
break;
case SpellChecker::NO_DICTIONARY: case SpellChecker::NO_DICTIONARY:
LYXERR(Debug::GUI, "No dictionary for language " + from_ascii(wl.lang()->lang())); LYXERR(Debug::GUI, "No dictionary for language " + from_ascii(wl.lang()->lang()));
// FALLTHROUGH // FALLTHROUGH