Customizing vim
Written By: Danny "Strike" DiPaolo
Don't forget, the comments can be used in these files as well. The main
macro I wanted to use as an example was the last one. Remember before
with the LaTeX example when I said you could run all of those commands in
one? Well, this is a really simple way of doing it. The ",a" macro in
this set of macros (which resides in my ~/.vim-files/.vimrc.asm file that
is referred to in my main ~/.vimrc above) simply runs the first three
macros in order. Another way I could have done this would have been to
actually take all three of the commands used in the other three macros and
to concatenate them all together. But, it's much much shorter to just run
the three things we have already defined. So, instead of having to type
,n,l,r we can save ourselves some keystrokes by just typing ,a instead.
Kinda neat, huh?
Okay, that is about all of the really neat stuff to do with command mode
macros that I have to show you guys, so the next (and final) step is ...
:::Input mode macros:::
These are very closely related to the command mode macros, but with their
own tiny little subtleties. Let's take a look at some examples, this time
some examples I use in my C macro file:
-----------------------
map! ]if if () {^[o}^[keei
map! ]for for () {^[o}^[keei
map! ]while while () {^[o}^[keei
map! ]inc #include <.h>^[hhi
-----------------------
Now these probably look incredibly cryptic. Part of them may look
somewhat straightforward, but if you can get them from just looking at
them, I'd be very impressed.
An important point to reiterate is that these macros are all entered while
you are actually still in input mode. For example, if I were to type
"]if" in input mode, it would perform the first macro (which I will get to
the meaning of in a bit). In the same vein, typing something like "]ifa"
would first expand the first macro and then put an "a" wherever the cursor
ended up after the macro was complete. So, it is important to choose
things that you are not likely to actually type in whatever you are
typing, because otherwise they will expand to the macros you defined.
This is why my macros begin with the "]" character. I don't use the "]"
character for anything in C except for arrays, and it is rarely ever
followed by words like "if", "for", etc. And even if it was, I do not
think it is ever necessary to use it in that fashion - these letter
combinations can pretty much always be avoided. However, I also like
them to be fairly easy to remember as well, and I think these examples
exemplify that as well.
As you may have noticed, we are no longer using "map" to define our
macros, but "map!" instead. Well, this is what defines an input mode
macro. "map" is only for command mode macros. I generally put these in a
separate section from my command mode macros so as not to clutter up my
.vimrc files too much so that I can further customize them later.
Okay, with all of that covered, let's tackle what these macros expand to.
Much like the command mode macros, you basically think of what keys you
want to be pressed, remembering that you start in input mode. Well, I'll
go ahead and tell you ahead of time what each of these macros is for in
case you haven't already figured it out. The first three are basic macros
to create a syntactically correct if/for/while loop quickly. The last one
is simply a shortcut for including files, and you will see how it works.
's take a look at the first one. Let's assume we are editing the source
code for something and we have these definitions sourced. I'm in input
mode and I'm ready to begin an if statement. Normally, I'd just start
typing something that might look like this:
-----------------------
if (a <=
-----------------------
But the problem here is this, I've already decided that I want to use an
if statement, but I can't focus entirely on the process that needs to take
place within that if statement because I have to remember to close the
loop in order to follow syntax correctly. In fact, with normal typing
methods, closing the if statement is the last thing you do even though it
is the first thing you decide with regards to that program block. True,
you could simply type out a basic if statement first so that it was
syntactically correct and then fill in the appropriate statements, but
that doesn't really apply here now does it?
Actually, yes it does, very much so. In fact, that is exactly what we are
going to do. But we will take it one step further. We will reduce that
step to a much smaller number of keystrokes (as you will see). Now, a
syntactically correct if statement looks like this:
-----------------------
if () {
}
----------------------
where the <condition> and <program statements> vary from task
to task. So, we want to insert this little bit:
----------------
if () {
}
----------------
and then prepare ourselves to start thinking of the condition we want to
put in this particular if statement. So, we've got our problem nailed
down now. Next we'll see how my macro does exactly what we want.
It's pretty obvious (now that you know what input mode macros do) that
most of this is fairly trivial. In fact, the entire first line is very
simple, it's just the part that reads "if () {" - since we are in input
mode, hitting those keys simply puts them in the file like we want.
However, now we have a bit of a problem. We have to move the cursor down
a line and input a final "}" and THEN we have to move the cursor back on
top of the second parentheses and drop ourselves back into input mode (for
the most seamless behavior - we start in input mode, we should end in
input mode, we did the same for command mode macros too). Well, there are
two ways to advance to the next line, actually.
One is fairly easy, and the other a little tougher but more illustrative.
The "fairly easy" method would be to simply to hit Enter and then insert
the final brace. However, I prefer the latter method because it is more
illustrative. This method is to escape OUT of input mode (yes, into
command mode), to begin a new line in input mode with the vi command "o",
and to insert the final brace. But, how does one enter in <Esc> as a
character into a macro? The only way to do it is to hit CTRL-V while in
input mode and then hit the <Esc> key. It produces two characters
like this ^[ but it isn't the same if you just type those two characters
in (if you do, then you will have a "}^[" at the end of your if statement
at this point in time.
Okay, now that we have gotten all the characters in place we have two
objectives left to accomplish - positioning the cursor so that we are in
between the parentheses (realistically, on top of the second paren), and
to make sure we end up in input mode for our seamless transition.
First, let's remember what we've done and where we are. This is what our
setup looks like right now:
-------------------
if () {
}_
---INSERT---
-------------------
(the underscore represents the current cursor position)
Well, now we are going to position the cursor, but there is not any way
of moving up a line in input mode, so we have to escape out again. That
is what the next ^[ in the sequence is for. This will put the cursor back
one spot, directly on top of the curly brace (on the second line). We
then want to move the cursor up one line using the vi navigation keys HJKL
- the appropriate one for this one is of course, "k". Now our cursor is
on top of the "i" in "if" - we have to move it forward to the end of the
"word" after it (well, this "word" is just the set of two parentheses, but
it will do). So, we put it at the end of "if" by telling it to go to the
end of that word (e) and then we tell it to go to the end of the next
"word" (e). Now we are in the right position, but have one thing left to
do - return to input mode. And any seasoned vi user can tell you that "i"
will put you back into input mode from command mode.
You string those all together, you get:
--------------------
for () {^[o}^]keei
--------------------
You may have noticed that using "e" to go to the end of "if" in the last
example was unnecessary and could have been done by moving right one
instead with "l". Well, that is true for "if" because it is a two-letter
word. Examine the macros I use for for and while and notice how they can
be almost identical because of the usage of "e" instead of simple
direction keys. In fact, now is a good time to take a good look over
those and notice the similarities.
Once you are satisfied with what you see (and maybe even comfortable, but
that may be aiming too high), we'll proceed to the final exercise which is
simply analyzing that last macro (a trivial process now that we just did a
more difficult one.
The last macro reads:
--------------------
map! ]inc #include <.h>^[hhi
--------------------
Any C programmer would notice right away that that looks a lot like an
#include line for inclusion of a header file, but it's missing a name.
Well, the rationale behind this one is similar to the one I used in
justifying the whole skeleton file idea. Basically, every #include'd file
follows the same format, only varying in one tiny bit (the part of the
filename before the .h). So, instead of typing stuff like this:
-------------------
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
------------------
(this is an actual set of #includes from a small sockets program)
I just wrote a macro that will print out
------------------
#include <.h>
------------------
and then put me in input mode before the ".h", with a construct like that
in place, writing all the includes is a trivial process that becomes much
faster.
Let's analyze what we need to do. First, we need to output what is shown
above, and then we need to simply position the cursor on the period and go
back into input mode. Like I said, after what we just did, this is pretty
trivial.
The first part is easy, it's just the text ("#include <.h>"). Next
we escape out of insert mode so we can move the cursor ("^[", our cursor
is now on the ">"). Then, we move it on top of the "." by moving it
left twice ("hh"). And, finally, we put ourselves back into input mode
("i"). And <begin cheerleader voice> What's that spell?
</cheerleader>
"#include <.h>^[hhi" !!!
Excellent! You now have a few more tools in your vim toolbox to get you
started on customizing vim to your needs. For more info, read the online
help or just experiment. There is a ton of other stuff you can do, but
this is enough to keep you (and me) busy enough for a while. Enjoy!
Would you like to have your article published online? Send them in to newfiles@linuxnewbie.org
|