markonm / traces.vim

Range, pattern and substitute preview for Vim
MIT License
742 stars 13 forks source link

Substituting over quickfix items with :cdo? #14

Closed jesseleite closed 6 years ago

jesseleite commented 6 years ago

I often perform substitutions with :cdo. For example,

:cdo %s/this/that/gc

That will apply the substitution across all files in my quickfix window from an ag search.

Think it might be possible to highlight & preview this type of substitution with traces.vim?

markonm commented 6 years ago

Yes, it's possible but I have some concerns over that feature.

Have you tried vim-qfreplace? It looks like it would be a perfect match for your use case and it works great with traces.vim.

jesseleite commented 6 years ago

Thanks for reply!

cdo is not a good match for substitute with % range as it would perform substitute on all lines containing pattern, not just the one listed in the quickfix list and if you don't use % range, then the preview would be shown on the one line only, which is not nearly as useful

That's why I put /gc at the end of my quickfix substitute 😉, because it allows me to confirm each substitution individually, regardless of %. Also, by confirming each individual substitution, I get to browse the code around it in context, which I'm not sure vim-qfreplace lets me do? (Though I could be wrong).

if cursor is positioned inside a buffer that is not in the quickfix list, live substitute would be showing unnecessary preview

That indeed would be a problem. If there's no way to detect whether the open buffer exists within the quickfix, then I might suggest only showing the preview on the quickfix window line items, rather than in loaded file buffers. Also, if you think it's too intrusive, maybe it could be disabled by default, but with option for users to enable? ie)

let g:traces_quickfix_preview = 1;
" or
let g:traces_cdo_preview = 1;

Thoughts?

markonm commented 6 years ago

That's why I put /gc at the end of my quickfix substitute 😉, because it allows me to confirm each substitution individually,

:cfdo seems like a better match for % specifier as it would ask you only once for every match in the file.

That indeed would be a problem. If there's no way to detect whether

It's possible to detect it, but it would add significant overhead if quickfix contains a lot of lines. I don't know any faster why except looping over getqflist() output.

I might suggest only showing the preview on the quickfix window line items

Lines inside quickfix window are different from their file matching lines (they are prefixed with path, colum, line). I'm not sure it's useful to use preview on them. In any case, it's already possible to do so, you just need to use set modifiable inside quickfix window and prefix your substitution with cdo after you are satisfied.

Anyway, please test the following patch and tell me if that is the behavior you wish.

diff --git a/autoload/traces.vim b/autoload/traces.vim
index 29ea5f1..3298f9d 100644
--- a/autoload/traces.vim
+++ b/autoload/traces.vim
@@ -933,7 +933,7 @@ function! traces#init(cmdl) abort
     call s:restore_marks()
     call winrestview(view)
   endif
-  let cmdl = s:evaluate_cmdl([a:cmdl])
+  let cmdl = s:evaluate_cmdl([substitute(a:cmdl, '\v^\s*%(cdo|cfdo|ld%[o]|lfdo)\!=\s+', '', '')])

   if s:buf[s:nr].duration < s:timeout
     " range preview
jesseleite commented 6 years ago

Good call about :cfdo. Also, just tried it...

When focused on the quickfix window, I understand what you mean about seeing the replacement without set modifiable on quickfix, which is fine. There's nothing you can do about this, and at least it now highlights the match (even if it can't render the replacement preview).

However, when focused on a window that was opened via pressing enter on a quickfix result, I now experience the full traces.vim preview, despite the :cdo/:cfdo 👌

jesseleite commented 6 years ago

❤️