rbong / vim-flog

A blazingly fast, stunningly beautiful, exceptionally powerful git branch viewer for Vim/Neovim.
765 stars 22 forks source link

Show/hide commit diffs #39

Closed treeman closed 1 year ago

treeman commented 3 years ago

It works fine to list commits from only the current file with:

:Flogsplit -path=%

I would however want to list only the commits that only change the selected lines. I tried this which sort-of works:

function! FlogSelectedLines()
  let start = getpos("'<")[1]
  let end = getpos("'>")[1]
  let file = expand("%:p")
  execute 'silent! Flogsplit -- --no-patch -L'.start.','.end.':'.file
endfunction
vnoremap glf :call FlogSelectedLines()<CR>

It works so far as it manages to filter the commits, but it gives out a strange "E16: Invalid range" error (why I use the silent!) and Tab has also stopped working. Return however works fine.

Is there a way to make this work?

rbong commented 3 years ago

You can view a range by creating a visual selection and then running :Flog. (ex. press V:Flog<CR> to show the history for the current line).

This might not work exactly how you'd like. The graph view will now show the diff patch for those lines inline instead of in a split window (screenshot).

There's a few reasons why it works this way instead of using splits. I couldn't find a command to display the diff nicely in fugitive, I couldn't think of a nice interface to make <CR> and <Tab> contextual, and this is the way it works in git log.

However, let me know what you think of the feature and if this solves your problem. This is my first chance to talk with someone about the feature. If it's not to your liking, I could possibly look into reworking it.

treeman commented 3 years ago

That's a step in the right direction for sure, although I would like to hide the diff patch to get an overview and then manually toggle the commits I'm interested in. Maybe I'm too used from magit, but I also think it's nice to have a consistent behavior no matter where the context git log operates in.

With this:

xnoremap glf :Flogsplit -- --no-patch<CR>

It's almost fine, except that <Tab> doesn't work. (I just noticed Tab doesn't work in :Flog either. Bummer.)

I was a bit confused that <Tab> opened a new split, I was expecting it to toggle the patch diff inline, similar to how you can toggle the diff of files in the fugitive status window with =. I can see the benefits with the split window too, but sometimes the window becomes too narrow (like on my laptop) where I'd prefer to toggle them inside the same window.

Maybe it would be possible to support both = and <Tab>, but I don't know how difficult it would be to implement.

And btw, I do think flog is very nice.

rbong commented 3 years ago

Toggling patches for specific commits is a very interesting idea. However updating the graph view for specific commits is something Flog's not built for and I'll have to put more thought into it.

There is something you can do right now though, and that's toggle --no-patch for all commits.

function ToggleFlogNoPatch() abort
    let l:state = flog#get_state()
    let l:raw_args = l:state['raw_args']
    if empty(l:raw_args)
        let l:raw_args = ''
    endif
    let l:split_raw_args = split(l:raw_args)
    let l:no_patch_arg_index = index(l:split_raw_args, '--no-patch')
    if l:no_patch_arg_index >= 0
        if len(l:split_raw_args) == 1
            let l:raw_args = v:null
        else
            call remove(l:split_raw_args, l:no_patch_arg_index)
            let l:raw_args = join(l:split_raw_args, ' ')
        endif
    else
        let l:raw_args .= ' --no-patch'
    endif
    let l:state['raw_args'] = l:raw_args
    call flog#populate_graph_buffer()
endfunction
autocmd FileType floggraph nnoremap <buffer> <silent> gp :<C-U>call ToggleFlogNoPatch()<CR>

With this you can press gp and --no-patch will toggle. Since the cursor stays on the same commit, you can effectively use it to expand/collapse when the cursor is over a commit.

Since this is so nice for visual mode, I think I'll add it to Flog. Just let me know if you have any feedback.

treeman commented 3 years ago

Thank you, I'll roll with this for now.

Another thing, it would be nice to also show/hide individual chunks. This works fine if I visit a commit with <CR> from :Flog, but not via <Tab> and not either way from logs generated from files with -path=% or selected lines.

rbong commented 3 years ago

Awesome, I added gp and the -no-patch option to Flog.

rbong commented 1 year ago

Flog now has the ability to hide specific commits since it builds the output itself. I will share my thoughts on how I think this should work, feel free to give feedback.

I am thinking of borrowing some bindings from Fugitive to implement this. Fugitive only uses these bindings to toggle diffs, but we could use them to hide any multi-line output, not just diffs.

Flog has a problem that Fugitive doesn't. And that's the fact that git log -L... shows diffs by default. Unless if anyone can think of a nice binding to hide all diffs, I think the workaround is going to have to be just visually selecting all diffs in the file and then hiding them with ggVG<.

The way I'm thinking of showing collapsed commits is to have an extra line that shows up like this:

• 2023-01-01 [abcdef] My commit
│ +-- (6 lines of collapsed output) --+
├─╮
• │ 2023-01-01 [123456] My other commit
│ │ +-- (2 lines of collapsed output) --+

Of course it would have commit highlighting and the text would be grayed out.

I think collapsed commits should persist over graph buffer updates.

I think if you try to hide a commit and it has 2 or less lines of output it should just do nothing.

Let me know what you think.

rbong commented 1 year ago

Added the ability to expand/collapse commit bodies, including diffs as described above.