diff --git a/news.d/feature/1160.core.md b/news.d/feature/1160.core.md new file mode 100644 index 000000000..a111a011e --- /dev/null +++ b/news.d/feature/1160.core.md @@ -0,0 +1 @@ +Allow higher priority dictionaries to delete entries from others. diff --git a/plover/steno_dictionary.py b/plover/steno_dictionary.py index 01e053f18..a31b3c0c4 100644 --- a/plover/steno_dictionary.py +++ b/plover/steno_dictionary.py @@ -178,7 +178,13 @@ def longest_key(self): def set_dicts(self, dicts): self.dicts = dicts[:] - def _lookup(self, key, dicts=None, filters=()): + def _lookup_keep_deleted(self, key, dicts=None, filters=()): + """ + Lookup a key in the given dicts. + If key appears in none of the dicts, return None. + If key appears in some dicts but with "{plover:deleted}" as value, + return "{plover:deleted}". + """ if dicts is None: dicts = self.dicts key_len = len(key) @@ -190,14 +196,26 @@ def _lookup(self, key, dicts=None, filters=()): if key_len > d.longest_key: continue value = d.get(key) - if value: + if value is not None: if not any(f(key, value) for f in filters): return value + def _lookup(self, key, dicts=None, filters=()): + """ + Same as _lookup_keep_deleted, but if key appears in some dicts + but with "{plover:deleted}" as value (case-insensitive), + return None instead. + """ + result = self._lookup_keep_deleted(key, dicts, filters) + if result is None or result.lower() == "{plover:deleted}": + return None + return result + def _lookup_from_all(self, key, dicts=None, filters=()): ''' Key lookup from all dictionaries - Returns list of (value, dictionary) tuples + Returns list of (value, dictionary) tuples. + Entries with value "{plover:deleted}" are kept. ''' if dicts is None: dicts = self.dicts @@ -241,7 +259,7 @@ def reverse_lookup(self, value): continue # Ignore key if it's overridden by a higher priority dictionary. keys.update(k for k in d.reverse_lookup(value) - if self._lookup(k, dicts=self.dicts[:n]) is None) + if self._lookup_keep_deleted(k, dicts=self.dicts[:n]) is None) return keys def casereverse_lookup(self, value): diff --git a/test/test_steno_dictionary.py b/test/test_steno_dictionary.py index 020680174..ccfa32aa0 100644 --- a/test/test_steno_dictionary.py +++ b/test/test_steno_dictionary.py @@ -14,18 +14,26 @@ def test_dictionary_collection(): d1 = StenoDictionary() d1[('S',)] = 'a' d1[('T',)] = 'b' + d1[('H',)] = '{PLOVER:deleted}' + d1[('R',)] = 'e' d1.path = 'd1' d2 = StenoDictionary() d2[('S',)] = 'c' d2[('W',)] = 'd' + d2[('H',)] = 'f' + d2[('R',)] = '{plover:deleted}' d2.path = 'd2' dc = StenoDictionaryCollection([d2, d1]) assert dc.lookup(('S',)) == 'c' assert dc.lookup(('W',)) == 'd' assert dc.lookup(('T',)) == 'b' + assert dc.lookup(('H',)) == 'f' + assert dc.lookup(('R',)) == None assert dc.lookup_from_all(('S',)) == [('c', d2), ('a', d1)] assert dc.lookup_from_all(('W',)) == [('d', d2)] assert dc.lookup_from_all(('T',)) == [('b', d1)] + assert dc.lookup_from_all(('H',)) == [('f', d2), ('{PLOVER:deleted}', d1)] + assert dc.lookup_from_all(('R',)) == [('{plover:deleted}', d2), ('e', d1)] f = lambda k, v: v == 'c' dc.add_filter(f) assert dc.lookup(('S',)) == 'a'