3

One of my vim usages is to do sketches of topologies in networking I've found the script Draw it really really useful for that So I can draw things like this by pasting these boxes

 +------+
 |ROUTER|
 +------+
 |  R   |
 +------+                                  

               +------+                                 +------+
               |ROUTER|                                 |ROUTER|
               +------+---------------------------------+------+
               |  R1  |                                 |  R2  |
               +------+                                 +------+
                   |                                       |
                   |                                       |
                   |                                       |
                   |                                       |
                   |               +------+                |
                   |               |ROUTER|                |
                   |               +------+                |
                   +---------------|  R3  |----------------+
                                   +------+

The issue is if I want to add additional boxes (apart of many other things) right after this , visual block mode yanking pasting becomes messy Say that I want to add a router in between R1 and R3 if I locate the cursor in 32,36 and paste it , it will shift all the characters written till the end of the lines

               +------+             +------+                    +------+ 
               |ROUTER|             |ROUTER|                    |ROUTER| 
               +------+-------------+------+--------------------+------+ 
               |  R1  |             |  R   |                    |  R2  | 
               +------+             +------+                    +------+ 
                   |                                       |     
                   |                                       |     
                   |                                       |     
                   |                                       |     
                   |               +------+                |     
                   |               |ROUTER|                |     
                   |               +------+                |     
                   +---------------|  R3  |----------------+     
                                   +------+                      

My expected result was:

               +------+             +------+            +------+    
               |ROUTER|             |ROUTER|            |ROUTER|    
               +------+-------------+------+------------+------+    
               |  R1  |             |  R   |            |  R2  |    
               +------+             +------+            +------+    
                   |                                       |                
                   |                                       |                
                   |                                       |                
                   |                                       |                
                   |               +------+                |                
                   |               |ROUTER|                |                
                   |               +------+                |                
                   +---------------|  R3  |----------------+                
                                   +------+                                 

Mainly a paste and replace kind of thing similar to what is R for text but for pasting Do you figure a work around for this? Thanks

4
  • You can visually select some text before p and it will be overwritten; does that help?
    – D. Ben Knoble
    Nov 12 '20 at 13:32
  • That helps a bit thanks, but is still a bit long workaround, ideally I wouldn't have to redraw the box (cause sometimes you will just don't know the exact size of the box) plus you need to manually "draw" another box Nov 12 '20 at 13:52
  • 1
    Fair enough. At any rate, welcome to Vi and Vim!
    – D. Ben Knoble
    Nov 12 '20 at 13:59
  • Thanks a lot @D.BenKnoble !! Nov 12 '20 at 14:28
3

Visual block mode (which you can enter with CTRL-V) is perfect for this kind of usage. You can copy and paste squares much like your router boxes and you can do so without shifting columns.

Here is an example working with your initial diagram.

Start by using a visual selection to copy the first router on the top left corner. First move to the upper left +, then use Ctrl+V to enter visual block select mode, then use 4j (to move down 4 lines, getting to the + on the bottom left corner) followed by e (to move to the + on the bottom right corner), so you'll have visually selected the whole router in visual block mode. You'll have this:

Visual Block selection of Router 1

Here you can use y to yank (copy) the visual block with the router.

At this point, move the cursor to the position where you want to paste it, which is on the upper line, but above the lower router. Place your cursor at the top left corner of where the box should go. Like this:

enter image description here

Here you can use a shortcut to select a block that has the same dimensions of your last selection, by passing a "count" to a v command. From :help v:

With [count], select the same number of characters or lines as used for the last Visual operation, but at the current cursor position, multiplied by [count].

So 1v will get you a selection of the right size you want to replace. Like so:

enter image description here

At this point, simply using p to put the block will replace the current block with what you have in your default register, which is the router you copied. This is what you get:

enter image description here

Which matches what you wanted in the first place.


But let's assume you pasted it without replacing a block and ended up with the shifted lines, like in your second diagram:

enter image description here

It's not too hard to correct that either. You can use a similar technique. Start by using a visual block selection around your router. (You'll use it only to "measure" it.) You can use the same sequence of commands mentioned on the first procedure.

enter image description here

Then hit Esc to clear the selection. You only used it to measure the size of the box, so you don't need to perform any operations on it.

Now move the cursor to the right, after the router.

enter image description here

Use 1v to select a box of the same size as your last selection:

enter image description here

And finally use x (or d) to remove it.

The final result is exactly what you expected:

enter image description here


One final tip if you're planning to use Vim for drawing diagrams is that you might want to use set virtualedit=all (see :help 'virtualedit', so you can move to parts of the buffer where you don't have any spaces and insert or paste items there, having Vim add spaces (or tabs) as needed to keep your text on the right columns.

In your particular example it turns out you didn't really need this, but if you're positioning boxes with routers in an empty buffer, it's quite advantageous to be able to move freely and have Vim take care of putting spaces around it.

To draw the lines, you can also use visual block selection. Select a visual block that is one line high (for a horizontal lines) covering the spaces you want to replace, then use r- to turn that into a sequence of dashes. For vertical line, create a visual block selection of a single column and use r| for a vertical line. See :help v_b_r for more details on visual block replace.

2
  • 3
    <count>v is genius 😃
    – D. Ben Knoble
    Nov 12 '20 at 19:02
  • 1
    @D.BenKnoble Vimgolf practice definitely pays off! :-)
    – filbranden
    Nov 12 '20 at 19:07

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.