# HG changeset patch # User Steve Losh # Date 1319515219 14400 # Node ID ae64d9c11fe71e149a668cba6a37d8525878d8e9 # Parent 8a5c406b39b89e31b2cfc773320964eb95bbe27e Execute, normal diff -r 8a5c406b39b8 -r ae64d9c11fe7 chapters/28.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chapters/28.markdown Tue Oct 25 00:00:19 2011 -0400 @@ -0,0 +1,65 @@ +Execute +======= + +The `execute` command is used to evaluate a string as if it were a Vimscript +command. Run the following command: + + :execute "echom 'Hello, world!'" + +Vim evaluates `echom 'Hello, world!'` as a command and dutifully echoes it to +the screen and message log. Execute is a very powerful tool because it lets you +build commands out of arbitrary strings. + +Let's try a more useful example. Prepare by opening a file in Vim, then using +`:edit "foo.txt"` in the same window to open a new buffer. Now run the +following command: + + :execute "rightbelow vsplit " . bufname("#") + +Vim will open the first file in a vertical split to the right of the second +file. What happened here? + +First, Vim sees builds the command string by concatenating "rightbelow vsplit +" with the result of the `bufname("#")` call. + +We'll look at the function more later, but for now just trust that it returns +the path of the previous buffer. You can play with it using `echom` if you want +to see for yourself. + +Once `bufname` is evaluated Vim has a string that looks something like +"rightbelow vsplit bar.txt". The `execute` command evaluates this as +a Vimscript command which opens the split with the file. + +Is Execute Dangerous? +--------------------- + +In most programming languages the use of such an "eval" construct to evaluate +strings as program code is frowned upon, to put it lightly. Vimscript's +`execute` command doesn't bear the same stigma for two reasons. + +First, most Vimscript code only ever takes input from a single person: the user. +If the user wants to input a tricky string that will cause an `execute` command +to do something bad, well, it's their computer! + +Contrast this with other languages, where programs constantly take input from +untrusted users. Vim is a unique environment where the normal security concerns +simple aren't common. + +The second reason is that because Vimscript has sometimes arcane and tricky +syntax, `execute` is often the easiest, most straightforward way to get +something done. In most other languages using an "eval" construct won't usually +save you much typing, but in Vimscript it can collapse many lines into a single +one. + +Exercises +--------- + +Skim `:help execute` to get an idea of some of the things you can and can't use +`execute` for. Don't dive too deeply yet -- we're going to revisit it very +soon. + +Read `:help leftabove`, `:help rightbelow`, `:help :split`, and `:help :vsplit` +(notice the extra colon in the last two topics). + +Add a mapping to your `~/.vimrc` file that opens the previous buffer in a split +of your choosing (vertical/horizontal, above/below/left/right). diff -r 8a5c406b39b8 -r ae64d9c11fe7 chapters/29.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chapters/29.markdown Tue Oct 25 00:00:19 2011 -0400 @@ -0,0 +1,101 @@ +Normal +====== + +So far we've covered some of the most useful Vimscript commands, but what about +all the stuff you do on a daily basis in normal mode? Can we somehow use all +the knowledge we have from editing text in our scripting? + +The answer is: "of course". Run the following command: + + :normal G + +Vim will move your cursor to the last line in the current file, just like +pressing `G` in normal mode would. Now run the following command: + + :normal ggdd + +Vim will move to the first line in the file (`gg`) and then delete it (`dd`). + +The `normal` command simply takes a sequence of keys and pretends they were +typed in normal mode. Seems simple enough. + +Avoiding Mappings +----------------- + +Run the following command to map the `G` key to something else: + + :nnoremap G dd + +Now pressing `G` in normal mode will delete a line. Try this command: + + :normal G + +Vim will delete the current line. The `normal` command will take into account +any mappings that exist. + +This means that we need something like the `nnoremap` version of `nmap` for +`normal`, otherwise we'll never be able to use it since we can't know what keys +our users have mapped. + +Luckily Vim has a `normal!` command that does exactly this. Run this command: + + :normal! G + +This time Vim moves to the bottom of the file even though `G` has been mapped. + +When writing Vim scripts you should **always** use `normal!`, **never** plain +old `normal`. You can't trust what keys your users will have mapped in their +`~/.vimrc` files. + +Special Characters +------------------ + +If you play around with `normal!` long enough you'll probably notice a problem. +Try the following command: + + :normal! /foo + +At first glance it may seem like this should perform a search for "foo", but +you'll see that it doesn't work. The problem is that `normal!` doesn't parse +special character sequences like ``. + +In this case Vim thinks you wanted to search for the character sequence "f, o, +o, left angle bracket, c, r, right angle bracket", and thinks that you never +even pressed return to perform the search! + +We'll talk about how to get around this in the next chapter. + +Exercises +--------- + +Read `:help normal`. The end of it will hint at the topic of the next chapter. + +Extra Credit +------------ + +If you're not feeling up for a challenge, skip this section. If you are, good +luck! + +Recall what `:help normal` said about undo. Try to make a mapping that will +delete two lines but let you undo each deletion separately. `nnoremap d +dddd` is a good place to start. + +You won't actually need `normal!` for this (`nnoremap` will suffice), but it +illustrates a good point: sometimes reading about one Vim command can spark an +interest in something unrelated. + +If you've never used the `helpgrep` command you'll probably need it now. Read +`:help helpgrep`. Pay attention to the parts about how to navigate between the +matches. + +Don't worry about patterns yet, we're going to cover them soon. For now it's +enough to know that you can use something like `foo.*bar` to find lines +containing that regex in the documentation. + +Unfortunately `helpgrep` can be frustrating at times because you need to know +what words to search for before you can find them! I'll cut you some slack and +tell you that in this case you're looking for a way to break Vim's undo sequence +manually, so that the two deletes in your mapping can be undone separately. + +In the future, be pragmatic. Sometimes Google is quicker and easier when you +don't know exactly what you're after. diff -r 8a5c406b39b8 -r ae64d9c11fe7 chapters/30.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chapters/30.markdown Tue Oct 25 00:00:19 2011 -0400 @@ -0,0 +1,2 @@ +Execute Normal! +===============