1

I've looked around in :help V but haven't found anything of this sort, but was wondering if there's a function I can call from vimscript that would visually select a region based on (row, column) coordinate pairs.

For example, I could call it with (1,1),(2,3) to visually select the rectangle with the top left corner at row 1, column 1, and bottom right corner at row 2, column 3.

Does such a function exist?

  • 2
    You first need to set the visual type manually using e.g. exe "norm! \<c-v>\<esc>" for visual block mode. Then you can set the marks '<, '> manually using setpos(). Then use gv – Christian Brabandt May 23 at 5:51
  • 1
    Following @ChristianBrabandt idea you could write it like this it seems to be working very well! – statox May 23 at 9:50
  • @statox, I am using this technique for my NrrwRgn plugin. – Christian Brabandt May 23 at 12:03
  • @ChristianBrabandt So that's an already tested code, great :) You could write an answer, I think it matches pretty well OP's question. – statox May 23 at 12:05
2

There is no direct function available to create a new block-wise selection. However you can work around it the following way:

1) First you need to set the visual selection type, so that when using gv the selection will be set correctly. You can simply abort it right afterwards, so e.g. use :exe ":norm! \<c-v>\<esc>. This sets block-wise selection and aborts it right afterwards.

2) Since patch 7.3.590 the visual marks '< and '> that define the start and end position of the visual selection are directly settable using setpos().

3) After the marks have been set, you can then use gv to "reselect" the last visual selected area. I have been using this technique in my NrrwRgn plugin ever since that patch has been included (commit) and is has been working well.

2

You can do this similarly to how you would do it manually, by using the :normal command:

:normal! 1G1|^V2G3|

The ^V is a CTRL-V character. You can enter this literally by pressing Ctrl-VCtrl-V, but as you’re most likely going to need to build the command as a string anyway so you can use variables for the line/column numbers, using a string escape sequence is cleaner:

:execute "normal! 1G1|\<C-V>2G3|"

In an actual script, I'd probably break it up over a few lines to make it a bit clearer what you're doing:

let select_command = line1 . 'G' . column1 . '|'
let select_command .= "\<C-V>"
let select_command .= line2 . 'G' . column2 . '|'
execute 'normal!' select_command

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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