2

Is there a n[vim] function to get the list of modified lines? A clunky way is to parse the output of :changes but I only require the changes since last write. I have to use it in a python-based plugin.

4
  • 1
    :help diff-original-file and vi.stackexchange.com/q/29568/10604 ought to get someone started
    – D. Ben Knoble
    Commented Mar 14, 2021 at 16:01
  • Both vim and neovim offer functionality to track fine grained changes in a buffer. However, they are wildly different APIs. As posed this question is too broad.
    – Mass
    Commented Mar 14, 2021 at 17:42
  • @Mass could you point me to the help for vim? I’m not sure I’m aware of this part of the api
    – D. Ben Knoble
    Commented Mar 14, 2021 at 17:52
  • 1
    @D.BenKnoble See :help listener_add(). It is far from straightforward, but the idea is you would set up a listener callback and accumulate the changes, then clearing them on writes. How to best do this depends greatly on the end use-case (not specified in the question). One obvious gotcha is the line numbers are changing constantly due to editing so there is some necessary bookkeeping overhead.
    – Mass
    Commented Mar 14, 2021 at 18:18

1 Answer 1

1

Here's how I would handle this, riffing on :help diff-original-file and Vimdiff line count of different lines :

  1. Get the original file in a diff
:vertical new | set bt=nofile | read ++edit # | 0 delete _ | diffthis | wincmd p | diffthis
  1. For both windows, collect the lines with Diff* highlighting (deleted lines don't show up, so we need both):
function GetDiffLines() abort
  return range(1, line('$'))->filter({_, v -> diff_hlID(v, 1)->synIDattr('name') =~# 'Diff*'})
endfunction
const current_diffs = GetDiffLines()
wincmd p
const original_diffs = GetDiffLines()
  1. Do a "set union" to know what's what overall; if you need the diff groups (say, to know whether it's deleted or added or changed), you'll need to add some steps here to process synIDattr({id}, 'name'), which may differ for some lines in the respective buffers.
const diff_lines = (current_diffs + original_diffs)->sort('n')->uniq()

It may actually be worth not doing step (3), as you lose the information of where each line came from. This is particularly relevant when lines are added in one buffer, which is equivalent to them being deleted in the other.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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