Page MenuHomeDevCentral

D3724.id9632.diff
No OneTemporary

D3724.id9632.diff

diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -63,6 +63,22 @@
See below if you wish to host the Git repository locally.
+### Delete words from a dictionary
+
+Now your dictionaries are synced, it can be tricky to delete words from them,
+as the next sync will overwrite them and restore words you removed if still in
+the Git repository or one local fi
+le.
+
+If you added a word in a dictionary, you can delete it:
+
+```shell
+$ merge-dictionaries --delete-words <word> [word ...]
+```
+
+This is a potentially destructive operation:
+your dictionary files will be overwritten.
+
## IDE support
Currently, the following IDEs are supported
@@ -83,6 +99,7 @@
* a method to dump the extracted words in the IDE format
* write
* a method to save the files, normally you can call the ones created
+ * a method to rewrite a file with a list of words, so delete works too
### How can I contribute?
@@ -92,23 +109,6 @@
## FAQ
-### Delete a word
-
-Not yet implemented. Here a proposal to implement this.
-
-Curently, the workflow is:
-
-[ extract ] -> { words } -> [ publish ]
-
-You want to add a new transformation step:
-
-[ extract ] -> { words } -> [ transform ] -> { words cleaned up } -> [ publish ]
-
-Add a transform step with an allowlist of the words to remove.
-
-It's not easy to detect if the user has removed a word explicitly
-from a dictionary, as we don't cache extracted words.
-
### Host locally the Git repository
If you want to host the repository on your local machine, use a bare repository:
diff --git a/setup.cfg b/setup.cfg
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
[metadata]
name = merge-dictionaries
-version = 0.3.0
+version = 0.4.0
author = Sébastien Santoro
author_email = dereckson@espace-win.org
description = Merge dictionaries
diff --git a/src/mergedictionaries/actions/__init__.py b/src/mergedictionaries/actions/__init__.py
new file mode 100644
--- /dev/null
+++ b/src/mergedictionaries/actions/__init__.py
@@ -0,0 +1,9 @@
+# -------------------------------------------------------------
+# Merge dictionaries :: Actions
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# License: BSD-2-Clause
+# -------------------------------------------------------------
+
+
+from .delete_words import DeleteAction
diff --git a/src/mergedictionaries/actions/delete_words.py b/src/mergedictionaries/actions/delete_words.py
new file mode 100644
--- /dev/null
+++ b/src/mergedictionaries/actions/delete_words.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+
+# -------------------------------------------------------------
+# Delete words from all dictionaries
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# Description: Delete words from all dictionaries from
+# all currently found sources.
+# License: BSD-2-Clause
+# -------------------------------------------------------------
+
+
+from mergedictionaries import sources, write
+from mergedictionaries.sources import GitRepository
+
+
+class DeleteAction:
+ def __init__(self, context):
+ self.git_config = context["config"].get("git", [])
+
+ if "git" not in context:
+ context["git"] = []
+ self.git_cached_repos = context["git"]
+
+ def run(self, words):
+ for source in self.get_sources():
+ for arg in source["query"]():
+ source["delete"](words, arg)
+
+ def get_sources(self):
+ return [
+ {
+ "query": sources.jetbrains.find_application_level_dictionaries,
+ "delete": lambda words, file: write.jetbrains.delete_words(file, words),
+ },
+ {
+ "query": self.query_git_repositories,
+ "delete": lambda words, repo: write.git.delete_words(repo, words),
+ },
+ ]
+
+ def query_git_repositories(self):
+ return [
+ GitRepository(git_repo_url, self.git_cached_repos)
+ for git_repo_url in self.git_config
+ ]
diff --git a/src/mergedictionaries/app/app.py b/src/mergedictionaries/app/app.py
--- a/src/mergedictionaries/app/app.py
+++ b/src/mergedictionaries/app/app.py
@@ -17,6 +17,7 @@
import yaml
from mergedictionaries import write, output, sources
+from mergedictionaries.actions import DeleteAction
# -------------------------------------------------------------
@@ -74,6 +75,15 @@
help="Merge all found dictionaries",
)
+ parser.add_argument(
+ "-D",
+ "--delete-words",
+ metavar="word",
+ dest="delete_words",
+ nargs="+",
+ help="Delete one or more words from the dictionaries",
+ )
+
return parser.parse_args()
@@ -84,17 +94,24 @@
def run(self):
args = parse_arguments()
- if args.task is None:
+ task = "delete" if args.delete_words else args.task
+ if task is None:
print("No task has been specified.", file=sys.stderr)
sys.exit(1)
self.context["config"] = parse_configuration()
self.context["args"] = args
- if args.task == "extract":
+ if task == "extract":
self.run_extract_all_words(args.format)
- elif args.task == "merge":
+ elif task == "merge":
self.run_merge()
+ elif task == "delete":
+ action = DeleteAction(self.context)
+ action.run(args.delete_words)
+
+ self.on_exit()
+ sys.exit(0)
def get_dictionary_writers(self):
return [
@@ -110,8 +127,6 @@
for method in self.get_dictionary_writers():
method(words)
- self.on_exit()
-
def get_words_sources(self):
return [
lambda: sources.git.extract_words_from_all_dictionaries(
@@ -137,8 +152,7 @@
for word in words:
print(word)
- self.on_exit()
- sys.exit(0)
+ return
# We need a specific formatter
formatters = get_dictionary_formatters()
@@ -148,12 +162,10 @@
sys.exit(2)
print(formatters[words_format](words))
- self.on_exit()
- sys.exit(0)
def on_exit(self):
"""Events to run before exiting to cleanup resources."""
- sources.git.on_exit(self.context["git"])
+ sources.git.on_exit(self.context.get("git", {}))
def run():
diff --git a/src/mergedictionaries/utils/collections.py b/src/mergedictionaries/utils/collections.py
new file mode 100644
--- /dev/null
+++ b/src/mergedictionaries/utils/collections.py
@@ -0,0 +1,31 @@
+# -------------------------------------------------------------
+# Merge dictionaries :: Utilities :: Collections
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# Description: Helper functions for lists
+# License: BSD-2-Clause
+# -------------------------------------------------------------
+
+
+from typing import List
+
+
+def remove_words(current_words: List, words_to_delete: List) -> List:
+ """
+ Removes specified words from a list of words.
+
+ Parameters:
+ current_words: list
+ The list of words from which specified words are to be removed.
+ words_to_delete: list
+ The list containing words that need to be removed.
+
+ Returns:
+ list
+ A new list containing words from the current_words list that are not
+ present in the words_to_delete list.
+ """
+ words = list(set(current_words) - set(words_to_delete))
+ words.sort()
+
+ return words
diff --git a/src/mergedictionaries/write/git.py b/src/mergedictionaries/write/git.py
--- a/src/mergedictionaries/write/git.py
+++ b/src/mergedictionaries/write/git.py
@@ -6,10 +6,14 @@
# from Git repository
# License: BSD-2-Clause
# -------------------------------------------------------------
+
+
import os
from tempfile import NamedTemporaryFile
+from typing import List
from mergedictionaries.sources import GitRepository
+from mergedictionaries.utils.collections import remove_words
def build_temporary_dictionary(words):
@@ -31,3 +35,18 @@
GitRepository(repo, cached_repos).publish(tmp_dictionary_path)
os.unlink(tmp_dictionary_path)
+
+
+def delete_words(repo: GitRepository, words_to_delete: List):
+ current_words = repo.extract_words()
+
+ if not any(word in current_words for word in words_to_delete):
+ # Nothing to do, the dictionary is already up to date.
+ return
+
+ words = remove_words(current_words, words_to_delete)
+
+ tmp_dictionary_path = build_temporary_dictionary(words)
+ repo.publish(tmp_dictionary_path)
+
+ os.unlink(tmp_dictionary_path)
diff --git a/src/mergedictionaries/write/jetbrains.py b/src/mergedictionaries/write/jetbrains.py
--- a/src/mergedictionaries/write/jetbrains.py
+++ b/src/mergedictionaries/write/jetbrains.py
@@ -10,6 +10,7 @@
from mergedictionaries.sources import jetbrains as jetbrains_source
from mergedictionaries.output import jetbrains as jetbrains_output
+from mergedictionaries.utils.collections import remove_words
def write(words):
@@ -19,3 +20,18 @@
with open(file_path, "w") as fd:
fd.write(contents)
fd.write("\n")
+
+
+def delete_words(file_path, words_to_delete):
+ current_words = jetbrains_source.extract_words(file_path)
+
+ if not any(word in current_words for word in words_to_delete):
+ # Nothing to do, the dictionary is already up to date.
+ return
+
+ words = remove_words(current_words, words_to_delete)
+
+ contents = jetbrains_output.dump(words)
+ with open(file_path, "w") as fd:
+ fd.write(contents)
+ fd.write("\n")

File Metadata

Mime Type
text/plain
Expires
Tue, Sep 30, 00:43 (20 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3028049
Default Alt Text
D3724.id9632.diff (9 KB)

Event Timeline