{"id":18391292,"url":"https://github.com/thblt/aspell-merge3","last_synced_at":"2025-07-19T03:36:40.165Z","repository":{"id":68387249,"uuid":"422628949","full_name":"thblt/aspell-merge3","owner":"thblt","description":"3-way merge for aspell custom dictionaries","archived":false,"fork":false,"pushed_at":"2023-08-04T16:50:19.000Z","size":41,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-12T11:43:38.643Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thblt.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-29T15:39:16.000Z","updated_at":"2021-11-16T17:39:01.000Z","dependencies_parsed_at":"2024-11-06T02:01:48.912Z","dependency_job_id":"973320d6-580a-40df-b150-ac3adc8a18fb","html_url":"https://github.com/thblt/aspell-merge3","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/thblt/aspell-merge3","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thblt%2Faspell-merge3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thblt%2Faspell-merge3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thblt%2Faspell-merge3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thblt%2Faspell-merge3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thblt","download_url":"https://codeload.github.com/thblt/aspell-merge3/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thblt%2Faspell-merge3/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265883680,"owners_count":23843800,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T01:51:22.007Z","updated_at":"2025-07-19T03:36:40.144Z","avatar_url":"https://github.com/thblt.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"#+TITLE: Three-way merge for aspell personal dictionaries\n\nThis is a very simple, non-interactive merge program for aspell\npersonal dictionaries (=.pws= files).  It is meant for people who sync\ntheir personal aspell dictionaries over multiple computers using a vcs\n(eg, git) or some cloud service.  Regular merge programs are easily\nconfused by aspell files, who are just an unordered list with an\nheader on the first line (they get especially confused by that header,\nsince it contains the number of words in the file, so it changes when\nadding/removing words).\n\n=aspell-merge3= automagically merges those files, taking deletions\ninto account, and works well with git (see [[#git-integration][the section on git\nintegration]], below)\n\n* Building and installation\n\nCompilation requires only =cabal= (usually packaged as =cabal-install=\nor =haskell-cabal=) and is as simple as:\n\n#+begin_example\n$ git clone https://github.com/thblt/aspell-merge3\n$ cd aspell-merge3\n$ cabal build\n#+end_example\n\n* Usage\n\nJust as simple.  Pass three paths, starting with the common ancestor,\nand =aspell-merge3= will produce a new dictionary file, either to\n=sdtout= (the default) or to a location passed to the =--output=, =-o=\narg.\n\n#+begin_example\n$ aspell-merge3 original modifiedA modifiedB --output combined\n#+end_example\n\nThe program will terminate without output and with a non-zero exit\ncode if headers in the three files differ in file format version,\nlocale or encoding.\n\n(If you need to combine two files without a common ancestor, simply\npass one of these files as the ancestor, eg =aspell-merge3 A A B\n--output O=)\n\n* git integration\n:PROPERTIES:\n:CUSTOM_ID: git-integration\n:END:\n\nIn your global or user git config (often =~/.config/git/config=), add\nthe following lines:\n\n#+begin_src ini\n[merge \"aspell-merge3\"]\n  name = A merge driver for aspell personal dictionaries.\n  driver = aspell-merge3 %O %A %B --output %A\n#+end_src ini\n\nthen, in your repo's =.gitattributes= (creating it if needed)\n\n#+begin_src ini\n*.pws merge=aspell-merge3\n#+end_src ini\n\n* Algorithm\n\nNothing fancy here. Given three sets of words, one from the ancestor\n(O), and two from variants we need to merge (A and B), words that\nmatch at least one of these conditions are added to the output:\n\n 1. The word present in both A and B.\n 2. The word is present in *either* A or B, and not in O.\n\nRule 1 is the obvious case where there's no conflict: either the word\nwas added on both sides, or it was already in O --- we don't need to\ncare.  Rule 2 is for words that have been added to one of the sides.\nThe extra condition in that rule, that the word is absent from O, is\nto propagate deletions: a word present in O, but not in both A and B,\nhas been /deleted/ on one side and that deletion must be propagated to\nthe final result.\n\nIn other words, the result of the merge is:\n\n#+begin_example\n  (A∩B)  ∪ (AΔB)\\O\n  -----    -------\n  Rule 1   Rule 2\n\n(Δ is symmetric difference. AΔB == A∪B\\A∩B)\n#+end_example\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthblt%2Faspell-merge3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthblt%2Faspell-merge3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthblt%2Faspell-merge3/lists"}