Softpanorama

May the source be with you, but remember the KISS principle ;-)
Contents Bulletin Scripting in shell and Perl Network troubleshooting History Humor

Vim - The editor

Softpanorama
Western Orthodox Editors Page
VIM

News See also Recommended Links Beginner Tutorials Advanced
Info
Reference Ctags Usenet and maillists
Pipes and ! command Text buffer execution Regular Expressions Searching and replacing External commands Multi
Windows support
Macros Cut and Paste
Color schemes in VIM Syntax Highlighting Folding Indenting Your Code in VIM ex commands Perl support    
VIM Configuration Vimrc Examples .exrc files History Tips  Random Findings Humor Etc

The introductory paper Orthodox Editors introduced some ideas on which this page was build. Here is the abstract of the paper:

This paper tried to introduce a new concept: orthodox editors as a special category of editors that have command line set of command and respective glue macrolanguage. We have found two such families:

We define the notion of  "orthodox editors" as having at least three distinct features:

This article is a modest attempt to create a basic classification useful for further studying this important class of editors. The author argues that this class of editors can serve as viable mid-weight editors for programmers (see a companion paper A Note on Size-based Classification of Text Editors for discussion of this editor classification)

Read more

I would like to stress the currently vim  is probably the best implementation of vi philosophy.  It preserved two modes editing paradigm and all important achievements of the original vi including:

At the same time vim editing mode (especially in gvim -- GUI version of vim) resembles more typical Windows editor editing mode. It also has better windows control, Perl interface (starting with version 5.x), folding (from  version 6). 

Folding in VIM

Plain vanilla folding primitives in vim6 are too low level to be convenient for the most users. I highly recommend you to install allfold macros  developed by Marion Berryman. It's better to add basic script (allfold_basic.vim)  to plugin directory. It provides all the necessary folding functionality. He also provided more complex experimental script (allfold_full.vim)  that you can play with if you became addicted to this folding ;-).  Some ideas developed by Marion in those two scripts are really good !!!. Here is a short description of the plugin:

The allfold scripts implement a feature set which allows VIM users to view ALL interesting lines in a buffer and FOLD the rest away.  Lines are selected to be interesting in one of the two following ways:

1. They match a regular expression pattern.
2. They are in a block of lines delimited inclusively by a line that matches  a beginning RE pattern and a line that matches an ending RE pattern.

Sets of lines matching different selection criteria can be combined using logical "and" and "or" operations. The selections may be inverted so that lines not matching the selection criteria are actually selected.

Beyond these basics other features do such things as manipulating lists of selection commands and using the raw selection "bit-map" directly to enhance the capabilities and ease of use of the scripts.

I would change the mnemonic to include the word "all" to respect history of this command. For example:

command! -nargs=+ Allb :call AFB_fold_blocks(<f-args>)
command! -nargs=0 Allf :call AFB_freshen()
command! -nargs=+ Allg :call AFB_grab_view_map(<f-args>)
command! -nargs=0 Allh :call AFB_has_folds()
command! -nargs=? Alli :call AFB_invert(<f-args>)
command! -nargs=+ All :call AFB_fold_pattern(<f-args>)
command! -nargs=0 ALL :call AFB_fold_remove()
command! -nargs=0 Allu :call AFB_undo_prev()

Please note that in the definitions above "All" is command to fold text and "ALL" to unfold. Actually if no parameters supplied to All, it can unfold the text (remove folding).  This was the original Xedit semantic and it makes sense to preserve it.

Like in other orthodox editors the central idea of vi is the idea of the command line command set, the idea that as I stressed before is in some respects more powerful and convenient than getting the same functionality implicitly via cascading menus. An interesting and pretty logical extensions of this idea in vi is the ability to generate command-line command parameters (or even whole commands) using screen.

The main ideas vi is pretty close to the orthodox editors paradigm that I discussed on the main page of the section.

I would like to reproduce Bill's Joy recollection of how vi was really written  (from  Linux Magazine November 1999 FEATURES The Joy of Unix):

LM:: What inspired you to write vi?

BJ: What happened is that Ken Thompson came to Berkeley and brought this broken Pascal system, and we got this summer job to fix it. While we were fixing it, we got frustrated with the editor we were using which was named ed. ed is certainly frustrating.

We got this code from a guy named George Coulouris at University College in London called em -- Editor for Mortals -- since only immortals could use ed to do anything. By the way, before that summer, we could only type in uppercase. That summer we got lowercase ROMs for our terminals. It was really exciting to finally use lowercase.

LM: What year was that?

BJ: '76 or '77. It was the summer Carter was president. So we modified em and created en. I don't know if there was an eo or an ep but finally there was ex. [laughter] I remember en but I don't know how it got to ex. So I had a terminal at home and a 300 baud modem so the cursor could move around and I just stayed up all night for a few months and wrote vi.

LM: So you didn't really write vi in one weekend like everybody says?

BJ: No. It took a long time. It was really hard to do because you've got to remember that I was trying to make it usable over a 300 baud modem. That's also the reason you have all these funny commands. It just barely worked to use a screen editor over a modem. It was just barely fast enough. A 1200 baud modem was an upgrade. 1200 baud now is pretty slow.

9600 baud is faster than you can read. 1200 baud is way slower. So the editor was optimized so that you could edit and feel productive when it was painting slower than you could think. Now that computers are so much faster than you can think, nobody understands this anymore.

The people doing Emacs were sitting in labs at MIT with what were essentially fibre-channel links to the host, in contemporary terms. They were working on a PDP-10, which was a huge machine by comparison, with infinitely fast screens.

So they could have funny commands with the screen shimmering and all that, and meanwhile, I'm sitting at home in sort of World War II surplus housing at Berkeley with a modem and a terminal that can just barely get the cursor off the bottom line.

It was a world that is now extinct. People don't know that vi was written for a world that doesn't exist anymore -- unless you decide to get a satellite phone and use it to connect to the Net at 2400 baud, in which case you'll realize that the Net is not usable at 2400 baud. It used to be perfectly usable at 1200 baud. But these days you can't use the Web at 2400 baud because the ads are 24 kilobytes.

Peter Salus in his Open Source Library - Papers gives the following version of events:

The original UNIX editor was ed. It was a line editor of reluctant and recalcitrant style. When UNIX (version 4) got to Queen Mary College, London, in 1973, George Coulouris -- a Professor of Computing -- wasn't happy with it. So he wrote a screen editor, which he called "em," or "ed for mortals."

Coulouris went on sabbatical to Berkeley, where he installed em on "his" machine. A graduate student noticed it one day, and asked about it. Coulouris explained. He then went off to New Jersey to Bell Labs, and when he returned to Berkeley, he found that em had been transmuted into ex, a display editor that is a superset of ed and a number of extensions -- primarily the one that enables display editing.

At the beginning of 1978, the first Berkeley Software Distribution was available. It consisted of a tape of the Berkeley Pascal System and the ex text editor. The graduate student was Bill Joy, and the distribution cost $50. The next year Berkeley got some ADM-3a terminals, and Joy rewrote em to vi -- a truly visual editor.

In sum, ed came out of Bell Labs in New Jersey, went to Queen Mary College in London, from there to the University of California at Berkeley, and from there back to New Jersey, where it was incorporated into the next edition of UNIX.

Dr. Nikolai Bezroukov


Top Visited
Switchboard
Latest
Past week
Past month

NEWS CONTENTS

Old News ;-)

2004 2003 2002 2001 2000

[Nov 01, 2017] Vim character info by Tom Ryder

Mar 31, 2013 | sanctum.geek.nz

Posted on Vim will show you the decimal, octal, and hex index of the character under the cursor if you type ga in normal mode. Keying this on an ASCII a character yields the following in the status bar:

<a>  97,  Hex 61,  Octal 141

This information can be useful, but it's worth it to extend it to include some other relevant information, including the Unicode point and name of the character, its HTML entity name (if applicable), and any digraph entry method . This can be done by installing the characterize plugin by Tim Pope .

With this plugin installed, pressing ga over a yields a bit more information:

<a> 97, \141, U+0061 LATIN SMALL LETTER A

This really shines however when inspecting characters that are available as HTML entities, or as Vim digraphs, particularly commonly used characters like an EM DASH:

< -- > 8212, U+2014 EM DASH, ^K-M, &mdash;

Or a COPYRIGHT SYMBOL:

<©> 169, \251, U+00A9 COPYRIGHT SIGN, ^KCo, ^KcO, :copyright:, &copy;

Or as one of the eyes in a look of disapproval:

<ಠ> 3232, U+0CA0 KANNADA LETTER TTHA

Note that ga shows you all the Unicode information for the character, along with any methods to type it as a digraph, and an appropriate HTML entity if applicable.

If you work with multibyte characters a lot, whether for internationalization reasons or for typographical correctness in web pages, this may be very useful to you.

[Nov 01, 2017] Bash prompts by Tom Ryder

Jul 09, 2012 | sanctum.geek.nz

You can tell a lot about a shell user by looking at their prompt. Most shell users will use whatever the system's default prompt is for their entire career. Under many GNU/Linux distributions, this prompt includes the username, the hostname, and the current working directory, along with a $ sigil for regular users, and a # for root .

tom@sanctum:~$

This format works well for most users, and it's so common that it's often used in tutorials to represent the user's prompt in lieu of the single-character standard $ and # . It shows up as the basis for many of the custom prompt setups you'll find online.

Some users may have made the modest steps of perhaps adding some brackets around the prompt, or adding the time or date:

[10:11][tom@sanctum:~]$

Still others make the prompt into a grand multi-line report of their shell's state, or indeed their entire system, full of sound and fury and signifying way too much:

-(23:38:57)-(4 users)-(0.00, 0.02, 0.05)-
-(Linux sanctum 3.2.0-3-amd64 x86_64 GNU/Linux)-
[tom@sanctum:/dev/pts/2:/home/tom]{2}!?[MAIL]$

Then there are the BSD users and other minimalist contrarians who can't abide anything more than a single character cluttering their screens:

$

Getting your prompt to work right isn't simply a cosmetic thing, however. If done right and in a style consistent with how you work, it can provide valuable feedback on how the system is reacting to what you're doing with it, and also provide you with visual cues that could save you a lot of confusion -- or even prevent your making costly mistakes.

I'll be working in Bash. Many of these principles work well for Zsh as well, but Zsh users might want to read Steve Losh's article on his prompt setup first to get an idea of the syntactical differences.

Why is this important?

One of the primary differences between terminals and windowed applications is that there tends to be much less emphasis on showing metadata about the running program and its environment. For the most part, to get information about what's going on, you need to request it with calls like pwd , whoami , readlink , env , jobs , and echo $? .

The habit of keeping metadata out of the terminal like this unless requested may appeal to a sense of minimalism, but like a lot of things in the command line world, it's partly the olden days holding us back. When mainframes and other dinosaurs roamed the earth, terminal screens were small, and a long or complex prompt amounted to a waste of space and cycles (or even paper). In our futuristic 64-bit world, where tiny CRTs are a thing of the past and we think nothing of throwing gigabytes of RAM at a single process, this is much less of a problem.

Customising the prompt doesn't have many "best practices" to it like a lot of things in the shell; there isn't really a right way to do it. Some users will insist it's valuable to have the path to the terminal device before every prompt, which I think is crazy as I almost never need that information, and when I do, I can get it with a call to tty . Others will suggest that including the working directory makes the length of the prompt too variable and distracting, whereas I would struggle to work without it. It's worth the effort to design a prompt that reflects your working style, and includes the information that's consistently important to you on the system.

So, don't feel like you're wasting time setting up your prompt to get it just right, and don't be so readily impressed by people with gargantuan prompts in illegible rainbow colors that they copied off some no-name wiki. If you use Bash a lot, you'll be staring at your prompt for several hours a day. You may as well spend an hour or two to make it useful, or at least easier on the eyes.

The basics

The primary Bash prompt is stored in the variable PS1 . Its main function is to signal to the user that the shell is done with its latest foreground task, and is ready to accept input. PS1 takes the form of a string that can contain escape sequences for certain common prompt elements like usernames and hostnames, and which is evaluated at printing time for escape sequences, variables, and command or function calls within it.

You can inspect your current prompt definition with echo . If you're using GNU/Linux, it will probably look similar to this:

tom@sanctum:~$ echo $PS1
\u@\h:\w\$

PS1 works like any other Bash variable; you can assign it a new value, append to it, and apply substitutions to it. To add the text bash to the start of my prompt, I could do this:

tom@sanctum:~$ PS1=bash-"$PS1"
bash-tom@sanctum:~$

There are other prompts -- PS2 is used for "continued line" prompts, such as when you start writing a for loop and continue another part of it on a new line, or terminate your previous line with a backslash to denote the next line continues on from it. By default this prompt is often a right angle bracket > :

$ for f in a b c; do
>   do echo "$f"
> done

There are a couple more prompt strings which are much more rarely seen. PS3 is used by the select structure in shell scripts; PS4 is used while tracing output with set -x . Ramesh Natarajan breaks this down very well in his article on the Bash prompt . Personally, I only ever modify PS1 , because I see the other prompts so rarely that the defaults work fine for me.

As PS1 is a property of interactive shells, it makes the most sense to put its definitions in $HOME/.bashrc on GNU/Linux or BSD systems. It's likely there's already code in there doing just that. For Mac OS X, you'll likely need to put it into $HOME/.bash_profile instead.

Escapes

Bash will perform some substitutions for you in the first pass of its evaluation of your prompt string, replacing escape sequences with appropriate elements of information that are often useful in prompts. Below are the escape sequences as taken from the Bash man page:

\a     an ASCII bell character (07)
\d     the date in "Weekday Month Date" format (e.g., "Tue May 26")
\D{format}
       the format is passed to strftime(3) and the result is inserted into
       the prompt string; an empty format results in a locale-specific time
       representation. The braces are required
\e     an ASCII escape character (033)
\h     the hostname up to the first `.'
\H     the hostname
\j     the number of jobs currently managed by the shell
\l     the basename of the shell's terminal device name
\n     newline
\r     carriage return
\s     the name of the shell, the basename of $0 (the portion following
       the final slash)
\t     the current time in 24-hour HH:MM:SS format
\T     the current time in 12-hour HH:MM:SS format
\@     the current time in 12-hour am/pm format
\A     the current time in 24-hour HH:MM format
\u     the username of the current user
\v     the version of bash (e.g., 2.00)
\V     the release of bash, version + patch level (e.g., 2.00.0)
\w     the current working directory, with $HOME abbreviated with a tilde
       (uses the value of the PROMPT_DIRTRIM variable)
\W     the basename of the current working directory, with $HOME
       abbreviated with a tilde
\!     the history number of this command
\#     the command number of this command
\$     if the effective UID is 0, a #, otherwise a $
\nnn   the character corresponding to the octal number nnn
\\     a backslash
\[     begin a sequence of non-printing characters, which could be used to
       embed a terminal control sequence into the prompt
\]     end a sequence of non-printing characters

As an example, the default PS1 definition on many GNU/Linux systems uses four of these codes:

\u@\h:\w\$

The \! escape sequence, which expands to the history item number of the current command, is worth a look in particular. Including this in your prompt allows you to quickly refer to other commands you may have entered in your current session by history number with a ! prefix, without having to actually consult history :

$ PS1="(\!)\$"
(6705)$ echo "test"
test
(6706)$ !6705
echo "test"
test

Keep in mind that you can refer to history commands relatively rather than by absolute number. The previous command can be referenced by using !! or !-1 , and the one before that by !-2 , and so on, provided that you have left the histexpand option on.

Also of particular interest are the delimiters \[ and \] . You can use these to delimit sections of "non-printing characters", typically things like terminal control characters to do things like moving the cursor around, starting to print in another color, or changing properties of the terminal emulator such as the title of the window. Placing these non-printing characters within these delimiters prevents the terminal from assuming an actual character has been printed, and hence correctly manages things like the user deleting characters on the command line.

Colors

There are two schools of thought on the use of color in prompts, very much a matter of opinion:

If you agree more with the first opinion than the second, you can probably just skip to the next section of this article.

Printing text in color in terminals is done with escape sequences, prefixed with the \e character as above. Within one escape sequence, the foreground, background, and any styles for the characters that follow can be set.

For example, to include only your username in red text as your prompt, you might use the following PS1 definition:

PS1='\[\e[31m\]\u\[\e[0m\]'

Broken down, the opening sequence works as follows:

The terminating sequence is very similar, except it uses the 0 display attribute to reset the text that follows back to the terminal defaults.

The valid display attributes for 16-color terminals are:

Note that blink may not work on a lot of terminals, often by design, as it tends to be unduly distracting. It'll work on a linux console, though. Also keep in mind that for a lot of terminal emulators, by default "bright" colors are printed in bold.

More than one of these display attributes can be applied in one hit by separating them with semicolons. The below will give you underlined white text on a blue background, after first resetting any existing attributes:

\[\e[0;4;37;44m\]

It's helpful to think of these awkward syntaxes in terms of opening and closing, rather like HTML tags, so that you open before and then reset after all the attributes of a section of styled text. This usually amounts to printing \[\e[0m\] after each such passage.

These sequences are annoying to read and to type, so it helps to put commonly used styles into variables:

color_red='\[\e[31m\]'
color_blue='\[\e[34m\]'
color_reset='\[\e[0m\]'

PS1=${color_red}'\u'${color_reset}'@'${color_blue}'\h'${color_reset}

A more robust method is to use the tput program to print the codes for you, and put the results into variables:

color_red=$(tput setaf 1)
color_blue=$(tput setaf 4)

This may be preferable if you use some esoteric terminal types, as it queries the terminfo or termcap databases to generate the appropriate escapes for your terminal.

The set of eight colors -- or sixteen, depending on how you look at it -- can be extended to 256 colors in most modern terminal emulators with a little extra setup. The escape sequences are not very different, but their range is vastly increased to accommodate the larger palette.

A useful application for prompt color can be a quick visual indication of the privileges available to the current user. The following code changes the prompt to green text for a normal user, red for root , and yellow for any other user attained via sudo :

color_root=$(tput setaf 1)
color_user=$(tput setaf 2)
color_sudo=$(tput setaf 3)
color_reset=$(tput sgr0)

if (( EUID == 0 )); then
    PS1="\\[$color_root\\]$PS1\\[$color_reset\\]"
elif [[ $SUDO_USER ]]; then
    PS1="\\[$color_sudo\\]$PS1\\[$color_reset\\]"
else
    PS1="\\[$color_user\\]$PS1\\[$color_reset\\]"
fi

Otherwise, you could simply use color to make different regions of your prompt more or less visually prominent.

Variables

Provided the promptvars option is enabled, you can reference Bash variables like $? to get the return value of the previous command in your prompt string. Some people find this valuable to show error codes in the prompt when the previous command given fails:

$ shopt -s promptvars
$ PS1='$? \$'
1 $ echo "test"
test
0 $ fail
-bash: fail: command not found
127 $

The usual environment variables like USER and HOME will work too, though it's preferable to use the escape sequences above for those particular variables. Note that it's important to quote the variable references as well, so that they're evaluated at runtime, and not during the assignment itself.

Commands

If the information you want in your prompt isn't covered by any of the escape codes, you can include the output of commands in your prompt as well, using command substitution with the syntax $(command) :

$ PS1='[$(uptime) ]\$ '
[ 01:21:59 up 7 days, 13:04,  7 users, load average: 0.30, 0.40, 0.36 ]$

This requires the promptvars option to be set, the same way variables in the prompt do. Again, note that you need to use single quotes so that the command is run when the prompt is being formed, and not immediately as part of the assignment.

This can include pipes to format the data with tools like awk or cut , if you only need a certain part of the output:

$ PS1='[$(uptime | cut -d: -f5) ]\$ '
[ 0.36, 0.34, 0.34 ]$

For clarity, during prompt setup in .bashrc , it makes sense to use functions instead for reasonably complex commands:

prompt_load() {
    uptime | cut -d: -f5
}
PS1='[$(prompt_load) ]'$PS1

Note that as a normal part of command substitution, trailing newlines are stripped from the output of the command, so here the output of uptime appears on a single line.

A common usage of this pattern is showing metadata about the current directory, particularly if it happens to be a version control repository or working copy; you can use this syntax with functions to show the type of version control system, the current branch, and whether any changes require committing. Working with Git, Mercurial, and Subversion most often, I include the relevant logic as part of my prompt function .

When appended to my PS1 string, $(prompt vcs) gives me prompts that look like the following when I'm in directories running under the appropriate VCS. The exclamation marks denote that there are uncommitted changes in the repositories.

[tom@conan:~/.dotfiles](git:master!)$
[tom@conan:~/Build/tmux](svn:trunk)$
[tom@conan:~/Build/vim](hg:default!)$

In general, where this really shines is adding pieces to your prompt conditionally , to make them collapsible. Certain sections of your prompt therefore only show up if they're relevant. This snippet, for example, prints the number of jobs running in the background of the current interactive shell in curly brackets, but only if the count is non-zero:

prompt_jobs() {
    local jobc
    while read -r _; do
        ((jobc++))
    done < <(jobs -p)
    if ((jobc > 0)); then
        printf '{%d}' "$jobc"
    fi
}

It's important to make sure that none of what your prompt does takes too long to run; an unresponsive prompt can make your terminal sessions feel very clunky.

Note that you can also arrange to run a set of commands before the prompt is evaluated and printed, using the PROMPT_COMMAND . This tends to be a good place to put commands that don't actually print anything, but that do need to be run before or after each command, such as operations working with history :

PROMPT_COMMAND='history -a'
Switching

If you have a very elaborate or perhaps even computationally expensive prompt, it may occasionally be necessary to turn it off to revert to a simpler one. I like to handle this by using functions, one of which sets up my usual prompt and is run by default, and another which changes the prompt to the minimal $ or # character so often used in terminal demonstrations. Something like the below works well:

prompt_on() {
    PS1="$color_prompt"'\u@\h:\w'"$(prompt_jobs)"'\$'"${color_reset}"' '
}
prompt_off() {
    PS1='\$'
}
prompt_on

You can then switch your prompt whenever you need to by typing prompt_on and prompt_off .

This can also be very useful if you want to copy text from your terminal into documentation, or into an IM or email message; it removes your distracting prompt from the text, where it would otherwise almost certainly differ from that of the user following your instructions. This is also occasionally helpful if your prompt does not work on a particular machine, or the machine is suffering a very high load average that means your prompt is too slow to load.

Further reading

Predefined prompt strings are all over the web, but the above will hopefully enable you to dissect what they're actually doing more easily and design your own. To take a look at some examples, the relevant page on the Arch Wiki is a great start. Ramesh Natarajan over at The Geek Stuff has a great article with some examples as well, with the curious theme of making your prompt as well-equipped as Angelina Jolie .

Finally, please feel free to share your prompt setup in the comments (whether you're a Bash user or not). It would be particularly welcome if you explain why certain sections of your prompt are so useful to you for your particular work.

[Nov 01, 2017] Actually using ed by Tom Ryder

Notable quotes:
"... Update 2016: Recent Hacker News discussion has reminded me of my long-standing mistake in asserting that ed(1) is included in every Unix and Unix-like system's base installation. This is not even close to true–many others exclude it–and the claim has been removed, which I should have done years ago. ..."
"... Thanks to A. Pedro Cunha for a couple of fixes to show correct typical output. ..."
Jun 17, 2012 | sanctum.geek.nz

The classic ed editor is a really good example of a sparse, minimal, standard Unix tool that does one thing, and does it well. Because there are so many good screen-oriented editors for Unix, there's seldom very much call for using ed , unless you're working on very old or very limited hardware that won't run anything else.

However, if part of the reason you use vi is because you think it will always be there (it may not be), then you should learn ed too. If your terminal is broken and neither vi nor nano will work, or you break it some other way, your choices may well be between cat and ed . Or even the grand heresy of sed -i

Not a friendly editor

Even more than its uppity grandchild ex / vi , ed has developed a reputation as terse and intimidating to newcomers. When you type ed at the command line, nothing happens, and the only error message presented by default is ? . If you're reading this, it's likely your first and only experience with ed went something like this:

$ ed
help
?
h
Invalid command suffix
?
?
^C
?
exit
?
quit
?
^Z
$ killall ed
$ vi

So, ed is not a terribly intuitive editor. However, it's not nearly as hard to learn as it might seem, especially if you're a veteran vi user and thereby comfortable with the ex command set. With a little practice, you can actually get rather quick with it; there's an elegance to its almost brutal simplicity.

It's also very interesting to learn how ed works and how to use it, not just because it might very well be useful for you one day, but because it occupies an important position in the heritage of the sed stream editor, the ex line editor, the vi visual editor, the grep tool, and many other contexts.

Why is ed so terse?

When ed was developed, the usual method of accessing a Unix system was via a teletype device, on which it wouldn't have been possible to use a screen-oriented editor like vi . Similarly, modems were slow, and memory was precious; using abbreviated commands and terse error messages made a lot of sense, because the user would otherwise be wasting a lot of time waiting for the terminal to react to commands, and didn't have a whole lot of memory to throw around for anything besides the buffer of text itself.

Of course, this is almost a non-issue for most Unix-like systems nowadays, so one of the first things we'll do is make ed a little bit less terse and more user-friendly.

Error messages

Start ed up the usual way:

$ ed

We'll start by deliberately doing something wrong. Type b and press Enter:

b
?

There's that tremendously unhelpful ? again. But if you press h , you can see what went wrong:

h
Unknown command

Of course, since it's the future now, we can spare the terminal cycles to have ed print the error message for us every time. You can set this up by pressing H :

H
b
?
Unknown command

That's a bit more useful, and should make things easier.

Quitting

You can quit ed with q . Go ahead and do that. If you had unsaved changes in a buffer, you could type Q to quit unconditionally. Repeating yourself works too:

q
?
Warning: buffer modified
q
Command prompt

Let's invoke ed again, but this time we'll use the -p option to specify a command prompt :

$ ed -p\*
*

We'll use that from now on, which will make things clearer both for interpreting this tutorial and for remembering whether we're in command mode, or entering text. It might even be a good idea to make it into a function :

$ ed() { command ed -p\* "$@" ; }
Basic text input

We'll start by adding a couple of lines of text to the new buffer. When you start ed with no filename, it starts an empty buffer for you, much like vi does.

Because there are no lines at all at present, press a to start adding some at the editor's current position:

*a
Start typing a few lines.
Anything you want, really.
Just go right ahead.
When you're done, just type a period by itself.
.

That's added four new lines to the buffer, and left the editor on line 4. You can tell that's the case because typing p for print, just by itself, prints the fourth line:

*p
When you're done, just type a period by itself.

A little more useful is n (or pn in some versions), which will show both the line number and the contents of the line:

*n
4       When you're done, just type a period by itself.

So just like in ex , the current line is the default for most commands. You can make this explicit by referring to the current line as . :

*.n
4       When you're done, just type a period by itself.

You can move to a line just by typing its number, which will also print it as a side effect:

*3
Just go right ahead.
*.n
3       Just go right ahead.

Pressing a like you did before will start inserting lines after the current line:

*a
Entering another line.
.
*n
4       Entering another line.

Pressing i will allow you to insert lines before the current line:

*i
A line before the current line.
.
*n
4       A line before the current line.

You can replace a line with c :

*c
I decided I like this line better.
.
*n
4       I decided I like this line better.

You can delete lines with d :

*6d

And join two or more lines together with j :

*1,2j

You can prepend an actual line number to any of these commands to move to that line before running the command on it:

*1c
Here's a replacement line.
.
*1n
1       Here's a replacement line.

For most of these commands, the last line to be changed will become the new current line.

Ranges

You can select the entire buffer with 1,$ or , for short ( % works too):

*,p
Here's a replacement line.
Just go right ahead.
I decided I liked this line better.
Entering another line.

Or a limited range of specific lines:

*2,3p
Just go right ahead.
I decided I liked this line better.

These ranges can include a reference to the current line with . :

*2
Just go right ahead.
*.,4p
Just go right ahead.
I decided I liked this line better.
Entering another line.

They can also include relative line numbers, prefixed with + or - :

*2
*-1,+1p
Here's a replacement line.
Just go right ahead.
I decided I liked this line better.

You can drop a mark on a line with k followed by a lowercase letter such as a , and you're then able to refer to it in ranges as 'a :

*3ka
*'ap
I decided I liked this line better.
Moving and copying

Move a line or range of lines to after a target line with m :

*1,2m$
*,p
I decided I liked this line better.
Entering another line.
Here's a replacement line.
Just go right ahead.

Copy lines to after a target line with t :

*2t4
*,p
I decided I liked this line better.
Entering another line.
Here's a replacement line.
Just go right ahead.
Entering another line.
Regular expressions

You can select lines based on classic regular expressions with the g operator. To print all lines matching the regular expression /re/ :

*g/re/p
Here's a replacement line.

(Hmm, where have I seen that command before?)

You can invert the match to work with lines that don't match the expression with v :

*v/re/p
I decided I liked this line better.
Entering another line.
Just go right ahead.
Entering another line.

Just like numbered line ranges, ranges selected with regular expressions can have other operations applied to them. To move every line containing the expression /re/ to the bottom of the file:

*g/re/m$
*,p
I decided I liked this line better.
Entering another line.
Just go right ahead.
Entering another line.
Here's a replacement line.
Searching

You can move to the next line after the current one matching a regular expression with / . Again, this will print the line's contents as a side effect.

*/like
I decided I like this line better.

You can search backward with ? :

*?Here
Here's a replacement line.
Substituting

You can substitute for the first occurrence per line of an expression within a range of lines with the s command:

*1s/i/j
I decjded I like this line better.

You can substitute for all the matches on each line by adding the /g suffix:

*1s/i/j/g
*p
I decjded I ljke thjs ljne better.
Reading and writing

You can write the current buffer to a file with w , which will also print the total number of bytes written:

*w ed.txt
129

Having done this once, you can omit the filename for the rest of the session:

*w
129

Like most ed commands, w can be prefixed with a range to write only a subset of lines to the file. This would write lines 1 to 4 to the file ed.txt :

*1,4w ed.txt
102

You can use W to append to a file, rather than replace it. This would write lines 3 to 5 to the end of the file ed.txt :

*3,5W
71

You can read in the contents of another file after the current line (or any other line) with r . Again, this will print the number of bytes read.

*r /etc/hosts
205

The output of a command can be included by prefixing it with ! :

*r !ps -e
5571

If you just want to load the contents of a file or the output of a command into the buffer, replacing what's already there, use e , or E if you've got an unmodified buffer and don't care about replacing it:

*E ed.txt
173

If you don't like seeing the byte counts each time, you can start ed with the -s option for "quiet mode".

Familiar syntax

Almost all of the above command sets will actually be familiar to vi users who know a little about ex , or Vimscript in Vim. It will also be familiar to those who have used sed at least occasionally.

Once you get good with ed , it's possible you'll find yourself using it now and then to make quick edits to files, even on systems where your favourite screen-based editor will load promptly. You could even try using ex .

Update 2016: Recent Hacker News discussion has reminded me of my long-standing mistake in asserting that ed(1) is included in every Unix and Unix-like system's base installation. This is not even close to true–many others exclude it–and the claim has been removed, which I should have done years ago.

Thanks to A. Pedro Cunha for a couple of fixes to show correct typical output.

[Nov 01, 2017] Advanced Vim registers by Tom Ryder

Oct 24, 2012 | sanctum.geek.nz

Posted on Registers in Vim are best thought of as scratch spaces for text, some of which are automatically filled by the editor in response to certain actions. Learning how to use registers fluently has a lot of subtle benefits, although it takes some getting used to because the syntax for using them is a little awkward.

If you're reasonably fluent with Vim by now, it's likely you're already familiar with the basic usage of the 26 named registers , corresponding to the letters of the alphabet. These are commonly used for recording macros ; for example, to record a series of keystrokes into register a , you might start recording with qa , and finish with q ; your keystrokes could then be executed with @a .

Similarly, we can store text from the buffer itself rather than commands in these registers, by prepending "a to any command which uses a register, such as the c , d , and y commands:

Like many things in Vim, there's a great deal more functionality to registers for those willing to explore.

Note that here I'll be specifically ignoring the * , + , and ~ registers; that's another post about the generally unpleasant business of making Vim play nice with system clipboards. Instead, I'll be focussing on stuff that only applies within a Vim session. All of this is documented in :help registers .

Capital registers

Yanking and deleting text into registers normally replaces the previous contents of that register. In some cases it would be preferable to append to a register, for example while cherry-picking different lines from the file to be pasted elsewhere. This can be done by simply capitalizing the name of the register as it's referenced:

This works for any context in which an alphabetical register can be used. Similarly, to append to a macro already recorded in register a , we can start recording with qA to add more keystrokes to it.

Viewing register contents

A good way to start getting a feel for how all the other registers work is to view a list of them with their contents during an editing session with :registers . This will show the contents of any register used in the editing session. It might look something like this, a little inscrutable at first:

:registers
--- Registers ---
""   Note that much of it includes
"0   execut
"1   ^J^J
"2   16 Oct (2 days ago)^J^Jto Jeff, Alan ^JHi Jeff (cc Alan);^J^JPlease 
"3   <?php^Jheader("Content-Type: text/plain; charset=utf-8");^J?>^J.^J
"4   ^J
"5   Business-+InternationalTrade-TelegraphicTransfers-ReceivingInternati
"6   ../^J
"7       diff = auto^J    status = auto^J    branch = auto^J    interacti
"8   ^J[color]^J    ui = auto^J    diff = auto^J    status = auto^J    br
"9       ui = true^J
"a    escrow
"b   03wdei^R=2012-^R"^M^[0j
"c   a
"e   dui{<80>kb^[^[
"g   ^[gqqJgqqjkV>JgqqJV>^[Gkkkjohttp://tldp.org/LDP/abs/html/^[I[4]: ^[k
"h   ^[^Wh:w^Mgg:w^M^L:w^Mjk/src^Mllhh
"j   jjjkkkA Goo<80>kb<80>kb<80>kbThis one is good pio<80>kbped through a
"-   Note that much of it includes
".    OIt<80>kb<80>kb<80>kbIt might looks <80>kb<80>kb something like thi
":   register
"%   advanced-vim-registers.markdown
"/   Frij

The first column contains the name of the register, and the second its contents. The contents of any of these registers can be pasted into the buffer with "ap , where a is the name of any of them. Note that there are considerably more registers than just the named alphabetical ones mentioned above.

Unnamed register

The unnamed register is special in that it's always written to in operations, no matter whether you specified another register or not. Thus if you delete a line with dd , the line's contents are put into the unnamed register; if you delete it with "add , the line's contents are put into both the unnamed register and into register a .

If you need to explicitly reference the contents of this register, you can use " , meaning you'd reference it by tapping " twice: "" . One handy application for this is that you can yank text into the unnamed register and execute it directly as a macro with @" .

Man, and you thought Perl looked like line noise.

Black hole register

Another simple register worth mentioning is the black hole register , referenced with "_ . This register is special in that everything written to it is discarded. It's the /dev/null of the Vim world; you can put your all into it, and it'll never give anything back. A pretty toxic relationship.

This may not seem immediately useful, but it does come in handy when running an operation that you don't want to clobber the existing contents of the unnamed register. For example, if you deleted three lines into the unnamed register with 3dd with the intent of pasting them elsewhere with p , but you wanted to delete another line before doing so, you could do that with "_dd ; line gone, and no harm done.

Numbered registers

The read-only registers 0 through 9 are your "historical record" registers. The register 0 will always contain the most recently yanked text , but never deleted text; this is handy for performing a yank operation, at least one delete operation, and then pasting the text originally yanked with "0p .

The registers 1 through 9 are for deleted text , with "1 referencing the most recently deleted text, "2 the text deleted before that, and so on up to "9 .

The small delete register

This read-only register, referenced by "- , stores any text that you deleted or changed that was less than one line in length, unless you specifically did so into some other named register. So if you just deleted three characters with 3x , you'll find it in here.

Last inserted text register

The read-only register ". contains the text that you last inserted. Don't make the mistake of using this to repeat an insert operation, though; just tap . for that after you leave insert mode, or have the foresight to prepend a number to your insert operation; for example, 6i .

Filename registers

The read-only register "% contains the name of the current buffer's file. Similarly, the "# register contains the name of the alternate buffer's file.

Command registers

The read-only register ": contains the most recently executed : command, such as :w or :help . This is likely only of interest to you if you're wanting to paste your most recent command into your Vim buffer. For everything else, such as repeating or editing previous commands, you will almost certainly want to use the command window .

Search registers

The read-only register / contains the most recent search pattern; this can be handy for inserting the search pattern on the command line, by pressing Ctrl-R and then / -- very useful for performing substitutions using the last search pattern.

Expression register

Here's the black sheep of the bunch. The expression register = is used to treat the results of arbitrary expressions in register context. What that means in actual real words is that you can use it as a calculator, and the result is returned from the register.

Whenever the expression register is referenced, the cursor is put on the command line to input an expression, such as 2+2 , which is ended with a carriage return.

This means in normal mode you can type "=2+2<Enter>p , and 4 will be placed after the cursor; in insert or command mode you can use Ctrl-R then =2+2<Enter> for the same result. If you don't find this syntax as impossibly awkward as I do, then this may well suit you for quick inline calculations personally, I'd drop to a shell and bust out bc for this.

Knowing your registers well isn't as profound a productivity boost as squelching a few of the other Vim anti-patterns , but it can certainly save you some of the annoyance of lost text. Posted in Vim Tagged advanced , black hole , expression , named , numbered , read-only , registers , unnamed Start Vim with splits Posted on September 11, 2012 by Tom Ryder If you want to call Vim to edit more than one file, you can add an option to the command line to open all of the buffers in split windows on startup:

Command line splits

The same can also be done for tabs:

Command line tabs Posted in Vim Tagged command line , option , splits , start , tabs

[Oct 31, 2017] Vim filename completion

Oct 31, 2017 | sanctum.geek.nz

Posted on February 1, 2012 by Tom Ryder The autocompletion for filenames in Vim in command mode is very useful, but by default it's a bit confusing for people accustomed to tab completion in Bash because it doesn't quite work the same way. Pressing Tab will complete the filename to the first match, and subsequent presses will not elicit any list of possible completions that might otherwise be expected; for that, by default you need to press Ctrl+D rather than Tab. Tab then tab

Fortunately, this is easily changed by using Vim's wildmenu , in an appropriate mode. Set the following options in your .vimrc :

set wildmenu
set wildmode=longest,list

You should now find that when you complete filenames after commands like :w and :e , the paths expand in a similar manner to the way they do in the shell. If you'd prefer to only press Tab once to get both the longest matching unique string and a list of possible complete matches, that's possible to arrange in both Bash and Vim as well.

Ignoring file types

There are probably certain filetypes in your directories that you'll never want to edit with Vim. There's hence no point in making them options for the autocompletion, and you can exclude them by pattern to make searching for the right file a bit quicker. This is done using the wildignore pattern. I use the following settings:

set wildignore+=*.a,*.o
set wildignore+=*.bmp,*.gif,*.ico,*.jpg,*.png
set wildignore+=.DS_Store,.git,.hg,.svn
set wildignore+=*~,*.swp,*.tmp
Compatibility

For the sake of keeping my .vimrc consistent and compatible on both older and newer machines, I like to wrap these options in a conditional block checking that the wildmenu feature is actually available:

" Wildmenu
if has("wildmenu")
    set wildignore+=*.a,*.o
    set wildignore+=*.bmp,*.gif,*.ico,*.jpg,*.png
    set wildignore+=.DS_Store,.git,.hg,.svn
    set wildignore+=*~,*.swp,*.tmp
    set wildmenu
    set wildmode=longest,list
endif
Insert mode

You can also complete file paths and names in insert mode with Ctrl+X Ctrl+F. It can be handy to map this to Tab if you don't use it for anything else:

inoremap <Tab> <C-X><C-F>

[Oct 31, 2017] Safely editing as root

Oct 31, 2017 | sanctum.geek.nz

Posted on February 2, 2012 by Tom Ryder Certain files on a UNIX-like system, such as /etc/passwd and /etc/sudoers , are integral for managing login and authentication, and it's thus necessary to be very careful while editing them using sudo not to accidentally leave them in a corrupted state, or to allow others to edit them at the same time as you. In the worst case scenario it's possible to lock yourself out of a system or out of root privileges in doing this, and things can only be fixed via physical access to the server or someone who knows the actual root password, which you may not necessarily know as a sudo user.

You should therefore never edit /etc/passwd , /etc/group , or /etc/sudoers by simply invoking them in your editor of choice. A set of simple utilities exist to help you make these edits safely.

vipw and vigr

If you want to safely edit the /etc/passwd file, for which you'll need to have root privileges, you should use the vipw tool. It doesn't require an argument.

# vipw

This will load a temporary copy of the file into your $EDITOR , and allow you to make changes. If all is well after you save and quit, you'll see a message like:

You have modified /etc/passwd.
You may need to modify /etc/shadow for consistency.
Please use the command 'vipw -s' to do so.

If you've made changes which might require changing something in the /etc/shadow file, you should follow these instructions too.

The command to edit groups, vigr , works in much the same way:

# vigr
visudo

The analogous tool for editing the /etc/sudoers file is visudo . This file not only does the necessary lock and file corruption checking as vipw does, it also does some basic checking of the syntax of the file after you save it.

# visudo

If the changes you make to this file work correctly, you'll simply be returned to your prompt. However, if you've made some sort of edit that means sudo won't be able to correctly parse the file, you'll get warned and prompted for an appropriate action:

visudo: >>> /etc/sudoers: syntax error near line 28 <<<
visudo: >>> /etc/sudoers: syntax error near line 29 <<<
visudo: >>> /etc/sudoers: syntax error near line 29 <<<
What now?

If you press ? here and then Enter, you'll get a list of the actions you can take:

Options are:
(e)dit sudoers file again
e(x)it without saving changes to sudoers file
(Q)uit and save changes to sudoers file (DANGER!)

You'll probably want the first one, to edit your changes again and make them work properly, but you may want to hose them and start again via the second option. You should only choose the third if you absolutely know what you're doing.

sudoedit

In general, you can edit root-owned files using sudoedit , or sudo -e , which will operate on temporary copies of the file and overwrite the original if changes are detected:

$ sudo -e /etc/network/interfaces

This has the added bonus of preserving all of your environment variables for the editing session, which may not be the case when invoking an editor and file via sudo . This turns out to be handy for newer versions of sudo which do not preserve the user's $HOME directory by default, meaning that configuration files for your editor, such as .vimrc , might not be read.

[Oct 31, 2017] Faster Vim search/replace by Tom Ryder

Apr 29, 2012 | sanctum.geek.nz

Entering search patterns and replacement strings in Vim can sometimes be a pain, particularly if the search or replacement text is already available in a register or under the cursor. There are a few ways to make working with search and replace in Vim quicker and less cumbersome for some common operations, and thereby save a bit of error-prone typing. Insert contents of a register

As in command mode or insert mode, you can insert the contents of any register by pressing Ctrl+R and then the register key. For example, to directly insert the contents of register a , you can type Ctrl+R and then a while typing a search pattern or replacement string.

Reference contents of a register

Similarly, if you want to use the contents of a register in a pattern or replacement but don't want to directly insert it, you can instead reference the contents of register a with \=@a :

:s/search/\=@a/

Both of the above tips work for both the search and replacement patterns, and for special registers like " (default unnamed register) and / (last searched text) as well as the alphabetical ones.

Insert word under cursor

If you happen to be hovering over a word that you want to use as as a search or replacement string, as a special case of the above you can do so by typing Ctrl+R and then Ctrl+W for a normal word, or Ctrl+R and then Ctrl+A for a space-delimited word.

Empty search string

You can use the previous search as a search pattern or replacement string by including it from the special / register, in the same way as any other register above, by inserting it with Ctrl+R and then / , or representing it with \=@/ . There's a convenient shorthand for this however in just using an empty search string:

:s//replacement/

This will replace all occurences of the previous search string with replacement . It turns out to be a particularly convenient shorthand when searching for words by pressing * or # .

[Oct 31, 2017] Advanced Vim macros by Tom Ryder

Notable quotes:
"... macros are just text ..."
"... Thanks to user bairui for suggesting a safer alternative for yanking macro lines from buffers, which I've changed. He's written a whole blog post replying to this one. It's a good read if you're interested in going in to even more depth about when to use macros in Vim. ..."
Jun 04, 2012 | sanctum.geek.nz

Vim's massive command set in both normal and command mode makes the concept of a macro especially powerful. Most Vim users, if they ever use macros at all, will perhaps quickly record an edit to one line, starting with qq and finishing with q , executing with @q , and otherwise never give the concept much thought.

For slightly more advanced Vim users, macros may be more frequently useful, but they perhaps still believe that macros are a niche Vim function unto themselves, and not really open to the deft manipulation of text that pretty much everything else in Vim is.

As is typical in Vim, the rabbit hole of functionality goes much deeper than most users will ever plumb.

Vanilla Vim macros

Suppose I had a plaintext table loaded into a Vim buffer containing the name, subject matter expertise, birth year, and nationality of a few well-known programmers:

Stallman  Richard GNU 1953  USA
Wall  Larry   Perl  1954  USA
Moolenar  Bram  Vim 1961  Netherlands
Tridgell  Andrew  Samba  1967  Australia
Matsumoto  Yukihiro  Ruby  1965  Japan
Ritchie  Dennis  C  1941  USA
Thompson  Ken  Unix  1943  USA

Actually, that's kind of untidy. Let's start by formatting it a bit, by running it through Unix's column tool.

:%!column -t

Stallman   Richard   GNU    1953  USA
Wall       Larry     Perl   1954  USA
Moolenar   Bram      Vim    1961  Netherlands
Tridgell   Andrew    Samba  1967  Australia
Matsumoto  Yukihiro  Ruby   1965  Japan
Ritchie    Dennis    C      1941  USA
Thompson   Ken       Unix   1943  USA

May as well sort it by surname too:

:%!sort -k1

Matsumoto  Yukihiro  Ruby   1965  Japan
Moolenar   Bram      Vim    1961  Netherlands
Ritchie    Dennis    C      1941  USA
Stallman   Richard   GNU    1953  USA
Thompson   Ken       Unix   1943  USA
Tridgell   Andrew    Samba  1967  Australia
Wall       Larry     Perl   1954  USA

That's better.

Now, suppose we've got the task of replacing the fourth column of this table with the approximate age of the person, which we can get naturally enough by sutracting their birth year from the current year. This is a little awkward to do in pure ex, so we'll record a macro for doing it on one line.

Experimenting a bit, we find that the following works well:

03wdei^R=2012-^R"^M^[0j

Broken down, this does the following:

So we record it into a macro a (to stand for "age", no other reason) as we fix up the first line:

qa03wdei^R=2012-^R"^M^[0jq

Matsumoto  Yukihiro  Ruby   47  Japan
Moolenar   Bram      Vim    1961  Netherlands
Ritchie    Dennis    C      1941  USA
Stallman   Richard   GNU    1953  USA
Thompson   Ken       Unix   1943  USA
Tridgell   Andrew    Samba  1967  Australia
Wall       Larry     Perl   1954  USA

This now means that for each line, we can run the macro by just tapping @a a few times:

Matsumoto  Yukihiro  Ruby   47  Japan
Moolenar   Bram      Vim    51  Netherlands
Ritchie    Dennis    C      71  USA
Stallman   Richard   GNU    59  USA
Thompson   Ken       Unix   69  USA
Tridgell   Andrew    Samba  45  Australia
Wall       Larry     Perl   58  USA

That's all pretty stock-standard macro stuff that you'll likely have learned in other tutorials. The only thing that's slightly voodoo (and certainly not vi-compatible) is the arithmetic done with the special = register. You can read about that in :help @= , if you're curious.

Repeating Vim macros

As a first very simple hint, if you're running a macro several times, don't forget that you can prepend a count to it; in our case, 6@a would have fixed up all the remaining lines. To take advantage of this, it's good practice to compose your macros so that they make sense when run multiple times; in the example above, note that the end of the macro is moving down onto the next line, ready to run the macro again if appropriate.

Similarly, if you've already run a macro once, you can run the same one again by just tapping the @ key twice, @@ . This repeats the last run macro. Again, you can prepend a count to this, @a5@@ .

The true nature of Vim macros

The registers that hold macros are the same registers that you probably use more frequently for operations like deleting, yanking, and pasting. Running a macro is simply instructing Vim to take the contents of a register and execute them as keystrokes, as if you were actually typing them. Thinking about macros this way has a couple of interesting consequences.

First of all, it means you needn't restrict yourself to the single-keystroke vi commands for Vim when you compose macros. You can include ex commands as well, for example to run a substitution during a macro:

qb:s/foo/bar/g^Mq
@b

Secondly, and more interestingly, all of the operations that you can apply to registers in general work with what we normally call macros, with the old standards, delete, yank, and paste. You can test this with the example macro demonstrated above, by typing "ap , which will dump the raw text straight into the buffer. Also like other registers, it'll show up in the output of the :registers command.

All this means is that like everything else in Vim, macros are just text , and all of Vim's clever tools can be used to work with them.

Editing Vim macros in a buffer

If you've used macros even a little bit you'll be very familiar with how frustrating they are to record. For some reason, as soon as you press qa to start recording a macro into register a , your normal fluency with Vim commands goes out the window and you keep making mistakes that will make the macro unsuitable to apply.

So, don't compose macros on the fly. Just stop doing it. I recommend that if a macro is more than three keystrokes, you should compose it directly in a scratch Vim buffer so that you can test it iteratively.

Here's an example using the macro above; suppose I realise partway through writing it that I made a mistake in typing 2011 instead of 2012. I finish recording the rest of the macro anyway, and dump the broken keystrokes into a new scratch buffer:

:enew
"ap

This gives me the contents of the macro in plain text in the buffer:

qa03wdei^R=2011-^R"^M^[0jq

So now all I have to do is change that bad year to 2012, and then yank the whole thing back into register a :

^"ay$

Now I can test it directly with @a on the appropriate file, and if it's still wrong, I just jump back to my scratch buffer and keep fixing it up until it works.

One potential snag here is that you have to enter keystrokes like Ctrl+R as literal characters, but once you know you can enter any keystroke in Vim literally in insert or command mode by prefixing it with Ctrl+V, that isn't really a problem. So to enter a literal Ctrl+R in insert mode, you type Ctrl+V, then Ctrl+R.

Running a Vim macro on a set of lines

It's occasionally handy to be able to run a macro that you've got ready on a specific subset of lines of the file, or perhaps just for every line. Fortunately, there's a way to do this, too.

Using the :normal command, you're able to run macros from the ex command line:

:normal @a

All it takes is prefixing this with any sort of range definition to allow you to run a macro on any set of lines that you're able to define.

Run the macro on each line of the whole buffer:

:% normal @a

Between lines 10 and 20:

:10,20 normal @a

On the lines in the current visual selection:

:'<,'> normal @a

On the lines containing the pattern vim:

:g/vim/ normal @a

When you get confident using this, :norm is a nice abbreviation to use.

Moving a Vim macro into a function

For really useful macros of your own devising, it's occasionally handy to put it into a function for use in scripts or keystroke mappings. Here again the :normal command comes in handy.

Suppose I wanted to keep the age calculation macro defined above for later use on spreadsheets of this kind. I'd start by dumping it into a new buffer:

:enew
"ap

The macro appears as raw text:

03wdei^R=2012-^R"^M^[0j

I prefix it with a :normal call, and wrap a function definition around it:

function! CalculateAge()
    normal 03wdei^R=2012-^R"^M^[0j 
endfunction

Then all I need to do is include that in a file that gets loaded during Vim's startup, possibly just .vimrc . I can call it directly from ex:

:call CalculateAge()

But given that I wanted it to be a quick-access macro, maybe it's better to bind it to \a , or whatever your chosen <leader> character is:

nnoremap <leader>a :call CalculateAge()<CR>
Saving a Vim macro

If you want to have a macro always available to you, that is, always loaded into the appropriate register at startup, that can be done in your .vimrc file with a call to let to fill the register with the literal characters required:

let @a='03wdei^R=2012-^R"^M^[0j'
Appending extra keystrokes to a Vim macro

If you just want to tack extra keystrokes onto an existing macro and don't care to edit it in a Vim buffer, you can do that by recording into it with its capital letter equivalent. So, if you wanted to add more keystrokes into the register b , start recording with qB , and finish with the usual q .

Recursive Vim macros

If you're crazy enough to need this, and I never have, there's an excellent Vim Tip for it. But personally, I think if you need recursion in your text processing then it's time to bust out a real programming language and not Vimscript to solve your problem.

If the issue for which you think you need recursion is running a macro on every line of a buffer with an arbitrary number of lines, then you don't need recursion; just record a one-line version of the macro and call it with :% normal @a to run it on every line.

Vim macro gotchas

Here are a few gotchas which will save you some frustration if you know about them ahead of time:

Thanks to user bairui for suggesting a safer alternative for yanking macro lines from buffers, which I've changed. He's written a whole blog post replying to this one. It's a good read if you're interested in going in to even more depth about when to use macros in Vim. Posted in Vim Tagged advanced , copy , functions , keep , macros , normal , paste , preserve , registers , vimrc , yank

[Oct 31, 2017] Local .vimrc files by Tom Ryder

May 26, 2012 | sanctum.geek.nz

If you can, it's a good idea to set up your .vimrc file using conditionals so that it's compatible on all of the systems with which you need to work. Using one .vimrc file enables you to include it as part of a centralized set of dotfiles that you can keep under version control .

However, if on a particular machine there's a special case which means you need to load some Vim directives for that machine, you can achieve this by way of a local Vim file kept in .vimrc.local , only on one particular machine, and detecting its existence before attempting to load it in your master .vimrc file with the following stanza:

if filereadable(glob("~/.vimrc.local")) 
    source ~/.vimrc.local
endif

As an example, on one of the nameservers that I manage, I wanted to make sure that the correct filetype was loaded when editing zone files ending in .nz or .au for New Zealand and Australian domains. The following line in .vimrc.local did the trick:

autocmd BufNewFile,BufRead *.au,*.nz set filetype=bindzone

If the .vimrc.local file doesn't exist on any particular machine, Vim will simply not attempt to load it on startup.

Besides machine-specific code, this kind of setup may be advisable if you keep secret or potentially sensitive information in your .vimrc file that you wouldn't want published to a public version control tracker like GitHub, such as API keys, usernames, machine hostnames, or network paths.

[Oct 31, 2017] Vim eval feature by Tom Ryder

Jul 19, 2012 | sanctum.geek.nz

Using your .vimrc file on many machines with different versions and feature sets for Vim is generally not too much of a problem if you apply a little care in making a gracefully degrading .vimrc . In most cases, using the output of vim --version and checking the help files will tell you what features to check in order to determine which parts of your .vimrc configuration to load, and which to ignore.

There's one particular feature that's less obvious, though, and that's eval . Vim's help describes it like this in :help +eval :

N  *+eval*      expression evaluation |eval.txt|

The eval.txt document, in turn, describes the syntax for various features fundamental to Vimscript, including variables, functions, lists, and dictionaries.

All this makes eval perhaps the most central feature of Vim. Without it, Vim doesn't have much of its programmable nature, and remains not much more than classic vi . If your particular build of Vim doesn't include it, then Vimscript essentially does not work as a programming language, and elementary calls like function and let will throw errors:

E319: Sorry, the command is not available in this version: function
E319: Sorry, the command is not available in this version: let

If you're getting this kind of error, you're probably using a very stripped-down version of Vim that doesn't include eval . If you just want to prevent the error by ignoring a block of code if the feature is unavailable, you can do this with has() :

if has("eval")
    ...
endif

Vim will still be perfectly functional as a vi -style editor without +eval , but if you're going to need any Vimscript at all, you should recompile Vim with a --with-features value for the ./configure line that does include it, such as normal , big , or huge , or install a more fully-featured packaged version. For example, on Debian-like systems, the vim-tiny package that is included in the netinst system does not include eval , but the vim and vim-runtime packages do.

Inspecting Vim's source, in particular the ex_docmd.c file, gives some indication of how fundamental this feature is, applying the C function ex_ni which simply prints the "not available" error shown above to a large number of control structures and statements if the FEAT_EVAL constant is not defined:

#ifndef FEAT_EVAL
# define ex_scriptnames     ex_ni
# define ex_finish      ex_ni
# define ex_echo        ex_ni
# define ex_echohl      ex_ni
# define ex_execute     ex_ni
# define ex_call        ex_ni
# define ex_if          ex_ni
# define ex_endif       ex_ni
# define ex_else        ex_ni
# define ex_while       ex_ni
# define ex_continue        ex_ni
# define ex_break       ex_ni
# define ex_endwhile        ex_ni
# define ex_throw       ex_ni
# define ex_try         ex_ni
# define ex_catch       ex_ni
# define ex_finally     ex_ni
# define ex_endtry      ex_ni
# define ex_endfunction     ex_ni
# define ex_let         ex_ni
# define ex_unlet       ex_ni
# define ex_lockvar     ex_ni
# define ex_unlockvar       ex_ni
# define ex_function        ex_ni
# define ex_delfunction     ex_ni
# define ex_return      ex_ni
# define ex_oldfiles        ex_ni
#endif

[Oct 31, 2017] Vim misconceptions by Tom Ryder

Jul 19, 2012 | sanctum.geek.nz

Vim isn't the best tool for every task, and there's no reason you shouldn't stick to your GUI IDE if you know it like the back of your hand and are highly productive in it. The very basic best practices for text editing in general apply just as well to more familiar editing interfaces as they do to Vim, so nobody should be telling you that Vim is right for everyone and everything and that you're wrong not to use it.

However, because Vim and vi -like editors in general have a lot of trouble shaking off the connotations of their serverside, terminal-only, mouseless past, there are a few persistent objections to even trying Vim that seem to keep cropping up. If you're someone curious about Vim but you heard it was useless for any of the following reasons, or if you're an experienced user looking to convince a hesitant neophyte to try Vim, the following list might clear a few things up.

Vim takes too long to learn

If you want analogues to all of the features in your IDE, that would likely take some time, just as it would in any other new editor. However, if all you need to start is to be able to enter text, move around, and load and save files, you just need to know:

To do pretty much everything Windows Notepad would let you do, on top of that you'd only need to learn:

From that point, you only get faster as you learn how to do new things. So saying that Vim takes weeks to learn is a bit disingenuous when the essentials can easily be mastered with a few minutes' practice.

Granted, the arrow keys are a bit of an anti-pattern , but you can worry about that later.

Vim has no GUI

Vim has a GUI version called Gvim for both Windows and Unix. For Mac OS X, the MacVim port is preferred. For experienced users the GUI's only real advantage over the terminal version is a wider color palette, but it has a toolbar and other GUI elements which some new users may find useful.

Vim doesn't have spell checking

Vim allows spell checking with system dictionaries, using :set spell and :set spelllang . Misspelt and unknown words are highlighted appropriately.

Vim doesn't have syntax highlighting

Vim has support for syntax highlighting that can be turned on with :syntax enable , for a very wide variety of programming languages, markup languages, and configuration file syntaxes.

Vim only allows eight colours

This is a limitation of terminal emulators rather than of Vim itself, but most modern GUI terminal emulators allow 256 colours anyway with a little extra setup. The GUI version, Gvim, has full color support with the familiar rrggbb color definitions.

Vim doesn't have class/function folding

Vim does in fact have support for folding , based on both code structure and manually defined boundaries. See :help folding for details.

Vim doesn't have autocompletion

Vim allows basic completion using words already in the current buffer, and also more advanced omnicompletion using language dictionaries for constants, variables, classes, and functions.

Vim doesn't have a file browser

Vim has had the Netrw plugin bundled for some time, which provides a pretty capable filesystem browser.

Vim can't do network editing

Again, the bundled Netrw plugin handles this. Editing files over FTP and SCP links is pretty transparent. You can open a file on a remote server by entering the following, which will prompt for your username and password:

:e ftp://ftp.example.com/index.html

When you're done editing, you just enter :w to save the file, and it's automatically uploaded for you. You can record your FTP credentials in a .netrc file to save having to type in usernames and passwords all the time. URIs with scp:// work the same way; with a good public key infrastructure set up, you can use Vim quite freely as a network-transparent editor.

Vim doesn't have tabs or windows

The model Vim uses for tabs and windows is rather different from most GUI editors, but both are supported and have been for some time.

Vim has too many modes

It has three major modes: normal mode, insert mode, and command mode. There's a fourth that's Vim-specific, called visual mode, for selecting text.

Most editors are modal in at least some respect; when you bring up a dialog box, or enter a prefix key to another command, you're effectively changing modes. The only real difference is that context shifts in Vim are at first less obvious; the screen doesn't look too different between normal, insert, and command mode.

The showmode option helps to distinguish between insert and normal mode, a common frustration for beginners. This gets easier when you get into the habit of staying out of insert mode when not actually entering text.

Vim doesn't work with the mouse

Vim works fine with the mouse , in both Gvim and xterm -like terminal emulators, if you really want it. You can change the position of the cursor, scroll through the document, and select text as normal. Setting the below generally does the trick:

:set mouse=a

However, even a little experience in Vim may show you that you don't need the mouse as much as you think. Careful use of the keyboard allows much more speed and precision, and it's quite easy to run a complex editing session without even moving from the keyboard's "home row", let alone all the way over to the mouse.

Vim doesn't do Unicode

Vim supports Unicode encodings with the encoding option. It's likely you'll only need to put the below in your .vimrc file and then never really think about encoding in your editor again:

:set encoding=utf-8
Vim isn't being developed or maintained

The original author of Vim, and its current maintainer and release manager, is Bram Moolenaar . At the time of writing, he is working for Google, and is paid to spend some of his time developing Vim. The development mailing list for Vim is very active, and patches are submitted and applied to the publically accessible Mercurial repository on a regular basis. Vim is not a dead project.

Vim is closed source

Vim isn't proprietary or closed source, and never has been. It uses its own GPL-compatible license called the Vim license .

The original vi used to be proprietary because Bill Joy based the code on the classic UNIX text editor ed , but its source code has now been released under a BSD-style license.

[Oct 31, 2017] Vim annoyances by Tom Ryder

Notable quotes:
"... Several of these fixes were inspired by Steve Losh's .vimrc file . Thanks also to commenters Alpha Chen and Rob Hoelz for suggestions. ..."
Aug 02, 2012 | sanctum.geek.nz

Like any highly interactive application, Vim has a few annoyances even for experienced users. Most of these consist of the editor doing something unexpected, particularly with motions or the behavior of regular expressions and registers. This is often due to vi and Vim being such venerable editors; their defaults sometimes make less sense decades after their creation.

Fortunately, Vim being the configurable editor that it is, many of the more common annoyances can be easily worked around. Bear in mind that not all of these are necessarily problems; if you actually prefer the way something behaves, you should stick with it.

Cursor jumps around while joining lines

If you want to keep the cursor in place when you join lines with J , you can do this, dropping a mark before the operation to which you return afterwards:

nnoremap J mzJ`z
Jumping lands on top or bottom of screen

If you'd like to center the window automatically around the cursor after jumping to a location with motions like n (next search pattern occurrence) or } (end of next paragraph), you can arrange that by remapping to add a zz after the motion:

nnoremap n nzz
nnoremap } }zz

If you don't need the jump to land you in the exact middle of the screen, but just don't want it to land right at the edge, you could also use scrolloff :

set scrolloff=10

Note that this also starts scrolling the window with single-line movements like j and k at this boundary, too, which you may not want.

Skipping lines when wrap is set

By default, the j and k keys don't move by row ; they move by line . This means that if you have the wrap option set, you might skip across several rows to reach the same point in an adjacent line.

This can be frustrating if you prefer the more intuitive behavior of moving up to the character immediately above the current one. If you don't like this behavior, you can fix it by mapping j to gj , and k to gk , which moves by rows rather than lines:

nnoremap j gj
nnoremap k gk

If you think you might need the default behavior at some point, you might want to include reverse mappings so you can move linewise with gj and gk :

nnoremap gj j
nnoremap gk k
Wrapping breaks words

By default, setting wrap displays lines by breaking words if necessary. You can force it to preserve words instead by only breaking at certain characters:

set linebreak

You can define the characters at which Vim should be allowed to break lines with the breakat option. By default this includes spaces and tabs.

Backup files are a nuisance

If you're developing with a version control system, you might find the in-place backups Vim keeps for saved files with the ~ suffix more annoying than useful. You can turn them off completely with nobackup :

set nobackup

Alternatively, you can set a single directory for them to keep them out of the way with backupdir :

set backupdir=~/.vim/backup
Swap files are a nuisance

Swap files can be similarly annoying, and unnecessary on systems with a lot of memory. If you don't need them, you can turn them off completely:

set noswapfile

If you do find the swap files useful but want to prevent them cluttering your current directory, you can set a directory for them with directory :

set directory=~/.vim/swap
Accidentally hitting unwanted keys in normal mode

Some of the keys in normal mode bring up functions that aren't terribly useful to a lot of people, and tend to accidentally get hit when Caps Lock is on, or when aiming for another key. Common nuisance keys are:

The simplest way to deal with these is to remap them to <nop> so that they don't do anything:

nnoremap <F1> <nop>
nnoremap Q <nop>
nnoremap K <nop>
Startup message is irritating

If you don't like the startup message that appears when you open Vim without a filename, you can remove it by adding the I flag to shortmess :

set shortmess+=I
Can't backspace past start of operation

If you're in insert mode, by default you can't use backspace to delete text past the start of the insert operation; that is, you can't backspace over where you first pressed insert. This is old vi behavior, and if you don't like it, you can make backspace work everywhere instead:

set backspace=indent,eol,start
Flashing screen is annoying

If you don't require the error feedback, you can turn off the flashing screen for the "visual bell":

set visualbell t_vb=
Don't know what mode I'm in

If you lose track of the current mode, you can get a convenient --INSERT-- indicator at the bottom of the screen with:

set showmode

If you're having this problem a lot, however, you might want to take stock of how much time you're spending in insert mode when you're not actively typing; it's good Vim practice to stay out of it otherwise, even when you stop to think.

Keep making typos of common commands

If you're fat-fingering :wq and similar commands a lot due to a sticky shift key, take a look at the Vim command typos fix. Also, don't forget about ZZ and ZQ as quicker alternatives to :wq and :q! .

Don't want case sensitive patterns

If you don't care for case-sensitive searches and substitutions, you can turn it off completely:

set ignorecase

You might find the slightly cleverer behavior of smartcase is better, though. This option only applies case sensitivity if at least one of the letters in the pattern is uppercase; otherwise, case is ignored.

set smartcase
Doesn't replace all occurrences

The default behavior for the substitute operation, :s/pattern/replacement/ , is to replace only the first occurrence of the pattern. To make it replace all occurrences on the appropriate lines, you add the g suffix. If you find that you never need to substitute for only the first occurrence of a pattern in a line, you can add that flag to the patterns by default:

set gdefault

If you do happen to need to replace only the first occurrence one day, you can get the default behavior back by adding the g suffix to your pattern; its meaning is reversed by this option.

Can't move into blank space in visual block mode

If you need to define a block in visual block mode with bounds outside the actual text (that is, past the end of lines), you can allow this with:

set virtualedit=block

This will let you move around the screen freely while in visual block mode to define your selections. As an example, this can make selecting the contents of the last column in a formatted table much easier.

Filename completion on command line is confusing

If you're used to the behavior of shell autocomplete functions for completing filenames, you can emulate it in Vim's command mode:

set wildmode=longest,list

With this set, the first Tab press (or whatever your wildchar is set to) will expand a filename or command in command mode to the longest common string it can, and a second press will display a list of all possible completions above the command line.

Yanking lines is inconsistent

D deletes from the cursor to the end of the line; C changes from the cursor to the end of the line. For some reason, however, Y yanks the entire line, both before and after the cursor. If this inconsistency bothers you, you can fix it with a remapping:

nnoremap Y y$
New splits appear in unintuitive places

If your language of choice is read from left to right, you may find it annoying that by default Vim places new vertical splits to the left of the current pane, and horizontal splits above the current pane. You can fix both:

set splitbelow
set splitright
Caps Lock sends Vim crazy

Caps Lock in normal mode makes Vim go haywire. This isn't really Vim's fault; Caps Lock is generally a pretty useless key. It's often useful for Vim users to remap it , so that it sends the same signal as a more useful key; Control and Escape are common choices. You might even find this reduces strain on your hands.

Several of these fixes were inspired by Steve Losh's .vimrc file . Thanks also to commenters Alpha Chen and Rob Hoelz for suggestions.

[Oct 31, 2017] Shell from vi by Tom Ryder

Feb 18, 2017 | sanctum.geek.nz

A good sign of a philosophically sound interactive Unix tool is the facilities it offers for interacting with the filesystem and the shell: specifically, how easily can you run file operations and/or shell commands with reference to data within the tool? The more straightforward this is, the more likely the tool will fit neatly into a terminal-driven Unix workflow.

If all else fails, you could always suspend the task with Ctrl+Z to drop to a shell, but it's helpful if the tool shows more deference to the shell than that; it means you can use and (even more importantly) write tools to manipulate the data in the program in whatever languages you choose, rather than being forced to use any kind of heretical internal scripting language, or worse, an over-engineered API.

vi is a good example of a tool that interacts openly and easily with the Unix shell, allowing you to pass open buffers as streams of text transparently to classic filter and text processing tools. In the case of Vim, it's particularly useful to get to know these, because in many cases they allow you to avoid painful Vimscript, and to do things your way, without having to learn an ad-hoc language or to rely on plugins. This was touched on briefly in the "Editing" article of the Unix as IDE series.

Choosing your shell

By default, vi will use the value of your SHELL environment variable as the shell in which your commands will be run. In most cases, this is probably what you want, but it might pay to check before you start:

:set shell?

If you're using Bash, and this prints /bin/bash , you're good to go, and you'll be able to use Bash-specific features or builtins such as [[ comfortably in your command lines if you wish.

Running commands

You can run a shell command from vi with the ! ex command. This is inherited from the same behaviour in ed . A good example would be to read a manual page in the same terminal window without exiting or suspending vi :

:!man grep

Or to build your project:

:!make

You'll find that exclamation point prefix ! shows up in the context of running external commands pretty consistently in vi .

You will probably need to press Enter afterwards to return to vi . This is to allow you to read any output remaining on your screen.

Of course, that's not the only way to do it; you may prefer to drop to a forked shell with :sh , or suspend vi with ^Z to get back to the original shell, resuming it later with fg .

You can refer to the current buffer's filename in the command with % , but be aware that this may cause escaping problems for files with special characters in their names:

:!gcc % -o foo

If you want a literal % , you will need to escape it with a backslash:

:!grep \% .vimrc

The same applies for the # character, for the alternate buffer .

:!gcc # -o bar
:!grep \# .vimrc

And for the ! character, which expands to the previous command:

:!echo !
:!echo \!

You can try to work around special characters for these expansions by single-quoting them:

:!gcc '%' -o foo
:!gcc '#' -o bar

But that's still imperfect for files with apostrophes in their names. In Vim (but not vi ) you can do this:

:exe "!gcc " . shellescape(expand("%")) . " -o foo"

The Vim help for this is at :help :! .

Reading the output of commands into a buffer

Also inherited from ed is reading the output of commands into a buffer, which is done by giving a command starting with ! as the argument to :r :

:r !grep vim .vimrc

This will insert the output of the command after the current line position in the buffer; it works in the same way as reading in a file directly.

You can add a line number prefix to :r to place the output after that line number:

:5r !grep vim .vimrc

To put the output at the very start of the file, a line number of 0 works:

:0r !grep vim .vimrc

And for the very end of the file, you'd use $ :

:$r !grep vim .vimrc

Note that redirections work fine, too, if you want to prevent stderr from being written to your buffer in the case of errors:

:$r !grep vim .vimrc 2>>vim_errorlog
Writing buffer text into a command

To run a command with standard input coming from text in your buffer, but without deleting it or writing the output back into your buffer, you can provide a ! command as an argument to :w . Again, this behaviour is inherited from ed .

By default, the whole buffer is written to the command; you might initially expect that only the current line would be written, but this makes sense if you consider the usual behaviour of w when writing directly to a file.

Given a file with a first column full of numbers:

304 Donald Trump
227 Hillary Clinton
3   Colin Powell
1   Spotted Eagle
1   Ron Paul
1   John Kasich
1   Bernie Sanders

We could calculate and view (but not save) the sum of the first column with awk(1) , to see the expected value of 538 printed to the terminal:

:w !awk '{sum+=$1}END{print sum}'

We could limit the operation to the faithless electoral votes by specifying a line range:

:3,$w !awk '{sum+=$1}END{print sum}'

You can also give a range of just . , if you only want to write out the current line.

In Vim, if you're using visual mode, pressing : while you have some text selected will automatically add the '<,'> range marks for you, and you can write out the rest of the command:

:'<,'>w !grep Bernie

Note that this writes every line of your selection to the command, not merely the characters you have selected. It's more intuitive to use visual line mode (Shift+V) if you take this approach.

Filtering text

If you want to replace text in your buffer by filtering it through a command, you can do this by providing a range to the ! command:

:1,2!tr '[:lower:]' '[:upper:]'

This example would capitalise the letters in the first two lines of the buffer, passing them as input to the command and replacing them with the command's output.

304 DONALD TRUMP
227 HILLARY CLINTON
3 Colin Powell
1 Spotted Eagle
1 Ron Paul
1 John Kasich
1 Bernie Sanders

Note that the number of lines passed as input need not match the number of lines of output. The length of the buffer can change. Note also that by default any stderr is included; you may want to redirect that away.

You can specify the entire file for such a filter with % :

:%!tr '[:lower:]' '[:upper:]'

As before, the current line must be explicitly specified with . if you want to use only that as input, otherwise you'll just be running the command with no buffer interaction at all, per the first heading of this article:

:.!tr '[:lower:]' '[:upper:]'

You can also use ! as a motion rather than an ex command on a range of lines, by pressing ! in normal mode and then a motion ( w , 3w , } , etc) to select all the lines you want to pass through the filter. Doubling it ( !! ) filters the current line, in a similar way to the yy and dd shortcuts, and you can provide a numeric prefix (e.g. 3!! ) to specify a number of lines from the current line.

This is an example of a general approach that will work with any POSIX-compliant version of vi . In Vim, you have the gU command available to coerce text to uppercase, but this is not available in vanilla vi ; the best you have is the tilde command ~ to toggle the case of the character under the cursor. tr(1) , however, is specified by POSIX–including the locale-aware transformation–so you are much more likely to find it works on any modern Unix system.

If you end up needing such a command during editing a lot, you could make a generic command for your private bindir , say named upp for uppercase, that forces all of its standard input to uppercase:

#!/bin/sh
tr '[:lower:]' '[:upper:]'

Once saved somewhere in $PATH and made executable, this would allow you simply to write the following to apply the filter to the entire buffer:

:%!upp

The main takeaway from this is that the scripts you use with your editor don't have to be in shell. You might prefer Awk :

#!/usr/bin/awk -f
{ print toupper($0) }

Or Perl :

#!/usr/bin/env perl
print uc while <>;

Or Python, or Ruby, or Rust , or

Incidentally, this "filtering" feature is where vi 's heritage from ed ends as far as external commands are concerned. In POSIX ed , there isn't a way to filter buffer text through a command in one hit. It's not too hard to emulate it with a temporary file, though, using all the syntax learned above:

*1,2w !upp > tmp
*1,2d
*0r tmp
*!rm tmp

[Oct 31, 2017] Vim search highlighting by Tom Ryder

Jan 21, 201 | sanctum.geek.nz

Being able to search by regular expression is a pretty fundamental thing in a text editor. Vim takes it to the next level by making entering a search into a motion all on its own, and even a few weeks' Vim experience and you'll probably catch yourself using the search to navigate your buffers.

One of the things I most commonly see recommended in threads and discussions about useful Vim features includes turning on two kinds of search highlighting: first, highlighting the search result on which you'll land as you type it, and secondly, once you've pressed Enter to run your search, highlighting all of the matches. You turn these on like this:

:set incsearch
:set hlsearch

This ends up being great for editing code in particular, because if you search for variable or function names, you can see at a glance where they're declared, defined, or used in your code. Couple that with the quick forward and backward search that you can do with the * and # keys, and you have a very convenient way to flick through successive uses of an identifier.

The only snag, really, is that it doesn't turn itself off, and it gets visually distracting when you've moved on from whatever task prompted the search, and because you might search to move around, you don't always actually want the highlighting to stay there. Text editors following a Windows model would probably clear away the highlighting as soon as you close the search box, or insert some text. This isn't the case with Vim, which can be good or bad, but most people I've spoken to about this feature seem to find it annoying.

Bram Moolenar, the author of Vim, addressed this very topic in a Google Tech Talk he gave about effective text editing . You can turn off the highlighting temporarily by typing:

:nohlsearch

This is different from :set nohlsearch in that it doesn't permanently disable the highlighting. It'll turn it on next time you search. I find this is kind of a pain to type, so I alias it to Ctrl+L in my .vimrc file, so that in addition to its default behaviour of clearing the screen it clears the search highlighting as well:

nnoremap <C-l> :nohlsearch<CR><C-l>

Additionally, I like to set leader keys to quickly turn the highlighting option on and off completely if for some particular project it's just thoroughly unhelpful. In this example, typing \i and \h will toggle the incsearch and hlsearch settings on and off, respectively. I'm assuming you're using the backslash key as your <leader> here.

nnoremap <leader>i :set incsearch!<CR>
nnoremap <leader>h :set hlsearch!<CR>

Finally, I find that while I'm in insert mode, I usually don't want to see the highlighting, so I define events to turn the highlighting off temporarily in the current buffer while I'm inserting text:

autocmd InsertEnter * :setlocal nohlsearch
autocmd InsertLeave * :setlocal hlsearch

I find these shortcuts make the search highlighting behaviour much less annoying. Interestingly, according to Vim's help, you can't simply add an event hook to run :nohlsearch when you enter Insert mode (from :help nohlsearch ):

This command doesn't work in an autocommand, because the highlighting state is saved and restored when executing autocommands. Same thing for when invoking a user function.

You can work around this by setting the search pattern to empty instead, as suggested by this Stack Overflow answer , but I don't really like doing that because I often like to recurse through more search results with n and N after leaving insert mode.

[Oct 31, 2017] Buffers, windows, and tabs by Tom Ryder

Notable quotes:
"... open instance of a file ..."
"... viewport onto a single buffer ..."
"... collection of one or more windows ..."
"... Thanks to Hacker News users anonymous and m0shen for pointing out potential confusion with the :set hidden option and the :bdelete command. ..."
Jan 22, 2012 | sanctum.geek.nz

Posted on If you've moved to Vim from an editor like Notepad++ or TextMate, you'll be used to working with the idea of tabs in a text editor in a certain way. Specifically, a tab represents an open file; while the tab's there, you've got an open file, as soon as you close it, it goes away. This one-to-one correspondence is pretty straightforward and is analogous to using tabs in a web browser; while the page is open, there's a tab there, and you have one page per tab, and one tab per page.

Vim has a system for tabs as well, but it works in a completely different way from how text editors and browsers do. Beginners with Vim are often frustrated by this because the model for tabs is used so consistently in pretty much every other program they're accustomed to, and they might end up spending a lot of fruitless time trying to force Vim to follow the same model through its configuration.

I think a good way to understand the differences in concept and usage between Vim's three levels of view abstraction -- buffers windows , and tabs -- is to learn how to use each from the ground up. So let's start with buffers.

Buffers

A buffer in Vim is probably best thought of for most users as an open instance of a file , that may not necessarily be visible on the current screen. There's probably a more accurate technical definition as a buffer need not actually correspond to a file on your disk, but it'll work for our purposes.

When you open a single file in Vim, that file gets put into a buffer, and it's the only buffer there on startup. If this buffer is unmodified (or if you're using hidden ), and you open another file with :edit , that buffer goes into the background and you start working with the new file. The previous buffer only goes away when you explicitly delete it with a call to :quit or :bdelete , and even then it's still recoverable unless you do :bwipe .

By default, a buffer can only be in the background like this if it's unmodified. You can remove this restriction if you like with the :set hidden option.

You can get a quick list of the buffers open in a Vim session with :ls . This all means that when most people think of tabs in more familiar text editors, the idea of a buffer in Vim is actually closest to what they're thinking.

Windows

A window in Vim is a viewport onto a single buffer . When you open a new window with :split or :vsplit , you can include a filename in the call. This opens the file in a new buffer, and then opens a new window as a view onto it. A buffer can be viewed in multiple windows within a single Vim session; you could have a hundred windows editing the same buffer if you wanted to.

Windows in Vim

Vim Session with multiple windows open, both horizontally and vertically. Tabs

Finally, a tab in Vim is a collection of one or more windows . The best way to think of tabs, therefore, is as enabling you to group windows usefully. For example, if you were working on code for both a client program and a server program, you could have the files for the client program open in the first tab, perhaps in three or four windows, and the files for the server program open in another, which could be, say, seven windows. You can then flick back and forth between the tabs using :tabn and :tabp .

Tab usage in Vim

Two tabs open in Vim, each with multiple windows. Move between two tabs with :tabn and :tabp.

This model of buffers, windows, and tabs is quite a bit more intricate than in other editors, and the terms are sometimes confusing. However, if you know a bit about how they're supposed to work, you get a great deal more control over the layout of your editing sessions as a result. Personally, I find I rarely need tabs as with a monitor of sufficient size it suffices to keep two or three windows open at a time when working on sets of files, but on the odd occasion I do need tabs, I do find them tremendously useful.

Thanks to Hacker News users anonymous and m0shen for pointing out potential confusion with the :set hidden option and the :bdelete command.

[Oct 31, 2017] Vim command window by Tom Ryder

Feb 05, 2012 | sanctum.geek.nz

The command line in Vim for ex commands can be edited with a few of the GNU Readline key combinations that may be familiar to Bash or Emacs users, so it's reasonably easy to edit it, for example to type in complex search patterns and replacements.

However, if you want the full facility of Vim editing for your commands, it can be helpful to use Vim's command line window, which will allow you to enter commands and edit previous ones with the usual normal and insert mode.

You can open the command line window from normal mode in one of four ways:

Note that this doesn't work while you're recording macros, since pressing q stops the recording.

The window is always immediately above the status bar, and its height can be set via the cmdwinheight option.

Command line window

Once the command line window is opened with q: , you can browse through it and press Enter on any line to issue the same command again. You can also edit it beforehand, perhaps to fix a mistyped command. The window will close when this is done, but you can close it with Ctrl+W, C the same as any other window if you change your mind.

Vim command line window

Vim command line window

Note that you can't move to another window while this one is open, nor can you load another buffer into it.

Search window

Similar to the above, if you open the command window with q/ or q? , it shows a history of your searches, and pressing enter on any line will issue the same again, in the appropriate direction.

Vim search window

Vim search window

For more information on how the command window works, check out :help command-line-window .

[Oct 31, 2017] Vim anti-patterns by Tom Ryder

Feb 07, 2012 | sanctum.geek.nz

The benefits of getting to grips with Vim are immense in terms of editing speed and maintaining your "flow" when you're on a roll, whether writing code, poetry, or prose, but because the learning curve is so steep for a text editor, it's very easy to retain habits from your time learning the editor that stick with you well into mastery. Because Vim makes you so fast and fluent, it's especially hard to root these out because you might not even notice them, but it's worth it. Here I'll list some of the more common ones. Moving one line at a time

If you have to move more than a couple of lines, moving one line at a time by holding down j or k is inefficient. There are many more ways to move vertically in Vim. I find that the two most useful are moving by paragraph and by screenful, but this depends on how far and how precisely you have to move.

If you happen to know precisely where you want to go, navigating by searching is the way to go, searching forward with / and backward with ? .

It's always useful to jump back to where you were, as well, which is easily enough done with two backticks, or gi to go to the last place you inserted text. If you like, you can even go back and forth through your entire change list of positions with g; and g, .

Moving one character at a time

Similarly, moving one character at a time with h and l is often a waste when you have t and f :

Moving wordwise with w , W , b , B , e , and E is better, too. Again, searching to navigate is good here, and don't forget you can yank , delete or change forward or backward to a search result:

y/search<Enter>
y?search<Enter>
d/search<Enter>
d?search<Enter>
c/search<Enter>
c?search<Enter>
Searching for the word under the cursor

Don't bother typing it, or yanking/pasting it; just use * or # . It's dizzying how much faster this feels when you use it enough for it to become automatic.

Deleting, then inserting

Deleting text with intent to replace it by entering insert mode immediately afterward isn't necessary:

d2wi

It's quicker and tidier to use c for change:

c2w

This has the added benefit of making the entire operation repeatable with the . command.

Using the arrow keys

Vim lets you use the arrow keys to move around in both insert and normal mode, but once you're used to using hjkl to navigate, moving to the arrow keys to move around in text feels clumsy; you should be able to spend the vast majority of a Vim session with your hands firmly centered around home row . Similarly, while the Home and End keys work the same way they do in most editors, there's no particular reason to use them when functional equivalents are closer to home in ^ and $ .

So wean yourself off the arrow keys, by the simple expedient of disabling them entirely, at least temporarily:

noremap <Up> <nop>
noremap <Down> <nop>
noremap <Left> <nop>
noremap <Right> <nop>

The benefits of sticking to home row aren't simply in speed; it feels nicer to be able to rest your wrists in front of the keyboard and not have to move them too far, and for some people it has even helped prevent repetitive strain injury .

Moving in insert mode

There's an additional benefit to the above in that it will ease you into thinking less about insert mode as a mode in which you move around; that's what normal mode is for. You should, in general, spend as little time in insert mode as possible. When you want to move, you'll get in the habit of leaving insert mode, and moving around far more efficiently in normal mode instead. This distinction also helps to keep your insert operations more atomic , and hence more useful to repeat.

Moving to Escape

The Escape key on modern keyboards is a lot further from home row than it was on Bill Joy's keyboard back when he designed vi. Hitting Escape is usually unnecessary; Ctrl+[ is a lot closer, and more comfortable. It doesn't take long using this combination instead to make reaching for Escape as you did when you were a newbie feel very awkward. You might also consider mapping the otherwise pretty useless Caps Lock key to be another Escape key in your operating system, or even mapping uncommon key combinations like jj to Escape. I feel this is a bit drastic, but it works well for a lot of people:

inoremap jj <Esc>
Moving to the start or end of the line, then inserting

Just use I and A . Again, these make the action repeatable for other lines which might need the same operation.

Entering insert mode, then opening a new line

Just use o and O to open a new line below and above respectively, and enter insert mode on it at the same time.

Entering insert mode to delete text

This is a pretty obvious contradiction. Instead, delete the text by moving to it and using d with an appropriate motion or text object. Again, this is repeatable, and means you're not holding down Backspace. In general, if you're holding down a key in Vim, there's probably a faster way.

Repeating commands or searches

Just type @: for commands or n / N for searches; Vim doesn't forget what your last search was as soon as you stop flicking through results. If it wasn't your most recent command or search but it's definitely in your history, just type q: or q/ , find it in the list , and hit Enter.

Repeating substitutions

Just type & to repeat the last substitution on the current line. You can repeat it on all lines by typing g& .

Repeating macro calls

Just type @@ .

These are really only just a few of the common traps to avoid to increase your speed and general efficiency with the editor without requiring plugins or substantial remappings. Check out the Vim Tips wiki for some other really helpful examples.

[Oct 31, 2017] Debugging Vim setup by Tom Ryder

Oct 31, 2017 | sanctum.geek.nz

While Vim's core is very stable, problems can come about when extending the editor with plugins, particularly if there are a high number of them or if they're buggy or not very well written. While Vim offers a number of ways to keep scripts' behaviours isolated from one another, it may happen that you find Vim behaving in an unexpected way that you can't quite pin down. There are a few very good approaches to figuring this out. List your scripts

First of all, it helps to get a handle on what exactly you've got loaded during your Vim sessions. You can do this with the :scriptnames command:

:scriptnames
1: /usr/share/vim/vimrc
2: /usr/share/vim/vim73/debian.vim
3: ~/.vimrc
4: ~/.dotfiles/vim/autoload/pathogen.vim
...

This list appears in the order in which the files were loaded, which might give you a starting point for figuring out where the problem lies.

Update your plugins

Check the documentation, release logs, known problems, and in particular the website of your chosen plugins to see if there are any recent updates to them. If they're hosted on GitHub, pull down the most recent versions.

Start with no plugins

You can start Vim with no plugins, in a pristine state that doesn't source any vimrc files from your system or home directories, to figure out if the behaviour you're observing still occurs with no plugins at all installed. This is done by calling Vim with the -u and -U options, which normally specify the path to a custom location for vimrc and gvimrc files respectively, with the special parameter of NONE :

$ vim -u NONE -U NONE

Vim will open and you'll see the usual blue tildes for opening a line and Vim's opening splash screen, having completely ignored your laborious setup.

This done, you can source plugins individually until you notice the problem starts happening, by a process of elimination:

:so plugin/fugitive.vim
:so plugin/unimpaired.vim
:so plugin/badplugin.vim
Profile startup time

If Vim was compiled with the +startuptime feature, you can also pass the --startuptime flag to it with a filename argument, and it will save a verbose log of its startup procedure to that file for you to inspect:

$ vim +q --startuptime startuptime.txt
$ vim startuptime.txt

There's way more information in here than you're ever likely to need, but in the case of a buggy setup or unacceptably slow startup time, it's very useful for diagnosing the bottleneck in your setup.

[Mar 03, 2017] How to Make Vim Editor as Bash-IDE Using bash-support Plugin in Linux

Notable quotes:
"... Predefined code snippets are files that contain already written code meant for a specific purpose. To add code snippets, type \nr and \nw to read/write predefined code snippets. Issue the command that follows to list default code snippets: ..."
Feb 20, 2017 | www.tecmint.com

bash-support is a highly-customizable vim plug-in, which allows you to insert: file headers, complete statements, comments, functions, and code snippets. It also enables you to perform syntax checking, make a script executable, start a debugger simply with a keystroke; do all this without closing the editor.

curl http://www.vim.org/scripts/download_script.php?src_id=24452 >bash-support.zip 

How To Use Run Operation in Vi Editor

The following is a list of some run operations key mappings:

\rr – update file, run script (n, I)
\ra – set script cmd line arguments (n, I)
\rc – update file, check syntax (n, I)
\rco – syntax check options (n, I)
\rd – start debugger (n, I)
\re – make script executable/not exec.(*) (in)

Make Script Executable

After writing script, save it and type \re to make it executable by pressing [Enter].

Make Script Executable
Make Script Executable

How To Use Predefined Code Snippets To a Bash Script

Predefined code snippets are files that contain already written code meant for a specific purpose. To add code snippets, type \nr and \nw to read/write predefined code snippets. Issue the command that follows to list default code snippets:

$ .vim/bash-support/codesnippets/

List of Code Snippets

To use a code snippet such as free-software-comment, type \nr and use auto-completion feature to select its name, and press [Enter]:

Add Code Snippet to Script
Add Code Snippet to Script

Create Custom Predefined Code Snippets

It is possible to write your own code snippets under ~/.vim/bash-support/codesnippets/. Importantly, you can also create your own code snippets from normal script code:
choose the section of code that you want to use as a code snippet, then press \nw, and closely give it a filename.
to read it, type \nr and use the filename to add your custom code snippet.

View Help For the Built-in and Command Under the Cursor

To display help, in normal mode, type:
\hh – for built-in help
\hm – for a command help

View Built-in Command Help
View Built-in Command Help

For more reference, read through the file :
~/.vim/doc/bashsupport.txt #copy of online documentation
~/.vim/doc/tags


Visit the Bash-support plug-in Github repository: https://github.com/WolfgangMehner/bash-support
Visit Bash-support plug-in on the Vim Website: http://www.vim.org/scripts/script.php?script_id=365

That's all for now, in this article, we described the steps of installing and configuring Vim as a Bash-IDE in Linux using bash-support plug-in. Check out the other exciting features of this plug-in, and do share them with us in the comments.

[Jul 12, 2013] The vimrc File - Derek Wyatt's Blog

[Aug 29, 2012] Vim Taglist plugin features

The taglist plugin provides the following features:

[Aug 29, 2012] Color schemes in VIM

[Aug 29, 2012] The ultimate Vim configuration - vimrc

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Text, tab and indent related
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Use spaces instead of tabs
set expandtab

" Be smart when using tabs ;)
set smarttab

" 1 tab == 4 spaces
set shiftwidth=4
set tabstop=4

" Linebreak on 500 characters
set lbr
set tw=500

set ai "Auto indent
set si "Smart indent
set wrap "Wrap lines


[May 13, 2011] Vim Outliner

freshmeat.net

Vim Outliner is a Vim plugin that make it behave as a full- featured outliner of the likes of MaxThink, Grandview, ThinkTank, and more. It has its own add-ons for checkboxes and hoisting and is compatible with Vim spell-checkers like vimspell and engspeak. There are several scripts available from other to convert text outlines to HTML pages, Docbook files, and Open Office Impress files.

customizing-your-vim-work-area

Adding a more visual cursor

Sometimes, you have a lot of syntax coloring in the file you are editing. This can make the task of tracking the cursor really hard. If you could just mark the line the cursor is currently in, then it would be easier to track it.

Many have tried to fix this with Vim scripts, but the results have been near useless (mainly due to slowness, which prevented scrolling longer texts at an acceptable speed). Not until version 7 did Vim have a solution for this. But then it came up with not just one, but two possible solutions for cursor tracking.

The first one is the cursorline command , which basically marks the entire line with, for example, another background color without breaking the syntax coloring. To turn it on, use the following command:

:set cursorline

The color it uses is the one defined in the CursorLine color group. You can change this to any color or styling you like, for example:

:highlight CursorLine guibg=lightblue ctermbg=lightgray

If you are working with a lot of aligned file content (such as tab-separated data), the next solution for cursor tracking comes in handy:

:set cursorcolumn

This command marks the current column (here the cursor is placed) by coloring the entire column through the entire file, for example.

As with the cursor line, you can change the settings for how the cursor column should be marked. The color group to change is named cursorcolumn.

Adding both the cursor line and column marking makes the cursor look like a crosshair, thus making it impossible to miss.

Even though the cursorline and cursorcolumn functionalities are implemented natively in Vim, it can still give quite a slowdown when scrolling through the file.

Modifying key bindings

All of us have probably, at some point, used an editor other than Vim. Because of this, most of us have learned to use some very specific keyboard shortcuts for doing different tasks. Even though the key bindings for the keyboard shortcuts in Vim are created with ease and use of speed in mind, sometimes it can still be faster to use the shortcuts you already know.

To facilitate this, Vim gives you the possibility to rebind almost every single key binding it has.

In this recipe, we will learn how to change the key bindings when using Vim in different modes.The main commands to know when dealing with key bindings are:

Each of the command takes two arguments-the first is what keys the command should be bound to, and the second is the command to bind. So, let's look at an example. Say you can't really get used to saving an open file by executing :w in the normal mode because you are used to using Ctrl-S to save a file and would like to keep it like that.

A mapping for this could be:

:map <C-s> :w<cr>

Notice the <C-s>;in the key binding. This is the Vim way for writing 'key combination Ctrl+S'. Instead of C (Ctrl), you could also use A (Alt) or M (Meta). The <cr> at the end of the command is what actually executes the command. Without it, the command would simply be written to the command line but not executed.

There are several other special notations for some of the other keyboard keys. The following table shows the most common of them:

Keys Notation
<BS> Backspace
<Tab> Tab
<CR> Enter
<Enter> Enter
<Return> Enter
<Esc> Escape
<Space> Space
<Up> Up arrow
<Down> Down arrow
<Left> Left arrow
<Right> Right arrow
<F1> <F12> Function keys 1 to 12
#1 #9#0 Function keys F1 to F9, F10
<Insert> Insert
<Del> Delete
<Home> Home
<End> End
<PageUp> Page up
<PageDown> Page down

Maybe you only want to be able to save when you are in the insert mode and actually editing the file. To change the command for this, you only need to have the following:

:imap <C-s> <esc>:w<cr>a

So, what happens now is that you map the Ctrl+S to do a combination of key presses. First, press <esc>; (the Escape key) to get out of the insert mode and into the normal mode. Then, use :w<cr> to execute the actual saving of the file, and finally the a to get back into the insert mode and go to the end of the line.

You could expand the mappings to fit all of the standard copy / paste / cut / save shortcuts from many applications. This could be constructed like this:

" save file (ctrl-s)
:map <C-s> :w<cr>
" copy selected text (ctrl-c)
:vmap <C-c> y
" Paste clipboard contents (ctrl-v)
:imap <C-p> <esc>P
" cut selected text (ctrl-x)
:vmap <C-x> x

 

If you are in Gvim, you can even get dialogs shown for the save-as and Open functionalities.

 

"Open new file dialog (ctrl-n)
:map <C-n> :browse confirm e<cr>
"Open save-as dialog (ctrl-shift-s)
:map <C-S-s> :browse confirm saveas<cr>

 

You can get into a situation where you map a key combination in which the first key is actually bound to a function of its own. An example could be the $ key, which is bound to the "jump to end of line" functionality in Vim. You might, however, want to have a key binding like $1 for some functionality, $2 for some other functionality, and so on. The mapping could then look like:

 

:map $1 :MyFunction1()<cr>
:map $2 :MyFunction2()<cr>

 

Now when you press $, Vim will wait for one second after you press the $ key, and if it does not get the second character in the key binding before the timeout, it will execute the normal "jump to end of line" functionality. However, if you press 1 before the timeout, it will execute your Myfunction1()function instead.

With the ability to change the keyboard mapping in Vim, you really have an access to a powerful way of modifying the editor completely according to your needs.

You can read more about mappings in the Vim help system under:

 

:help key-mapping

 

[Jan 15, 2010] Scripting the Vim editor

[Dec 16, 2009] Finally! A decent text editor for Linux with Windows key bindings. 46palermo

Vim Tip, on November 8th, 2009 at 19:32 Said:

just thought you might like to know, that vim does actually support windows keybindings. There should be an mswin.vim file on your system, which you can load to get ctrl-x, ctrl-v etc.

You may just owe me a White Russian

[Nov 21, 2009] Vim 101 A Beginner's Guide to Vim Linux Developer Network by Joe 'Zonker' Brockmeier

Searching and Replacing

Now that you know how to enter text, make some changes and so forth, it's time to learn how to use search and replace in Vim. It's really pretty easy. If you want to search through the document from command mode, use / followed by the text you want to search for. So, if I want to search for "bunny" I can enter / and then bunny and hit enter.

If I want to find it again, I hit n. If I want to look for a previous instance of the text, I'll use N instead, which will search the opposite direction through the document.

Want to reverse the direction of your search? Use ? instead of / and Vim will move backwards through the document. Using n and N as above will reverse the direction of the search.

That's all pretty easy, isn't it? Now to move on to an important operation: Cutting and pasting text.

... ... ...

Hit v to highlight some text. Then hit y to yank it into the buffer. Then move the cursor where you want it, and use p in command mode. There you go--you've just pasted some text!

The commands you most need to start out:

[Aug 28, 2009] vimconfig

Vimconfig is a complete set of Vim 6.x configurations files. It includes a personal vimrc config file with many features and some useful plugins, e.g. for HTML, TeX, Perl, mail, PHP, and so on.

[Jul 11, 2009] Screen (vim + gnu screen) - Start gnu screen w- your vim session and a split shell + send commands to the sh vim online

created by Eric Van Dewoestine

Screenshot: http://eclim.sourceforge.net/_images/screenshots/vim/gnu_screen_shell.png

Note: gvim is not supported. You must be running vim in a console.

Currently tested on Linux and cygwin, but should work on any unix based
platform where screen is supported (OSX, BSD, Solaris, etc.). Note that
in my testing of cygwin, invocations of screen were significantly slower
and less fluid than on Linux.

This plugin aims to simulate an embedded shell in vim by allowing you to
easily convert your current vim session into one running in gnu screen
with a split gnu screen window containing a shell, and to quickly send
statements/code to whatever program is running in that shell (bash,
python, irb, etc.).

Commands:
:ScreenShell [cmd] - Opens the split shell by doing the following:
1. save a session file from your currently running vim instance
(current tab only)
2. start gnu screen with vim running in it
3. load your saved session file
4. create a lower gnu screen split window and start a shell
5. if a command was supplied to :ScreenShell, run it
Ex. :ScreenShell ipython

Note: If you are already in a gnu screen session, then only steps
4 and 5 above will be run.

:ScreenSend - Send the visual selection or the entire buffer contents to
the running gnu screen shell window.

:ScreenQuit - Save all currently modified vim buffers and quit gnu
screen, returning you to your previous vim instance
running outside of gnu screen
Note: :ScreenQuit is not available if you where already in a gnu
screen session when you ran :ScreenShell.
Note: By default, if the gnu screen session was started by
:ScreenShell, then exiting vim will quit the gnu screen session
as well (configurable via g:ScreenShellQuitOnVimExit).

An example workflow may be:
Open a python file to work on:
$ vim something.py

Decide you want to run all or pieces of the code in an interactive
python shell:
:ScreenShell python

Send code from a vim buffer to the shell:
:ScreenSend

Quit the screen session and return to your original vim session:
:ScreenQuit
or
:qa

Gotchas:
- While running vim in gnu screen, if you detach the session instead of
quitting, then when returning to the non-screen vim, vim will complain
about swap files already existing. So try to avoid detaching.
- Not all vim plugins support saving state to or loading from vim
session files, so when running :ScreenShell some buffers may not load
correctly if they are backed by such a plugin.

install details

Download the script and put it in your plugin directory (~/.vim/plugin).

[Jul 10, 2009] Scripting the Vim editor, Part 1 Variables, values, and expressions

Vimscript is a mechanism for reshaping and extending the Vim editor. Scripting lets you create new tools (such as a problem-word highlighter) and simplify common tasks (like changing tabspacing, or inserting time and date information, or toggling syntax highlighting), and even completely redesign existing editor features (for example, enhancing CTRL-Y's "copy-the-previous-line" behavior).

For many people, the easiest way to learn any new language is by example. To that end, you can find an endless supply of sample Vimscripts-most of which are also useful tools in their own right-on the Vim Tips wiki. Or, for more extensive examples of Vim scripting, you can trawl the 2000+ larger projects housed in the Vim script archive. Both are listed in the Resources section below.

If you're already familiar with Perl or Python or Ruby or PHP or Lua or Awk or Tcl or any shell language, then Vimscript will be both hauntingly familiar (in its general approach and concepts) and frustratingly different (in its particular syntactic idiosyncrasies). To overcome that cognitive dissonance and master Vimscript, you're going to have to spend some time experimenting, exploring, and playing with the language. To that end, why not take your biggest personal gripe about the way Vim currently works and see if you can script a better solution for yourself?

This article has described only Vimscript's basic variables, values, expressions, and functions. The range of "better solutions" you're likely to be able to construct with just those few components is, of course, extremely limited. So, in future installments, we'll look at more advanced Vimscript tools and techniques: data structures, flow control, user-defined commands, event-driven scripting, building Vim modules, and extending Vim using other scripting languages. In particular, the next article in this series will focus on the features of Vimscript's user-defined functions and on the many ways they can make your Vim experience better.

[Jul 10, 2009] Scripting the Vim editor, Part 2 User-defined functions

Functions in Vimscript are defined using the function keyword, followed by the name of the function, then the list of parameters (which is mandatory, even if the function takes no arguments). The body of the function then starts on the next line, and continues until a matching endfunction keyword is encountered. For example:

Listing 1. A correctly structured function

function ExpurgateText (text)
    let expurgated_text = a:text

    for expletive in [ 'cagal', 'frak', 'gorram', 'mebs', 'zarking']
        let expurgated_text
        \   = substitute(expurgated_text, expletive, '[DELETED]', 'g')
    endfor

    return expurgated_text
endfunction

The return value of the function is specified with a return statement. You can specify as many separate return statements as you need. You can include none at all if the function is being used as a procedure and has no useful return value. However, Vimscript functions always return a value, so if no return is specified, the function automatically returns zero.

Function names in Vimscript must start with an uppercase letter:

Listing 2. Function names start with an uppercase letter
function SaveBackup ()
    let b:backup_count = exists('b:backup_count') ? b:backup_count+1 : 1
    return writefile(getline(1,'$'), bufname('%') . '_' . b:backup_count)
endfunction

nmap <silent>  <C-B>  :call SaveBackup()<CR>

This example defines a function that increments the value of the current buffer's b:backup_count variable (or initializes it to 1, if it doesn't yet exist). The function then grabs every line in the current file (getline(1,'$')) and calls the built-in writefile() function to write them to disk. The second argument to writefile() is the name of the new file to be written; in this case, the name of the current file (bufname('%')) with the counter's new value appended. The value returned is the success/failure value of the call to writefile(). Finally, the nmap sets up CTRL-B to call the function to create a numbered backup of the current file.

Instead of using a leading capital letter, Vimscript functions can also be declared with an explicit scope prefix (like variables can be, as described in Part 1). The most common choice is s:, which makes the function local to the current script file. If a function is scoped in this way, its name need not start with a capital; it can be any valid identifier. However, explicitly scoped functions must always be called with their scoping prefixes. For example:

Listing 3. Calling a function with its scoping prefix
" Function scoped to current script file...
function s:save_backup ()
    let b:backup_count = exists('b:backup_count') ? b:backup_count+1 : 1
    return writefile(getline(1,'$'), bufname('%') . '_' . b:backup_count)
endfunction

nmap <silent>  <C-B>  :call s:save_backup()<CR>

Redeclarable functions

Function declarations in Vimscript are runtime statements, so if a script is loaded twice, any function declarations in that script will be executed twice, re-creating the corresponding functions.

Redeclaring a function is treated as a fatal error (to prevent collisions where two separate scripts accidentally declare functions of the same name). This makes it difficult to create functions in scripts that are designed to be loaded repeatedly, such as custom syntax-highlighting scripts.

So Vimscript provides a keyword modifier (function!) that allows you to indicate that a function declaration may be safely reloaded as often as required:

Listing 4. Indicating that a function declaration may be safely reloaded
function! s:save_backup ()
    let b:backup_count = exists('b:backup_count') ? b:backup_count+1 : 1
    return writefile(getline(1,'$'), bufname('%') . '_' . b:backup_count)
endfunction

No redeclaration checks are performed on functions defined with this modified keyword, so it is best used with explicitly scoped functions (in which case the scoping already ensures that the function won't collide with one from another script).

Calling functions

To call a function and use its return value as part of a larger expression, simply name it and append a parenthesized argument list:


Listing 5. Using a function's return value
"Clean up the current line...
let success = setline('.', ExpurgateText(getline('.')) )

Note, however, that, unlike C or Perl, Vimscript does not allow you to throw away the return value of a function without using it. So, if you intend to use the function as a procedure or subroutine and ignore its return value, you must prefix the invocation with the call command:

Listing 6. Using a function without using its return value

"Checkpoint the text...
call SaveBackup()

Otherwise, Vimscript will assume that the function call is actually a built-in Vim command and will most likely complain that no such command exists. We'll look at the difference between functions and commands in a future article in this series.

Parameter lists

Vimscript allows you to define both explicit parameters and variadic parameter lists, and even combinations of the two.

You can specify up to 20 explicitly named parameters immediately after the declaration of the subroutine's name. Once specified, the corresponding argument values for the current call can be accessed within the function by prefixing an a: to the parameter name:


Listing 7. Accessing argument values within the function
function PrintDetails(name, title, email)
    echo 'Name:   '  a:title  a:name
    echo 'Contact:'  a:email
endfunction

If you don't know how many arguments a function may be given, you can specify a variadic parameter list, using an ellipsis (...) instead of named parameters. In this case, the function may be called with as many arguments as you wish, and those values are collected into a single variable: an array named a:000. Individual arguments are also given positional parameter names: a:1, a:2, a:3, etc. The number of arguments is available as a:0. For example:

Listing 8. Specifying and using a variadic parameter list

function Average(...)
    let sum = 0.0

    for nextval in a:000        "a:000 is the list of arguments
        let sum += nextval
    endfor

    return sum / a:0            "a:0 is the number of arguments
endfunction

Note that, in this example, sum must be initialized to an explicit floating-point value; otherwise, all the subsequent computations will be done using integer arithmetic.

Combining named and variadic parameters

Named and variadic parameters can be used in the same function, simply by placing the variadic ellipsis after the list of named parameters.

For example, suppose you wanted to create a CommentBlock() function that was passed a string and formatted it into an appropriate comment block for various programming languages. Such a function would always require the caller to supply the string to be formatted, so that parameter should be explicitly named. But you might prefer that the comment introducer, the "boxing" character, and the width of the comment all be optional (with sensible defaults when omitted). Then you could call:


Listing 9. A simple CommentBlock function call
call CommentBlock("This is a comment")

and it would return a multi-line string containing:


Listing 10. The CommentBlock return
//*******************
// This is a comment
//*******************

Whereas, if you provided extra arguments, they would specify non-default values for the comment introducer, the "boxing" character, and the comment width. So this call:


Listing 11. A more involved CommentBlock function call
call CommentBlock("This is a comment", '#', '=', 40)

would return the string:


Listing 12. The CommentBlock return
#========================================
# This is a comment
#========================================

Such a function might be implemented like so:


Listing 13. The CommentBlock implementation

function CommentBlock(comment, ...)
    "If 1 or more optional args, first optional arg is introducer...
    let introducer =  a:0 >= 1  ?  a:1  :  "//"

    "If 2 or more optional args, second optional arg is boxing character...
    let box_char   =  a:0 >= 2  ?  a:2  :  "*"

    "If 3 or more optional args, third optional arg is comment width...
    let width      =  a:0 >= 3  ?  a:3  :  strlen(a:comment) + 2

    " Build the comment box and put the comment inside it...
    return introducer . repeat(box_char,width) . "\<CR>"
    \    . introducer . " " . a:comment        . "\<CR>"
    \    . introducer . repeat(box_char,width) . "\<CR>"
endfunction

If there is at least one optional argument (a:0 >= 1), the introducer parameter is assigned that first option (that is, a:1); otherwise, it is assigned a default value of "//". Likewise, if there are two or more optional arguments (a:0 >= 2), the box_char variable is assigned the second option (a:2), or else a default value of "*". If three or more optional arguments are supplied, the third option is assigned to the width variable. If no width argument is given, the appropriate width is autocomputed from the comment argument itself (strlen(a:comment)+2).

Finally, having resolved all the parameter values, the top and bottom lines of the comment box are constructed using the leading comment introducer, followed by the appropriate number of repetitions of the boxing character (repeat(box_char,width)), with the comment text itself sandwiched between them.

Of course, to use this function, you'd need to invoke it somehow. An insertion map is probably the ideal way to do that:


Listing 14. Invoking the function using an insertion map
"C++/Java/PHP comment...
imap <silent>  ///  <C-R>=CommentBlock(input("Enter comment: "))<CR>

"Ada/Applescript/Eiffel comment...
imap <silent>  ---  <C-R>=CommentBlock(input("Enter comment: "),'--')<CR>

"Perl/Python/Shell comment...
imap <silent>  ###  <C-R>=CommentBlock(input("Enter comment: "),'#','#')<CR>

In each of these maps, the built-in input() function is first called to request that the user type in the text of the comment. The CommentBlock() function is then called to convert that text into a comment block. Finally, the leading <C-R>= inserts the resulting string.

Note that the first mapping passes only a single argument, so it defaults to using // as its comment marker. The second and third mappings pass a second argument to specify # or -- as their respective comment introducers. The final mapping also passes a third argument, to make the "boxing" character match its comment introducer.

Functions and line ranges

You can invoke any standard Vim command-including call-with a preliminary line range, which causes the command to be repeated once for every line in the range:

"Delete every line from the current line (.) to the end-of-file ($)...
:.,$delete

"Replace "foo" with "bar" everywhere in lines 1 to 10
:1,10s/foo/bar/

"Center every line from five above the current line to five below it...
:-5,+5center

You can type :help cmdline-ranges in any Vim session to learn more about this facility.

In the case of the call command, specifying a range causes the requested function to be called repeatedly: once for each line in the range. To see why that's useful, let's consider how to write a function that converts any "raw" ampersands in the current line to proper XML &amp; entities, but that is also smart enough to ignore any ampersand that is already part of some other entity. That function could be implemented like so:

Listing 15. Function to convert ampersands
function DeAmperfy()
    "Get current line...
    let curr_line   = getline('.')

    "Replace raw ampersands...
    let replacement = substitute(curr_line,'&\(\w\+;\)\@!','&amp;','g')

    "Update current line...
    call setline('.', replacement)
endfunction

The first line of DeAmperfy() grabs the current line from the editor buffer (getline('.')). The second line looks for any & in that line that isn't followed by an identifier and a colon, using the negative lookahead pattern '&\(\w\+;\)\@!'(see :help \@! for details). The substitute() call then replaces all such "raw" ampersands with the XML entity &amp;. Finally, the third line of DeAmperfy()updates the current line with the modified text.

If you called this function from the command line:

:call DeAmperfy()

it would perform the replacement on the current line only. But if you specified a range before the call:

:1,$call DeAmperfy()

then the function would be called once for each line in the range (in this case, for every line in the file).

Internalizing function line ranges

This call-the-function-repeatedly-for-each-line behavior is a convenient default. However, sometimes you might prefer to specify a range but then have the function called only once, and then handle the range semantics within the function itself. That's also easy in Vimscript. You simply append a special modifier (range) to the function declaration:

Listing 16. Range semantics within a function
function DeAmperfyAll() range
    "Step through each line in the range...
    for linenum in range(a:firstline, a:lastline)
        "Replace loose ampersands (as in DeAmperfy())...
        let curr_line   = getline(linenum)
        let replacement = substitute(curr_line,'&\(\w\+;\)\@!','&amp;','g')
        call setline(linenum, replacement)
    endfor

    "Report what was done...
    if a:lastline > a:firstline
        echo "DeAmperfied" (a:lastline - a:firstline + 1) "lines"
    endif
endfunction

With the range modifier specified after the parameter list, any time DeAmperfyAll() is called with a range such as:

:1,$call DeAmperfyAll()

then the function is invoked only once, and two special arguments, a:firstline and a:lastline, are set to the first and last line numbers in the range. If no range is specified, both a:firstline and a:lastline are set to the current line number.

The function first builds a list of all the relevant line numbers (range(a:firstline, a:lastline)). Note that this call to the built-in range() function is entirely unrelated to the use of the range modifier as part of the function declaration. The range() function is simply a list constructor, very similar to the range() function in Python, or the .. operator in Haskell or Perl.

Having determined the list of line numbers to be processed, the function uses a for loop to step through each:

for linenum in range(a:firstline, a:lastline)

and updates each line accordingly (just as the original DeAmperfy() did).

Finally, if the range covers more than a single line (in other words, if a:lastline > a:firstline), the function reports how many lines were updated.

Visual ranges

Once you have a function call that can operate on a range of lines, a particularly useful technique is to call that function via Visual mode (see :help Visual-mode for details).

For example, if your cursor is somewhere in a block of text, you could encode all the ampersands anywhere in the surrounding paragraph with:

Vip:call DeAmperfyAll()

Typing V in Normal mode swaps you into Visual mode. The ip then causes Visual mode to highlight the entire paragraph you're inside. Then, the : swaps you to Command mode and automatically sets the command's range to the range of lines you just selected in Visual mode. At this point you call DeAmperfyAll() to deamperfy all of them.

Note that, in this instance, you could get the same effect with just:

Vip:call DeAmperfy()

The only difference is that the DeAmperfy() function would be called repeatedly: once for each line the Vip highlighted in Visual mode.

A function to help you code

Most user-defined functions in Vimscript require very few parameters, and often none at all. That's because they usually get their data directly from the current editor buffer and from contextual information (such as the current cursor position, the current paragraph size, the current window size, or the contents of the current line).

Moreover, functions are often far more useful and convenient when they obtain their data through context, rather than through their argument lists. For example, a common problem when maintaining source code is that assignment operators fall out of alignment as they accumulate, which reduces the readability of the code:

Listing 16. Assignment operators out of alignment
let applicants_name = 'Luke'
let mothers_maiden_name = 'Amidala'
let closest_relative = 'sister'
let fathers_occupation = 'Sith'

Realigning them manually every time a new statement is added can be tedious:


Listing 17. Manually realigned assignment operators

let applicants_name     = 'Luke'
let mothers_maiden_name = 'Amidala'
let closest_relative    = 'sister'
let fathers_occupation  = 'Sith'

To reduce the tedium of that everyday coding task, you could create a key-mapping (such as ;=) that selects the current block of code, locates any lines with assignment operators, and automatically aligns those operators. Like so:

Listing 18. Function to align assignment operators

function AlignAssignments ()
    "Patterns needed to locate assignment operators...
    let ASSIGN_OP   = '[-+*/%|&]\?=\@<!=[=~]\@!'
    let ASSIGN_LINE = '^\(.\{-}\)\s*\(' . ASSIGN_OP . '\)'

    "Locate block of code to be considered (same indentation, no blanks)
    let indent_pat = '^' . matchstr(getline('.'), '^\s*') . '\S'
    let firstline  = search('^\%('. indent_pat . '\)\@!','bnW') + 1
    let lastline   = search('^\%('. indent_pat . '\)\@!', 'nW') - 1
    if lastline < 0
        let lastline = line('$')
    endif

    "Find the column at which the operators should be aligned...
    let max_align_col = 0
    let max_op_width  = 0
    for linetext in getline(firstline, lastline)
        "Does this line have an assignment in it?
        let left_width = match(linetext, '\s*' . ASSIGN_OP)

        "If so, track the maximal assignment column and operator width...
        if left_width >= 0
            let max_align_col = max([max_align_col, left_width])

            let op_width      = strlen(matchstr(linetext, ASSIGN_OP))
            let max_op_width  = max([max_op_width, op_width+1])
         endif
    endfor

    "Code needed to reformat lines so as to align operators...
    let FORMATTER = '\=printf("%-*s%*s", max_align_col, submatch(1),
    \                                    max_op_width,  submatch(2))'

    " Reformat lines with operators aligned in the appropriate column...
    for linenum in range(firstline, lastline)
        let oldline = getline(linenum)
        let newline = substitute(oldline, ASSIGN_LINE, FORMATTER, "")
        call setline(linenum, newline)
    endfor
endfunction

nmap <silent>  ;=  :call AlignAssignments()<CR>

The AlignAssignments() function first sets up two regular expressions (see :help pattern for the necessary details of Vim's regex syntax):
let ASSIGN_OP   = '[-+*/%|&]\?=\@<!=[=~]\@!'
let ASSIGN_LINE = '^\(.\{-}\)\s*\(' . ASSIGN_OP . '\)'

The pattern in ASSIGN_OP matches any of the standard assignment operators: =, +=, -=, *=, etc. but carefully avoids matching other operators that contain =, such as == and =~. If your favorite language has other assignment operators (such as .= or ||= or ^=), you could extend the ASSIGN_OP regex to recognize those as well. Alternatively, you could redefine ASSIGN_OP to recognize other types of "alignables," such as comment introducers or column markers, and align them instead.

The pattern in ASSIGN_LINE matches only at the start of a line (^), matching a minimal number of characters (.\{-}), then any whitespace (\s*), then an assignment operator.

Note that both the initial "minimal number of characters" subpattern and the operator subpattern are specified within capturing parentheses: \(...\). The substrings captured by those two components of the regex will later be extracted using calls to the built-in submatch() function; specifically, by calling submatch(1) to extract everything before the operator, and submatch(2) to extract the operator itself.

AlignAssignments() then locates the range of lines on which it will operate:

let indent_pat = '^' . matchstr(getline('.'), '^\s*') . '\S'
let firstline  = search('^\%('. indent_pat . '\)\@!','bnW') + 1
let lastline   = search('^\%('. indent_pat . '\)\@!', 'nW') - 1
if lastline < 0
    let lastline = line('$')
endif

In earlier examples, functions have relied on an explicit command range or a Visual mode selection to determine which lines they operate on, but this function computes its own range directly. Specifically, it first calls the built-in matchstr() function to determine what leading whitespace ('^\s*') appears at the start of the current line (getline('.'). It then builds a new regular expression in indent_pat that matches exactly the same sequence of whitespace at the start of any non-empty line (hence the trailing '\S').

AlignAssignments() then calls the built-in search() function to search upwards (using the flags 'bnW') and locate the first line above the cursor that does not have precisely the same indentation. Adding 1 to this line number gives the start of the range of interest, namely, the first contiguous line with the same indentation as the current line.

A second call to search() then searches downwards ('nW') to determine lastline: the number of the final contiguous line with the same indentation. In this second case, the search might hit the end of the file without finding a differently indented line, in which case search() would return -1. To handle this case correctly, the following if statement would explicitly set lastline to the line number of the end of file (that is, to the line number returned by line('$')).

The result of these two searches is that AlignAssignments() now knows the full range of lines immediately above or below the current line that all have precisely the same indentation as the current line. It uses this information to ensure that it aligns only those assignment statements at the same scoping level in the same block of code. Unless, of course, the indentation of your code doesn't correctly reflect its scope, in which case you fully deserve the formatting catastrophe about to befall you.

The first for loop in AlignAssignments() determines the column in which the assignment operators should be aligned. This is done by walking through the list of lines in the selected range (the lines retrieved by getline(firstline, lastline)) and checking whether each line contains an assignment operator (possibly preceded by whitespace):

let left_width = match(linetext, '\s*' . ASSIGN_OP)

If there is no operator in the line, the built-in match() function will fail to find a match and will return -1. In that case, the loop simply skips on to the next line. If there is an operator, match() will return the (positive) index at which that operator appears. The if statement then uses the built-in max() function to determine whether this latest column position is further right than any previously located operator, thereby tracking the maximum column position required to align all the assignments in the range:

let max_align_col = max([max_align_col, left_width])

The remaining two lines of the if use the built-in matchstr() function to retrieve the actual operator, then the built-in strlen() to determine its length (which will be 1 for a "=" but 2 for '+=', '-=', etc.) The max_op_width variable is then used to track the maximum width required to align the various operators in the range:
let op_width     = strlen(matchstr(linetext, ASSIGN_OP))
let max_op_width = max([max_op_width, op_width+1])

Once the location and width of the alignment zone have been determined, all that remains is to iterate through the lines in the range and reformat them accordingly. To do that reformatting, the function uses the built-in printf() function. This function is very useful, but also very badly named. It is not the same as the printf function in C or Perl or PHP. It is, in fact, the same as the sprintf function in those languages. That is, in Vimscript, printf doesn't print a formatted version of its list of data arguments; it returns a string containing a formatted version of its list of data arguments.

Ideally, in order to reformat each line, AlignAssignments() would use the built-in substitute() function, and replace everything up to the operator with a printf'd rearrangement of that text. Unfortunately, substitute() expects a fixed string as its replacement value, not a function call.

So, in order to use a printf() to reformat each replacement text, you need to use the special embedded replacement form: "\=expr". The leading \= in the replacement string tells substitute() to evaluate the expression that follows and use the result as the replacement text. Note that this is similar to the <C-R>= mechanism in Insert mode, except this magic behavior only works for the replacement string of the built-in substitute() function (or in the standard :s/.../.../ Vim command).

In this example, the special replacement form will be the same printf for every line, so it is pre-stored in the FORMATTER variable before the second for loop begins:

let FORMATTER = '\=printf("%-*s%*s", max_align_col, submatch(1),
\                                    max_op_width,  submatch(2))'

When it is eventually called by substitute(), this embedded printf() will left-justify (using a %-*s placeholder) everything to the left of the operator (submatch(1)) and place the result in a field that's max_align_col characters wide. It will then right-justify (using a %*s) the operator itself (submatch(2)) into a second field that's max_op_width characters wide. See :help printf() for details on how the - and * options modify the two %s format specifiers used here.

With this formatter now available, the second for loop can finally iterate through the full range of line numbers, retrieving the corresponding text buffer contents one line at a time:

for linenum in range(firstline, lastline)
    let oldline = getline(linenum)

The loop then uses substitute() to transform those contents, by matching everything up to and including any assignment operator (using the pattern in ASSIGN_LINE) and replacing that text with the result of the printf() call (as specified by FORMATTER):
    let newline = substitute(oldline, ASSIGN_LINE, FORMATTER, "")
    call setline(linenum, newline)
endfor

Once the for loop has iterated all the lines, any assignment operators within them will now be aligned correctly. All that remains is to create a key-mapping to invoke AlignAssignments(), like so:
nmap <silent>  ;=  :call AlignAssignments()<CR>

Looking ahead

Functions are an essential tool for decomposing an application into correct and maintainable components, in order to manage the complexity of real-world Vim programming tasks.

Vimscript allows you to define functions with fixed or variadic parameter lists, and to have them interact either automatically or in user-controlled ways with ranges of lines in the editor's text buffer. Functions can call back to Vim's built-in features (for example, to search() or substitute() text), and they can also directly access editor state information (such as determining the current line the cursor is on via line('.')) or interact with any text buffer currently being edited (via getline() and setline()).

This is undoubtedly a powerful facility, but our ability to programmatically manipulate state and content is always limited by how cleanly and accurately we can represent the data on which our code operates. So far in this series of articles, we've been restricted to the use of single scalar values (numbers, strings, and booleans). In the next two articles, we'll explore the use of much more powerful and convenient data structures: ordered lists and random-access dictionaries.

[Sep 16, 2008] Vim 7.2

About:

Vim is an almost fully-compatible version of the Unix editor Vi. Many new features have been added including multi-level undo,

It is descended from the vi clone "stevie" and runs on many systems, including Unix, MS Windows, OS/2, Macintosh, VMS, and Amiga.

Changes:
This is a stable version with many bugfixes and updated runtime files. The only new feature worth mentioning is support for floating point. Upgrading from a previous version is highly recommended: A few crashing bugs and several security issues were fixed.

[Feb 6, 2008] Eclim 1.3.4 by Eric Van Dewoestine

About: Eclim (Eclipse integration in vim) is a set of eclipse and vim plugins that bring Eclipse functionality to the vim editor. It exposes Eclipse features through a server interface and includes a set of vim plugins that communicate with Eclipse over that interface.

[Feb 6, 2008] freshmeat.net Project details for Cream for Vim

Cream is a configuration of the famous Vim text editor that makes it easier to use, like an Apple- or Windows-style text editor. It uses Vim's own extensibility to improve menus, keyboard shortcuts, and editing behavior. Cream seamlessly maintains Vim's insertmode to access all the power of the original Vim plus many custom Cream extensions.

Release focus: Minor feature enhancements

Changes:
This is a minor release that adds three common keyboard shortcuts, an updated French translation for menus, better Apple/Mac behavior, and improvements to the Email Prettyfier and Slide Generator add-ons. Cream is now distributed under the newest version of the GNU General Public License, now version 3.

[Dec 28, 2007] Linux.com Vim tips Using tabs By Joe 'Zonker' Brockmeier

January 24, 2007 | Linux.com
Before Vim 7.0 was released last May, I usually had six or seven xterms or Konsole windows open, each with a single Vim session in which I was editing a single file. This takes up a lot of screen space, and isn't very efficient. With Vim 7.0, users now have the option of using tabs within Vim. With Vim's tab features you can consolidate all your sessions into one window and move between files more easily.

If you're using an version of Vim older than 7.0, you won't have access to this feature. By now, though, most distros have moved to Vim 7.0, so if you're using a recent release you should be OK.

Opening a tab

Let's start by opening a new tab in Vim. There are a few ways to do this. Probably the easiest to remember is to run the :tabnew command while in normal mode. This will open a new tab with an empty buffer. If you want to edit a file in the new tab, you can run :tabnew filename and Vim will load the file in the new tab.

Another way to do this is to open more than one file at startup using the -p option. If you want to open three files in separate tabs, you'd use this syntax:

vim -p file1 file2 file3

This will start a Vim session with file1 in the first tab, file2 in the second tab, and file3 in the third.

Vim will open up as many tabs as you like on startup, up to the maximum number of tabs set in the .vimrc file. The default maximum is 10 tabs, but you can change this by setting the tabpagemax option in your .vimrc, like so:

set tabpagemax=15

If you exceed the number of tabs allowed by tabpagemax Vim will simply open the maximum number of tabs, and the other files will be open but not displayed. You can edit the remaining files by using the :next or :last command to move to the files that are not displayed in a tab. Note that this setting only applies to the maximum number of tabs Vim will open on startup -- you can still open more tabs during your Vim session.

The :tabf command allows you to search for a file in your current path and open it in a new tab. For instance, if you want to open a file called inventory.txt that's in your current path, you could run:

:tabf inven*

That will search for a file that matches the string inven and any number of characters after it. If only one file is found, Vim will open it in a new tab. If you have several files that match, Vim will complain that too many files match, and you'll have to narrow the search a little. The :tabn command will do autocompletion of file names in your path, so you can just type the first few characters of a filename and hit Tab to find the right file.

Moving between tabs

You can switch between tabs using :tabn and :tabp, or you can use gt while you're in normal mode. Of course, if you're using Vim's GUI, GVim, you can also use the mouse to switch between tabs or use keyboard shortcuts. In GVim, you can also access a context menu for tabs by right-clicking on the tab bar. Here you can open new tabs with a new buffer or an existing file, or close the current tab.

If you have a lot of tabs open, you can use :tabfirst, or just :tabfir, to jump to the first tab, and :tablast to jump to the last tab that's open.

By default, the tab labels are shown at the top of the Vim window only when tabs are open. If you want to see the tab bar all the time, you can modify the showtabline option in your .vimrc. To set this to display all of the time, use:

set showtabline=2

If you want to turn it off altogether, use 0 instead of 2.

Note that the tabs are still there, even if the tab bar isn't displayed. If you have the tabline option set to 0, you can still see what tabs are open by using the :tabs command, which will provide a summary of open tabs, as you can see in the figure.

Speaking of setting options, if you don't like the existing shortcuts for the tab commands, you can add your own. For instance, if you want to make it easy to open a new tab, you might insert this into your .vimrc:

imap ,t <Esc>:tabnew<CR>

This tells Vim to set up a keymap for ,t in insert mode, to run Esc to put Vim into normal mode, then :tabnew and a carriage return to run the command. You can set up mappings for all of the tab commands that you use regularly. For more on setting up mappings, see our article Using Vim mappings and abbreviations.

Rearranging tabs

If you're really meticulous and want to position tabs just so in Vim, you can move the tabs to a specific spot in the tab order using :tabm n , where n is the position number that you want to use. If you don't give the :tabm command an argument, then the current tab will be moved to the last spot.

Vim starts tab numbering from 0, so if you have six tabs open, you'll have tab 0 through tab 5. So, if you're in the first tab and want to move it to the fourth position, you'd run :tab 3.

Note that you can still use viewports normally within tabbed windows, and tabs are useful for doing a quick edit in a file when you have a main Vim window set up with a couple of viewports arranged just right.

Running commands in tabs

Let's say you're editing six or seven files in Vim and realize that you need to replace a variable name with a new one. Using the :tabdo command, you can run a search and replace through all of the tabs at once rather than changing each file individually. For instance, if you want to replace foo with bar, you'd run this:

:tabdo %s/foo/bar/g

That will run through each open tab and run the search and replace command (%s/foo/bar/g) in each one.

Tabs can be extremely useful, and it only takes a short while to become proficient with them. For more on working with tabs in Vim, run :help tab-page-intro within Vim.

[Nov 6, 2007] Adding a little Cream to (g)Vim By Scott Nesbitt

May 16, 2007 | Linux.com
Even though I'm a die-hard Emacs user, there are times when I have to use the vi editor -- specifically gVim, the graphical face of the popular vi clone Vim. Since I use gVim so infrequently, I don't readily remember many of the editor's basic commands. Either I muddle through or reach for my well-thumbed copy of the vi Editor Pocket Reference. That was until I discovered Cream. With Cream, gVim becomes an easy-to-use editor -- so easy, in fact, you might not believe that you're using vi.

Cream is a set of scripts and add-ons that sit on top of gVim. Cream doesn't change the appearance of gVim, but it does change the way it behaves. You no longer need to remember or use the traditional colon followed by one or more letters to execute a command -- for example, :w to save a file. Instead, you can use keystroke combinations that are common to many Linux and Windows text editors, such as Ctrl-C to copy text or Alt-F to open the File menu. Cream's developers bill it as "a modern configuration of the Vim text editor."

Getting Cream is easy. You can download the sources, as well as packages for Debian, Gentoo, Ubuntu, and FreeBSD, from the Cream Web site. A Windows installer is also available. Ubuntu users can get Cream using the Synaptic Package Manager, while users of Linspire and Freespire can install it via the CNR Service. If you use Debian, just run apt-get install cream at the command line.

Cream's gVim menus
Cream's gVim menus - click to enlarge
Getting to work

You start Cream by either clicking the icon that was added to your menu (Applications -> Accessories in Ubuntu), or by typing cream at the command line or in your application launcher. If you've used gVim before, you'll notice that, post-Cream, the menus have changed. As one friend of mine put it, "Cream un-techified Vim." Gone are menus like Syntax and Buffers, which have been replaced by more user-friendly menus with names like Format, Settings, and Insert. You don't have to dig as deeply through Cream's menus to find the command that you're looking for; those commands are just a couple of clicks away.

Cream retains just about all of Vim's features, and it has a few interesting ones of its own. Some of the more useful are a tabbed interface (only available if you're using Vim 7.0 or newer), the ability to quickly wrap or justify text, and a spelling checker. While version 7.0 of Vim has an on-the-fly spelling checker, that feature is missing from older versions of the editor -- like the one I use, version 6.4.6. You can also switch between using Cream keystrokes and commands and those used by vi or Vim. That way, you get the best of both worlds, if you're so inclined.

One aspect of Cream that I found a bit frustrating was not being able to use the handful of Vim extensions that I'd installed. For example, when I open a LaTeX document in gVim, the LaTeX extension displays three additional menus that help me edit and compile files -- but not if I have Cream installed. I wasn't able to find a way to get around this problem.

Files via Cream
Files via Cream - click to enlarge
Using add-ons and plugins

Add-ons are functions that add extra flexibility to Cream. Cream comes with 20 add-ons, some of which you may find useful and others you can do without. With the add-ons, you can strip ASCII text from a binary file, convert a text file to HTML, sort lines, and reformat an email address so that it's not vulnerable to harvesting by spammers. There's also a slide generator add-on that can create an HTML-based slide show using images in a directory that you specify, and a built-in typing tutor for users who wants to improve their typing speed.

Cream also comes with some useful plugin utilities. One is the File Tree, which acts a lot like the Emacs Speedbar extension. Using the File Tree, I quickly navigate around my file system and open files without using the Open File dialog box. While I don't find it incredibly useful, I know a couple of Cream aficionados who can't live without the Calendar plugin, which embeds a calendar within the editor.

If you're a long-time user of Vim and/or gVim, Cream probably isn't for you. You're undoubtedly familiar with many of Vim's commands, and don't need the assistance of a CUA-enabled editor. On the other hand, if you use gVim infrequently or want to take advantage of the power of Vim without learning the editor's commands, then Cream is definitely worth a look.

Scott Nesbitt is a freelance journalist and technical writer.

[Nov 5, 2007] Linux.com A more informative status line for Vim

This article is excerpted from the recently published book Hacking Vim.

To the right, the default status line shows the number of the current row and column and to the left it shows name of the file currently open (if any). Whenever you execute a Vim command, the status line disappears and the command buffer is shown in that line instead. If the command you execute writes any messages, then those are shown on the right of the status line.

For simple and fast file editing, this status line is adequate. But if you use Vim every day and for a lot of different file formats, it would be nice to have a more informative status line.

The command that sets how the status line should look is called:

:set statusline format

where format is a printf-like string that describes how the status line should look.

If you look in the Vim help system by typing :help 'statusline', you will see that the status line can contain a wide variety of information. Some pieces are more useful in your daily work than others.

My status line always contains information about:

The following command will turn your status line into a true information bar with all the above information:

:set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [ASCII=\%03.3b]\ [HEX=\%02.2B]\ [POS=%04l,%04v][%p%%]\ [LEN=%L] 

I have added a '[ ]' around each of the pieces of information so that it is easier to distinguish them from each other. This is purely to give a visual effect; you can leave them out.

Even after entering that command, the status line still shows the old non-informative status line, as in the default installation. This problem occurs because Vim, by default, does not show the status line at all. Instead, it just shows the command buffer with a little bit of information in it. To tell Vim that you would like to have a real status line shown, you have to add the following setting to your vimrc file. This command will make sure that your status line is always shown as the second last line in the editor window:

:set laststatus=2 

You will then see that the command buffer gets a place of its own in the last line of the editor window. This way there's always room for the status line, and you will always have information about the file right in front of you. The status line does of course take up some of the editing area. You can always remove it for the rest of the editing session by executing the following command from within Vim:

:set laststatus=0

Toggle menu and toolbar

If you are used to working with Vim in the console mode, you are used to having no menus and toolbars at the top of the window. Gvim, however, provides both a menu and toolbar by default in the GUI.

Many users believe that extra room for text is more important than the menu and the toolbar. However, some scripts add useful functionality in the menu, and it is therefore important to have the menus. The solution for this could be toggling whether the menu and toolbar is shown.

The following code maps the key combination Ctrl-F2 to toggle the menu and toolbar in Gvim. You can add it to your vimrc file if you want this functionality.

map <silent> <C-F2> :if &guioptions =~# 'T' <Bar>
                         \set guioptions-=T <Bar>
                         \set guioptions-=m <bar>

                    \else <Bar>
                         \set guioptions+=T <Bar>
                         \set guioptions+=m <Bar>

                    \endif<CR> 

Now, whenever you don't need the menu and toolbar, you can just press Ctrl-F2 and you will get the full space for your text.

If you want either the menu or the toolbar to be hidden all the time, add one of the following lines to your vimrc file. To remove the menu completely:

:set guioptions-=m 

To remove the toolbar completely:

:set guioptions-=T 

Other parts of the GUI can be modified with the setguioptions command. To find out what you can modify, look in :help 'guioptions'.

[Oct 5, 2007] Turn Vim into a bash IDE By Joe 'Zonker' Brockmeier

June 11, 2007 | Linux.com
By itself, Vim is one of the best editors for shell scripting. With a little tweaking, however, you can turn Vim into a full-fledged IDE for writing scripts. You could do it yourself, or you can just install Fritz Mehner's Bash Support plugin.

To install Bash Support, download the zip archive, copy it to your ~/.vim directory, and unzip the archive. You'll also want to edit your ~/.vimrc to include a few personal details; open the file and add these three lines:

let g:BASH_AuthorName   = 'Your Name'
let g:BASH_Email        = 'my@email.com'
let g:BASH_Company      = 'Company Name'

These variables will be used to fill in some headers for your projects, as we'll see below.

The Bash Support plugin works in the Vim GUI (gVim) and text mode Vim. It's a little easier to use in the GUI, and Bash Support doesn't implement most of its menu functions in Vim's text mode, so you might want to stick with gVim when scripting.

When Bash Support is installed, gVim will include a new menu, appropriately titled Bash. This puts all of the Bash Support functions right at your fingertips (or mouse button, if you prefer). Let's walk through some of the features, and see how Bash Support can make Bash scripting a breeze.

Header and comments

If you believe in using extensive comments in your scripts, and I hope you are, you'll really enjoy using Bash Support. Bash Support provides a number of functions that make it easy to add comments to your bash scripts and programs automatically or with just a mouse click or a few keystrokes.

When you start a non-trivial script that will be used and maintained by others, it's a good idea to include a header with basic information -- the name of the script, usage, description, notes, author information, copyright, and any other info that might be useful to the next person who has to maintain the script. Bash Support makes it a breeze to provide this information. Go to Bash -> Comments -> File Header, and gVim will insert a header like this in your script:

#!/bin/bash
#===============================================================================
#
#          FILE:  test.sh
#
#         USAGE:  ./test.sh
#
#   DESCRIPTION:
#
#       OPTIONS:  ---
#  REQUIREMENTS:  ---
#          BUGS:  ---
#         NOTES:  ---
#        AUTHOR:  Joe Brockmeier, jzb@zonker.net
#       COMPANY:  Dissociated Press
#       VERSION:  1.0
#       CREATED:  05/25/2007 10:31:01 PM MDT
#      REVISION:  ---
#===============================================================================

You'll need to fill in some of the information, but Bash Support grabs the author, company name, and email address from your ~/.vimrc, and fills in the file name and created date automatically. To make life even easier, if you start Vim or gVim with a new file that ends with an .sh extension, it will insert the header automatically.

As you're writing your script, you might want to add comment blocks for your functions as well. To do this, go to Bash -> Comment -> Function Description to insert a block of text like this:

#===  FUNCTION  ================================================================
#          NAME:
#   DESCRIPTION:
#    PARAMETERS:
#       RETURNS:
#===============================================================================

Just fill in the relevant information and carry on coding.

The Comment menu allows you to insert other types of comments, insert the current date and time, and turn selected code into a comment, and vice versa.

Statements and snippets

Let's say you want to add an if-else statement to your script. You could type out the statement, or you could just use Bash Support's handy selection of pre-made statements. Go to Bash -> Statements and you'll see a long list of pre-made statements that you can just plug in and fill in the blanks. For instance, if you want to add a while statement, you can go to Bash -> Statements -> while, and you'll get the following:

while _; do
done

The cursor will be positioned where the underscore (_) is above. All you need to do is add the test statement and the actual code you want to run in the while statement. Sure, it'd be nice if Bash Support could do all that too, but there's only so far an IDE can help you.

However, you can help yourself. When you do a lot of bash scripting, you might have functions or code snippets that you reuse in new scripts. Bash Support allows you to add your snippets and functions by highlighting the code you want to save, then going to Bash -> Statements -> write code snippet. When you want to grab a piece of prewritten code, go to Bash -> Statements -> read code snippet. Bash Support ships with a few included code fragments.

Another way to add snippets to the statement collection is to just place a text file with the snippet under the ~/.vim/bash-support/codesnippets directory.

Running and debugging scripts

Once you have a script ready to go, and it's testing and debugging time. You could exit Vim, make the script executable, run it and see if it has any bugs, and then go back to Vim to edit it, but that's tedious. Bash Support lets you stay in Vim while doing your testing.

When you're ready to make the script executable, just choose Bash -> Run -> make script executable. To save and run the script, press Ctrl-F9, or go to Bash -> Run -> save + run script.

Bash Support also lets you call the bash debugger (bashdb) directly from within Vim. On Ubuntu, it's not installed by default, but that's easily remedied with apt-get install bashdb. Once it's installed, you can debug the script you're working on with F9 or Bash -> Run -> start debugger.

If you want a "hard copy" -- a PostScript printout -- of your script, you can generate one by going to Bash -> Run -> hardcopy to FILENAME.ps. This is where Bash Support comes in handy for any type of file, not just bash scripts. You can use this function within any file to generate a PostScript printout.

Bash Support has several other functions to help run and test scripts from within Vim. One useful feature is syntax checking, which you can access with Alt-F9. If you have no syntax errors, you'll get a quick OK. If there are problems, you'll see a small window at the bottom of the Vim screen with a list of syntax errors. From that window you can highlight the error and press Enter, and you'll be taken to the line with the error.

Put away the reference book...

Don't you hate it when you need to include a regular expression or a test in a script, but can't quite remember the syntax? That's no problem when you're using Bash Support, because you have Regex and Tests menus with all you'll need. For example, if you need to verify that a file exists and is owned by the correct user ID (UID), go to Bash -> Tests -> file exists and is owned by the effective UID. Bash Support will insert the appropriate test ([ -O _]) with your cursor in the spot where you have to fill in the file name.

To build regular expressions quickly, go to the Bash menu, select Regex, then pick the appropriate expression from the list. It's fairly useful when you can't remember exactly how to express "zero or one" or other regular expressions.

Bash Support also includes menus for environment variables, bash builtins, shell options, and a lot more.

Hotkey support

Vim users can access many of Bash Support's features using hotkeys. While not as simple as clicking the menu, the hotkeys do follow a logical scheme that makes them easy to remember. For example, all of the comment functions are accessed with \c, so if you want to insert a file header, you use \ch; if you want a date inserted, type \cd; and for a line end comment, use \cl.

Statements can be accessed with \a. Use \ac for a case statement, \aie for an "if then else" statement, \af for a "for in..." statement, and so on. Note that the online docs are incorrect here, and indicate that statements begin with \s, but Bash Support ships with a PDF reference card (under .vim/bash-support/doc/bash-hot-keys.pdf) that gets it right.

Run commands are accessed with \r. For example, to save the file and run a script, use \rr; to make a script executable, use \re; and to start the debugger, type \rd. I won't try to detail all of the shortcuts, but you can pull up a reference using :help bashsupport-usage-vim when in Vim, or use the PDF. The full Bash Support reference is available within Vim by running :help bashsupport, or you can read it online.

Of course, we've covered only a small part of Bash Support's functionality. The next time you need to whip up a shell script, try it using Vim with Bash Support. This plugin makes scripting in bash a lot easier.

[Nov 14, 2006] Vifm

Vifm is a ncurses based file manager with vi like keybindings. If you use vi, vifm gives you complete keyboard control over your files without having to learn a new set of commands.

Basic Movement

Marks

Searching Additional Normal Mode Keys Commands File Filters

[Oct 25, 2006] Vim 7!

May 8, 2006 (vimannonce grroup) Vim 7 is ready! After years of development this feature packed editor
is waiting for you.

Since Vim 6.4 many new features have been added. To mention a few:

- Spell checking support for about 50 languages
- Intelligent completion for C, HTML, Ruby, Python, PHP, etc.
- Tab pages, each containing multiple windows
- Undo branches: never accidentally lose text again

- Vim script supports Lists and Dictionaries (similar to Python)
- Vim script profiling
- Improved Unicode support
- Highlighting of cursor line, cursor column and matching braces
- Translated manual pages support.
- Internal grep; works on all platforms, searches compressed files
- Browsing remote directories, zip and tar archives
- Printing multi-byte text

Once you have installed Vim 7.0 you can find details about the changes
since Vim 6.4 with ":help version7".

[May 25, 2006] Linux.com Vim tips Folding fun

The problem with writing and editing on a computer, versus having words on paper, is that it's usually hard to compare text from different sections of a document when they don't fit on the screen together. One way to do it is to use Vim's viewports feature. Another is to "fold" the text. Using Vim's folding features, you can tuck away portions of a file's text so that they're out of sight until you want to work with them again. Here's how.

Vim's folding commands begin with z -- which, as the Vim docs point out, sort of looks like a folded piece of paper. OK, maybe not much, but at least the commands are consistent. If you want to do something with folding, it probably starts with z. (Since Vim 7 added spellchecking, some of the spellcheck commands also start with z, but that's a topic for another article.)

Creating folds

Let's start with some simple folding actions. Pick a text file, preferably a longer one like your xorg.conf, or just about any text file that's too big to fit on the screen by itself. Open it in Vim, and place the cursor at the beginning of a paragraph. Make sure you're in normal mode, and type zf2j. After you press j, Vim will create a fold covering three lines -- the line you started the fold on, and the next two lines. If you're familiar with Vim's movement commands, you know that the command 2j would usually tell Vim to move down two lines. Vim uses the same movement commands to define folds.

Folding also works in visual mode. If you enter visual mode using v or V, then select a few lines of text using the movement keys, and type zf, Vim will create a fold comprising those lines.

Another option is to specify a range in command mode. For instance, if you wanted to create a fold from lines 20 through 101, you could just use :20,101 fold and press Enter. In fact, you don't even need to type the entire word -- you can use fo instead of fold if you want to save a couple of keystrokes. Note that this will work backwards as well -- so if you use :.,20 fo when the cursor is on line 101, Vim will reverse the range and create the fold from lines 20 to 101.

Vim can also make some smart text selections. Let's say you're working on a script or program and you have a block of text within braces ({}). Position the cursor on the first brace, and type zfa}. Vim will create a fold from the line with the first brace through the last; it's not necessary to know which lines you're working with, Vim will just look for the closing brace. This also works with other block enclosures -- parenthesis, brackets ([]), and angle brackets (<>).

As an added bonus, Vim also recognizes nested blocks, so it will create the fold based on matching delimiters, and not the first closing bracket it comes across. Vim will also work backwards. If you're on a closing brace, type zfa{ and Vim will create a fold from the current spot to the beginning brace.

Folds are nestable as well -- that is to say, you can create a fold, and then include that within a larger section of folded text.

Finally, you can create a fold from the cursor position to a search result. If you run zf/string , Vim will create a fold from the cursor position to the first instance of the search string. Again, this is useful when you know you want a fold to go from the line you're on to a line further down in the file, but you're not sure what the line number is.

Once you've created a fold you'll see a single line of text that shows how many lines are folded, as well as the initial text, like this:

+-- 15 lines: set_up_socket_dir () {--------------------------------------------

The dashes indicate the foldlevel of the particular fold. For a top-level fold, you should see two dashes. Nested folds will have more dashes. We'll cover the foldlevel in more depth in just a bit.

Vim folding commands
zf#j creates a fold from the cursor down # lines.
zf/string creates a fold from the cursor to string .
zj moves the cursor to the next fold.
zk moves the cursor to the previous fold.
zo opens a fold at the cursor.
zO opens all folds at the cursor.
zm increases the foldlevel by one.
zM closes all open folds.
zr decreases the foldlevel by one.
zR decreases the foldlevel to zero -- all folds will be open.
zd deletes the fold at the cursor.
zE deletes all folds.
[z move to start of open fold.
]z move to end of open fold.

Using folds

Creating folds is only half the fun. At some point, you'll no doubt want to unfold the text. One way to do this is to place the cursor on the same line as the fold and type zo. This will "open" the fold, but not delete it. So if you want to do a quick check on some text that's been folded, use zo, and then zc to close it back up when you're finished.

To move between folds quickly, use the zj and zk commands to move to the next and previous fold. Note that it doesn't matter whether the folds are open or closed; if they exist, zj and zk will move backwards and forwards between them. These commands should be easy to remember, since they combine the fold command (z) with movement commands (j to move down a line, and k to move up a line). If you want to move between the start and end of a fold, use [z and ]z, respectively.

As we've already covered, Vim will create nested folds. If you use zo on a nested fold, it will open only the first fold -- the remaining folds will stay closed. However, if you'd like to open all of the nested folds on that line, use zO -- Vim will open all of the folds. Running zc in normal mode will close all the folds after using zO.

The zr command will open all first-level folds in Vim, and zR will open all of the folds in the file. The zm command will re-fold the first-level folds, and zM will close all open folds in a file. If you have multiple foldlevels, a fold within a fold within a fold, running zm will refold them sequentially -- so if all folds are open it will refold the deepest folds, then folds on the next foldlevel, and so on. The zr command works the same way, only in reverse -- it will open the top-level fold, then the next level, and so forth.

When you decide you want to get rid of a fold entirely, position the cursor on the fold and run zd. This will work whether the fold is open or closed. To zap all of the folds at once, type zE. Delete with caution, however. Vim's undo and redo features don't apply to folds; if you delete a fold, you can't press u and bring it back, and the . command won't run the last fold command.

You might be wondering, how does Vim treat text within folds when you are searching for text, or doing a search and replace on a file? Vim treats the text normally. If you search for a string of text that's within a fold, Vim will unfold the text when the cursor moves to the string within the fold. Unfortunately, Vim is a little less than tidy in this regard -- if a search causes a fold to be expanded, Vim doesn't re-fold the text after moving the cursor outside the fold. However, a quick zm will restore the folds.

Vim also treats a folded section of text as a single line for the purpose of deleting and yanking text. If you place the cursor on a section of folded text and use dd, it will delete the entire section, not just the first line. Vim will also allow you to yank the entire folded section of text just by placing the cursor on the folded text and typing Y or yy. The folded section can then be pasted into another section of the text using the p or P commands.

The foldmethod option

Vim's foldmethod option might be of interest to programmers. The default foldmethod is manual -- that is, creating folds manually. However, Vim can also create folds based on the way a file is indented, its syntax, or markers in the text.

To set the foldmethod according to the way a file is indented, run :set foldmethod=indent. This will automatically create folds at every indent. Consider a Cascading Style Sheet (CSS) file like this one:

body {
        background-color: #CCCCCC;
	font-family: arial, helvetica, sans-serif;
}

strong.header {
        font-family: arial, helvetica, sans-serif;
        color: #1D3C47;
}

Once you've set foldmethod=indent, it will look like this:

body {
+---  2 lines: background-color: #CCCCCC;---------------------------------------
}

strong.header {
+---  2 lines: font-family: arial, helvetica, sans-serif;-----------------------
}

Vim also offers a marker method, where folds are set by visible text markers rather than invisible manual marks. To set this mode, run :set foldmethod=marker. Then, when you set a fold, you'll see a marker with three braces at the beginning and end of the fold, like this:

/*{{{*/
Folded text goes here...
/*}}}*/

The braces are set off by comment characters, depending on the type of file. So, if you're working with an HTML file, you'll see <!--{{{-->, and if you're editing a Python script, you'll see #{{{. You can also insert fold markers manually if you want, and Vim will recognize them as well. Vim will also delete the markers with the zd command, whether they were set manually or not.

Fold created with the marker method are subject to undo and redo operations, unlike normal manual folds.

It's possible to set the foldmarker to something other than {{{ if you need to, but the Vim docs recommend that you stick with the defaults. To change the foldmarker, use :set foldmarker=nnn,mmm where nnn is the character string to start the marker, and mmm is the string to end the marker.

If you want to use a foldmethod other than "manual" all the time, add this line to your ~/.vimrc:

set foldmethod=foldoption

Vim has a few other foldmethods that may come in useful. See the foldmethod documentation in the Vim reference materials for more on the foldmethod option.

Saving folds

After you've gone to all the trouble of creating several folds in a longer document, it'd be a shame to lose them when you close the file. If you'd like to save the folds before you leave the file, run :mkview. When you reload the file, run :loadview, and Vim will restore the folds to the state the file was in at the time you ran :mkview.

The :mkview command supports multiple revisions of a file's state, so you can give a view a number and reload later on. For example, if you run :mkview 2, make a few changes, and then run :loadview 2, it will revert to the previous state of the file as far as folds are concerned. Note that it won't restore the file itself to the previous state; if you delete 10 lines of text after saving a view, Vim won't restore those lines when you load an older view using :loadview.

But why do something manually when you can do it automatically? To see to it that Vim saves and restores folds when a file is closed and re-opened, add these two lines to your ~/.vimrc:

au BufWinLeave * mkview
au BufWinEnter * silent loadview

Now, each time you close a file, its fold state will be saved and reloaded when you reopen the file in Vim.

When you add folds to other features like viewports and marks and jumps, Vim becomes an insanely productive tool for text editing and programming.

[May 17, 2006] Linux.com Vim tips Moving around using marks and jumps by Joe 'Zonker' Brockmeier

Basically, a mark is a bookmark or placeholder that allows you to return to a spot in the file where you were editing. This can be handy when you're working on longer projects, whether you're writing a long paper, making changes to your Apache configuration, or writing code.

Jumps are movements within a file. For example, when you use G to move to the last line of a file from your current position, that's a jump. Vim not only makes it easy to move from one point in the file to another, it also makes it easy to retrace your steps.

m marks the spot

Let's take a look at Vim marks. All you need to do to set a mark is to enter normal mode, then type mx , where x is the letter you want to assign to the mark.

For example, if you're typing and decide that you need to set a mark so you can return to a sentence or line of code you're not entirely happy with, press Esc to leave insert mode, then type ma to set a mark at the spot your cursor was on.

You can use any letter in the alphabet, upper or lower case. However, capital letters are global marks, so you should use them only in special circumstances, which I'll explain in just a bit. It's not necessary to use them in alphabetical order; you can set mark z right after setting mark a if you like, or skip a altogether and start with z.

To return to the mark you've set, enter normal mode (if you're not in normal mode already) and type `x where x is the letter associated with the mark you want to revisit. The backtick (`) will return you to the exact spot where the mark was set. You can also use the single quote ('), which will return you to the beginning of the line you were at, but not the exact cursor position.

Marks set with lowercase letters are specific to the file that they're set in. That is to say, if you are using a Vim session to edit two files in a split viewport, then you can set mark a in both files. When you're editing file 1, using `a would take you to mark a in file 1. When in file 2, `a would take you to the spot in file 2 marked a -- which is probably what you'd expect.

However, if you're using Vim to edit two files and you've set mark A, it will be specific to that file. So, if you're editing file 2, and have mark A set in file 1 and use `A, Vim will close the current file and take you to mark A in file 1. If file 2 has unsaved changes, Vim will complain that you haven't written the file since the last change, and refuse to open the new file.

While global bookmarks are useful on occasion, it's usually best to stick to lower-case marks unless you have a specific need for global bookmarks.

Now where did I leave that?

After spending an hour or two editing a file, you might forget exactly where you've set marks in a file. If you'd like to see where they are, you can enter command mode and use the :marks command. Vim will display the name of each mark, the line and column number where it is set, and part of the text from that line. Note that Vim won't start the display on the column where the mark begins -- instead, you'll see the beginning of the line where the mark is set. So, if you've set marks for a, b, and c, you will see where those marks are set, but you'll also see a few other marks that you might not recognize. Here's a shortish example:

mark line  col file/text
 '    112    0
 a     11    3 <p>For example, if you're typing and decide that you
 b    103    0 <p>By default, when you exit Vim, the marks that you've
 D     26    0 ~/src/gaim-2.0.0beta2/src/Makefile
 0     61   60 <p>The " mark is set to the last position of the cursor
 1    103    0 <p>By default, when you exit Vim, the marks that you've
 "     35    0 <p><strong><code style="background-color: yellow;">'"</code>
 [     52    0
 ]     54    0
 ^     54    0
 .     73  115 <p>The . mark will take you to the last position a change
Press ENTER or type command to continue
Vim mark quick reference

mx tells Vim to add a mark called x.

`x tells Vim to return to the line and column for mark x.

'x tells Vim to return to the beginning of the line where mark x is set.

`. moves the cursor to the line and column where the last edit was made.

'. moves the cursor to the line where the last edit was made.

'" moves the cursor to the last position of the cursor when you exited the previous session.

:marks shows all marks set.

:marks x shows the mark named x.

:jumps shows the jumplist.

Ctrl-o moves the cursor to the last jump.

Ctrl-i moves the cursor to the previous jump.

H moves the cursor to the top of the screen or viewport.

M moves the cursor to the middle of the screen or viewport.

L moves the cursor to the bottom of the screen or viewport.

Specifically, you'll see marks for ., [, ], ", ', and a few others. Those marks are present whether you've set any marks manually or not. The [ and ] marks indicate the last changed or copied ("yanked") text. The [ mark is the first character of the text that's been changed or yanked, the ] is the last character of that text. Note that these marks don't work until you actually make a change in the file.

The . mark will take you to the last position a change was made. So, '. will take you to the line where the last change was made in your file, and `. will take you to the cursor position where the last change was made.

If you make a jump within a file -- that is, if you use a movement or search command to move within the file -- the ` character will return you to the position you started from. For example, using the G movement command you can jump to the bottom of the file. If you want to return to the last cursor position, use `` and you'll be moved back to the last location of the cursor before using G. We'll discuss jumps in more detail a bit later.

The " mark is set to the last position of the cursor when you exited the previous Vim session, if you have Vim configured to save your session information using a viminfo file. We'll cover that in just a bit too.

Finally, if your session information is being saved, you can also use numbered marks to return to the last position the cursor was at when you closed a file. Using numbered marks, `0 will move the cursor to the last position it was at when you closed a file. `1 will move the cursor to the last position it was at when you closed the file the time before last, and so forth.

If you just want to know where a specific mark is in the file, you can use :marks markname to display just those marks. To see marks a and B, for instance, you'd just use :marks aB. This is pretty useful when you have 10 or 20 marks set.

Advanced marking

Marks are useful for more than just moving about a file -- though that feature alone is very useful. Marks can also be used to specify a range for commands. Normally, if you want to delete a few lines, you can use line numbers to specify the line, like so:

:22,55 d

That will delete lines 22 through 55. But it's much easier to remember marks than line names most of the time. If you have line 22 marked as g and 55 marked as k, you could substitute :'g,'k d and remove those lines without having to go back and confirm the line numbers. This works with other commands too, so you could just as easily write those lines to a file using :'g,'k w filename or use the range for a substitution command like this:

:'g,'k s/foo/bar/g

The jumplist

Vim stores a list of your movements throughout a file, whether they're associated with marks or not. To see a full list of jumps within a file, use :jumps. Here's a short sample:

:jumps
 jump line  col file/text
    3     1    0 /**
    2   608    0 }
    1    33    0 #include "log.h"
>
Press ENTER or type command to continue

Vim lists the jump number, line number, and column of the last location of the cursor for each jump, as well as a bit of text to help provide context. You can cycle between jump locations using the Ctrl-o and Ctrl-i keybindings. Ctrl-o will move you to the last jump, then the next-to-last, and so forth. In this instance, if you use Ctrl-o, you'd be taken to line 33, then line 608, then 1. To move forwards through the jump history, use Ctrl-i -- which would take you from line 1 (jump 3) to line 608, then line 33.

Though they're not jumps, since we're discussing moving around a file easily, you might want to familiarize yourself with the movement commands G, gg, H, M, and L. G, as we've already discussed, will take you to the bottom of the file. The gg command will move you to the top of the file. The H, M, and L commands will move you to the top, middle, and bottom of the screen, respectively.

Saving marks and jumps

By default, when you exit Vim, the marks and jumps that you've created are lost. Luckily, there's an easy way to save the marks you've created by making use of the viminfo file, which saves state information between Vim sessions.

To make sure this feature is enabled, open your .vimrc and look for a line that begins with set viminfo=. If you don't have that line, insert it. It should look something like this:

set viminfo='100,f1

If you have viminfo set, it will save local marks (a-z) by default. The '100 tells Vim to save marks and other information for up to 100 files. The f1 directive tells Vim to also save global marks (A-Z) when it exits. If you don't want Vim to do this, set it to f0 instead.

You can use the viminfo file for a lot more than saving marks and jumps, but we'll have to cover that in a future installment.

[May 10, 2006] Linux.com Vim tips Using viewports

A lot of folks use Vim, but many exploit only a small percentage of the editor's features. Sure, you might know how to do the basics in Vim, but what about using more advanced features such as folding, split windows, and marks? With a little practice, you can really boost your productivity with Vim.

In this and future articles, I'm going to cover Vim features that you may not be familiar with if you're a casual Vim user. If you're confident using Vim to edit configuration files or make short edits in text files, but maybe not too comfortable with undertaking major writing or coding in Vim, then these articles should be for you.

Splitting Vim's viewport

A really useful feature in Vim is the ability to split the viewable area between one or more files, or just to split the window to view two bits of the same file more easily. The Vim documentation refers to this as a viewport or window, interchangeably.

You may already be familiar with this feature if you've ever used Vim's help feature by using :help topic or pressing the F1 key. When you enter help, Vim splits the viewport and opens the help documentation in the top viewport, leaving your document open in the bottom viewport.

Vim viewport keybinding quick reference

:sp will split the Vim window horizontally. Can be written out entirely as :split .

:vsp will split the Vim window vertically. Can be written out as :vsplit .

Ctrl-w Ctrl-w moves between Vim viewports.

Ctrl-w j moves one viewport down.

Ctrl-w k moves one viewport up.

Ctrl-w h moves one viewport to the left.

Ctrl-w l moves one viewport to the right.

Ctrl-w = tells Vim to resize viewports to be of equal size.

Ctrl-w - reduce active viewport by one line.

Ctrl-w + increase active viewport by one line.

Ctrl-w q will close the active window.

Ctrl-w r will rotate windows to the right.

Ctrl-w R will rotate windows to the left.

If you want to use this feature for something other than viewing Vim's help files, you can split the viewport by using :sp, :split, or Ctrl-w n -- they do the same thing, but just typing :sp will save you a few characters, and it's easier to use with arguments, such as filenames. Remember the Ctrl-w part, though, because it will come in handy for most operations with windows.

The :sp command will divvy up the viewport into two equal viewports for the file that you have open. If you'd like to work on two files simultaneously, no problem -- just follow the command with the filename you'd like to use, like this:

:sp filename

That will open filename in the new viewport. You can even add a search string to that to move directly to the first instance of a keyword, like so:

:sp +/searchstring filename

Easy as falling off a log. What if you don't want to have equal viewports? For example, let's say you want to open a reference file in the top viewport, but want the majority of the viewport available for the file you're actually editing. No problem. Just prepend a number to the sp command, and the new viewport will fill that number of lines:

:10 sp filename

Now you have a viewport with 10 lines, but what if you've decided that you'd like to give both viewports equal real estate? That's easy enough too. Instead of going into command mode, you can use a normal keybinding to accomplish this. Ctrl-w = tells Vim to assign an equal number of lines to each viewport.

To move between the viewports while working, use Ctrl-w j to move down, and Ctrl-w k to move up. This should prove easy to remember -- Ctrl-w for "window" commands, and the normal vi movement commands j for down and k for up. You can also cycle between viewports by using Ctrl-w Ctrl-w.

You can increase or decrease a viewport's size after it's been created. Use Ctrl-w + to increase the active viewport, and Ctrl-w - to decrease its size by one line. If one line at a time isn't sufficient, add a modifier before the + or -. For instance, to add 13 lines, use Ctrl-w 13+.

If horizontal viewports just don't do it for you, Vim also supports splitting viewports vertically. To do this, just use :vsp, or :vsplit if you prefer to spell it out. Movement between vertical viewports is similar to moving between horizontal viewports. Ctrl-w Ctrl-w works, and instead of using the j and k movement keys, use the h and l movement keys to move back and forth between viewports. To move to the viewport to the right, for example, you'd use Ctrl-w l.

It's also worth mentioning that you can open a file in a viewport just to view the file, without opening it to edit. To do this, use the :sview filename command. To do it vertically, use :vert sview filename .

You can close a window in one of several ways. The easiest is to just use the quit command, :q, or you can use Ctrl-w q. Note that if it's the only window open with a file, Vim will prompt you to save the file if it isn't saved already.

Also, it's possible to rotate the windows, if you decide you'd prefer to have the top window on the bottom or vice versa. To do this, use Ctrl-w r to move windows to the right or down. When you do this, for example, in a Vim session with three horizontal viewports open, the top viewport would go to the middle position, the middle viewport would take the bottom position, and the bottom viewport would rotate to the top. To go in the opposite direction, use Ctrl-w R instead.

Vim often offers several different ways to achieve the same things. For instance, as I pointed out, :sp, :split, and Ctrl-w n all create a new viewport. I haven't listed all of the possible commands or keybindings to accomplish all of the tasks here.

Over the years, I've found Vim's split windows features to be very useful. I often use it to edit a column or article in one viewport, and to read and copy from notes in another viewport.

[Mar 28, 2006] All about Linux Vim author gets hired by Google

Things have changed though - at least for Mr Moolenaar, because he has just been hired by Google and will start working for the search giant in Zurich. Does that mean, further development of Vim is going to take a back seat? Not at all! Bram has committed himself to its further support and development albeit at a reduced pace.

On a different note, I came across this cool cheatsheet which acts as a spring board in getting up and running in using vi / vim with ease. Of course, this is not in any way related to the official project.

[Nov 15, 2005] Windows Manager - 1.0

winmanager.vim is a plugin which implements a classical windows type IDE in Vim-6.0. Vim6.0 has some very cool features one of which is vertical splitting of windows. The time was thus ripe to make something like this. People have already made excellent File and Buffer explorers seperately and I thought that it might be a cool idea to combine them both.

winmanager.vim combines the standard File Explorer which ships with Vim6.0 and a Buffer Explorer written by Jeff Lanzarotta into one package. Unfortunately, I had to change a few features here and there so instead of using the packages as is, I have to ship a relatively very small plugin with all of the original code from both packages basically just dumped at the end with just a few things changed here and there. When you open up a new file, simply type in :WManager. This will start up the file explorer.

[Jun 01, 2005] perl-support.vim : Perl-IDE

Write and run Perl-scripts using menus and hotkeys. (2.6) + blocks: opening brace no longer on a new line (adjustable for backward compatibility). + Vim (without GUI): new key mappings: all entries in the run menu do have mappings now. + Vim (without GUI): perldoc can be read with hotkeys \h and \rp . + Vim (without GUI): perldoc displays docs using plain text converter.+ output into buffer: cursor goes to top of file. + trailing ^M in perldoc window... - Fritz Mehner

[Mar 1, 2005] Vim Color Schemes

Featuring 161 themes:

Continued...


Usenet and mail lists

Please read all of the VIM FAQ before asking questions. Thanks!

Usenet Newsgroup with a lot of vim users: comp.editors

Yahoo! Groups vim


Tutorials


Advanced VI


Reference

see also The VI Pages - All About VI and its clones

Reference cards:

  1. How do I move the cursor in the file?

  2. How do I insert text?

Once you entered input mode, the way to return to command mode is by hitting the Escape key: ESC or CONTROL-[.

  1. How do I delete something?

  2. How to undo and repeat commands?

Sun bloggers

The Clingan Zone

Random Findings

the vi reference mug



Etc

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available in our efforts to advance understanding of environmental, political, human rights, economic, democracy, scientific, and social justice issues, etc. We believe this constitutes a 'fair use' of any such copyrighted material as provided for in section 107 of the US Copyright Law. In accordance with Title 17 U.S.C. Section 107, the material on this site is distributed without profit exclusivly for research and educational purposes.   If you wish to use copyrighted material from this site for purposes of your own that go beyond 'fair use', you must obtain permission from the copyright owner. 

ABUSE: IPs or network segments from which we detect a stream of probes might be blocked for no less then 90 days. Multiple types of probes increase this period.  

Society

Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy

Quotes

War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes

Bulletin:

Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law

History:

Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least


Copyright © 1996-2016 by Dr. Nikolai Bezroukov. www.softpanorama.org was created as a service to the UN Sustainable Development Networking Programme (SDNP) in the author free time. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License.

The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to make a contribution, supporting development of this site and speed up access. In case softpanorama.org is down you can use the at softpanorama.info

Disclaimer:

The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the author present and former employers, SDNP or any other organization the author may be associated with. We do not warrant the correctness of the information provided or its fitness for any purpose.

Last modified: November 08, 2017