DigitalNomad
DigitalNomad

Reputation: 1031

Make a ascii box around the code block in Vim

Is it possible to create a ASCII comment box around the code block?

Here is an example.

Before

  ; Convert to radians          
  theta45 = (theta + 45.)/!RADEG
  theta90 = (theta + 90.)/!RADEG
  theta   = theta / !RADEG      
  Ey = Ey * normal              

  ; Engineering shear strain    
  Gxy = shear * Exy             

After

; -----------------------------------------;
  ; Convert to radians                     ;
  theta45 = (theta + 45.)/!RADEG           ;
  theta90 = (theta + 90.)/!RADEG           ;
  theta   = theta / !RADEG                 ;
  Ey = Ey * normal                         ;
                                           ;
  ; Engineering shear strain               ;
  Gxy = shear * Exy                        ;
; -----------------------------------------;

What I have tried so far

'<,'>s/^\(\s*\)\(.*\)$/\=join([submatch(1), ';', submatch(2), repeat('-', 50-len(submatch(1)) - len(submatch(2))), ';'], '')

note I selected a visual block first.

Issues with it

Here is how it looks:

  ;; Convert to radians          ------------------;
  ;theta45 = (theta + 45.)/!RADEG------------------;
  ;theta90 = (theta + 90.)/!RADEG------------------;
  ;theta   = theta / !RADEG      ------------------;
  ;Ey = Ey * normal              ------------------;
;--------------------------------------------------;
  ;; Engineering shear strain    ------------------;
  ;Gxy = shear * Exy       ------------------------;

While, it is not very close to what I want to get. I could only get this far!

Thanks for reading and your help.

Upvotes: 4

Views: 722

Answers (2)

DJMcMayhem
DJMcMayhem

Reputation: 7679

How about this:

<esc>'>o;<esc>'<O;<esc>v'>j:norm 51A <C-v><esc>51|Dr;<cr>:'<s/ /-/g<cr>:'>&&<cr>

Explanation:

So first, we need to add the extra lines. So we <esc> visual mode, jump to the end of our previous selection and add a newline with a semicolon on it. '>o;<esc>. Then, jump back to the beginning of the previous selection, and add a newline with a semicolon on it upwards '<O;<esc>. Now, we need to start visual mode on this line, jump to the previous end, and one more line v'>j. Right now, the buffer looks like this:

;
Here
are
a whole bunch of
uneven
lines
;

and it's all visually selected. Then, we need to make every line padded to 50 spaces. So,

:norm 51A <C-v><esc>51Dr;

Will first add 51 spaces, then jump to the 51st column, delete to the end, and replace the 50th with a semicolon. Now our buffer looks like this:

;                                                ;
Here                                             ;
are                                              ;
a whole bunch of                                 ;
uneven                                           ;
lines                                            ;
;                                                ;

Now, we just substitute spaces for dashes on the beginning of the selection:

:'<s/ /-/g<cr>

and do the same substitution on the end of the selection:

:'>&&<cr>

Now the buffer looks like this:

;-------------------------------------------------;
;Here                                             ;
;are                                              ;
;a whole bunch of                                 ;
;uneven                                           ;
;lines                                            ;
;-------------------------------------------------;

Obviously, you probably want to wrap this in a mapping, function, or macro for convenience.

Upvotes: 1

Ingo Karkat
Ingo Karkat

Reputation: 172580

Here's one improvement (broken into several lines for readability):

:'<,'>s/.*/\=submatch(0) . repeat(' ', 50-len(submatch(0)) + 2) . ';'/ |
\   '>put ='; ' . repeat('-', 50) . ';' |
\   '<put! ='; ' . repeat('-', 50) . ';' |
\   nohlsearch
  • To add the lines for the block, use separate commands (:put); you can use the visual selection marks ('< and '>) to address the borders of the selection. The expression register = allows to generate the lines.
  • :nohlsearch clears the search highlighting

Here's the result:

; --------------------------------------------------;
  ; Convert to radians                              ;
  theta45 = (theta + 45.)/!RADEG                    ;
  theta90 = (theta + 90.)/!RADEG                    ;
  theta   = theta / !RADEG                          ;
  Ey = Ey * normal                                  ;
                                                    ;
  ; Engineering shear strain                        ;
  Gxy = shear * Exy                                 ;
; --------------------------------------------------;

There are still some issues:

  • The length calculation only works for printable, non-Tab ASCII characters.
  • The width is hard-coded. It would be better to first determine the maximum length of the block.

If you really want to develop this further, the first step I'd recommend is putting all the commands into a :function.

You might also want to have a look at my AlignFromCursor plugin, which tackles a similar problem (if only to realize the full complexity of the problem :-).

Lastly, let me mention that these kind of alignment-based formattings are high-maintenance (also think of your non-Vim colleagues who might have to edit this), and are best avoided.

Upvotes: 0

Related Questions