https://github.com/thblt/aspell-merge3
3-way merge for aspell custom dictionaries
https://github.com/thblt/aspell-merge3
Last synced: 11 months ago
JSON representation
3-way merge for aspell custom dictionaries
- Host: GitHub
- URL: https://github.com/thblt/aspell-merge3
- Owner: thblt
- License: gpl-3.0
- Created: 2021-10-29T15:39:16.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2023-08-04T16:50:19.000Z (almost 3 years ago)
- Last Synced: 2025-04-12T11:43:38.643Z (about 1 year ago)
- Language: Haskell
- Size: 40 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.org
- License: LICENSE
Awesome Lists containing this project
README
#+TITLE: Three-way merge for aspell personal dictionaries
This is a very simple, non-interactive merge program for aspell
personal dictionaries (=.pws= files). It is meant for people who sync
their personal aspell dictionaries over multiple computers using a vcs
(eg, git) or some cloud service. Regular merge programs are easily
confused by aspell files, who are just an unordered list with an
header on the first line (they get especially confused by that header,
since it contains the number of words in the file, so it changes when
adding/removing words).
=aspell-merge3= automagically merges those files, taking deletions
into account, and works well with git (see [[#git-integration][the section on git
integration]], below)
* Building and installation
Compilation requires only =cabal= (usually packaged as =cabal-install=
or =haskell-cabal=) and is as simple as:
#+begin_example
$ git clone https://github.com/thblt/aspell-merge3
$ cd aspell-merge3
$ cabal build
#+end_example
* Usage
Just as simple. Pass three paths, starting with the common ancestor,
and =aspell-merge3= will produce a new dictionary file, either to
=sdtout= (the default) or to a location passed to the =--output=, =-o=
arg.
#+begin_example
$ aspell-merge3 original modifiedA modifiedB --output combined
#+end_example
The program will terminate without output and with a non-zero exit
code if headers in the three files differ in file format version,
locale or encoding.
(If you need to combine two files without a common ancestor, simply
pass one of these files as the ancestor, eg =aspell-merge3 A A B
--output O=)
* git integration
:PROPERTIES:
:CUSTOM_ID: git-integration
:END:
In your global or user git config (often =~/.config/git/config=), add
the following lines:
#+begin_src ini
[merge "aspell-merge3"]
name = A merge driver for aspell personal dictionaries.
driver = aspell-merge3 %O %A %B --output %A
#+end_src ini
then, in your repo's =.gitattributes= (creating it if needed)
#+begin_src ini
*.pws merge=aspell-merge3
#+end_src ini
* Algorithm
Nothing fancy here. Given three sets of words, one from the ancestor
(O), and two from variants we need to merge (A and B), words that
match at least one of these conditions are added to the output:
1. The word present in both A and B.
2. The word is present in *either* A or B, and not in O.
Rule 1 is the obvious case where there's no conflict: either the word
was added on both sides, or it was already in O --- we don't need to
care. Rule 2 is for words that have been added to one of the sides.
The extra condition in that rule, that the word is absent from O, is
to propagate deletions: a word present in O, but not in both A and B,
has been /deleted/ on one side and that deletion must be propagated to
the final result.
In other words, the result of the merge is:
#+begin_example
(A∩B) ∪ (AΔB)\O
----- -------
Rule 1 Rule 2
(Δ is symmetric difference. AΔB == A∪B\A∩B)
#+end_example