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
, andforward-paragraph
. They are namedw
,$
,G
,}
. That may seem more cryptic but the Emacs bindings for these functions areESC-F
,CTL-E
,ESC->
,ESC-}
. Of course in Vim they are bound tow
,$
,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 haskill-word
(bound toESC-D
) andkill-line
(bound toCTL-K
). Vim just hasd
(bound tod
). That doesn’t sound very explicit and that’s because it isn’t. It gets combined with the movement keys to formdw
,d$
,dG
, andd}
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 thatd/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. -
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
-
Excellent tutorial for serious beginners.
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
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/
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.
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
- Alsots
. 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
- Alsoet
. When tabs are entered as normal, this puts spaces in the document instead. The number of spaces is controlled bytabstop
. To enter a real tab whenexpandtab
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
- Alsoret
. Replace all whitespace sequences with appropriate tabs based on the newtabstop
value. This means that 8 tabs with atabstop
value of 4 will turn into 4 tabs when:retab 8
is declared. Ifexpandtab
is set, then tabs are converted to the number of spaces specified. -
set shiftwidth=4
- Alsosw
. Used withautoindent
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.
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".
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.
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 ofvi
. Puttingset 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.