Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add function for calculating diff numbers of whole project #16

Open
skbolton opened this issue Jul 5, 2019 · 13 comments
Open

Add function for calculating diff numbers of whole project #16

skbolton opened this issue Jul 5, 2019 · 13 comments
Labels
enhancement New feature or request

Comments

@skbolton
Copy link

skbolton commented Jul 5, 2019

First off loving this plugin great work. I have been thinking lately though that it would be nice to have a function available to calculate the diff stats of the whole project instead of only a function for the current buffer. What do you think about this?

@niklaas niklaas added enhancement New feature or request question Further information is requested labels Jul 6, 2019
@niklaas
Copy link
Owner

niklaas commented Jul 7, 2019

Thank you for the nice words.

For me, the purpose of this plugin is to know whether the current buffer is "clean" i.e. whether it has uncommitted changes1 or not. If I want to know whether the repository I am working on is clean, I use :Gstatus (or simply :G) by tpope/vim-fugitive. This also allows me to jump to uncommitted changes in other files quickly.

So, I don't see the purpose of showing a diff of the entire repository yet but I am interested to hear more about the user scenario you are thinking about. Why would you like to see the diff of the entire repository in the statusline?

@skbolton
Copy link
Author

skbolton commented Jul 7, 2019

I can always script it myself no problem. My use case is that I am trying to improve git habits and make sure I am not doing too many changes per commit. I am working on more focused commits so that my rebasing summary is cleaner And easier to remember all the changes I made along the way. Too often I do 750 plus changes per commit. I need some feedback that once that number is getting high to break off a chunk into a reasonable commit and keep going.

@niklaas
Copy link
Owner

niklaas commented Jul 8, 2019

This is a very good scenario/reason indeed. I will take a look at the code these days, but my guess is that implementing this will be quite easy. Probably the most complicated aspect about it is not to query git too often using the cache wisely.

Have you thought about how to differentiate between the diff per buffer and diff per repository visually? My feeling is that showing both simultaneously would be visual overload. And probably there is no user scenario for that. So I'm thinking about a flag that can be swtched while editing. What are your thoughts?

@skbolton
Copy link
Author

skbolton commented Jul 9, 2019

I was planning on the project level diff in my tab line and the file based one down in my status line. So either two separate functions or a flag to pass in like you mentioned

@niklaas
Copy link
Owner

niklaas commented Jul 17, 2019

I am still contemplating about this. So stay tuned. :)

@niklaas niklaas removed the question Further information is requested label Jul 19, 2019
@niklaas
Copy link
Owner

niklaas commented Jul 19, 2019

This needs quite some changes because at the moment

  1. the algorithms expect a buffer as input.
    function! lightline#gitdiff#algorithms#word_diff_porcelain#calculate(buffer) abort
    We would need to rewrite these to take filenames as input. (To be honest, the current state is bad design. I had a bad feeling when coding it this way but I didn't know why. Now, I know.)
  2. the algorithms expect a diff for a single file only.
    function! s:transcode_diff_porcelain(porcelain) abort
    Since we want to parse a diff for an entire repository, we will need to extend the algorithms to support a git diff for multiple files.
  3. the cache is per buffer.
    let g:lightline#gitdiff#cache = {}
    We will need another cache per repository. We would need to figure out when to invalidate that cache.

Medium-term we will need to think about the following: Probably it does not make sense to invalidate the cache for an entire repository if a single file of that repository changes. Rather only these changes should be added/subtracted from the cached values. Well, that would get really complicated then. Hm, probably the performance loss is not that big though if we invalidate on each change...

Just to keep you updated and writing down my thoughts.

@niklaas
Copy link
Owner

niklaas commented Jul 19, 2019

The cache per repository would have the result of

git rev-parse --show-toplevel

as key and a (what I call) "diff dict" as values.

@skbolton
Copy link
Author

There is nothing wrong with plugins being focused and doing only one thing. Especially light line plugins. I can always script this up and if I like the way it is package it up as it’s own plugin. Feel free to close this issue if you agree

@niklaas
Copy link
Owner

niklaas commented Jul 26, 2019

I guess it's debatable whether this should be part of this plugin or not. I think it definitely can be. Because we can leverage the "parsers" that I wrote for reading the diffs. The current code base just needs some modifications.

That said, feel free to implement the feature in another plugin or send a pull request to this project. I haven't had time to implement it myself yet but I maybe will have this weekend. I'll keep you informed.

@skbolton
Copy link
Author

I will poke around your plugin and see what I can make happen this weekend

@gblock0
Copy link
Contributor

gblock0 commented Jun 17, 2020

I have a couple of thoughts on how to implement this:

Thought 1: Create a new algorithm

Create a separate algorithm that returns the total diff for the directory/project and basically ignores the buffer passed in. This way it plugs into (no pun intended :P) the existing architecture and I don't believe much would have to change.

Maybe the easiest of my two proposals? This has the potential to be slow if the user has changes in a lot of files.

Thought 2: Calculate a global git diff state and keep that in the cache

NOTE: This is going off @niklaas' thoughts and the more I think about this option, the more involved it seems, but here is the general idea.

NOTE 2: The plugin's cache would need to use file paths/names instead of buffer numbers for this to work

On VimEnter the plugin can calculate the current git diff state of the directory/project and store it in the cache (maybe use a background job so this doesn't cause an increase in startup time?). The plugin would store the indicator counts for each file in the directory/project.

Whenever the user updates a buffer, the algorithm would update that buffer's file indicator counts in the cache.

lightline#gitdiff#format() could read a new global variable and return the total number of added, deleted, and/or modified lines to the status line instead of the numbers for the current buffer. This way the algorithms are still only executing on the buffer the user is working in, since I assume there is the potential for a performance hit if the plugin is running git diff... on the whole directory/project vs only the current buffer's file.

@niklaas
Copy link
Owner

niklaas commented Jun 21, 2020

Thanks a lot for your thoughts. I really appreciate them! I’ll see whether I can work on this issue in the near future. It would need to be something one can opt-out to because of the performance impacts.

@niklaas
Copy link
Owner

niklaas commented Feb 15, 2021

@skbolton why have you closed the issue? I'd like to keep it open as reference for a feature request I find worth implementing.

I haven't had time to improve the plug-in for a long time but I use is everyday still. So it's far from being abandoned. 🙂

@niklaas niklaas reopened this Feb 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants