2

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.

3 Answers 3

2

One can configure ediff-filtered-filters such that it replaces multiple leading stars with one leading star and call ediff-buffers.

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)))
0
2

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)

Each 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 stardiff in $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 :-)

2

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.

2
  • I cannot find a command "ediff-buffers-wordwise"
    – Edman
    Commented Dec 14, 2019 at 7:40
  • Same question for me. I guess that this is a custom function defined in emacs.stackexchange.com/a/46195/226
    – Seki
    Commented Dec 5, 2022 at 17:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.