2

When I run tests for my projects, failing tests produce output that looks something like this:

        expected: "..."
         but got: "..."

The "..." are long lines that often only have small differences.

How can I quickly diff lines like this?

I've tired copying the lines to separate buffers and using ediff-buffers, but that had a few downsides:

  • the diff is line-oriented in a way that works poorly for comparing two long lines

  • ediff messes up my window configuration, so I either need to spawn a new frame or save my current configuration in a register—in practice, this disrupts my workflow a bit

  • ediff uses a separate frame for its controls, which is awkward when I'm running Emacs as a full-screen application in macOS

  • doing this manually is pretty laborious

I could solve the last problem by wrapping this up into an Elisp function, but the other issues would remain. Is there some way to configure ediff or use some other diff function that would work better for this usecase?

2
  • Split the window.
  • In each window, put point at the start of one of the two lines (or at the start of each "..." in your example).
  • M-x compare-windows RET
  • C-xzzzz... to repeatedly compare as many times as necessary.

Or of course, bind compare-windows to a key (I use C-M-=), and you can just type that repeatedly.


There's also M-x ediff-regions-wordwise

(I find the set-up process for this awkward by comparison, but YMMV.)


ediff messes up my window configuration, so I either need to spawn a new frame or save my current configuration in a register—in practice, this disrupts my workflow a bit

Put (winner-mode 1) in your config, and then you can simply C-c<left> (repeatedly, if necessary) to undo the window config changes.


ediff uses a separate frame for its controls, which is awkward when I'm running Emacs as a full-screen application in macOS

Yes, I find that to be a bad default, personally. It tends to break badly with tiling window managers, and it can be noticeably slower due to the need to create a new frame. You can fix this with:

(setq ediff-window-setup-function #'ediff-setup-windows-plain)

I recommend that you M-x customize-group RET ediff RET

1

Some user options (a.k.a. parameters) are initialized for a mouse-driven session. It may be worthwhile to note that Ediff may be customized using ediff-customize.

First, as mentioned by @phils, you should customize the variable ediff-window-setup-function e.g. M-x customize-variable. Set this variable to "Single Frame" by clicking on the button Value Menu, then press the key 2 and finally saves the setting using the button Apply and Save.

The function ediff-regions-wordwise can act on different regions in the same buffer. Therefore, you just need to select the different regions consecutively.

Press C-g if you need to deactivate the preselected region. To mark a region, press C-SPC to activate the mark and then move the cursor. As indicated, you should "submit" the active region using C-M-c.

Concerning the frame configuration, I think that you should set the variable ediff-before-setup-hook. You may also look at ediff-hook using M-x customize-group.

Note: I find that the user manual is of no help for your issue. It may be worthwhile to know that C-u M-x ediff-windows-wordwise compares the windows without user selections if the frame already contains the corresponding windows.

0

Not sure about your "messes up" problems, but you can do this:

You can use C-x 4 n n (command ni-narrow-to-region-indirect-other-window) from library Narrow Indirect to create an indirect buffer for each line. Then put each buffer in visual-line-mode. Then use ediff on the buffers.

I don't see the problems you mention, with that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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