Is Vim Right For You? Answer: Yes

Vim has many things going for it. Not small detail things. All the small detail things can be customized. Vim is different in major ways.

  • Vi keys - Don’t like CTS, RSI, or even just feeling clumsy? Getting used to HJKL as movement keys seems very weird at first (I know! I remember my awkward early experiences clearly) but once you’ve spent a little time with this concept, you’ll hate all software that does not take advantage of it. Although many excellent programs do use it naturally (Mutt, less/man, even Bash if you want), when they don’t there’s often a way to fix that. The most important example is Vimperator and Vimium which turns your browser’s frustratingly clumsy interface into something efficient and productive.

  • Modal - Vim has a concept of "modes" which is very profound and worth contemplating seriously before rushing off with the shiny editor du jour. There are quite a few modes in Vim, but the two critical ones are "insert" and "edit". This sounds a bit technical, but think of "insert" mode as "compose" mode. Now you can see that Vim has divided all functionality into categories which, if you think about it, are very different. The only downside to this is that you have to explicitly know (and specify) which of these modes you want to be in. But once you’ve committed to making that decision every time you either compose or edit, the power available to you is greatly increased while distractions are removed. Just as MS Word with its one mode, "compose/edit/typeset/leak-metadata", is pointless if you plan to never typeset (i.e. most code), having an editor with fully live "compose" functions makes no sense if you are just debugging code ("editing").

  • The Unix way - Small things done properly is a core Unix value. Small things can be combined to form complex things. Learning the small things can be done at your own pace and each thing learned magnifies the power of all the other things you learn. For example, in Vim there are equivalent functions for the Emacs functions named forward-word, move-end-of-line, end-of-buffer, and forward-paragraph. They are named w,$,G,}. That may seem more cryptic but the Emacs bindings for these functions are ESC-F, CTL-E, ESC->,ESC-}. Of course in Vim they are bound to w,$,G,}. What’s really interesting, however, is what you find when you look deeper. Consider deleting. What if you want to delete a word, delete to the end of a line, delete to the end of a file, or delete to the end of a paragraph? Emacs has kill-word (bound to ESC-D) and kill-line (bound to CTL-K). Vim just has d (bound to d). That doesn’t sound very explicit and that’s because it isn’t. It gets combined with the movement keys to form dw, d$, dG, and d} which stand for "delete word", "delete to end of line", "delete to end of file", and "delete to end of paragraph" respectively. Now if you learned that to search for the word "stdio" in Vim was /stdio it probably wouldn’t surprise you or be hard to learn that d/stdio deletes everything up to the next instance of the word "stdio". If you learn that the command for inverting the case of something was ~, it wouldn’t surprise you to learn that inverting the case of the next word was ~w. Although the commands can seem cryptic, they do all have an incredibly elegant plan. They all work together and build upon each other. This makes learning much easier than you thought, even if it isn’t optimized only to be easy for novices. I believe that if using an editor is and will be a serious part of your vocation, optimizing on "easiest to use in the first few days" is a mistake anyway.

  • More on Vim’s compelling big concepts.

  • To really get a sense of Vim’s power, you can look at a newfangled text editor that earnestly tries to improve on Vim. The Kakoune editor has some very excellent ideas. Unlike other more trendy modern editors that compete only for "Best Editor That Is Not Vim", Kakoune squarely confronts the titanic majesty of Vim and endeavors to make some sensible plausible progress. Many of its core motivations — described here — are validations of Vim’s strategic approach.

Vim References

How To Use Vim To Manage Passwords

Modern life is filled with passwords. I personally have hundreds of accounts and if there is any hope of me using good unique passwords, I simply can not remember them all. Some people use fancy password managers. The technique I use is to simply keep them in a text file which I manage with Vim. Of course keeping your passwords in a text file sounds like it would have many security deficiencies and were it not for Vim’s fantastic features this would not be a good idea. Here’s what I do.

Since I use this pretty often, I set up an alias to do all the hard work. The alias looks like this:

# Set up an alias for a Vim-based password manager.
PWFILE="~/mysecuredir/pw"
PWOPTS="\
foldmethod=indent \
noswapfile \
bufhidden=wipe \
tw=0 \
nobackup \
nowritebackup \
viminfo= \
foldclose=all \
"
PWCMD="/usr/bin/vim $PWFILE "
for PWOPT in $PWOPTS; do PWCMD="$PWCMD -c \"set $PWOPT\" " ; done
eval "alias pw='$PWCMD'"

If you use screen/tmux a lot, you sometimes can get into trouble opening your password file in two different terminals which is not ideal. I now use the following instead of the last line defining the alias shown above.

function pass {
if ps -ef | grep mysecuredir/p[w] >/dev/null; then
    echo "Already open?"
else
    eval $PWCMD
fi
}

This format of the alias definition shows clearly all the special Vim settings that I use. This suppresses Vim’s normally helpful behavior to save everything you do in a somewhat insecure way. This does not allow a viminfo file, nor backup creation, nor swapfile use. The option for tw (text width) is so I don’t get automatic line feeds since I’m not typing prose. Finally the foldmethod and foldclose options set up folding.

The idea with the folding is that when the file is opened, none of the passwords will be visible. Only when you search for the password you want will it be revealed under the fold. The point to this is that if you have to look up a password in an insecure place, people in the vicinity won’t be able to gawk at all your passwords. To make this work you need to exercise some discipline with the format of your password file, but it’s not complicated. Here is an example of a password list with the correct formatting.

-
    southcentralairlines.com
    mrfflyer:nLew7f-il
-
    eztax.com
    mrtaxpayer87:bDtc8fPa
-
    at&t AT&T att ATT
    1-800-288-2020
    Called 11-06-27 to cancel Confirmation #D91429932
    My land line number 858-560-1254
    Account number 858 560 1254 718 2
    Online registration code: 30287891
    vengeful@pookmail.com:fu1l0wrath:fullof-sh1t (required a # in username!)
    These guys are complete shite:
    "TLE107: We apologize for the inconvenience. We are currently experiencing a
    temporary system error that prevents us from retrieving your account
    information." April 30, 2011
    CC#: 6999999999999999 1/12 123
    Security questions:
    "What is your dream job?":"Putting ATT out of business."
    "What is your favorite football team?":"I seriously hate ATT!"
-
    monstersfighting.com
    http://parents.monstersfighting.com
    quitedead:xed-monstersfighting@pookmail.com:30ssapb33bd
    Birthday used: January 1, 2005
    Hint: penguin, tiger, fox, fox, rabbit
    crazebra:30sszp933bd
-
    cheapjunkfromchina.com
    mrbuyalot:oex3nLGep

Things to note: Each record begins with a -. This is used to let the folding know that this is a record separator. It is not indented. Next notice that all the other lines are indented. You can make it tabs or spaces but it’s a good idea to be consistent. I use four spaces. You can see that I don’t just store password data, but I also often include pretty full details about what I need to remember about a company or account. In the infamous ATT example, I keep a record of all the times their stupid web site was down. I also keep particular custom credit card numbers that I only use with this vendor here (Discover used to provide this capability). Since it’s Vim, you have complete flexibility. Since you’re using folds, it’s perfectly reasonable to write as much as you want. When you save this file and then use the alias (pw as defined above) to edit it, it should look like this:

 -
 +--  2 lines: southcentralairlines.com------------------------------
 -
 +--  2 lines: eztax.com---------------------------------------------
 -
 +-- 15 lines: at&t AT&T att ATT-------------------------------------
 -
 +--  6 lines: monstersfighting.com----------------------------------
 -
 +--  2 lines: cheapjunkfromchina.com--------------------------------

As you navigate around the document, only the fold that your cursor is on will be open. Since I have so many accounts in this file, I generally hit / right away and search for the account I’m interested. Because of this, I’m pretty careful to always use lower case, or, as with the AT&T example, multiple options if I think I will forget.

Now that you have a nice system for creating a very straightforward text file for storing your passwords, it is probably a very good idea to impart some cryptographic protection. It turns out that Vim comes with an encryption mechanism built in.

Warning
The Vim developers claim that the encryption isn’t the strongest encryption possible. I could imagine that a very dedicated attacker could break this encryption. However, I don’t think that’s a realistic threat model for me. If you do, you might want to use other encryption techniques (gpg or ccrypt maybe).
Note
The putative insecurity of Vim’s default mechanism has been fixed with an option that allows the user to specify the encryption method. The option is cryptmethod and it can be the default zip or the theoretically more secure blowfish. People in the know say the latter is much more secure so it’s probably a good idea to do a set cryptmethod=blowfish while your file is open. You only need to do this once and from that point on it should be encrypting with the Blowfish cipher. It’s like having Bruce Schneier personally kung-fu fighting the NSA.
Note
While the blowfish method described above was a big improvement for Vim encryption, this seemed to invite even greater scrutiny by sophisticated people now deigning to use Vim for secure tasks. And it turned out that there were some weaknesses found. And then there was a resulting fix, a cryptmethod called blowfish2. This is available on Vim 7.4.399. Read about the details here.

To encrypt a file with Vim (remember, this handy feature works with any file you want to keep private), in edit mode type :X. It should respond with Enter encryption key: which you should do. Note that a long pass phrase with spaces is allowed and probably a good idea. Perhaps something Dylanesque like "2 much confusion, I can’t get no relief." It will ask you to Enter same key again: to make sure you really know how to type what you think you’re typing. Now the encryption key is set. To encrypt it, just do a normal :w. It should say something like "pw" [crypted] 34L, 1060C written where the "crypted" flag lets you know it’s no longer being saved as plain text. Now when I do less pw to look at the file from the unix command line, it says "pw" may be a binary file. See it anyway?". It sure is a binary file:

$ cat -A pw | head -c 20
VimCrypt~01!9M-^QM-^

That’s all that you get to know about the file from examining its encrypted contents.

In the future, when you use the pw alias, it will ask you for your pass phrase. Once you enter it, you can edit as normal and when you’re done, you can save it as normal. To make a file stop being encrypted, just do :X as before, but just hit enter for the passwords. Then use :w to save it as plain text again. This is also how to change the password, for example, if you think it became compromised.

Warning
One other thing to keep in mind is that if you are using a normal modern terminal (gnome-terminal, etc) you may have a bunch of sensitive password information from your edit session tied up in your scrollback buffer. I pretty much always use a new window of a screen session to work with my passwords and exit from that window when I’m done. It might be a good idea to open a fresh terminal to use your password file and kill that terminal when you’re done. Also, it should be obvious that if you put sensitive things in the clipboard buffer, well, there will be sensitive things in the clipboard buffer.
Warning
After using Vim to store passwords like this for 15+ years I discovered a serious flaw. It is easy to fix but you must be aware of it. Let’s say that you’re not feeling well and your typing skills are severely diminished (true story!). When you go to enter your password, it is more likely than ever that you’ll mistype it. That’s not too unusual. But if you’re really off your game, you may mistype ":q" to quit the gibberish that your failed decryption presents you with. If you accidentally type ":w" then you will save the random noise over your real encrypted password file. This is very bad. The answer is to have a backup. Having cron cp a week’s worth one per night might not be a bad plan. They all will still be encrypted. This just gives you some latitude if you mess up your original. There might be a way to have Vim just fail instead of "opening" the file on an unsuccessful passphrase. Official Vim documentation even says this: If you make a typo when entering the key and then write the file and exit, the text will be lost!

Large Amounts Of Prose

How To Remove Hard Returns From Paragraphs

The question is whether to put hard returns in as you go or keep each paragraph continuous. I like to see the hard returns and can deal with them fine. But when you need to export your composition to a word processor or a web form box, it can be necessary to join the lines in a paragraph. The following works pretty well for that:

:%s/\n\([^\n]\)/ \1/
:%s/^/\r/
:%s/*/\r*/g

The last one sorts out any bullet lists you may have had. If you don’t need bullets worked out.

:%s/\n\([^\n]\)/ \1/ | :%s/^/\r/

Or this also may be an even better strategy.

:g/^./,/^$/-1 join

How to break up large chunks of single line text

Often you get a file that comes from a sensible word processor (maybe even vi itself). This text only puts hard returns at the end of paragraphs. If you need hard returns put in everywhere so that you can deal with the text in vi or other line oriented tools, here’s the sequence. This routine basically makes a textwidth of 75.

# This is obsolete but still serves as an example of the macro format.
qq        # start a macro named `q'
77|        # move to column 77
?<spc><enter>    # search for the previous space which should be before 77
r<enter>    # replace it with an enter
k        # move up to the line that was just created to prime search
/^.\{75,} <enter>    # goto next line with more than 75 characters
q        # end macro definition

To execute this, go to a line that needs some hard returns (don’t start on a small line that doesn’t need any!) and use @q. Using @@ will cause it to continue. Since the number of lines is not known (you’re creating new ones all the time with this), it’s tough to automate it completely. Try 500@q and see if that gets it. It should stop at the end if the search is not found, but this could depend on the WRAPSCAN setting.

Also note that the gq command will automatically sort out text like this macro. Probably best to stick with that.

Email And Lists And Comments And Other Tricky Formatting

When responding to email it’s nice if replies start with >. Vim is very good at this but if the setting that makes this work gets turned off for some reason, it can be a pain to figure out what exactly it is. The setting of importance here is the comments variable. You can do this to get email working.

set formatoptions+=n
set comments+=n:>

I had to reload the buffer and do these changes before it started working so YMMV.

To format some Bash/Python/Docker comment text.

set comments=:#

This is important for, obviously, comments but also for things like bullet points and that weird dash problem where trailing dashes get wrapped weirdly. See :help format-comments for all the gory details.

Vimium

Vimium is an extension for Google Chrome that makes the browser interface much less horrific. Here are some useful shortcuts for it.

?

Help

gs

go source

d|u

down|up a half a page

yy

copy current URL to clipboard

yf

copy link’s URL to clipboard

gf

go next frame

H|L

back|forward in history

[[|]]

previous|next link follower on pages with "Next" features

gi

go to next input box

How To Use Vim For C Programming

First you need to understand how to get make to work for you. Use set makeprg=make to set your make executable (gmake or maybe a make\ \CC=gcc). Set up your Makefile or whatever your make program likes.

Tip
Makefiles are annoyingly fussy about tabs (which I usually avoid in all other situations). See the section on tabs for details.

Test the make process from the command line outside of Vim and when it works fine, it should work fine in Vim by using the :make command. This can be shortened to :ma for the impatient.

After make runs, if there are errors, Vim takes you to the first of them. To move to the next error use :cnext or :cn. Also there are clast, cfirst, and cprevious.

Some people like to see line numbers (with :set number or :se nu) but I find it pointless since you can always go right to where the issue is by typing the line number of interest and gg. So to go to line 15, type 15gg.

I haven’t used it but there is also support for exuberant-ctags (try apt-get install exuberant-ctags). And maybe look into :cscope (try apt-get install cscope).

Look at the section on customizing Vim’s syntax highlighting where I show specifically useful things about C++.

Tabs

I do not like tabs because to me it seems like non-obvious behavior. There is, or may be, maybe not something invisible lurking in your document. When moving around a document, having it suddenly jump is unnerving when you didn’t tell it to do that. It is easy in Vim to not use tab characters and get the same indentation functionality.

Show Tabs

Sometimes just seeing the mess is the most important step to solving it. To see tabs you can have search highlighting on and just do /\t or you can turn on set list. Set list can be customized further with something like this.

set listchars=tab:>-,trail:_

Or if you want fancy characters that you won’t confuse for your real ones, try something like this.

set listchars=tab:»·,trail:¤

Tab Settings

Here are the important functions for dealing with tab settings.

  • set tabstop=4 - Also ts. Sets how many spaces a tab is worth. If real tab codes aren’t to be used, it is the number of spaces that are used.

  • expandtab - Also et. When tabs are entered as normal, this puts spaces in the document instead. The number of spaces is controlled by tabstop. To enter a real tab when expandtab is active, use CTL-v and then <tab>. If you have no tab key (think SSH from a phone), use CTL-v CTL-i.

  • retab - Also ret. Replace all whitespace sequences with appropriate tabs based on the new tabstop value. This means that 8 tabs with a tabstop value of 4 will turn into 4 tabs when :retab 8 is declared. If expandtab is set, then tabs are converted to the number of spaces specified.

  • set shiftwidth=4 - Also sw. Used with autoindent to assign how many columns text is indented. Also used with << and >> to indent blocks.

Converting From Tabbed Formatting

If there are tabs in a file and you wish that was not the case do this:

set ts=4 | set et | ret 4

Converting To Tabbed Formatting

If you have a sensible document and heretics (like Linus Torvalds) insist that you put stupid tabs in something, then do this.

set ts=8 | set noet | %s/        /\t/g

Multi window operations

ctrl-W

kicks off the multiwindow functions

s or :split

splits window into 2 parts

:split filename

splits to edit filename simultaneously

f

splits and edits file under cursor

n

splits to New window

q

quit editing and close a split window

c

close window and put buffer in background

o

make current window the only one on the screen

j

move to window below

k

move to window above

:buffers

list buffers in action

:bnext

puts next buffer in window

Searching

The general form of a search and replace operation is: :1,$s/findme/repwithme/g

  • the 1 is the line #1

  • the $ is the "last" line

  • the s is the command that kicks off the search

  • the / is the first of three delimeters that separate the parts

  • findme is the string that we are looking for

  • repwithme is the string that we’d like to be in the place of findme

  • the g is a flag to make the operation global - otherwise only one s&r per line

  • :%s... can be used instead of 1,$ to specify the entire range

Macros - Hey, they’re easy!

Define A Macro

To define a macro, press q and then some symbol, usually a letter. This starts the macro recorder for the macro named the symbol you chose. For example: press q then x. This sets the recorder for the macro named x. Now everything that you type will be saved as something you might want replayed later. When you are finished recording your sequence that you want repeated, press q again.

Replay A Macro

Then position the cursor where you want the sequence to kick off again and press @ (shift 2 on my keyboard and on a German one it’s in the same area). This is the play button, but you still need to tell it what to play. Press x.

If for some weird reason you’d like to pretend a macro didn’t happen (not undo!) and purge it and replace it with the original nothingness, use this: qxq

You should not define a macro that plays itself like this: qxiHITHERE!<esc>q qx@xq That’s bad! I’ve had it go crazy, but I think hanging is more normal - pressing Ctrl-c seems to do the trick. At least Vim has a well behaved error recovery!

Custom Commands

If Vim is missing a command that you think should be present, you are free to fix that.

  • Must be upper case.

  • % is translated into the current file name (See :registers).

  • To escape %, you need to precede it with backslash, but you might need to do that both when defining the command and when running it. This means two backslashes.

Here’s an example that inserts a custom formatted date into your document.

:command! Day execute '!r date "+\\%Y-\\%m-\\%d~\\%a"'
:Day

This will put 2017-08-12~Sat in your file.

Using Vim To Acquire Input

Let’s say you have a script that needs the user to contribute some text. You could use simple things like Bash’s read built-in but maybe you want the program to allow fancier editing. For example, I have a program that processes my blog and one of the modes allows me to compose an entry in the middle of this running program.

Bash

#!/bin/bash
VIMCMD="/usr/bin/vim"
TDIR="/tmp"
T=$(mktemp --tmpdir=${TDIR} textinput.tmp.XXXXX)

${VIMCMD} -c "set tw=0" ${T}

# Do something with file ${T}
D=$(date "+%Y%m%d %H:%M")
sed -i "1s/^/${D} /" ${T}

cat ${T}
rm ${T}

Python

def live_edit_new_content():
    import tempfile
    import subprocess
    tmpfileob= tempfile.NamedTemporaryFile(dir='/tmp')
    tmpfile= tmpfileob.name
    vimcmd= '/usr/bin/vim'
    subprocess.call([vimcmd,tmpfile])
    the_content= tmpfileob.read()
    tmpfileob.close() # Deletes tempfileob too.
    return the_content

Visual Mode - (it’s vi, not ex, but that’s not what they mean)

The "visual" mode is just a mode where you can highlight text and then do things to it. And they say vi is old fashioned! Just press v and do the move around bit. You can also do Shift-V for linewise selecting and ctrl-V for blockwise selecting. Isn’t that great?

Well what are you gonna do with that highlighted text? d :: Gets rid of it ~ :: Changes its case "miXED up!" is now "MIxed UP!" U :: Uppercase "Mixed up!" is now "MIXED UP!" u :: Lowercase "Mixed up!" is now "mixed up!" y :: seems like copy - you can then use p to reinsert it o :: go to the other end of the selection to modify that point J :: joins the selected lines of text together <<:: Indents it to the left. >>:: Indents it to the right.

Set the settings

To set the digraphs flag use :set dg This allows you to do cool stuff by typing part one, BS, and then part two.To see what your options are, check out the codes with :dig Sometimes this doesn’t work out on some displays and some terminals, etc. But I have little doubt that Vim is planting the correct character codes for your encoding as you specify.

Another one that I like is the tw setting. I usually use 70, like this:

:set tw 70

Why 70? Voodoo superstition. Anyway, this adds a hard return after the last word that was completed before the column number you specify.

Compilation Feature

This is a list of some of the relevant things that should be compiled into Vim. This can be discovered by using the :ve command (version). (see :help feature-list)

autocmd

allows things to happen on events - works with syntax

cindent

special formatting modes for C programs

cmdline_compl

commandline completion

cmdline_info

facility enabling ruler and status display

comments
cryptv

a general purpose encryption scheme

cscope
digraphs

ability to enter accented characters

eval

ability to perform calculations and logic operations

ex_extra
extra_search
insert_expand

allows for various useful completions (filename, word, etc)

linebreak
menu
mouse
mouse_gpm
perl

a tie in with perl itself, execute perl commands in vim

smartindent
syntax

color and highlights of special formats (html,c,etc)

title
user-commands

allows user to define ex style commands

viminfo

auto saves registers and history across sessions in a file

visualextra

allows a few more things in visual mode

wildignore

can skip certain patterns in filename completion

wildmenu

shows completion options dynamically

xterm_clipboard
X11

restores old title to window (kvt, for example)

Configuring Syntax Highlighting

"16 CT|8 CT|COLOR NAME  See :help cterm-colors
"0     0    Black
"1     4    DarkBlue
"2     2    DarkGreen
"3     6    DarkCyan
"4     1    DarkRed
"5     5    DarkMagenta
"6     3    Brown, DarkYellow
"7     7    LightGray, LightGrey, Gray, Grey
"8     0*   DarkGray, DarkGrey
"9     4*   Blue, LightBlue
"10    2*   Green, LightGreen
"11    6*   Cyan, LightCyan
"12    1*   Red, LightRed
"13    5*   Magenta, LightMagenta
"14    3*   Yellow, LightYellow
"15    7*   White

So on 16 color terminals, just use the number. On 8 color terminals, * is bold to modify. Also the names are valid replacements for the numbers.

To see details about what is going on with a style you like:

:verbose highlight Identifier
Identifier     xxx term=underline cterm=bold ctermfg=6 guifg=#00c0c0
       Last set from /usr/share/vim/vim82/colors/pablo.vim line 16

Sometimes you see some weird irritating syntax in your program and you’d love to fix it but you have no idea what it is being controlled by. This nice tip will set up the F10 key to provide more detailed information about the syntax at the cursor position. It looks like this.

nnoremap <F10> :echo "hi<" . synIDattr(synID(line("."),col("."),1),"name") . '> trans<'
\ . synIDattr(synID(line("."),col("."),0),"name") . "> lo<"
\ . synIDattr(synIDtrans(synID(line("."),col("."),1)),"name") . ">"<CR>

A lot of times after you find that a certain style is being used, it then turns out that this style is "linked" to another. To make your own link to a better target, or unlink it and make your own version look at something like this.

highlight! link Boolean NONE
highlight! link Boolean Constant

Here the first line unlinks whatever the Boolean group was doing. The next line says that the Boolean group should behave like the definitions for the Constant group.

Note that for C++ specifically, there is a special filetype=cpp that goes beyond the filetype=c that adds things like class and true, etc. So make sure you’re not fighting with something like that.

Are there some things that should be highlighted but are not? Maybe you want common calls from a library you use a lot highlighted in a particular way. This nice C++ extension syntax file is a good model for how to add your own items to highlight.

Generally, for simple highlighting, the idea is you want to add some keywords to a named keyword set. Then link that to the type which renders the way you want this set to look.

syntax keyword Xed_color_cpp_extra_types
  \ ifstream iterator list array vector string deque map set stack queue
syntax keyword Xed_color_cpp_extra_kw
  \ case default
highlight default link Xed_color_cpp_extra_types Type
highlight default link Xed_color_cpp_extra_kw Statement

I have no idea how case and default didn’t get in the default; is this not kosher C++? But the C++ container types are just some examples of ones I happen to be using right now. If you look at the vim-cpp-modern vimrc, you’ll see that there are, of course, 23k keywords. Just kidding. I think.

Custom Syntax Highlighting

Sometimes you need to support a completely new type of syntax highlighting and for this you’ll want to prepare a syntax file just for this new format. Syntax highlighting is actually done by sourcing the syntax file. So if you’re testing your new syntax file out, just source it.

Sometimes you want to start Vim with a particular non-obvious syntax. This works.

vim '+set syn=svg' myembeddedlogo.html

The natural place for personal custom syntax files is here.

~/.vim/syntax/gg.vim

With that you can just :set syn=gg

And to make it automatic, you can put something like this in ~/.vimrc.

au BufNewFile,BufRead *.gg set filetype=gg tw=0

This page has a pretty good example of installing someone else’s syntax for exotic needs. In this case, it’s CNC G-codes — ahem, not all that exotic!

$ wget -O ~/.vim/syntax/ngc.vim https://wiki.linuxcnc.org/uploads/ngc.vim
$ wget -qO- https://wiki.linuxcnc.org/uploads/filetype.vim >> ~/.vim/filetype.vim

That last resource may be able to be put comfortably in your ~/.vimrc file, but I’ll show it here to provide a different approach.

filetype.vim
if exists("did_load_filetypes")
  finish
endif
augroup filetypedetect
  au! BufRead,BufNewFile *.ngc,*.gcode  setfiletype ngc
augroup END

Note that I also added the *.gcode extension because that was weirdly missing (e.g. Cura exports to that).

The actual details of creating your own syntax are pretty murky due to the profound efficiency of Vim’s syntax. But basically you need to define some stuff with syntax (or syn or synt, etc.) and then you need to link that to some highlighting style with highlight. The syntax specifier can look for a keyword (or many specified on one line). It can look for a regular expression match. It can also look for a range which I didn’t use.

Here’s my rough attempt to make a syntax highlighting file for GeoGad.

" Vim syntax file
" Language: GeoGad
" Maintainer: Chris X Edwards
" Latest Revision: 26 May 2018

if exists("b:current_syntax")
  finish
endif

syntax case match

syntax match ggBAD   /[,]/
syntax match ggTXT   /''.*''/
syntax match ggVAL   /[-+]\?[0-9]*\.\?[0-9]\+\([eE][-+]\?[0-9]\+\)\?/
syntax match ggLST   /\[.*\]/ contains=ggCmd,ggVAL,ggTXT,ggLST2
syntax match ggLST2  /\[.*:: *! *\]/ contains=ggCmd,ggVAL,ggTXT

syn match ggCmd /\s[~?!#%*+-/]\s/
syn match ggCmd /^[~?!#%*+-/]\s/
syn match ggCmd /\s[~?!#%*+-/]$/
syn match ggCmd / %n ++ -- ->/
syn match ggCmd /:* :+ < << <= = == > >= >>/
syn keyword ggCmd 2rad ZZ abs acos add all 2deg 2list
syn keyword ggCmd allent and angle asin atan avg blender ceil chtag clear
syn keyword ggCmd comb corr cos cov dd decorate depth detag dgg dist distexp
syn keyword ggCmd distgauss distweibull div doubles drop drop2 drop3 dropn dup
syn keyword ggCmd dup2 dup3 dupn e_ edup edup? entdup entpts entropy entscale
syn keyword ggCmd eq erase eval exit exp fact filter floor for foreach ge
syn keyword ggCmd get getn ggdG gt head headn help helpall idiv if ifelse
syn keyword ggCmd inert inv l ladd last lastn le len line list-> lmul log
syn keyword ggCmd log10 logbase lt m map max mean mid midn min mm mmdump
syn keyword ggCmd mmdumpb mmi mmitem mmlist mmsave mmsaveas mmtest mod move
syn keyword ggCmd mul name names nand ndist ne neg nor not nottag? or over
syn keyword ggCmd p parallelogram pcorr pcov perm pgram pi pick pickn place
syn keyword ggCmd pointform pos pow psdev pts put putn pvar quit rand range
syn keyword ggCmd rdz redo redraw refresh repeat repl rev revlist rot rotate
syn keyword ggCmd same scale sdev shuffle sin size sort source sq sqrt srand
syn keyword ggCmd sto sub sum svgout swap t tag tag? tail tailn tan tanimoto
syn keyword ggCmd tot tri undo undocheck undon unsto untag var version
syn keyword ggCmd viewshow vshow wake weightedmean while xnor xor xroot yank yy

highlight Normal ctermfg=Gray
highlight ggCmd ctermfg=yellow guifg=#ffff00
highlight ggTXT ctermfg=green  guifg=#00ff00
highlight ggLST ctermfg=cyan   guifg=#00ffff
highlight ggLST2 ctermfg=red   guifg=#ff0000
highlight ggBAD ctermbg=red   guibg=#ff0000
highlight ggVAL ctermfg=magenta  guifg=#ff00ff
"hi def link ggCmd Statement
"hi def link ggTXT Comment

let b:current_syntax = "gg"

This isn’t 100% correct, but it works pretty well and makes editing gg code a real pleasure.

Troubleshooting

Some time in 2014 my Vim started to get very laggy. I could type entire sentences before they would show up. I discovered that this was curable with set syntax=off. Unfortunately, I like syntax highlighting.

After a tiny bit of research I found some other things that can be done to help.

set re=1
set ttyfast
set lazyredraw

Unfortunately these help but don’t help enough. The first one is interesting since it changes the regular expression engine to an older one that is actually faster in many situations.

My Vim:

VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Oct 15 2014 09:10:07)
Included patches: 1-273
Modified by Gentoo-7.4.273

Still working on this.

On newer Vim, I have found that running external commands using :!<cmd> will work, but when the command finishes, it just drops to a shell prompt with Vim never waking up from being suspended. It can be recovered with the shell builtin fg (foreground). But this is extremely frustrating for things like !make which can be run hundreds of times a day. The best lead on this, and I think the solution is this setting:

:set shellcmdflag=

The help documentation, worth noting because it’s not an easy thing to search for, says:

On Unix the command normally runs in a non-interactive shell. If you want an interactive shell to be used (to use aliases) set shellcmdflag to "-ic".

I did find that sending a -i to $SHELL actually caused the problem requiring the fg. I am now trying -lc without -i to try and give Bash the sensation of a "login" shell (i.e. hopefully all aliases, etc.).

Managing Your Custom Spell Dictionary

Very often set spell=on flags words as misspelled that are spelled correctly. How do you tell Vim that you are confident that Vim has made the error? You use the zg command to add it to the list. (If you do that by mistake, zug will remove the word under the cursor from your custom spell dictionary.)

What is that list and where does it live? The file that contains the words you know to be spelled correctly lives in ~/.vim/spell/en.utf-8.add. When Vim uses them they need to be in an economical binary format. Vim has a special command to create that.

:mkspell ~/.vim/spell/en.utf-8.add.spl ~/.vim/spell/en.utf-8.add

The first argument is the binary file. I went ahead and added this spelling dictionary as a link to a file in my configuration so that my backups get my plain text word list, but the binary cache of them can be ignored.

Note that if you go with the defaults (which are shown in the previous example) you can just use :mkspell to compile the dictionary.

In the .vimrc you can add something like this.

set spellfile=~/.vim/spell/en.utf-8.add

Or as I’ve done, this.

set spellfile=~/X/skelx/vim-xed-spell

And then set that up with this.

cd ~/.vim/spell
ln -s ~/X/skelx/vim-xed-spell en.utf-8.add

Now you can keep it named what you want and the important/editable part can be saved in your personal configuration system (i.e. not Vim’s). Note that you don’t need the en.utf-8.add.spl compiled form in your own configuration system — let Vim make it when needed.

Or another way to approach it is to just have the vimrc spellfile= definition point right to the one in your skeleton. This will generate the compiled file there too but that’s generally ignorable.

It is important not to use underscores in spellfile names! These will get confused with default region spellfiles and cause vague and mysterious errors.

Vimb

Vimb is a Vim-like browser. Like all modern web browsers it is based on Webkit. It is like the old Vimium and Vimperator plugins but it is a stand alone client. Here’s what I did to get it working.

First you need to sort out dependencies. I don’t know exactly what they are but this definitely was one for my system.

apt install libwebkit2gtk-4.0-dev

Then obtain the source code.

cd /tmp
git clone https://github.com/fanglingsu/vimb
cd vimb

Here is how to compile in a safe way so that it does not actually mess with your system-wide software.

make sandbox
./sandbox/usr/bin/vimb http://xed.ch

It is by design a bit bewildering to the ignorant masses. Here’s how you can read the man page that will cure your ignorance.

man /tmp/vimb/doc/vimb.1

If you like Vimb and want to keep it, I found that it seemed to behave when I just dropped the executable in a directory in my path where it runs just fine.

cp /tmp/vimb/sandbox/usr/bin/vimb ~/bin/
vimb http://xed.ch/h/vim

Oh wait. No. That’s wrong. It needs a library that’s still lingering in /tmp/, so probably better to check out the repo to a non-volatile location and carry on as described.

Vimb Configuration

How do you configure Vimb? Hard to say. Probably need to put some stuff in ~/.config/vimb/PROFILENAME/config or something like that. This guy seems to have some kind of vimb-config file. Check the end of the man page for hints.

The user configuration directory is (in order of preference) looked for here (in order).

  • $XDG_CONFIG_HOME/vimb[/PROFILE]

  • $HOME/.config/vimb[/PROFILE]

This contains things like this.

  • config - Main configuration file. Note the exemplar found here.

  • scripts.js - User scripts run for every page.

  • style.css - Applied to pages is the variable stylesheets is enabled.

This being a browser, it is able to store a bunch of stuff about your browsing. The good news is that it’s not an inscrutable quagmire of potentially private data. It can be reviewed (and automatically deleted by, say, cron) by looking here (in order).

  • $XDG_DATA_DIRS/vimb/

  • $HOME/.local/share/vimb/

This location contains stuff like:

  • closed

  • command

  • cookies.db

  • history

  • search

Vimb Usage Hints

  • hkjl - Obviously Vim keys do the correct thing in "Normal Mode". You will always be in Normal Mode after pressing Escape.

  • [C]-o - Back, i.e. to previous loaded page.

  • ; - Start (silent) hinting mode. Note that you need to start typing what you want until the links become numbered. Then select the link you want with the number or tab or some other semi-obvious way.

  • gf - Should open a Vim session with contents which sounds pretty cool. Strangely the default opening has an error which tries to run -vi instead of vi. Putting set editor-command=mate-terminal -e "vim %s" in your $HOME/.config/vimb/config solves it. But even with that, I couldn’t get it to quite work.

  • [C]-v - Pass through to window manager, maybe only GTK.

  • o - Same as :open `. Note that just o and enter with no argument sends you back to the home page as defined in the config file with `set home-page=http://xed.ch/tp.

  • f - Should be the same as ";f" which should put hinting on normal links.

  • gU - Go to the stripped domain of the current URL.