5

I'm trying to interrupt a for loop such as in code below,

for num in buffer_number_list
    " Select the buffer
    exe 'buffer' num
    " Run the command that's passed as an argument
    exe a:command
    " Save if necessary
    update
endfor

instead of interrupting only line exe a:command, when a:command is a :s/// command.

The purpose is to change code on response to How to do search & replace with ack in vim?

I've tried surrounding the line exe a:command with a try/catch block, but it doesn't worked, probably because the command handled the interrupt signal without re-throwing it.

Tried remapping CTRL-c to change some variable (which would be checked inside of the loop), but it didn't worked:

let original_Ctrl_c = maparg('<c-c>', 'n')
exe 'nnoremap <c-c> :call <SID>BreakLoop()<CR>' . original_Ctrl_c

It seems that the mapping didn't trigger when the interrupt signal is caught.

Any ideas?

EDIT:

It seems that this problem only occurs in gVim (thanks @ib.)

Community
  • 1
  • 1
mMontu
  • 8,983
  • 4
  • 38
  • 53
  • using your `QFDo` function would this be closer to the effect you are looking for: `function! QFDo(command) abort`? – Peter Rincker Sep 20 '11 at 16:09
  • @PeterRincker The idea is similar to that, but I've tested and it doesn't worked. Maybe it is because the `CTRL-c` is intercepted by the command. – mMontu Sep 20 '11 at 16:42
  • how about `v:errmsg`. see `:h v:errmsg`. – Peter Rincker Sep 20 '11 at 17:38
  • @PeterRincker how exactly you sugest to use this variable? I've performed some tests and typing Ctrl-c to interrupt a :s/// command doesn't changed it at all. – mMontu Sep 20 '11 at 20:46
  • I have my own copy of `QFDo` (basically the same except no `update`) and I do not see the behavior you are trying to avoid. Maybe I am missing something, but I would imagine between using `try`/`finally`, `abort`, and `v:errmsg` do not work then it may be un-catch-able. The only thing left I can think of is setting some global variable like you are using. Make sure you use `g:variable_name` – Peter Rincker Sep 22 '11 at 22:24
  • Could you provide the exact code of your function as well as the command you are passing into it to run? If I understand the question correctly, pressing `Ctrl`+`C` when that function is running a particular command does not interrupt the loop over buffers and does not terminate the function? – ib. Sep 29 '11 at 08:43
  • @ib. Yes, you understood the question correctly. The exact code of the function and the command passed to it is on the link referenced on the question, http://stackoverflow.com/questions/4792561/how-to-do-search-replace-with-ack-in-vim/4793316#4793316 (command `v/skipPat/s/Pat/Rep/gce`). Let me know if you think it is better to copy that code to this question. – mMontu Sep 29 '11 at 16:40
  • @mMontu: Trying to reproduce the behavior you describe I have created two identical files, `$ echo -e "skip\npat\npat" | tee a1 >a2`, and opened Vim with all initializations disabled, `$ vim -u NONE`. Then I have sourced the file containing only the code of that `QFDo` function, `:so qfdo.vim`, and run `:vimgrep /skip/ a?`. Interrupting the command `:QFDo v/skip/s/pat/rep/gce` with `Ctrl`+`C` after the first replacement (in `a1` file), *terminates the whole `:QFDo` command* (`a2` remains untouched). Could you reproduce these steps and confirm that in your case `:QFDo` does not terminate? – ib. Oct 02 '11 at 13:22
  • @ib. I've reproduced the steps you described and the problem didn't show up indeed. But it does shows up when I replace `$ vim -u NONE` with `$ vim -gu NONE` (gVim instead of console vim). – mMontu Oct 03 '11 at 12:20
  • @mMontu: This fact means that the behavior you are trying to overcome is caused by some `.vimrc` configuration or plugin. Try to enabling them one by one and repeating the test I propose to detect the plugin that breaks `Ctrl`+`C` termination. – ib. Oct 03 '11 at 14:18
  • @mMontu: Regarding GVim, I bet that if you run it with `$ vim -g -u NONE -U NONE` the problem will not occur either. By the way, should I add the "testing" procedure as an answer? – ib. Oct 03 '11 at 14:21
  • @ib. You are right, the problem didn't showed up in gVim either with the command you proposed. I've investigated the .vimrc/plugins as you sugested, and the culprit seems to be line `vnoremap "+y`in `$VIMRUNTIME/mswin.vim`. Thank you very much! Please add your comments as an answer so I can accept it. – mMontu Oct 03 '11 at 17:38

1 Answers1

1

Trying to reproduce the behavior you describe I have constructed the following test case. It includes two identical files created using the command

$ echo -e "skip\npat\npat" | tee tmp1 >tmp2

and opened in Vim without any initialization apart from sourcing the file containing implementation of the :QFDo command:

$ vim -u NONE -S qfdo.vim

or

$ gvim -u NONE -U NONE -S qfdo.vim

Searching for a pattern in those two files,

:vimgrep /pat/ tmp{1,2}

populates the contents of the quickfix window that can be used to run the command in question,

:QFDo v/skip/s/pat/rep/gce

Interrupting this command using Ctrl+C after the first replacement, which occurs to be in the file tmp1, terminates the whole :QFDo command, and therefore the file tmp2 remains untouched. This fact means that the behavior you are trying to overcome is caused by some .vimrc customization or plugin. To locate the actual configuration breaking Ctrl+C behavior, disable all of the plugins and try enabling them one by one running the above test case each time.

ib.
  • 27,830
  • 11
  • 80
  • 100
  • @ib.I was trying to avoid the problem in `QFDo` function by unmapping the `Ctrl-c` before entering the for loop, then restoring it in a finally block, but didn't work. After some investigation I'm suspicious that it is a vim bug. To reproduce: `$ echo "for i in range(1,4) | %s/r/x/gc | endfor" > temp.vim` and `$ vim -N -u NONE -U NONE temp.vim`. Then `:so %` and `Ctrl-c` interrupted the loop. But after entering `:map abc` and `:unmap ` the `:so %` is NOT interrupted by `Ctrl-c` anymore. If you can confirm that it also happens on your machine I will report this as a bug – mMontu Oct 07 '11 at 18:01
  • @mMontu: Yes, mapping and un-mapping of `Ctrl`+`C` makes it behave as `Esc` in `:substitute` prompts--in your example it is necessary to press `Ctrl`+`C` four times in a row to stop substitutions. However, while it is certainly strange, I am not completely sure this is a bug after reading `:h map_CTRL-C`. – ib. Oct 08 '11 at 08:35