Как я могу показать различия между двумя программами?

Я выступаю с докладом о программировании. Вместо того, чтобы использовать слайды, я представляю последовательность постепенно увеличивающихся программ, хранящихся в именах файлов 0001.py, 0002.py и т. д.

Код в каждой программе представляет собой всего одну или несколько строк кода в качестве модификации предыдущей.

Я намерен представить исключительно с использованием emacs. Я знаком с ediff, но было бы немного неудобно использовать его вживую во время выступления (поскольку существует около 50 небольших программ, каждая из которых занимает одну минуту).

Существует ли пакет emacs, который позволил бы мне разделить окно и выделить то, что на самом деле отличается между (n).py и (n+1).py. (Я использую .py для конкретики, но, надеюсь, решение будет работать для любого текстового файла.)

Я спрашиваю здесь, а не на https://emacs.stackexchange.com, потому что я буду доволен решением, использующим emacs, git или любую комбинацию, которую я могу объединить, чтобы дать живую демонстрацию, особенно с возможностью изменять код вживую, отвечая на вопросы.

Обновлять

Как предполагает phils, M-xcompare-windows почти решает эту проблему, но:

  1. Было бы неплохо, если бы он корректно работал вне зависимости от текущего положения курсора в двух буферах.
  2. Было бы неплохо, если бы все изменения отображались в одном представлении, а не повторялись по diffs. Суть в том, чтобы сказать: «Посмотрите, в программе справа я добавил только эту строку и эту строку, и посмотрите на все, что может сделать программа это по сравнению с предыдущей».

Обновление 2

Другими словами, как мне сгенерировать то, что делается вручную в приведенном ниже HTML, чтобы показать различия рядом друг с другом?

.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>

Продолжение

(Я добавляю это продолжение сюда только потому, что Филс великодушно вызвался ответить на больше, чем я изначально просил.)

Рассмотрим программу (на каком-то воображаемом языке, хранящуюся в .txt файле):

hello

и учтите, что мы вставляем ключевое слово, требующее отступа:

repeat:
    hello

Теперь, когда мы показываем две программы в разделенном окне, было бы неплохо, если бы hi была выделена нет, несмотря на то, что две строки отличаются отступом; только repeat: есть.

Идея состоит в том, что мы добавляем какой-то оператор цикла и не хотим, чтобы взгляд слушателя переходил на либо отступ или на всю строку, только на оператор.

Другими словами, при отображении разницы мы бы в идеале выделяли строку repeat, но не hello и предшествующий ей отступ.

Как я могу показать различия между двумя программами?

Начиная с точки в начале каждого из двух буферов, повторный вызов compare-windows будет проходить через различия. Это работает для вашего варианта использования?

phils 28.05.2019 15:29

@филс Да! Вот почти все. Добавлю к сути вопроса.

Calaf 28.05.2019 16:10

Почему неудобно использовать ediff или M-x diff? Пожалуйста, уточните, что вам нужно, на что они не отвечают.

Drew 28.05.2019 17:54

вы можете поместить свои изменения в последовательные ветки git и использовать magit-ediff

Rorschach 28.05.2019 19:02

@Drew ediff/diff покажет различия один за другим. Мне нужно повторить, чтобы показать, что они собой представляют. Я бы хотел, чтобы различия были выделены (в виде transient-region или любого другого маркера), чтобы привлечь внимание слушателя к этим сегментам.

Calaf 28.05.2019 19:59
diff показывает все отличия - показывает дифф (только), т.е. патч. В любом случае, пожалуйста, укажите в вопросе, что именно вас интересует - комментарии могут быть удалены в любое время. Спасибо.
Drew 28.05.2019 20:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
193
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я подозреваю, что некоторые существующие функции 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)

Хороший!! Это делает это. Проблема для (будущего) вопроса о продолжении будет состоять в том, чтобы изменить определение «diff», чтобы оно игнорировало отступ. Например, если я оборачиваю конструкцию начала-конца цикла вокруг блока кода, блок получает отступ, что дает нежелательный визуальный сигнал от выделения о том, что тело цикла изменилось, хотя новыми являются только оболочки.

Calaf 29.05.2019 12:41

Впоследствии я добавил поведение аргумента префикса, которое касается проблемы отступа, которую вы описали (используя существующий аргумент ignore-whitespace для compare-windows); и я исправил то, что считал ошибкой, добавив выделение любого несоответствующего текста в конце буфера (впоследствии до конечной совпадающей области). Я думаю, что с этими дополнениями это работает довольно хорошо (хотя и не слишком быстро для большого количества различий).

phils 01.11.2019 11:30

Это очень мило. Но ваша модификация еще не идеальна :). Я добавил продолжение к вопросу. Вы не обрабатываете часть "либо". (Или, более подробно, теперь вы обрабатываете часть «вся строка», а не часть «либо отступ, либо».)

Calaf 01.11.2019 12:42

Мы находимся на территории «именно так compare-windows работает». Попробуйте это со своим тестовым случаем, и вы увидите, что он вообще не считает, что между двумя окнами есть какое-либо сходство. Таким образом, моя функция затем выделяет все в каждом окне (в каждом случае это «конечный несоответствующий текст в конце»). Если вы хотите, чтобы это изменилось, для самого compare-windows потребуется патч восходящей ветки.

phils 01.11.2019 13:10

Экспериментально мне кажется, что «привет» — это просто слишком короткий текст для compare-windows рассмотрения. Увеличение его как минимум до четырех символов делает то, что вы хотели (с оговоркой «Это не препятствует выделению пробелов, которые являются частью различия, которое включает символы, отличные от пробелов»).

phils 01.11.2019 13:19

Отступ остается выделенным после увеличения длины слова. Я добавил изображение для иллюстрации.

Calaf 01.11.2019 13:31

Действительно - согласно цитируемой оговорке из моего предыдущего комментария. Опять же, это просто то, как работает compare-windows.

phils 01.11.2019 13:40

Другие вопросы по теме