List of changed lines

21 views
Skip to first unread message

Salman Halim

unread,
Dec 1, 2022, 9:26:14 AM12/1/22
to Vim Users
Hello,

Is it possible, either natively or through Vim script (I'm happy to write the code, but not sure what to look for), to get a list of the lines that have been changed since a particular moment?

For example, I want a list of the lines I've added, deleted or modified since the last time I saved the file or since the last time I opened the file, even if it's been saved in between, or in the past hour. 

Thank you very much,

Salman

Christian Brabandt

unread,
Dec 1, 2022, 9:52:14 AM12/1/22
to Vim Users
I would use one of the undo plugins (like gundo python or undotree
vimscript) plugins for this. I think they also show the diff between
versions.

I even created a plugin histwin when the persistence undo feature was
introduced, that allowed you to tag certain states and allowed to show
you the diff between states

Best,
Christian
--
Von den Schlechten Verlacht zu werden ist fast ein Lob.
-- Desiderius Erasmus von Rotterdam

Salman Halim

unread,
Dec 1, 2022, 10:11:50 AM12/1/22
to vim...@googlegroups.com
On Thu, Dec 1, 2022 at 9:52 AM Christian Brabandt <cbl...@256bit.org> wrote:

On Do, 01 Dez 2022, Salman Halim wrote:

> Hello,
>
> Is it possible, either natively or through Vim script (I'm happy to write the
> code, but not sure what to look for), to get a list of the lines that have been
> changed since a particular moment?
>
 
I would use one of the undo plugins (like gundo python or undotree
vimscript) plugins for this. I think they also show the diff between
versions.

I even created a plugin histwin when the persistence undo feature was
introduced, that allowed you to tag certain states and allowed to show
you the diff between states

Best,
Christian


Christian,

Thanks for your response. I actually already use Gundo. I'm not trying to visually step through the changes. I literally want to end up with a Vim9 function that, when called with a time (such as for :earlier) or 'since last save', returns me a list of changed lines. I then will use that list to execute commands on those lines, such as removing trailing whitespace or reformatting them.

For various reasons, I am not in a position to do those operations on the entire file, only on the bits I personally changed or added. I noticed that Eclipse has an option to only affect the lines that were explicitly modified, so was wondering if it was possible to do something like that in Vim.

One obvious way would be to have Vim go to the :earlier state, grab the contents of the buffer, come back to 'now' and then manually do a diff to see what's changed. However, that seems expensive for a large file. I was wondering, instead, if there might be a way to somehow get access to the undo information kept by Vim. I tried :wundo, but the file that was written was in a binary format, so wasn't something I could parse.

All the best,

Salman

Christian Brabandt

unread,
Dec 1, 2022, 10:52:24 AM12/1/22
to vim...@googlegroups.com
I believe gundo provides a way to directly show the diff between various
undo states¹ and I think you are right, the only way to do this is to
manually safe the state of the buffer and run a diff over that file with
the current buffer. I don't think there is an simpler way than that.

¹) see e.g. https://simnalamburt.github.io/vim-mundo/#usage and search
for preview pane

Best,
Christian
--
Sei sparsam, koste es was es wolle.

Owajigbanam Ogbuluijah

unread,
Dec 1, 2022, 3:32:22 PM12/1/22
to vim...@googlegroups.com
Does :h changes help?

--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/vim_use/20221201155216.GC472721%40256bit.org.

Salman Halim

unread,
Dec 1, 2022, 5:01:40 PM12/1/22
to Vim Users
On Thu, Dec 1, 2022, 10:52 Christian Brabandt <cbl...@256bit.org> wrote:

I believe gundo provides a way to directly show the diff between various
undo states¹ and I think you are right, the only way to do this is to
manually safe the state of the buffer and run a diff over that file with
the current buffer. I don't think there is an simpler way than that.

¹) see e.g. https://simnalamburt.github.io/vim-mundo/#usage and search
for preview pane

Best,
Christian

I looked at the code for Gundo. It does indeed go back to an earlier state using : earlier, grabs the entire buffet contents and then uses a Python diff library to generate a diff between the two versions. I might do something similar. Thank you for the confirmation that I wasn't missing something obvious. 

Salman

Salman Halim

unread,
Dec 1, 2022, 5:04:26 PM12/1/22
to Vim Users

On Thu, Dec 1, 2022, 15:32 Owajigbanam Ogbuluijah <xigb...@gmail.com> wrote:
Does :h changes help?

I hadn't thought to look at that. That's interesting. I suspect I'm going to just do the diff stuff similarly to Mundo (as suggested by Christian) or Gundo because I need an exact list of lines that were added or changed, but want to skip any that were deleted. 

Thanks very much. 

Salman 

Tony Mechelynck

unread,
Dec 2, 2022, 7:13:05 AM12/2/22
to salma...@gmail.com, vim...@googlegroups.com
Maybe see ":help :DiffOrig"

Best regards,
Tony.

Salman Halim

unread,
Dec 2, 2022, 8:12:27 PM12/2/22
to Vim Users
I looked at DiffOrig as suggested by Tony Mechelynck and looked up the longest common subsequence algorithm off Wikipedia (basically, how 'diff' works) and wrote a pure Vim9 script that takes two lists of strings and returns two lists, one of all the added and modified lines and one of all the removed lines. This does exactly what I wanted, except that it takes a second or so for my test file, which is over 1500 lines long, and is far too long to wait after every save. I have much longer files, also.

I might upload the Vim9 diff functions because they aren't terribly slow with smaller lists, but I think I'll try the Python difflib, much as Gundo does, to see if it's faster. Otherwise, I might just abandon the idea.

Basically, I can't check the entire file after every save. I need to have some way of restricting the diff regions.

--
 
Salman

I, too, shall something make and glory in the making.

Suresh Govindachar

unread,
Dec 2, 2022, 8:51:31 PM12/2/22
to vim...@googlegroups.com
On 12/3/2022 6:42 AM, Salman Halim wrote:
On Thu, Dec 1, 2022 at 5:04 PM Salman Halim <salma...@gmail.com> wrote:

On Thu, Dec 1, 2022, 15:32 Owajigbanam Ogbuluijah <xigb...@gmail.com> wrote:
Does :h changes help?

I hadn't thought to look at that. That's interesting. I suspect I'm going to just do the diff stuff similarly to Mundo (as suggested by Christian) or Gundo because I need an exact list of lines that were added or changed, but want to skip any that were deleted. 

[...]


Basically, I can't check the entire file after every save. I need to have some way of restricting the diff regions.

1) Vim can diff contents of buffers that are not associated with physical files. On detecting a save, from the change list get the lines of interest in the previous and current version; then appendingly-yank the regions of interest in the current buffer and likewise appendingly-yank the corresponding regions in the saved file; and then open a new buffer that compares the yanked stuff. (I don't mean do these steps manually, but via a script.)

2) I came late to this thread and do not know if comparing an entire file but restricting the display via folds meets your needs. If so, one could detect a save command and write a script that opens a new buffer that visually compares the previous and current versions with unchanged regions folded and the ability to jump to changes via ]c and [c.

--Suresh


Salman Halim

unread,
Dec 3, 2022, 12:04:34 AM12/3/22
to vim...@googlegroups.com

1) Vim can diff contents of buffers that are not associated with physical files. On detecting a save, from the change list get the lines of interest in the previous and current version; then appendingly-yank the regions of interest in the current buffer and likewise appendingly-yank the corresponding regions in the saved file; and then open a new buffer that compares the yanked stuff. (I don't mean do these steps manually, but via a script.)

Suresh, when you say 'from the change list', do you mean the output of :changes or something else? If you do mean :changes, does it go far enough back to the previous save where it's possible many lines have changed since the last save?
 

2) I came late to this thread and do not know if comparing an entire file but restricting the display via folds meets your needs. If so, one could detect a save command and write a script that opens a new buffer that visually compares the previous and current versions with unchanged regions folded and the ability to jump to changes via ]c and [c.

--Suresh

So, some editors/IDEs such as Eclipse have an option, when saving Java files, to only reformat/reindent lines that were actually modified, leaving the rest of the file alone. I'm trying to do something similar: find all lines that have been added or modified (looks pretty much like an add to diff) and execute commands on only those lines. The commands could be anything from removing trailing whitespace to reformatting the lines, anything. However, I don't want to do this in a diff window: I want it to be part of a save action, such as on BufWrite.

At this point, I have it pretty much working with regards to pointing out the lines and being able to execute commands on them, but I am running into the whole thing being slow once I've got a file around 1500 lines (I wrote a pure Vim9 diff routine, but am debating involving Python's difflib and parsing its output).

One optimization I've put in is the observation that most editing changes usually happen to a small part of a source file, so I skip over any common lines at the top and bottom of the file, so the range I actually compare both starts and stops at an actual diff, making it faster, but that's easily thwarted by simply making changes at the top and bottom of a file.

I'm now debating generating a hash code for the lines and comparing those, instead. To make that quick, I'll generate a relatively quick hash code and will then compare the actual strings themselves if I get a hash code match.

Once I have it working with a degree of speed, I'll hook into it by writing a 'SaveActions' plugin or some such that can take a list of commands and will run them on the changed lines.

Thanks very much for the suggestions.

Salman Halim

unread,
Dec 7, 2022, 9:47:59 AM12/7/22
to Vim Users
I wrote this a few days ago. If python is available, it uses python's difflib to do the work as that's much faster. 

I didn't build a full plugin around it. Currently, it just lists the changed lines and trims trailing whitespace and calls :retab on the lines.

Is there any interest in this? Should I throw the more generic diff methods (all Vim9) that compare two lists of strings onto the Vim site or is this not really something anybody cares about?

Thank you to everybody who took the time to offer guidance and advice. 

Best regards,

Salman
Reply all
Reply to author
Forward
0 new messages