Center Macro Hall of Fame

Center Intro

I am always looking for new ways to use vi. In July, 1996, Joshua Wright (jwright@jwu.edu) shared with me his macro for centering a single line of text. I added the commentary you will find below to my vi Web page, and asked several folks on the Net to look it over for errors, and invited anyone to improve the macro. Over time, I got a number of versions and so created this "hall of fame."

Pete Mastren improved on Johsua Wright's version, and about the time that I discovered that the January, 2003 vi FAQ, section 2, had a version I liked better, I got another version from Logan Shaw which was pretty good, though I still like the one in the vi FAQ better (you can see this on my vi page, under macros, where the center macro is described). Here, on this page, I have preserved the various forms which have been sent to me. My thanks to all who have contributed.

The map command is placed in your .exrc file, and in mine, the command, '=c' (or in Joshua's case, '^Kc') is executed when you need something centered in vi.

Sandy Herring points out that wrapmargin should be set to zero before entering the macro. Most vi editors default to this setting, but if yours does not, or if you have it set in your .exrc file, you can unset it with ':set wrapmargin=0' when working on the .exrc file. Sandy also noticed that this macro will not work with a string length of more than 74 characters. This turns out to be an artifact of the editor prompting for you to "[hit return to continue]" when the command which has been executed is long enough to wrap a line, as happens when the text to be centered goes beyond 74 characters.

 

Logan Shaw's Center Macro

Logan Shaw sent this along to me on the 24th of January, 2003. It seemed pretty clever to me, so I added it to my Center Macro Hall of Fame!

map =c >>d0O^[80a ^[jA^[kd02i ^[:.s/../ /g^MJ0xx

Note: the acronym LTBC stands for Line To Be Centered).

>>d0
Trim off leading whitespace (>> adds a tab, moves to 1st non-blank; d0 deletes whitespace preceeding that point).
 
O^[80a ^[j
Use 'O' to open up a new line above the LTBC, escape, '80a ' to add 80 spaces, escape, 'j' to go back to the LTBC.
 
A^[kd0
Use 'A', escape to go into append mode at the end of the line, then back out of it, causing vi to remember that column position. 'k' moves to the same column position on the line of spaces above. The 'd0' removes the same number of leading blanks as there are characters in the LTBC.
 
2i ^[:.s/../ /g^M
This line replaces every two spaces with one, which is effectively a divide-by-two. It is preceeded with a '2i ' to insert two blanks to prevent the failure of the 's' replace in case there were no blanks. Failure of the 's' would blow the macro.
 
J0xx
Use 'J' to join the trimmed, blank line with the LTBC. '0' to move to the front of the line and 'xx' to delete two characters (extra blanks added with the '2i ').

 

Pete Mastren's Center Macro

Pete's center macro--which, if I recall correctly, was sent to me in late summer 1996--functions as follows:

map =c >>d0:co.^Mk:s/./x/g^M40A x^[077lD:s/x//g^MJj

 

>>d0
Trim off leading whitespace (>> adds a tab, moves to 1st non-blank).

:co.^M
Make a copy of the line to be centered.

k
Move back up to the original.

:s/./x/g^M
Convert all characters in original line to x's, creating the first part of a template, which will become a leading-pad.

40A x^[
Append forty pairs of ' x' to the x...x template.

0
Move to the beginning of the template line.

79l
Move over to column eighty of the template line (79 l).

D
Delete everything from column 80, on.

:s/x//g^M
Remove all x's, effectively leaving the number of blanks in an eighty-column line, less the length of the line to be centered, divided by two.

J
Join the leading-pad with the next line--the copy of the line to be centered, thus centering it. Done. The cursor stays on the now-centered line. If you want it to advance, place a 'j' on the end of the macro.

 

Joshua Wright's Center Macro

The 'map =c' is shown on two lines but must appear as one line!

map =c o^[k:c0.^M:s/./ /g^Mo^[80a ^[:-1s;^;:s/;^M:s;$;//;^M
"mdd@m:s/  / /g^M:s;^;:-1s/^/;^M"mdd@mjdd^L

Note: the acronym LTBC stands for Line To Be Centered):

o^[
Create an open line after the LTBC, then escape-out. This deals with anomalies which occur when working on the last line in the file).

k
:co.^M
Move back to the LTBC and make a copy of it.

:s/./ /g^M
Convert all characters in the copy line to blanks to create a blank template.

o^[
Open yet another empty line after the blank template, and...

80a ^[
Make this third line 80 chars of blanks.

:-1s;^;:s/;^M
Modify the blank template line to begin with ':s/'.

:s;$;//;^M
Modify the blank template line to end with '//'.

"mdd
Delete the blank template line into buffer "m".

@m
Execute the blank template line, now a command. This removes a number of blanks from the 80 char blanks line equal to the number of characters in the line to be centered.

:s/  / /g^M
Divide the remaining number of blanks by two. This is the second change I made to the macro, with the original containing ':s/\(.\)./\1/g'. Both work, but the latter would only be required for dividing the length of an arbitrary character string.

:s;^;:-1s/^/;^M
"mdd
@m
Build a substitute command to modify the LTBC, by prepending it with the correct number of blanks, then execute the command out of the m buffer, after deleting the newly-built command from the document and into the m buffer.

jdd^L
Remove the extra buffer line added in the first step, and repaint the screen to clean up any left-over messages or other garbage. The cursor will end up on the next line.


Have a vi tip you'd like to share? Just drop me a line, like Joshua did!

This document may be found at: http://www.nacs.uci.edu/indiv/gdh/vi/center-hof.html
Comments and suggestions welcome.
Last revised Friday, 24-Jan-2003 18:00:47 PST.

Garrett Hildebrand -- gdh@uci.edu