I want to compare and merge some org files. How can I make a diff tool assume that some tasks or notes are identical, even if they are on different levels, i.e. strings only differ in the number of asterisks (*) at the beginning? I would then collapse those strings and consider merging only the rest that really differ.
One can configure
ediff-filtered-filters such that it replaces multiple leading stars with one leading star and call
The following Elisp function
my-org-ediff does that for you. Just copy the Elisp code to your init file, restart Emacs, and use
my-org-ediff for diffing org files in the way you want it.
(defvar ediff-filtered-filters) (defun my-org-ediff () "Ediff like `ediff-buffers' but convert all heading leaders \\*+\\([[:space:]]\\) to \\*\\1." (interactive) (let ((ediff-filtered-filters '(("^\\*+\\([[:space:]]\\)" . "*\\1")))) (call-interactively #'ediff-buffers)))
If you are content to use
diff on the bash command line and are not looking for a pure emacs solution, you can use process substitution to pass into
diff slightly modified files:
diff <(sed -E 's/^\*+/*/' file1.org) <(sed -E 's/^\*+/*/' file2.org)
sed command outputs its input file unchanged, except that a string of one or more asterisks at the beginning of a line is changed to a single asterisk. Bash process substitution makes a file out of that output. Conceptually, the above is equivalent to
sed -E 's/^\*+/*/' file1.org > /tmp/file1.modified.org sed -E 's/^\*+/*/' file2.org > /tmp/file2.modified.org diff /tmp/file1.modified.org /tmp/file2.modified.org rm /tmp/file1.modified.org /tmp/file2.modified.org
You can also write a bash script to simplify the invocation:
#!/bin/bash diff <(sed -E 's/^\*+/*/' $1) <(sed -E 's/^\*+/*/' $2)
Save it as
$HOME/bin (which I assume is in your
$PATH), make it executable:
chmod +x $HOME/bin/stardiff and invoke it like this:
stardiff file1.org file2.org
Process substitution is a general mechanism and is very useful in situations like this one, where we basically want to pipe the output of a command (the sed command output) into the input of another command (the diff command), except that we have two or more inputs: an ordinary pipe cannot deal with that, but process subsitution can.
Of course, this has nothing to do with emacs, but I hope the emacs SE moderators will not be too upset :-)
You can do an
ediff-buffers-wordwise and type #h
\*+ to ignore words consisting of stars.
If you advance to the next diff by pressing SPC ediff will skip words only differing in the number of stars.