Hack39.Exploit the Power of Vim


Hack 39. Exploit the Power of Vim

Use Vim's recording and keyboard macro features to make monotonous tasks lightning fast.

Every administrator, at some point in his career, runs into a scenario in which it's unclear whether a task can be performed more quickly using the Vim command . (a period) and one or two other keystrokes for every change, or using a script. Often, admins wind up using the . command because they figure it'll take less time than trying to figure out the perfect regex to use in a Perl, sed, or awk script.

However, if you know how to use Vim's "recording" feature, you can use on-the-fly macros to do your dirty work with a minimum of keystrokes. What's more, if you have tasks that you have to perform all the time in Vim, you can create a keyboard macros for those tasks that will be available any time you open your editor. Let's have a look!

4.12.1. Recording a Vim Macro

The best way to explain this is with an example. I have a file that is the result of the dumping of all the data in my LDAP directory. It consists of the LDIF entries of all the users in my environment.

One entry looks like this:

 dn: cn=jonesy,ou=People,dc=linuxlaboratory,dc=org objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: posixAccount objectClass: evolutionPerson uid: jonesy sn: Jones cn: Brian K. Jones userPassword: {crypt}eRnFAci.Ie2Ny loginShell: /bin/bash uidNumber: 3025 gidNumber: 410 homeDirectory: /u/jonesy gecos: Brian K. Jones,STAFF mail: jonesy@linuxlaboratory.org roomNumber: 213 fileas: Jones, Brian K. telephoneNumber: NONE labeledURI: http://www.linuxlaboratory.org businessRole: NONE description: NONE homePostalAddress: NONE birthDate: 20030101 givenName: Brian displayName: Brian K. Jones homePhone: 000-000-0000 st: NJ l: Princeton c: UStitle: NONE o: Linuxlaboratory.orgou: Systems Group 

There are roughly 1,000 entries in the file. What I need to do, for every user, is tag the end of every labeledURI line with a value of ~username. This will reflect a change in our environment in which every user has some web space accessible in her home directory, which is found on the Web using the URL http://www.linuxlibrary.org/~username. Some entries have more lines than others, so there's not a whole heckuva lot of consistency or predictability to make my job easy. You could probably write some really ugly shell script or Perl script to do this, but you don't actually even have to leave the cozy confines of Vim to get it done. First, let's record a macro. Step 1 is to type (in command mode) qn, where n is a register label. Valid register labels are the values 09 and az. Once you do that, you're recording, and Vim will store in register n every single keystroke you enter, so type carefully! Typing q again will stop the recording.

Here are the keystrokes I used, including my keystrokes to start and stop recording:

 qz /uid:<Enter> ww yw /labeledURI<Enter> A /~ <Esc> p q 

The first line starts the recording and indicates that my keystrokes will be stored in register z. Next, I search for the string uid: (/uid:), move two words to the right (ww), and yank (Vim-ese for copy) that word (yw). Now I have the username, which I need to paste on the end of the URL that's already in the file. To accomplish this, I do a search for the labeledURI attribute (/labeledRUI), indicate that I am going to append to the end of the current line (A), type a /~ (because those characters need to be there and aren't part of the user's ID), and then hit Esc to enter command mode and immediately hit p to paste the copied username. Finally, I hit q to stop recording.

Now I have a nice string of keystrokes stored in register z, which I can view by typing the following command:

 :register z "z /uid: ^Mwwyw/labeledURI: ^MA/~^[p 

If you can see past the control characters (^M is Enter and ^[ is Escape), you'll see that everything I typed is there. Now I can call up this string of keystrokes any time I want by typing (again, in command mode) @z. It so happens that there are 935 entries in the file I'm working on (I used wc l on the file to get a count), one of which has been edited already, so if I just place my cursor on the line underneath the last edit I performed and type 934@z, that will make the changes I need to every entry in the file. Sadly, I have not found a way to have the macro run to the end of the file without specifying a number.

4.12.2. Creating Vim Shortcut Keys

I happen to really like the concept of WYSIWYG HTML editors. I like the idea of not having to be concerned with tag syntax. To that extent, these editors represent a decent abstraction layer, enabling me to concentrate more on content than form. They also do away with the need to remember the tags for things such as greater than and less than characters and nonbreaking spaces, which is wonderful.

Unfortunately, none of these shiny tools allows me to use Vim keystrokes to move around within a file. I'm not even asking for search and replace or any of the fancy register stuff that Vim offersjust the simple ability to move around with the h, j, k, and l keys, and maybe a few other conveniences. It took me a long time to figure out that I don't need to compromise anymore! I can have the full power of Vim and use it to create an environment where the formatting, while not completely invisible, is really a no-brain-required activity.

Here's a perfect example of one way I use Vim keyboard shortcuts every day. I have to write some of my documentation at work in HTML. Any time my document contains a command that has to be run, I enclose that command in <code></code> tags. This happens a lot, as the documentation I write at work is for an audience of sysadmins like me. The other two most common tags I use are the <p></p> paragraph tags and the <h2></h2> tags, which mark off the sections in the documentation. Here's a line I've entered in my ~/.vimrc file so that entering code tags is as simple as hitting F12 on my keyboard.

 imap <F12> <code> </code> <Esc>2F>a 

The keyword imap designates this mapping as being active only in insert mode. I did this on purpose, because I'm always already in insert mode when I realize I need the tags. Next is the key I'm mapping to, which is, in this case, F12. After that are the actual tags as they will be inserted. Had I stopped there, hitting F12 in insert mode would put in my tags and leave my cursor to the right of them. Because I'm too lazy to move my cursor manually to place it between the tags, I put more keystrokes on the end of my mapping. First, I enter command mode using the Esc key. The 2F> bit says to search from where the cursor is backward to the second occurrence of >, and then the a places the cursor, back in insert mode, after the > character. I never even realize I ever left insert modeit's completely seamless!



Linux Server Hacks (Vol. 2)
BSD Sockets Programming from a Multi-Language Perspective (Programming Series)
ISBN: N/A
EAN: 2147483647
Year: 2003
Pages: 162
Authors: M. Tim Jones

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net