7

I need to display word-diffs of a number of small strings.

That is, I have a list of pairs similar to the following:

"aaa bbb ccc" . "aaa vv ccc"
"abcd ef ghkl" . "ghkl"
"a (u -> h)" . "(a -> g) (u -> h)"

In each case I'd like to highlight changed or added text. I can do this with many calls to the diff command, but I'm afraid of the cost.

Are there elisp libraries that I could use for this purpose?

legoscia
  • 6,012
  • 29
  • 54
Clément
  • 3,924
  • 1
  • 22
  • 37
  • Have you actually tried calling the compiled diff command? The cost might be less than the speed you'd lose moving from compiled c code to elisp. – Tyler Jan 25 '16 at 16:07
  • @Tyler I haven't, since I don't have anything to compare the cost against. – Clément Jan 25 '16 at 16:14
  • 2
    Well no, but if it turns out it's already fast enough, you don't need to compare it to anything else – Tyler Jan 25 '16 at 16:17
  • Maybe cost wasn't the right word; beyond performance, I'm interested in other aspects: a lisp solution would be more robust (Windows users don't necessarily have diff installed, for example) and probably more easy to maintain. AFAIK diff requires files, so I'd have to write two files for each pair. That's 200 cycles of reading and writing for a list of 100 pairs to compare; unless I don't have other options, I don't really want to be doing that. – Clément Jan 25 '16 at 18:04
  • The wdiff front-end to diff will do this, without requiring you to explicitly write any files: `wdiff <(echo "abc def ghi" ) <(echo "abc ghi")` => `abc [-def-] ghi`. But that depends on having wdiff and diffutils installed, which won't help if you're building something for general use on Windows, so I guess you do need an elisp solution. – Tyler Jan 25 '16 at 18:33
  • The `<(...)` construct only works in bash-like shells, doesn't it? – Clément Jan 25 '16 at 18:33
  • Let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/34835/discussion-between-tyler-and-clement). – Tyler Jan 25 '16 at 18:34

1 Answers1

3

I don't think there is an existing Elisp solution for that. But if you look at how I implemented smerge-refine-subst (also used in diff-refine-hunk) it should give you some idea of how you can play with diff.

IOW you should be able to run a single diff process to handle all your lines at once, by concatenating them and adding "synchronization lines" in between. Also, to prevent diff from getting confused when lines from one pair match with lines from another pair, you'll probably want to prepend some text (unique to each pair) in front of every line.

Stefan
  • 26,154
  • 3
  • 46
  • 84
  • Thanks Stefan! The context is diffing two Coq goals in PG. I wonder if I could simply reuse `diff-refine-hunk`? I could create a fake diff file with each pair, and then call refine-hunk on each. – Clément Jul 04 '16 at 02:33
  • Better usde `smerge-refine-subst` (which is what is used internally by `diff-refine-hunk`. But that executes one `diff` process, so if you want to run a single diff for all pairs, you'll need to massage your input by hand. – Stefan Jul 04 '16 at 21:10