如何显示两个程序之间的差异?

How can I show the differences between two programs?

我正在进行编程讲座。我没有使用幻灯片,而是展示了一系列逐渐变长的程序,这些程序存储在文件名 0001.py0002.py

每个程序中的代码仅引入一行或几行代码作为对前面代码的修改。

我打算只使用 emacs 进行演示。我熟悉ediff,但在演讲中现场使用它会有点痛苦(因为有大约50个小程序,每个增量用一分钟介绍)。

是否存在允许我拆分 window 并突出显示 (n).py 和 (n+1).py 之间实际不同之处的 emacs 包。 (为了具体起见,我使用 .py,但希望该解决方案适用于任何文本文件。)

我在这里而不是在 https://emacs.stackexchange.com 上提问,因为我很乐意使用 emacs、git 或任何我可以组合在一起进行现场演示的解决方案,尤其是能够在回答问题时实时修改代码。

更新

正如 phils 所建议的那样,M-x compare-windows 几乎可以解决这个问题,但是:

  1. 如果无论光标在两个缓冲区中的当前位置如何都能正常工作,那就太好了。
  2. 如果所有更改都显示在一个视图中,而不是遍历 diff,那就太好了。重点是说 "see, in the program on the right I've added just this line and that line, and look at all that that program can do compared to the previous one."

更新 2

换句话说,如何生成下面HTML中手动完成的内容以显示差异side-by-side?

.myflex {
  display: flex;
  flex-direction: row;
}

.before,
.after {
  border: 1px solid black;
  padding: 20px;
  margin: 20px;
  border-radius: 2px;
}

.pink {
  background-color: pink;
}

.green {
  background-color: PaleGreen;
}
<div class="myflex">
  <div class="before">
    <pre>
<span class='pink'>And so without particularly analyzing all the contiguous sections of a</span>
<span class='pink'>cone and of the ranks of an army, or the ranks and positions in any</span>
while the less their direct participation in the action itself, the more
they command and the fewer of them there are; rising in this way from
the lowest ranks to the man at the top, who takes the least direct share
in the action and directs his activity chiefly to commanding.
        </pre>
  </div>
  <div class="after">
    <pre>
<span class='green'>We see a law by which men, to take associated action, combine</span>
<span class='green'>in such relations that the more directly they participate in performing</span>
<span class='green'>the action the less they can command and the more numerous they are,</span>
while the less their direct participation in the action itself, the more
they command and the fewer of them there are; rising in this way from
the lowest ranks to the man at the top, who takes the least direct share
in the action and directs his activity chiefly to commanding.
        </pre>
  </div>
</div>

Sequel

(我在这里添加这个 sequel 是因为 phils 慷慨地自愿回答了比我最初要求的更多的问题。)

考虑程序(以某种虚构的语言,存储在 .txt 文件中):

hello

并考虑我们插入一个需要缩进的关键字:

repeat:
    hello

现在,当我们在 split-window 中显示这两个程序时,如果 hi 而不是 突出显示就好了,尽管这两行不同通过缩进;只有 repeat: 是。

我们的想法是,我们将添加一些循环运算符,并且不希望听众的目光转向 缩进或整行,而只是操作员。

换句话说,当显示差异时,我们最好突出显示 repeat 行,而不是 hello 和它前面的缩进。

我怀疑一些现有的 diff 功能可以做到这一点,所以会有更好的答案,但我已经使用 compare-windows.

一起破解了以下内容
(defun my-compare-windows-complete (&optional ignore-whitespace)
  "Highlight all differences between two windows.

With a prefix argument, do not highlight whitespace-only differences.
\(This does not prevent the highlighting of whitespace that is part of
a difference which includes non-whitespace characters.)

To remove the highlighting, use \[compare-windows-dehighlight]."
  (interactive "P")
  (require 'cl-lib)
  (require 'compare-w)
  (compare-windows-dehighlight)
  (let ((w1 (get-buffer-window))
        (w2 (funcall compare-windows-get-window-function)))
    (cl-letf ((w1p (window-point w1))
              (w2p (window-point w2))
              (compare-windows-highlight 'persistent)
              ((symbol-function 'compare-windows-dehighlight) #'ignore)
              ((symbol-function 'ding) (lambda () (error "done"))))
      (with-selected-window w1
        (goto-char (point-min)))
      (with-selected-window w2
        (goto-char (point-min)))
      (ignore-errors
        (while (compare-windows ignore-whitespace)))
      ;; Highlight any non-matching remainder in both buffers.
      (let ((b1 (window-buffer w1))
            (b2 (window-buffer w2))
            (p1 (window-point w1))
            (p2 (window-point w2))
            (max1 (with-selected-window w1 (point-max)))
            (max2 (with-selected-window w2 (point-max))))
        (compare-windows-highlight p1 max1 b1 w1 p2 max2 b2 w2))
      (set-window-point w1 w1p)
      (set-window-point w2 w2p))))

之后可以使用M-xcompare-windows-dehighlight去掉高亮

用于突出显示的面孔是:

  • compare-windows-removed(继承自diff-removed
  • compare-windows-added(继承自diff-added