Ballmerpeak devblog

Software development, related stuff and others

Pro vim development environment 2: mid-level tricks and tips

July 26, 2020 — Richárd Thier

Pro "haxxors" and coders can live without a full-blown IDE and usually prefer a good editor, a good terminal, a good operating system, scripts and habits.

The second part of the vim devenv story. Read on, more heavy, but still mid level stuff is presented here. I am presenting this not from a purely "vim" viewpoint, but from a "what comes up handy when programmng" viewpoint!

Motivation

Screenshot 0

Come on! Who does not want screens like the above on their screen? It is real world example code environment of mine - except that I prefer to use tabs and not windows like here. Jokes aside I hope this to be useful source for people who have already passed beginner level vimming or vi-ing, and mid-level people and provide some of the lesser known - OR really useful - tricks and tips.

There are many sources on vim, but I wanted to create a collection for various levels of expertise - specifically from a software development environment viewpoint. Hopefully it serves as a collection from which one can start and further develop their real-world usage of vim.

For this I tried to collect not just raw information, but always the reasons behind why and for what I am using that given functionality. Beacuse one does most of these out of muscle memory, this is in no way complete, but hopefully a useful infocollection.

If you want to read the more beginner level post, you can click here for it!

Otherwise read on and I wish you happy vimming!

Handy macros

Just like regexes and smart replace being always there when you need it, the same applies to creating "macros". I think in most IDEs and editors it is a bit cumbersome to create a macros and it is usually a permanent thing that is only used for many-times occurring operations.

In vim you can find yourself thinking "oh if I could just do the same thing now for all of those functions" and voila: there is a fast solution! You do not need to open a config file or any dialog to create simple macros for that kind of times!

  • Create a macro: q<letter> ... do your operations ... q (again)
  • Run your macro: @<letter>

to do temporal things I just used to write "qq" then do my actions, then "q" then go where I next want to apply the macro changes and press "@q". If you want to do the macro multiple (lets say 5) times press "5@q".

That is all. You can also combine this with the fast movements using the "/" or "?" searches or so.

You can even use the "g" global command to execute a macro for lines that does match a given regex pattern or apply the macro for all lines between two:

    :5,10norm! @q

This for example applies the macro in the "q" register (the letter you used) on the lines between the fifth an tenth. Of course you do not need to stay in the same line while recording a macro, so being able to combine macros with all kinds of the movement commands is really awsome stuff!

Even just manually applying them if you know how to do so and how to just move around in vim will yield to awsome results and you can so easily use them!

Multiline regex replace

Also really handy is to be able to make multiline sed-like replace expressions! Not all regex-supporting editors make it easy for you to do this, but vim does.

You can use \_., which means "match any single character including newline":

    /This\_.*text

This will find the longest text that starts with "This" on some line and in an other line there is "text". What happens here is that "*" means what it used to mean in all regex situations (any number of preceding character) but there is this special \_. character that "any single character incluing newlines"!

This is not always the most useful because sometimes you do not want the longest but the shortest matching sequence. This is possible with \{-} which means the same as "*" but instead of being greedy and looking for the longest possible mathing result, we will be non-greedy and return the first match.

Okay this is something I was not really liking: for me thats greedy algorithm which return the first match but it is just terminology used differently.

    /This\_.\{-}text

This finds a shortest possible such text.

These are useful for substitutions and global commands too! Just imagine how much awsome "half-automized" refactors you can come up with by just using the multiline regex - let alone global commands and such.

Global "g" command

Some do not unleash the power of g even though it is one of the best kind of refactor tools out there for fast hacking together of half-manual refactors.

The ":g" command practically gets a regex to match then an operation to do.

For example you can delete all lines mathing a pattern:

    :g/TRACE:/d

Useful to delete TRACE level log lines for example if you do not need them.

Similar is when you want to invert the pattern:

    :g!/ERROR:/d

For example here - to delete all lines not having "ERROR:" in them.

The global command can be used even with substitutions:

    g/^-*$/s;-;=;g

For example to find all lines start and begin with with "-" an only have dash in them and change all the dashes to "=" signs. Practically to make single underlined texts in markdown all become double-underlined.

I did this when seperating my blog post into two pieces for example.

The global command can even work with macros or applying other normal commands:

    :g/pattern/norm! @a

If you think about it a bit and use this with multiline regexes and macros... wow you will end up with quite a big possibility for refactors and I am not considering simple refactors here like renaming a function, but those kind of refactors when you see that someone did not use a lock as he should have done and you see a pattern in how he wrote his code so you can fix threading issues in 26 seperate files using a simple script that even though is not perfect, but lets you manually intervene when needed and makes you do it in 10 minutes.

Been there, done that!

Save and load vim sessions

Even those who use vim regularly (for example on servers when using SSH) but not so regularly for their main coding devenv miss out on vim sessions.

Even I used to make scripts called devenv.sh in git repos in which all I did was to open relevant files into the editor.

Saving a session practically creates a vimscript that makes you reach the very state that you see when you save the session. If you have 7 open tabs and one other tab for file browsing - you will have them all open. Also after loading you will be right where you were when saving the session.

To save a session:

    !mks session.vim

The '!' in the beginning just let you overwrite the "session.vim" file if it is already existing. This is handy because I usually create a session.vim file for every project (in the main project directory) and I tend to overwrite it from time to time. Some people set up vim to automatically save and load the session file if it exists, but I prefer only updating it when I want. This way whenever I work on the project I see my predefined open tabs for files that I am working on in the longer or mid-term.

To load a session on startup:

    vim -S session.vim

Or just do this when vim is already opened:

    source session.vim

It must be told here, that "source" just loads and runs all operations in the given file in order or writing. So a session is really just a script to create the environment that you were in when you saved it.

Windows session load tricks:

  • On linux I used to be in the terminal anyways, but windows lack wisdom of the terminal so you might be on some GUI seeing session.vim
  • You can either configure your file manager (like doublecmd) to open vim files with vim -S or if you are only there for a quick hack on the machine of someone else, you can do my favourite trick: open the file via gvim (for example if it is the default editor of doublecmd) and because it starts vim there in that directory, you can source the file easily without looking up the full path to the file.

Simplest vim "scripts"

Now that you have learned that a session is practically is just a script that vim plays back, you might be wondering what other kind of scripts are there?

Simple commands

Create the following file and name it "titler.vim":

    :command Titlize :execute "normal! yypp"|s/./-/g|execute "normal! kk"|s/./-/g

Now source it! Nothing happens, but you got a new "command" that you can write after pressing ":". It is user-defined, but similar to ":s" or ":g".

What this is doing?

    This will be a title|

:Titlize

    --------------------
    This will be a title
    --------------------

So practically we wrote simple new command for creating title-like terminal graphics style. I sometimes used similar stuff for code grouping comments.

I like these kind of simple "commands" most:

  • I prefer ":"-commands like the above against user defined key maps because to me it is cleaner and I think twice before going with my own way instead of using some already existing commands. Also this nearly completely rules out "surprises" or at least ends with less surprisen than overwriting hotkeys.
  • I also prefer these much more than long "real" vimscript code. In most places people dislike tools like "execute" but in an editor there is no security issue or "dumb user" issue so we can just build commands as strings and such. It is much more readable and much faster to write these commands than other alternatives because your existing vim muscle-memory helps.

Key mapping

Okay so you disregard my style of preferring ":commands" and want to define "hotkeys". Fine! You are covered, because it is pretty easy to create new key mappings in any kind of modes vim is in.

I am only going to show the "proper" way to do it:

    :nnoremap - O<esc>jddk

Where:

  • "n" means normal mode the key is mapped
  • "nore" means recursion is not done (so if someone have overwritten "dd" map you still use the default deletion)
  • "map" jut means what is says - that we will map a key or some key presses as the following.
  • "O" opens a line above current (we are in normal mode)
  • <esc> exits insert mode because "O" makes you in insert mode. Special keys can be referred to like <esc> was here.
  • "j" goes down one line (this is the original line we had before - the cursor was on the created one).
  • "dd" deletes the original line (and moves the cursor below it)
  • "k" moves the cursor to the created empty line.

Practically you "emptied out" the line you are standing on. People from mainframe world seem to like and miss this operation...

If you want the defaults back just unmap this:

    :nunmap -

This command has nothing to do with nuns, so it is "normal-unmap" of course. You can also create key mappings for insert and visual modes using "inoremap" and "vnoremap". You can also really easily create multi-character commands:

    :nnoremap -d jdd

This deletes the above-the-cursor line when you press minus, shortly followed by the letter "d".

Option setting

You can set, toggle and unset values that you do otherwise.

    " set numbering
    :set number

    " set no numbering
    :set nonumber

    " toggle numbering
    :set number!

    " check what it is set now
    :set number?

This works with all kinds of options, like autoindent, smartindent and all. It is advised that you are not shorten commands and options in scripts as other scripts might came with commands that crash with your shortenings.

Knowing all the above you can now easily create stuff you need. For example you want to create a hotkey to turn numbering on/off fast while in insert mode of vim? Lets do that!

    :inoremap <c-n>u <Esc>:set number!<Enter>i

This now works whenever you push "CTRL+n" and then press "u" and is faster a bit than ":set nu!" even though not much so it is personal if you want it.

Remarks:

  • I did not wanted to remap "CTRL+n" because it is smart completion by default!
  • Be sure to release control if you run my example before pushing the "u" letter as it is alone not a <c-u>!

Functions

Sometimes you might want to write your own vim functions even if you do not want to have a deep-delve into full branching, looping and other full-language parts of vimscript so I will present it here for grouping operations that you might want to turn on/off on the fly.

A simple (non-meaningful) function looks like the following:

    fu! MyTestFunny(var1, var2)
      let str=a:var1
      let str2=a:var2
      echom str
      echo str2
    endfu!

Now you can call it:

    :call MyTestFunny(42, 13)
    :messages

For things you might to debug, you should always write out with "echom" as that variant keeps the message around and you can watch later with ":messages".

A bigger example:

    " Create our mappings if someone runs the function
    fu! EnableHtmlBudaism()
        :inoremap html <lt>html><enter>
            \<lt>!DOCTYPE HTML><enter>
            \<lt>html lang="en"><enter>
            \<lt>head><enter>
            \   <lt>title>TODO: Add title here<lt>/title><enter>
            \   <lt>meta charset="UTF-8"><enter>
            \<lt>/head><enter>
            \<lt>body><enter>
            \<lt>/body><enter>
            \<lt>/html><enter><esc>kO
        :inoremap div <lt>div><enter>
            \<lt>/div><esc>O
        :inoremap img <lt>img src=""/><esc>hhhi
    endfu

    " Remove our mappings if someone runs this function
    fu! DisableHtmlBudaism()
        :iunmap html
        :iunmap div
        :iunmap img
    endfu

    " Create shortcut commands so
    " that we can enable them easier
    :command! HtmlOn :call EnableHtmlBudaism()
    :command! HtmlOff :call DisableHtmlBudaism()

Put the above into a file called trickz.vim (or your .vimrc) and source it! After prepared like that, you can say ":HtmlOn" to go into "html mode" that I have just made up right here for this blog post and from that on you have a very special system when in insert mode. You write "html" and it becomes a full html skeleton, you write "div" and code for a div is added, same with writing "img". Just try it! All you need to enable this with ":HtmlOn" and write "html" (push four letters on the keyboard) to insert that snippet.

This is a very generic trick and useful to enter all kinds of snippets for all kinds of different project needs. I prefer having functions to enable these so that they are not active unless I want them to be active.

Of course for more heavy stuff you might consider a plugin that supports emmet or zencode kind of stuff.

Remarks:

  • As you can see a function name must start uppercase!
  • Use ":help functions" to see built-in functions you can use up!

Further reading and possibilities

To be honest, the above is all pretty well for everyday usage and for adding scripts to your .vimrc (which is the automatically sourced script file). All further complexities are usually used more rare and you can even be prouctive if you always need to re-learn other, less daily used parts of vimscript.

This is just scratching the surface. Read the relevant book on the topic if you are interested in knowing more. You can use vimscripts to do some real programming: With variables, debugging messages, branches, loops and you can write code that will automatically run on opening special file extensions etc.

Mark file locations

I always find it interesting that many people do not know about "mark points". These are used for making it faster to jump around in the source code / text.

Mark a location / jump point into register x:

    mx
    mX

The small letter is local to the file, the big letters are between files. All previous register content gets deleted by these. I usually do mx for temporal marks (like I mark current location and jump to top of the file) so that I can come back later.

How do you come back?

    "x
    "X

Yes, that is all and it is extremely fast!

I actually do not used to open splits if I want to do something where I should see two far-away locations (like you want to do a switch-case for all cases of an enum that is defined somewhere in the current file). I just create two mark for each location and it because of the speed of the operation it works well.

Simple file browsing

Doing Sex with netrw

Many people tell you to intall vim plugins for going around in directories. I think however most operations are simple-enough to be done using the lesser known build-in file browser called the netrw and I actually prefer that.

How to use it? Just do :Sex with netrw!

    :Sex

Haha, I could not stand walking past this joke!

Actually you likely not do sex with vim usually, but you will prefer to do a :Ex after you set netrw up properly. There is :Ex for default opening of the file browser, :Vex, for opening in a vertical split and :Sex for opening in a split (by default horizontal split). This is similar to :split and :vsplit!

This already work pretty well out of the box actually!

Better netrw configuration

Despite the above already works fine, I always do some little fixups on config.

netrw .vimrc config to open in tabs:

    " This makes the netrw file browser that ships with vim by default
    " open selected files in the 'previous window' by default.
    "
    " To use netrw just enter ':Sex' (S_plit and EXplore)
    " or Vex (V_ertical-split and E_X_plore)
    " or Explore to open in current window.
    "
    " With this setting one can keep the explorer open
    " after using ':Sex' and walk around the files easily.
    "let g:netrw_browse_split = 4
    " This lets it open in new tab which is even better
    " This way one can just start vim in the directory of a 
    " project and enter :Sex to open files need to be edited
    " or just use :Ex in an empty vim (started at project root)
    let g:netrw_browse_split = 3

netrw .vimrc config to hide useless top bar:

    " This makes netrw not show the useless info bar on the top
    " You can turn it on/off by pressing 'I' (shift+i) anyways.
    let g:netrw_banner = 0

"Unlimited" tabs

When we use netrw heavily we might want unlimited tabs (.vimrc):

    " Necessary for enabling us to 
    " use more than 10 tabs
    set tabpagemax=100

Use vim-like general programs

This might worth a full post, but I at least want to mention at this point that not only there is a little file manager built in vim, but you can even use a vim-like keybindings file manager for your common tasks (like opening files and copying around) even for not developing.

It is called ranger and I practically use it now instead of doublecmd.

I advise you if you use it add these to ".config/ranger/rc.conf":

    set preview_images true
    set draw_borders true
    set sort atime

and set up preview images in the terminal using the knows trick the terminal browsers use - but even more necessarily to sort by date by default.

There are also other programs that are vim-like, like "radare2" for reverse engineering (less vim-like) and various browser plugins like "vimperator".

Go to definition, tags, completion, etc.

The easiest completion in vim is CTRL+n. It completes a word and you can do this multiple times to cycle through found matches. This is actaully even better in my opinion than code completion of an IDE, because this also works in plain text files, comments, whatever place. Practically it looks for the words that fit from opened files, tabs and sometimes other sources. Just start writing a long word and press CTRL+n. You can also use it if you enter into the middle of a word and add an infix there!

What is lesser known is CTRL-x CTRL-n! If you do this after a CTRL-N, the system continues your completion with the next word after the completed and you can do this as many times as you want! This is literally UTTER AWSOME!

More stuff:

    :help ins-completion

    1. Whole lines             |i_CTRL-X_CTRL-L|
    2. keywords in the current file         |i_CTRL-X_CTRL-N|
    3. keywords in 'dictionary'         |i_CTRL-X_CTRL-K|
    4. keywords in 'thesaurus', thesaurus-style     |i_CTRL-X_CTRL-T|
    5. keywords in the current and included files     |i_CTRL-X_CTRL-I|
    6. tags               |i_CTRL-X_CTRL-]|
    7. file names             |i_CTRL-X_CTRL-F|
    8. definitions or macros         |i_CTRL-X_CTRL-D|
    9. Vim command-line           |i_CTRL-X_CTRL-V|
    10. User defined completion         |i_CTRL-X_CTRL-U|
    11. omni completion           |i_CTRL-X_CTRL-O|
    12. Spelling suggestions         |i_CTRL-X_s|
    13. keywords in 'complete'         |i_CTRL-N|

For going to definition in the same file I just tend to use "*" first. If that fails or the thing I look for is elsewhere, I use a (c)tag file setup.

If you have tags, go to definition:

    CTRL+]

If you have tags, go back to previous tag location:

    CTRL+t

This is like a stack so you can walk around multiple deepness like that, but you need a tags file and from time to time update it to correspond the source code.

Below I add details about how to do that from within vim on linux.

Shell and vim - best devenv mix

There are various ways you can mix your shell devenv skills with vim skills.

Using your bash aliases inside vim

Just put this into the end of your .vimrc:

let $BASH_ENV="~/.bash_aliases"

This opens up a whole world! Literally! At least for me it opens it up as I like to use aliases (and functions) when in the terminal and already have them and I always wanted to use them from inside vim. This is maybe less useful for you if you are windows user, but you better stuck to linux anyways if possible!

Some useful bash aliases / functions

Even with the above goodness of tags, going to definition and such, still there are some cases where you feel "grepping to search for something" is the best thing to do.

I add these (.bash_)aliases for finding and grepping in project directories:

    grepr() {
     if [ $# -lt 1 ]; then
      echo "Usage"
      echo ""
      echo "grepr <filenamepart>"
      echo "grepr <filenamepart> <path>"
     else
      local path="."
      if [ $# -gt 1 ]; then
       path="$2"
      fi
      grep -R "$1" "$path"
     fi 
    }

    greprs(){
     if [ $# -lt 1 ]; then
      echo "Usage: greprs <filenamepart>"
     else
      grepr "$1" "src/"
     fi
    }

    # Shortcut to find
    # Usage: ff filenamepart; ff filenamepart path
    ff() {
     if [ $# -lt 1 ]; then
      echo "Usage"
      echo ""
      echo "ff <filenamepart>"
      echo "ff <filenamepart> <path>"
     else
      local path="."
      if [ $# -gt 1 ]; then
       path="$2"
      fi
      find "$path" -name "*$1*"
     fi 
    }

    # Shortcut to find
    # Usage ffs filenamepart # searches in src/ subdir
    ffs(){
     if [ $# -lt 1 ]; then
      echo "Usage: ffs <filenamepart>"
     else
      ff "$1" "src/"
     fi
    }

    greprsmore() {
        if [ $# -lt 1 ]; then
            echo "Usage: greprs <filenamepart>"
        else
            grepr "$1" "src/"
        fi
    }

    greprmore() {
        if [ $# -lt 1 ]; then
            echo "Usage"
            echo ""
            echo "grepr <filepart>"
            echo "grepr <filepart> <path>"
        else
            local path="."
            if [ $# -gt 1 ]; then
                path="$2"
            fi
            grep -R -A 5 "$1" "$path"
        fi     
    }

To use the above you can just enter "!ffs Update" and it will seearch sources that have that in it. I added the -s suffixed versions because how many of my projects are structured is that they have the source code under "src/". If the project of yours is not structured that well for any reason, try using ripgrep or for a more vim-integrated search try :grep or :vimgrep and their variants!

I like to add cscope and ctags as functions so that I do not forget how to do it :-)

    # cscope (better than ctags) stuff:

    dev_cs_index_all() {
     find -iregex '.*\.\(h\|hpp\|c\|cpp\|cu\)$' > .files_for_cscope
     cscope -i .files_for_cscope
    }

    dev_cs_index_pre() {
     find -iregex '.*\.\(h\|hpp\|c\|cpp\|cu\)$' > .files_for_cscope
    }

    dev_cs_index_update() {
     cscope -i .files_for_cscope
    }

    # CTAGS (mostly as a memo as the original command is shorter)

    dev_ctags_setup() {
      ctags -R
      echo "Use ctrl+] and ctrl+t in vim. See help ctags."
    }

    # jtags for javascript - see: https://medium.com/adorableio/modern-javascript-ctags-configuration-199884dbcc1
    dev_jtags() {
     # -E is undocumented and is same as -r (for extended regex)
     # I have no idea what this should do but it do it wrongly I think:
     ctags -R app config lib && sed -i -E '/^(if|switch|function|module\.exports|it|describe).+language:js$/d' tags
    }

    # My approach to make ctags for typescript-only (excluding the generated and other js files)
    dev_tstags() {
     # I made some choices based on the jtags idea above - but fixing it to my purpose
     # We just delete all js sources from tags - this will get rid of generated and unrelated stuff both...
     # REM.: I only create this on the given directory if there is a parameter!
     if [ $# -eq 0 ]; then
      ctags -R src && sed -i -E '/\.js/d' tags
     else
      # "$@" makes "src bin" into one and "src" "bin" as two
      # The $@ without quotes makes it bad and split a single ".. .."
      ctags -R "$@" $src && sed -i -E '/\.js/d' tags
     fi
    }

You can also add git (or build)-oriented commands:

    # Simple faster to type and more proper git blame command alias
    gitblame() {
     # Not counting whitespaces and moves
     git blame -w -M "$@"
    }

    # Usage: cloc_git http://github.com/prenex/tiehackz
    cloc_git () {
     git clone --depth 1 "$1" temp-linecount-repo &&
     printf "('temp-linecount-repo' will be deleted automatically)\n\n\n" &&
     cloc temp-linecount-repo &&
     rm -rf temp-linecount-repo
    }

I also have handy things in my bash aliases and functions like these ones:

    # Usage: hex2dec 320; hex2dec A000 (small letters do not work!)
    hex2dec() {
     echo "obase=10; ibase=16; $@" | bc
    }

    # Usage: dec2hex 1024
    dec2hex() {
     echo "obase=16; ibase=10; $@" | bc
    }

    hex2bin() {
     echo "obase=2; ibase=16; $@" | bc
    }

    bin2hex() {
     echo "obase=16; ibase=2; $@" | bc
    }

    alias snippingtool='snippingtool.sh'
    alias recterm='asciinema rec -i 2.5 term.cast'
    alias recgif='gif-byzanz.sh'

Please keep in mind that because of the above trick of having BASH_ENV as is, we can run these right in vim without need to exit to the terminal!

I also have some aliases that I do not intend to run from vim (as "!: greprs task"), but these aliases still help me work with my vim-based devenv:

    alias vimalias='vim ~/.bash_aliases'
    alias applyalias='. ~/.bash_aliases'
    alias vimvimrc='vim ~/.vimrc'
    alias histvim='history | vim -'

Some bash things that does not work

In my development environment I like to open a separate terminal for each kind of project folder where opening a separate terminal makes sense. For example I open one for the client, one for the server-side and one for docker test env.

To help these go faster for each project, I usually create "cdXYZ" aliases or functions, where XYZ is the folder name. These do not only go there to that very folder, but also might set up project-specific aliases - which then can be shorter (like: "lint" vs. "lintprojectnamemodulename") - or do other stuff.

Many of these do not work from-within vim: above all you cannot create new aliases and functions in a function this way - something that I routinely do in my cdXYZ functions.

This is not a big deal to me, because most of the project specfic things are not code-writing related, but usually build related where I am just in the terminal instead of being in vim - except for c/c++ and simple projects with a makefile, because vim can run make using :make (you do not even need '!')

Some examples:

    alias cdnostrum='cd munka/c_c++/nostrum/'
    alias cdobjmasterexamples='cd ~/munka/c_c++/ObjMaster/examples'
    alias cdturul='cd /home/prenex/munka/c_c++/turul'
    cdmagosit(){
     cd '/home/prenex/munka/magosit/python/magosit-website'
     source ".venv/bin/activate"
     alias build="prosopopee"
     alias run="prosopopee preview"
    }
    alias cdprosopopee='cd /home/prenex/munka/magosit/python/prosopopee'
    alias cdfasttrack='cd /home/prenex/munka/c_c++/fastrack/'
    alias cdopenlens='cd /home/prenex/munka/openlens-thesis'

Folding and vimdiff

Did you know that you can evn use vim as a diff tool? Try vimdiff!

It is not only great because you can use all your known muscle-memory while you are analysing a diff or resolving merge, but because it is practically a vim with a vertical split for the two versions, you can even open new tabs to investigate other files and so on. It is complete vim-ness.

You can jump between windows in the same way as before (using CTRL+w, arrow) and this might be the first case when you find folded lines.

So yes, vim also knows folding lines together. For existing folds, you can open the fold using "zo" and close it again using "zc". Here they are used for folding around unchanged code of the diff.

You can also define your own folds in your own code:

  • Just select an area in visual (V) mode
  • Press "zf" - to Fold selection

You can of course combine and use this folding in your scripts, for example one can create a script that collapse multiline comments as a single line.

Sadly there is no way to make a fold completely disappear currently, but I guess it might be not that hard to add that functionality for purists who do not want to see any comments while browsing source code and want a plugin that hides those for some hotkey...

Using plugins

I will not delve deep into vim plugins, but there are some really handy ones. I try to limit my plugin usage to minimal while still being productive, but some just come in really handy.

A simple plugin (useful for windows users) looks like this:

Plugin to show gvim always fullscreen on windows

I prefer "all-fullscreen" work when I am coding so I find that handy when I am forced to work on windows for a project or two.

Another useful thing:

Typescript syntax highlight

There are even things for plugin bundle management for vim lately and stuff like the well known "Vundle" and so on. Still there is sometimes a grey zone in what one calls a plugin and what is "just some script" or "highlighter". It is not really a big barrier between those usually from the usage viewpoint.

Creating html from view

Did you know about this?

    :TOhtml

If you say that, vim creates a html document from the current view. Let it be vimdiff or some file that you have opened or anything. I actually once used this functionality to create a bash-backed code-review tool that created the diff pages by calling a scripted-up vimdiff, calling :TOhtml and cleaning up!

Joining lines, full matched pattern in regex

It is overkill to add a section on its own to these, but "J" is useful to join two or more lines. For example visually selected lines or 5 lines below etc.

Also I forgot to mention that "&" captures the full regex pattern in the substitute operations so :s/alma/&&& makes an "alma" to "almaalmaalma"!

I just forgot these even though I use them daily - and who-knows what really basic stuff I did not mention when doing muscle-memory. This is not a book! :-)

Closing words

Where to go

There is innumerable things you can do, but most of them (or at least those of them that you use daily) are self-descriptive if you already start to "feel" vim. For example one day I was explaining to my friend that big-letter normal mode commands are usually variants of the small letter ones, while doubling them used to be "default operation" of them. Think about "dd" or "yy" or "G" and "gg" for example. I thought to myself: hmm then "E" and "B" must likely do something interesting and I found they are indeed different from "e" and "b" normal mode mapped keys. The latter of course goes to end and beginning of a word the cursor is on, but it stops at most non-text characters, like dot or a comma (or a paranthesis in a programming language). Usually that is what you want, but the big letter variants step more: they practically go until the whitespace! Useful if you use these to copy or delete stuff or if you do some FORTH language programming for example.

I think above some level anyone customize vim to their own needs and wishes, but whenever you are sitting at an other vimmers machine I prefer being able to do all what is written here - at least.

For full mastery, go and read books like this one and just use vim. ;-)

When it is easy to use vim as devenv

I wanted to add when you can expect to easily work only from within vim on the project of yours. The answer is: the more devops a project is using and the more multi-platform development it is - the easier it will be.

Why? Because if the project has linting support from the terminal because of the automated build, or at least can be built because of the automation then you likely will find it easy to use vim. Maybe you also get some docker to completely set up and host your own dev environment which helps a lot too.

The key, the minimal thing in my opinion is that the project is buildable from within a terminal and not tied to some ide with propriately config files!

Practically if you have a speedy build from the terminal, you will never look into any kind of IDE - or at least not need to do so.

When it is harder to use vim as devenv

It is then imperative that the worst to your "vim-dreams" is when you are tied to some technology that is tied with some IDE. For example I was working on projects where the java GUI was done using an eclipse plugin that generated the forms and windows. Because it is an eclipse plugin you MUST use eclipse...

What if things are not so bad but there is still no proper building setup for continous integration of building from the terminal? Either you can do that yourself which might be time consuming (but worth it) or there might be sad cases where it does not worth it. Maybe you work on that project only for a short time substitute for your collegue who is on vacation and fix 2-3 bugs. Do you want to spend time on refactoring their build? Beware it might be some heavy corporate legacy stuff with lots of undocumented settings stored in some big xml file that the "supported editor uses". Likely it does not worth it.

What can you do if you cannot run vim directly? Thank God and a lot of good developers out there, there are countless "vim-plugins" for all editors!

Some IDE plugins that I used:

  • vsvim: Visual Studio plugin (I advise to let the plugin overmap VS defaults by going to settings!)
  • Vrapper: Eclipse
  • IdeaVim: Idea (also for AndroidStudio)
  • etc.

These tools also make it funny-easy to jump between different editors while keeping all your muscle-memory intact. Practically if you learn vim, you do not really need to learn the (worse anyways) hotkeys of XYZ editor, nor you need to spend time learning your environment because vim is everywhere ;-)

Everywhere? Maybe... Maybe except GUI-only programming tools where you drag and drop boxes and icons and has binary, propriately representation...

Tags: vim, devenv, development, environment, tips, tricks, pro, hacker, hackz, tutorial, linux, bash, sex

comments powered by Disqus