9

For some reason or another I often divide the code into subsections separated by headers like these:

################################################################################
#################################### LOAD ######################################
################################################################################

These are 3 80-column wide lines of # with a title centered in the middle. So far I haven't find a quick way to generate these in vim.

What I usually do is something along the lines of 80i# and then yypp to give me 3 lines, but then I need to navigate to the middle and add text. I usually do this with replace, but replace does not center the header inside ## So I delete the excess of #'s manually.

How to center the text in the middle row? And what would be a faster way to achieve this result?

15

Here's a slightly more efficient / easier method. Type it with the cursor at the beginning of the line of text (i.e. LOAD) that you want to center.

  • :center 80<cr>: center the text with Vim's built in function
  • hhv0r#: add the #s on the left
  • A<space><esc>40A#<esc>: add plenty of #s on the right
  • d80|: delete excess #s on the right
  • YppVr#kk.: add top and bottom #s

So, the full command:

:center 80<cr>hhv0r#A<space><esc>40A#<esc>d80<bar>YppVr#kk.

You could put something like this in your .vimrc in order to add a convenient mapping:

nnoremap <C-b> :center 80<cr>hhv0r#A<space><esc>40A#<esc>d80<bar>YppVr#kk.

Mini-screencast demonstration:

demonstration

3

First, you need to :set expandtab.

  1. 80i#Esc to create the top line
  2. Yp to duplicate it
  3. OSpaceLOADSpaceEsc
  4. :center 80 (The 80 may be omitted, depending on your textwidth setting.)
  5. hhv0r# to fill the left side (using visual select and replace)
  6. $hjlly$kp to fill the right side (by duplicating some characters from the bottom line)
3

I would use a vimscript function for that.

function Header(width, word)
    let a:inserted_word = ' ' . a:word . ' '
    let a:word_width = strlen(a:inserted_word)
    let a:length_before = (a:width - a:word_width) / 2
    let a:hashes_before = repeat('#', a:length_before)
    let a:hashes_after = repeat('#', a:width - (a:word_width + a:length_before))
    let a:hash_line = repeat('#', a:width)
    let a:word_line = a:hashes_before . a:inserted_word . a:hashes_after

    :put =a:hash_line
    :put =a:word_line
    :put =a:hash_line
endfunction

And it could be called like

: call Header(80, 'Hello')
  • 1
    Thank you, this is a really great answer. Works for any number of lines and can even be modified to include other characters (not only #) easily. Shame I can only give 1 upvote and accept only a single answer. This time I had to go with the one I am more familiar with (and writing functions - I am not familiar with that, but thanks to you I see how they work). – Karolis Koncevičius Feb 5 '15 at 16:38
2

Or you could use visual blocks:

  1. Make sure you already have at least three blank lines at the top, then CtrlV80L

  2. R#

  3. Move to the middle of the block (you're going to have to eyeball this)
  4. CtrlV and select the area of the block you want to remove
  5. RSpace
  6. Go to beginning of empty space, hit R and type your header.

Granted, it's not the most perfect way to create a header, as you have to eyeball it, but it's an interesting case for the Visual Block selection.

Result

#################################################################################
##########################    this is a header      #############################
#################################################################################

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.