Internals

vimtutor

To follow navigation in vim :help you can use <c-]>

quick reference card We will use vims keynames :help keycode but lowercase (anywas it is case insensitive), for example <c-d> is control Ctrl and d, in help it can be written as ^d or <ctrl-d> but we will stick with <c-d>

  • <esc> is escape key (when recording macro it is ^[<80>y)
  • <space> space
  • <cr> sometimes it is <Enter>
  • <bs> backspace
  • <left> left arrow
  • <s-left> shift left
  • <c-left> control left
  • ^I is when we insert <tab>
  • <nl> new line. If you use echom "a\nb" you will see a^@b (CTRL-v and CTRL-j)
  • <tab> tab

If you press <c-s> ctrl-s ^s than terminal will freeze all output and looks like vim hangs and stop working, but you need to run <c-q> ctrl-q ^q to exit from that.

special variables

  • <leader> by default is \ but I use <space>. To check current value use: :echo mapleader, to set use :let mapleader=" "
  • <localleader>
  • <non-keyword-character> maps all non keyword chars: :set iskeyword? returns iskeyword=@,48-57,_,192-255,- ie alphabetic ascii, digits 0-9, _ , and some special chars
  • <nop> no operation, usefull when you want to disable some keys

Run vim without any plugins or settings with

vim --clean

# start vim without plugin , no plugins
vim --noplugin

# vanila vim without vimrc
vim -u NONE

Reload vimrc. Note that old config is not automatically reseted (you need to exit vim and start again)

:source $MYVMRC<cr>

My Vimrc

Good starting poing for .vimrc is http://vim.wikia.com/wiki/Example_vimrc Also nice default vimrc :r $VIMRUNTIME/defaults.vim You can find my .vimrc

Main settings

" do not need to be backward compatible
set nocompatible

Note that control key can be written as caret ^ so instead Ctrl-n it can be written as ^n.

Use vim help, with:

  • :help
  • :help user-manual help on some topic
  • :helpgrep windows search all help pages (also plugins) for topic
  • :help ctrl-i what Ctrl-i do in normal mode (normal is by default searched) we could also write :help ^i
  • :help i_^i what ctrl-i do in insert mode
  • :help v_^i what ctrl-i do in visual mode
  • :help c_^i what ctrl-i do in command line editing mode
  • :help :s what s do in ex-command mode
  • :help -t help with command line options (run :options to see all options)
  • :help 'list help on some option
  • :help myfunc() add brackets to search only functions
  • :help hl-WarningMsg highlighting groups start with hl-
  • :help /\+ regexp items start with /
  • :help quote: registers start with quote
  • :help >cont debugging commands

Other help commands can be found :help 0.8. Follow link with ctrl-] and jump back with ctrl-o

Use Ctrl-o to run normal mode command from insert Mode

  • <ctrl-o> take to normal mode for just ONE command, so if you want to go up while in insert mode <ctrl-o> k, or to reformat paragraph <ctrl-o> gqip, clear whole line but not new line <ctrl-o><s-o> (similiar to <ctrl-u>

Other usefull commands in insert mode:

  • <ctrl-t> <ctrl-d> indent deindent in insert mode
  • <ctrl-o> d delete everything to the right of cursor
  • <ctrl-u> delete everything to the left
  • <ctrl-w> delete word to the left of cursor
  • <ctrl-h> backspace
  • <ctrl-j> return
  • <ctrl-a> insert the text you typed last time you were in Insert mode
  • <ctrl-p> complete words under the cursor. If there is no word, it look previous word, <ctrl-p> again look previous…
  • <ctrl-r> a in insert mode will yarn register a (usefull when there are a lot of similar words and completion does not help much)
  • <ctrl-v> {digit} insert character with special meaning like for <esc> it is ^[. <ctrl-v> {key} insert char with key number like <ctrl-v> 110 is n.
  • <ctrl-k> Co insert special digraph char from the list :digraphs but instead using key you use two chars

Operators

  • to change case you can select and press ~
  • gq text formatting (gw formating without cursor movement) to 80 char textwidth lines and proper code indent. Visually select the range or use motion like gqap format a paragraf, gggqG whole file.
  • c change, y yank, d delete
  • < shift left > shift right, == indent current line, gg=G indent whole file

Motions and selections

  • shortcuts x (dl delete char), C (c$ change to end of line)
  • ciw change inner word, caw including spaces that follows the word
    • ca] change all inside brackets including both [ ]
    • S change whole line (delete and go to insert mode)
  • daw removes the inner word
  • dt delete until the space, df delete until the space including space
  • dap}p switch two paragraph
  • dE removes to the End of the string
  • vit inner or vat outer visual select (including html tag) :h tag-blocks
    • repeat at to select wraped tag
    • jump to closing (Oposite) html tag with o in visual mode. more on :help visual-operators :help v_it
    • vap select paragraph (until next empty line, including that empty line) other text objects are aw(a word), a( (a block of any of the paranthesis quotes). Note the differences between using object and movement command, dw will delete from current position to the end of word, daw will delete whole word regardless of cursor position
    • dst delete surround tag with vim surround plugin.
    • cil change inner line with line text object plugin
    • vii select same indent level with indent text object
  • va' visually select all inside ‘ including ‘
  • cgn change visually selected text using previous search
  • recording macro to q with qq, exit with q, run with @q. To repeat last macro registar you can use @@. You can edit macro by simply pasting "qp and edit the line and yank back to the same register "qyil. To add new commands to register use uppercase, for example adding search to q register qQ/word<enter>q (this appending also works for yanking) To cancel recording the macro you can copy existing (before you exit recording, existing is still available) to new register and than back to original https://superuser.com/questions/666377/how-to-cancel-recording-a-macro-in-vim#comment1558163_666428
    # recording qa but I wanted to execute @a
    :let @t=@a
    q
    :let @a=@t
    
  • paste commands in insert mode with ^Rq
  • ^T indent ^D dedent in insert mode. Shift can be also done in visual mode (also in blockwise selection) with >. In normal mode you can select and indent with = To indent whole file you can jump to begging and indent to last line gg=G.
  • Sort selection with :sort
  • :set scrollbind in two buffers will make them scroll simultaneously. toggle scrolling with :set scb!

Motion in visual mode

  • '< to the first line of last selected visual area. Note that you need to exit current visual area and than jump to first or last line/char
  • gv to reselect previous selected visual area

Normal mode

  • Repeat last colon command @:, repeat last command @@
  • K in normal mode opens documentation for that keyword in any language, for example Error in ruby file will open ri Error. :set keywordprg is program used for documentation (default is :help or man)
  • :set backup will create myname.txt~ (or :set backupext=.bak) inside :set backupdir. To keep original file :set patchmode=.orig.

Command line mode

Command line mode :help usr_20.txt is when using : or search /,?.

  • You can press <Enter> anywhere inside line
  • Navigation with cursors <Left>, <S-Left> (one word left) and CTRL-B/CTRL-E begin/end of line. Difference with bash is that ^b is begin of line (char left in bash), ^e is the same, and ^f (char right in bash) enters Replace mode in comand line window so you can use l
  • Delete with <BS>(or ^h) and CTRL-W delete whole word, CTRL-U delete all before text. ctrl-d is not as in bash, it is completion in vim.
  • tab completion works and you can see all matches with CTRL-D (match is when command starts or short name starts with that). So ^d to show all completion and <tab> to iterate over completions , ^p to iterate in reverse direction (^n in forward direction). Note if you are not yet in completion mode ^p will just show previos command (not previous completion). To get a value use tab two times: :set isk<TAB>=<TAB>
  • command line history can be used when you type start of command and :se<UP> CTRL-P will go to previous command no matter what you have types so far ctrl+p and ctrl+n will go up and down, ctrl+y will accept current ctrl+e will cancel suggestions
  • Command line window q: or CTRL-F is used to edit long commands. <CR> to execute comand and exit. Exit with :q or CTRL-C. Search previos with ?
  • You can join multiple commands with | or <NR> (more help with cmdline-lines)
  • :set viminfo=<TAB> will show what is saved when you exit vim. To jump back to last file use mark '0 when you start vim.
    • '100 how many files for which vim save marks
    • f1 if 0 global marks are not stored. If missing or 1 global marks are stored
    • <100 how many lines per register is stored, 0 nothing. By default all lines are stored
    • s10 max size in KByte
    • h disable ‘hlsearch’ highlighting when starting
  • :mksession! a.vim will create a.vim file and save all windows, files … Restore with vim -S a.vim. viminfo stores marks, registers, history and you can also write :wviminfo ~/.vim/myapp.viminfo and than rviminfo.
  • You can instruct vim how to view the file using first or last 5 lines commands are between : colons
    /* vim: set shiftwidth=4 : */
    

Command line options

  • Edit multiple files
    vim one.txt two.txt
    

    it will open one.txt. You need to save and :next or :wnext to write and go to next file. You can see all arguments with :args. Going back is :previous, also works :first, :last, :2next.

  • You can open in split windows
    vim one.txt two.txt -o # or -O for vertical split
    
  • :args app/*/* to add all files to arg list
  • open file on specific line vi +10 README
  • open readonly mode vim -R file but it can be overwritten with :write!. To really keep read only use vim -M file (but this also can be turned of with :set modifiable).
  • vimdiff a b will show differences. Inside vim :e a and :vertical diffsplit b. If you are in left window you can use dp to copy change to the right (diff put), or do (diff obtain) to pull from other right window.
  • read commands from file change.vim example
    for file in *.txt; do
      vim -e -s $file < change.vim
      lpr -r tempfile
    done
    
  • read file from stdin ls | vim -

Exploring

  • :edit . (short :e.) opens (:vsp) splits netrw of folder,
  • cd ~ to change directory to home folder for all windows. If you use gf in Gemfile, it will not change directory (you can check that :pwd is showing same folder). To manually change current folder directory to file path you can use :lcd %:p:h. % is the current file name, %:p file full path, %:p:h give its directory. Or you can type cd when cursor is on the line where is the path: %< expands filename without trailing extension
    :help filename-modifiers
    
  • beside window local directory :lcd, you can set tab local directory so to work with other gem you can use tabe Gemfile, gf and :tcd %:p:h
  • gf uses path (which stores all apsolute paths, run :set path=<tab> to see them).
  • instead of :w other and :e other you can use :saveas other. Similar is using :file other (which will be ‘Not edited’ ie not saved yet).

Windows buffers and tabs

terminology

  • :split will create new window of the same file, :new will create new window for new file. :3split file will open 3 lines height window, you can increate with ctrl-w +
  • :tabe file open file in new tab, gt switch between tabs
  • move between windows is with ctrl-w w
  • :help Ctrl-W_T move current buffer in new tab (similar to :tabe %), Disable default Terminal -> Preferences -> Shortcuts
  • gx open link under cursor with gnome-open. Issue #1386
  • :vsp #1 vertically split window with file #1
  • :on (:only) or Ctrl-W o closes all windows except current
  • :buffers, :b1 open first, :bun closes the buffer, :sbuffer 2 u unlisted % current # alternate (jump to it with ^^) a loaded and displayed, h loaded and hidden = read only - not modifiable + has been modified
  • CTRL-^ (shift+6) jump to previous buffer
  • :retab this will actually reformat all source
  • ctrl-w f is the same as gf but opens in new vertical split window
  • :b substring_of_filename open buffer that matches substring (press tab in case of multiple mathces)
  • Status Line :set statusline=%f\ -\ FileType:\ %y will change status line
    • %f path to the file
    • %F full path to the file
    • %y filetype of the file
    • %L total lines
  • set file type in magic comment
    # vi: ft=conf
    

Movements and Navigation

  • w b next (prev) begging of word. Use W and B to include 'iskeyword' option characters like "|- . Use e and ge for end of word.
  • gj gk for long lines that are wrapped to multiple lines, it will go up and down
  • $ end of line, 0 start of line (or ^), use _ to select end of line before new line character
  • + and - move line up or down on the first letter
  • { { and }} move on start or end of paragraph (empty line), single brace is default but I changed to double
  • ^B(^U, ^Y) or ^F (^D, ^E) scroll next page up (half page, one line) or down (half page, one line). But for one line it is easier to use Ljjj
  • H M L jump to the top/middle/bottom of what you see
  • move screen one line CTRL+y up (down is remaped ctrl+e)
  • mA then 'A jump there (downcase letter a can jump only on current file buffer, use a backtick to jump to specific column instead of beggining of the line), :marks gives the jump location, two ‘ '' is jump back, '. jump to last change
  • ^o and ^i will jump to previos and next location. ^] to jump to section under cursor - hyperlink - ctags
  • % jump closing brackets or other matching brace
  • 5G or :5 goes to the line 5
  • gg goes top, G goes bottom
  • g, and g; jump to next/prev change on current buffer
  • g ^g print column, line, word, character. Used for word count
  • show line numbers :set number or relative numbers :set relativenumber (or shorter :set rnu. To disable you can :set norelativenumber
  • show approx position in text ^G
  • gf go to file, follow that link path

Quickfix and location list

QuiCkfix window is just a preview window. You can open with :copen or :cw (open only if there are errors, close if there are no errors). Location list is similar to quickfix but for current window replacing c with l like :lopen, :lmake. There is Location in status bar and is independed from quickfix list.

  • :cnext jump to next error, :clast to jump to last (with plugin :help unimpaired-next you can use ]q go next [q prev error). For ALE rubocop use list ]l
  • :cc to show full error message in status bar for this line
  • :clist to list all errors

to get quickfix title (usually it is command that generates the list)

:echo getqflist({'title' : 1})

Error format efm is using scanf tags :help error-file-format

  • %f file name
  • %l line number
  • %t error type
  • %m error message
  • %r rest of a single line file message %O/P/Q

:set efm=

Using unimpaired

  • [c ]c go to prev next change in diffsplit
  • [l ]l ALE rubobop errors. To close error window you need to :lcl
  • ]b buffers
  • ]ow to enable wrap, toggle with yow, more :help unimpaired-toggling

Copy paste

  • select which register to use with (use character not number) for example: yank link to register a is "add and paste: "ap". When deleting or changing it will override default register, so you need to select some other register, like black hole register "_ if you want to paste same stuff multiple times, for example "_d or "_c will keep default register untouched.
  • %y+ copy all lines to clipboard
  • "+y copy visual selection to system clipboard, ubuntu should run sudo apt-get install vim-gtk. or vim-gnome
  • to move a line to buffer on the left you can record macro (something like yy ^wh p ^wl)
  • to paste with proper indend use vim-unimpaired ]p , also from plugin :help unimpaired
  • insert text from external command is with :read !date
  • undo u redo ctrl-r. :help 32. If you know the change number you can jump to it using :undo 2 . Use g+ (:later) and g- (:earlier) to jump back and see change number so you can jump to it. See change numbers with :undolist or use time in :earlier 10s. Try plugin :UndotreeShow https://github.com/mbbill/undotree remaped to F5

Search and replace

Seach files

:grep subject -R * --exclude-dir={log,spec,public,features,tmp,vendor,assets,db} -I

Instead of :grep I use :Ack (which uses ag) https://github.com/ggreer/the_silver_searcher. It will ignore all from .gitignore so no need to exclude dir. Invoke with double search // Here are some ack.vim helpers:

  • ? quick summary of keys, h open in horizontal split
  • ag pattern -G show will search only filenames like show.html.erb (-G is short for --file-search-regex patter), -i ignore case, -l show only filenames. --ignore-dir=lib will ignore specific folders (regex not supported). Filter only specific file type ag --list-file-types| less you can use ag MyClass --ruby. :Ack can be used to find in files. In vim it uses ag instead of grep or Ack. To search specific types use option -G and regexp like: :Ack montserrat -G 'css$' For two line search you can use: :Ack 'destroy\n.*authorize' app/controllers/ For multiline (does not matter how many lines are in between) :Ack 'destroy(\n.*)*flash.now..notice' app/controllers/

  • vimgrep my_string **/*.md | copen search only md files for my_string and show results

Search text in a file

  • :help usr_27.txt and :help pattern
  • / for searching, to search in oposite direction ? (n and N for next and previous result). If search string is all lowercased than it will search ignore case (when :set ignorecase option is set), but if you have at least on uppercased letter than case is important (when you have :set smartcase)
  • use * search forward (# backward) of the word nearest to the cursor (middle fingeers are clicking the * and #). Use g* to match words that include the string (no boundary constrains)
  • offset is used to position cursor on prev line /default/-1 or character /default/e+1 (1 char from end of search word) /default/b+1 (one char from beginning of match)
  • use :match Error /asd/ to highlight asd in buffer
  • instead of zero or more .*, you can use .\+ to match one or more times (.\* means any char and star, .+ means any char and plus)
  • use very magic regexp (like in other languages) if you start with \v for example those two are equivalent searches :help magic (very magic does not need to escape + | ( ) { })
    /for .\+ in .\+:
    /\vfor .+ in .+:
    
  • :help pattern-overview
  • search with end of the word /usan\> help with :h /\>
  • beggining and end of line marks like /^asd and /asd$ works fine (not in the middle /asd^qwe)
  • For multiline search you can use:
    • \n new line
    • \_s space, tab or newline,
    • \_. any char including new line
    • \_^ (\_$) match new line or beggining (end) of line
  • instead of * which will stop at last occurrence till the end of line, you can use minimum matcher \{-} to stop as soon as possible. Use \{2,4} to match 2, 3 or 4 times. For example
    • /asd\_.\{-}qwe find asd followed with any character (including new line) and stop at qwe (match as few as possible)
    • /asd\(.*\n\)\{2,3}.*qwe find qwe if it is after asd in 2 or 3 lines
    • You can use S and S! snippet
  • or operator is \| for example /one\|two. If you use inside other match you need to put \( and \), for example t\(wo\|hree\). If it is chars than use character ranges for example:
    • /[a-z] or /[abcdef] will match any of the chars included in list.
    • /[^xyz] matches char which is not in the list
    • special characters: \t tab \e esc,
  • predefined ranges \d is [0-9] digit, \D non digit [^0-9], \s white space or tab, \a, \l and \u any, lower and upper case alphabetic character. Note that predefined ranges can not be used inside range, use or operator instead
  • you can use character classes like \f (any char than can be a file name, depends on the OS).
  • character classes and ranges can be modified to include new line like \_a or even for inverse ranges /"\_[^"]*" strings that may split up in several lines
  • :set nowrapscan is usefull when you want to stop search when you hit bottom of a file. With gg you can jump to begging. :set wrapscan when you want to back to wrapped search
  • clear highlights until next search :noh, to clear completely :set nohlsearch

  • q: shows history of commands
  • q/ shows history of searches

Replace text

Replace command synax is :[range]substitute/from/to/[flags] also add % so it applies to whole file. Use + instead of / if you need to escape a lot, for example :%s+http://+https://+g

  • :%s/old/new/gc g means global (each occurence in a line) c confirm
  • :%s/old/new/ge e means not to return error if old is not found, usefull in macros, so it does not stop the macro
  • replace tabs with two spaces in whole file(you can use % also) :1,$s/\t/ /g range from current line to the end is :.,$s/yes/no/. To split the line by space into multiple lines use: :.,.s/ /\r/g This is example to replace grey with gray only in current chapter (each chapter starts with Chapter) search backward from current position use ?
    :?^Chapter?,/^Chapter/s=grey=gray=g
    

    This will also include a lines with Chapter. To exclude them use offset like

    :.+3,$-$s/a/b/g
    

    From current position till the exact number of lines you can write 5: which will expand to :.,.+4 Instead of writing the rage you can set marks mt and mb and use them

    :'t,'bs/a/b/g
    

    In visual mode it marks with angle brackets :'<,'>

  • remove all non acii charaters :%s/[^[:print:]]//g for example <200b>^F
  • match replace first group with second group,for example Doe, John -> John Doe
    :s/\([^,]*\), \(.*\)/\2 \1/
    
  • :argdo %s/foo/bar/ge | update replace (substitute) in all arg.

Global command to find a match and execute command there

Syntax is [range]global/{pattern}/{command} . command can be s (substitute), m (move the line). Default range is whole file. For normal commands use :normal.

  • search for comment and inside that line replace foo with bar
    :g=//=s/foo/bar/g
    
  • reverse all lines
    # It matches every line and move to the top
    :g/^/m 0
    # also works with marks, for example reverse from mark t to current line
    :'t+1,.g/^/m 't
    

Insert Completions

  • ^n or ^p in insert mode to autocomplete strings and get next/previous item
  • ^x^o to autocomplete using omni completion (intellisense) inteligent way of completion for example complete only methods that exists on that object :help compl-omni-filetype
    • in html you can auto close last opened tag if after </ you click ^x^o (similar with ragtag plugin that completes using <Ctrl-x>/)
    • in css :set omnifunc=csscomplete#CompleteCSS
    • in ruby
       let g:rubycomplete_buffer_loading = 1
       let g:rubycomplete_classes_in_global = 1
       let g:rubycomplete_rails = 1
      
  • ^x^n only strings from current file
  • ^x^l complete whole lines
  • ^x^f to complete filename (keep ^x^f when you navigate subfolders)
  • ^x^] for tags find other shortcuts with :help ins-completion
  • ^a and ^x to increment and decrement numbers speeddating if you want to increment dates

Installing

Update to vim 8 use

sudo add-apt-repository ppa:jonathonf/vim
sudo apt-get update
sudo apt-get install vim

On ubuntu 18 that package is outdated so I need to compile from source https://stackoverflow.com/questions/37079424/ubuntu-16-04-lts-cant-enable-xterm-clipboard-in-vim/37079474#37079474 Add gtk so we can copy to clipboard

sudo apt-get build-dep vim
git clone https://github.com/vim/vim.git vim_source
cd vim_source/
./configure \
    --enable-perlinterp=dynamic \
    --enable-pythoninterp=dynamic \
    --enable-rubyinterp=dynamic \
    --enable-cscope \
    --enable-gui=auto \
    --enable-gtk2-check \
    --enable-gnome-check \
    --with-features=normal \
    --with-x \
    --with-compiledby="DevNull <darkstar@/dev/null>" \
    --with-python-config-dir=/usr/lib/python2.7/config-$(uname -m)-linux-gnu
make -j8
sudo checkinstall

Plugins

Pathogen is no longer needed since you can install packages to the pack folder .vim/pack/my-package. Start using :packadd! my-package.

Plugins are installed in ~/.vim/plugin/. You can add subfolders for better organizations ~/.vim/plugin/rails/*.vim For specific file type (based on extension .c, or first line #!/bin/bash) only specific plugins from ~/.vim/ftplugin are loaded ~/.vim/ftplugin/c.vim.

Help doc files are added to ~/.vim/doc like ~/.vim/doc/my_plug.vim, than run :helptags ~/.vim/doc so that doc is added to local help. List of all added files is :help local-additions

Instead of installing pathogen and

mkdir -p ~/.vim/autoload ~/.vim/bundle && \
curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim

cd ~/.vim/bundle
git clone git://github.com/tpope/vim-rails.git # example: Rview

you can use vim builtin way

:help packages

You can find my list of plugins

  • rails-vim is nice
    • if you want to use rspec instead of minitest, you need to remove tests folder so :Espec works
    • run <leader>s to run nearest spec (also t,l,a for file, last and all specs)
    • there are mappings for minitests: Efunctionaltest are controller tests, Eunittest are model tests, Eintegrationtest are integration between controllers. Do not know how to jump system tests.
    • use projections to add custom commands, for example app/services
    let g:rails_projections = {
        \ "app/services/*.rb": {
        \   "command": "service",
        \   "template":
        \     ["class {camelcase|capitalize|colons}", "end"],
        \   "test": [
        \     "test/services/{}_test.rb",
        \     "spec/models/{}_spec.rb"
        \   ],
        \ }}
    
  • vim-commentary comment line, visual select and press gc

  • ctrlp ctrl+p
    • to seach already opened buffers, hit <ctrl-p> and than <ctrl-f>
    • to open in horizontal sprit use <ctrl-p> and <ctrl-x>
    • to open in current buffer, instead of patching autoload/ctrlp.vim:1309 to use let md = 'r' instead of let md = argmaps you can configure different prompt mappings for <ctrl-o> to immediatelly replace buffer.
    " make ctrl-o immediatelly replace buffer so we don't need to answer OpenMulti prompt
    " Open Selected: [t]ab/[v]ertical/[h]orizontal/[r]eplace/h[i]dden? 
    let g:ctrlp_prompt_mappings = {
    \ 'PrtSelectMove("j")':   ['<down>'],
    \ 'AcceptSelection("r")': ['<c-j>'],
    \ }
    
  • splitjoin for inline ruby blocks { } to convert do multiline do\n end.

Some not used anymore

  • You complete me: its too much visualisation

    # http://vimawesome.com/plugin/vim-rspec-sad-beautiful-tragic # :RunSpec
    git clone [email protected]:Valloric/YouCompleteMe.git && cd YouCompleteMe && ./install.sh && cd -
    
  • vim-markdown: issue with syntax highlight for * inside code block

  • vim-autoclose: annoying O char waiting next input

  • ragtag plugin in insert mode:
    • <ctrl-x>/ close last html tag
    • <ctrl-x>= append <%= %>, use <ctrl-x>+ to wrap around last line
    • <ctrl-x>- append <% %>, use <ctrl-x>_ to wrap around last line
    • <ctrl-x>@ insert stylesheet or <ctrl-x>$ javascript tags
  • multicursors mode change several strings at the same time https://github.com/mg979/vim-visual-multi

Running ruby in vim and show in separate window

link Press F7 to run selected or all code. Shift + F7 close the window.

"save code, run ruby, show output in preview window
function! Ruby_eval_vsplit() range
  let src = tempname()
  let dst = tempname()
  execute ": " . a:firstline . "," . a:lastline . "w " . src
  execute ":silent ! ruby " . src . " > " . dst . " 2>&1 "
  execute ":pclose!"
  execute ":redraw!"
  execute ":vsplit"
  execute "normal \<C-W>l"
  execute ":e! " . dst
  execute ":set pvw"
  execute "normal \<C-W>h"
endfunction
vmap <silent> <F7> :call Ruby_eval_vsplit()<CR>
nmap <silent> <F7> mzggVG<F7>`z
imap <silent> <F7> <Esc><F7>a
map <silent> <S-F7> <C-W>l:bw<CR>
imap <silent> <S-F7> <Esc><S-F7>a

Seeing is believing

Show ruby return values on each line in vim. Install seeing_is_believing with gem install seeing_is_believing --version 3.0.0.beta.7 and add plugin cd ~/.vim/bundle && git clone https://github.com/hwartig/vim-seeing-is-believing and add mappins: F4 mark, F5 run (not in visual) and enter mark and run (not in insert mode)

" .vimrc Enable seeing-is-believing mappings only for Ruby
augroup seeingIsBelievingSettings
  autocmd!

  autocmd FileType ruby nmap <buffer> <Enter> <Plug>(seeing-is-believing-mark-and-run)
  autocmd FileType ruby xmap <buffer> <Enter> <Plug>(seeing-is-believing-mark-and-run)

  autocmd FileType ruby nmap <buffer> <F4> <Plug>(seeing-is-believing-mark)
  autocmd FileType ruby xmap <buffer> <F4> <Plug>(seeing-is-believing-mark)
  autocmd FileType ruby imap <buffer> <F4> <Plug>(seeing-is-believing-mark)

  autocmd FileType ruby nmap <buffer> <F5> <Plug>(seeing-is-believing-run)
  autocmd FileType ruby imap <buffer> <F5> <Plug>(seeing-is-believing-run)
augroup END

Indent

HTML indent works fine but note when to avoid erb tags. It detects %> as closed tag except when line starts with <%. Do not use comment in the middle of erb since that line somehow is not indented. Better is to add another comment tag inline <%# if condition? %>

Instead
<div>
  text node <%= name %>
</div>

Use
<div>
  text node
  <%= name %>
</div>

For if else anotation use separated tag
<% if b %>
<% else %><%# if b %>
<% end %><%# if b %>

For multiline ruby there is a problems so use single line erb
<% one %>
<% two %>

For case switch there is a problem since it is not recognized as valid ruby
    <fieldset>
      <% case searchable %>
      <% when Book %>
        <legend>Book</legend>
        <%= searchable.title %>
      <% when User %>
      <% end %>
only solution is to merge two line into one
    <fieldset>
      <% case searchable when Book %>
        <legend>Book</legend>
        <%= searchable.title %>
      <% when User %>
      <% end %>

Netrw

netrw.vim is native exprorer. :Explore(short :E) :Vex of current editing file To change current folder just press c on folder line help :netrw-c. That’s better than cd ../path which change in all tabs. It will not affect already opened windows, so it should be done on the first window in the tab.

Inside netrw:

  • % create new file, more info :help netrw-%
  • d create new directory
  • R rename file/directory under cursor
  • D delete file/directory under cursor

NERD tree

  • to change current directory to selected folder, type in normal mode cd. It will change directory only in current buffer.
  • refresh with r (selected dir) or R (all)
  • to preview file you have to open :NERDTreeToggle instead of :e . and that you can use go to preview or <cr> to jump to file. To remap <cr> for preview and to cursor stay you can add
    " https://github.com/preservim/nerdtree/issues/1123#issuecomment-628737990
    let NERDTreeCustomOpenArgs = {'file':{'where':'p','keepopen':1,'stay':1}}
    let g:NERDTreeMapPreview = "<CR>"
    

CTAGS

You need to generate tags file with ctags -R .. You can use default params.

# ~/.ctags
--recurse=yes
--exclude=.git
--exclude=log
--languages=ruby

Some vim keys:

  • ^] ctrl-] : jump to tag under cursor
  • ^t jump back in tags stack, stack is when you jump with ^], see all with :tags. You can open in split window <ctrl-w> ]
  • ^x^] autocomplete tags
  • g] list all ambiguous tags: same method could be defined in multiple classes :ts my_met select tags for my_met. :tfirst :tnext to jump next
  • To search for all tags that contains met use :tag /met and press To open a window (preview window) and stays at current position you can use `:ptag met` (close preview window with `:pclose`). ctrp tags

To generate tags for all gems install https://github.com/tpope/gem-ctags

gem install gem-ctags
gem ctags

Create template to git hook http://tbaggery.com/2011/08/08/effortless-ctags-with-git.html

Also use CtrlPTag so you can navigate to tag

Syntastic checker

Instead of synstastic I use ALE https://github.com/w0rp/ale Results are put in location list so you can navigate with ] l.

" config/vim/ale.vim
" change message
let g:ale_echo_msg_format = '[%linter%] %s [%severity%]'

" disable linter on change
let g:ale_lint_on_text_changed = 'never'

" use only erubylint
let g:ale_linters = {'eruby': ['erubylint']}

" enable airline
let g:airline#extensions#ale#enabled = 1

" use less invansive color for warnings
highlight ALEWarning ctermbg=DarkMagenta

" disable ale for all subrepositories under real-world-rails
let g:ale_pattern_options = {
\ '.*real-world-rails.*': { 'ale_enabled': 0},
\}

You can disable ALE with ALEToggle. You can see error message ALEDetail. Yo see all configuration options ALEInfo. There was issue with erb https://github.com/w0rp/ale/issues/580 but this erubylint was recently removed from ale linters.

On Ruby 3.2.0 there is a warning

Passing trim_mode with the 3rd argument of erb.new is deprecated.

https://github.com/dense-analysis/ale/issues/4167 so maybe the solution could be to define it’s own linter like https://github.com/dense-analysis/ale/issues/580#issuecomment-337676607

Syntastic (deprecated, use ALE instead)

syntastic vim plugin is great to write your code. Just need to install external syntac checkers and they will be eabled. SyntasticInfo can give you current checkers and help syntastic-checkers will show you all available checkers.

To check if some checker is installed you can try with system command (here we show current path):

:echo syntastic#util#system('echo "$PATH"')

You need to activate checkers for specific filetype and you can customise speific checker

let g:syntastic_<filetype>_checkers = ['<checker-name>']
let g:syntastic_<filetype>_<checker>_args = "--my --args --here"

Here is my configuration for syntastic and vim https://github.com/duleorlovic/config/blob/master/vim/syntastic.vim You need to install this tools:

  • Markdown gem install mdl
  • Ruby, Rails gem install rubocop. You can automatically fix some errors with rubocop --auto-correct Gemfile. Configuration is in .rubocop.yml in $HOME or project root. You can can generate TODO config file with rubocop --auto-gen-config

    My preferred configuration is https://github.com/duleorlovic/config/blob/master/.rubocop.yml

    • inline in comment # rubocop:disable Metrics/AbcSize, Metrics/MethodLength to disable whole file you can put at first line
      # rubocop:todo all
      
    • gem ‘rubocop-rspec’ is nice linter for rspec. You can run manually with -D param to see cop names.

To disable some errors define quiet messages in syntastic.vim (:help syntastic_quiet_messages) g:syntastic_eruby_ruby_quiet_message

  • fix possibly useless use of a constant in void context in erb is with <%= CONST.to_s %>, when is problem with + than fix with assign <%= total = a + b; total %>

  • for js I use jshint with es6 and disabled semicolons
  • semicolons also disabled in eslint (which extends from airbnb-base) inline comments
    # disable one line
    }(function( $, window, document, undefined ) { // eslint-disable-line
    
  • for styles I use stylelint and local .stylelintrc since version 9.10 does not pick my home configuration
  • Javascript npm install -g jscs jscs-angular and create files [.jscs](
  • json npm install -g jsonlint link to issue

    " .vimrc
    au BufRead,BufNewFile *.json set filetype=json
    let g:syntastic_json_checkers=['jsonlint']
    
  • coffeescript npm install -g coffeelint

Vimium chrome extension

https://github.com/philc/vimium

Normal mode:

  • j and k down and up on a page
  • f follow links F follow in new tab
  • H and L back and forward in history
  • J and K prev and next tab
  • o search and open history links
  • T search open tabs
  • r reload the page
  • gg top or G bottom of the page
  • gi go to first input element

Additional navigation commands:

  • yy copy current url to clipboard
  • gu go up one level in URL path
  • gU go to root of domain

Find mode, enter with /:

  • n and N next and prev search match

Insert mode, enter with i. So if you notice that x closes tab even you are inside input, jump into insert mode first…

Since gmail has own j k prev and next email, I added rule to ignore all (*) keys

Do not know https://stackoverflow.com/questions/53918093/why-is-class-demo-button-so-special-in-vimium?noredirect=1#comment94679088_53918093

Vimum VimFx

Vimium-FF VimFx does not support firefox 57+ source is vimium for firefox. f for navigation and clicks, / for search (n N), x X for close and reopen tab, J K switch, space shift+space page down up. Hints mode:

  • f anything clicable F opens in new tab (or press Ctrl) ew new window
  • by default lowercase letter will filter hint strings, but you can use uppercase letter to filter by text (you can see what is entered in lower right corner)
  • yf copy text and links

Rails vim

Some todos:

Pluralize

  • When I type :Rcontroller customer it should go to :Rcontroller customers instead of error: No such controller customer. This usually happens when I have a lot of models customer_invoices, customer_payments and customers.

Localize

  • When I’m in index.html.erb and I type :Rcontroller than I jump to controller, but if I’m on index.in.html.erb than there is an error Argument required. Also problem with :Eview another_

Jump to system tests

Create scripts for vim

help usr_41.txt is Write a vim script in user manual. https://en.wikibooks.org/wiki/Learning_the_vi_Editor/Vim/VimL_Script_language

Detect if some features are enabled, for example only on macOS :help feature-list:

" copy to clipboard on macOS need to use pbcopy
if has('macunix')
  vnoremap "+y :w !pbcopy<cr><cr>
endif

Vim scripts in ruby:

https://subvisual.co/blog/posts/139-how-to-program-vim-using-ruby/

Vim ruby support

:help ruby Some integrated stuff in vim https://github.com/vim-ruby/vim-ruby/blob/master/doc/vim-ruby.txt https://github.com/vim-ruby/vim-ruby/wiki/VimRubySupport

WHEREAMI my plugin to show dedented lines above

When looking at large files in small window (I have 4 vim windows in my single terminal window) than I want to see to which block current line belongs. In schema.rb, current line in which table ?

ActiveRecord::Schema.define(version: 20170124131420) do
  create_table "projects", force: :cascade do |t|
    ... long ...
    t.integer title

In ability.rb, current ability to which user ?

When I’m in long spec file, I want to see setup block for current example and all outer example groups (maybe to group all descriptions in one sentence).

RSpec.describe Project do
 let(:project) { Project.new }
 before
 ... long ...
 describe "create task" do
   ... long ...
   it "order by date" do
     project

Also in view, I want to be able where current element belongs, so list all wrapped elements. And when I’m in scss I want to see all parent selector, classes and media queries.

Solution is to use similar row as in https://github.com/chrisbra/csv.vim :Header

similar but does not work for rspec http://vim-taglist.sourceforge.net/installation.html :TlistToggle

Nice example of opening sidewindow is undotree plugin Also similar showing info per each line is vim-fugitive plugin

usage:

  • in rspec you can see all previous describe blocks
  • in db/schema.rb when you search for column_name, you can see in which table this column under cursor belongs to

My solution is using search https://github.com/duleorlovic/config/blob/master/bin/whereami.rb which I mapped to leader w

" whereami
set errorformat+=%f%l%m
set grepprg=~/config/bin/whereami.rb
" move to function and use silent
" three <cr> one for execute, one for grep and one for copen to jump back to line
nnoremap <leader>w :execute ":grep %:p " . line('.') .  "\|clast\|copen"<cr><cr><cr>

TODO: try to follow the cursor

RubocopFix vim plugin rubocop

Fix current rubocop errors and comment uncorrectable

rubocop --auto-correct --disable-uncorrectable

but this is applying to whole file

TODO: write vim code that takes only the patch which is on current line

Graph visualization in markdown

https://markvis-editor.js.org/

Debug profile startup time

  • if vim does not show properly, blank or empty screen, try :redraw!

https://github.com/bchretien/vim-profiler

Vim test

https://8thlight.com/blog/chris-jordan/2016/06/13/running-tests-in-vim.html

" run single rspec test example for current line
nnoremap <leader>rs :execute "!rspec %:" . line(".")<cr>

" set compiler
:compiler rspec
:make %

Place language specific (file type) plugins inside ~/.vim/ftplugin/ruby.vim so they are automatically loaded when you open ruby file.

Use https://github.com/janko-m/vim-test

  • <leader>t test nearest spec to the line (if not inside example, whole file will be run) :TestNearest
  • <leader>T test whole file :TestFile
  • <leader>a test whole suite :TestSuite
  • <leader>l test last, usefull if you navigate to the code and see if test pass :TestLast
  • <leader>g visit test, jump back to the test to write more tests :TestVisit

I use strategy let test#strategy = "dispatch". Asyncrun will not correctly parse errors:

# instead of one error
# AsyncRun show two

expected `#<User id: 1061, email: "[email protected]", created_at: "2017-09-23 09|19| 48", updated_at: "2017-09-23 09:19:48">.confirmed?` to return true, got false
spec/features/user_confirmation_spec.rb|25| in `block (2 levels) in <top (required)>'

I prefer to use xdotool and send command to actual window

" config/vim/ftplugin/ruby.vim
function! EchoStrategy(cmd)
  let current_window = system('xdotool getactivewindow | tr -d "\n"')
  let target_window = system('xdotool search --classname vp_3_class_slash | tr -d "\n"')
  execute 'Dispatch!  xdotool windowactivate --sync '.target_window.' type "'.a:cmd.'"; xdotool key --delay 50 space Return windowactivate '.current_window
endfunction

let g:test#custom_strategies = {'echo': function('EchoStrategy')}
let g:test#strategy = 'echo'

Vim plugin

https://github.com/junegunn/vim-plug vim plugin manager is installed with one command curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim and setup in .vimrc

call plug#begin('~/.vim/plugged')
" Make sure you use single quotes
" Shorthand notation; fetches https://github.com/junegunn/vim-easy-align
Plug 'junegunn/vim-easy-align'
call plug#end()

And install with PlugInstall

Vim Color Scheme

https://github.com/nightsense/vimspectr is installed using vim-plug

Plug 'nightsense/vimspectr'
colorscheme vimspectr60flat-dark

but I prefer to tweek one by one color

highlight Comment cterm=underline ctermbg=Blue ctermfg=White

You can find example color scheme :e $VIMRUNTIME/colors

term defines attribute in black and white terminal, cterm in color terminal. cterm accepts bold underline reverse italic but no colors. ctermfg and ctermbg accepts colors, list of all on :help cterm-color Highlight groups can be found on highlight-groups

To see where the color is defined use verbose, for example

verbose hi Comment

Using ALE I see :help g:ale_set_highlights that groups are ALEError, ALEWarning … so I use less invasive color:

hi ALEWarning m

If color is not properly set and wrong wile scrolling bottom to top, that could be since vim does not read whole file. You can refresh with ctrl-l

Folding

In visual mode you can select and run :fold to collapse. Also as operator in normal mode you can use zfap a paragraf. zo is to open, zc it to close again (if fold already created on that line previously), zr to reduce (open) and zm to minimize (close) all folds in buffer. Use zM and zR to recursivelly close and open all nested folds. zn disable zN brings back the folding.

To see all lines that can be folded you can :set foldcolumnd=2. To automatically open and close folds when you navigate over it use :set foldopen=all and :set foldclose=all

Save all fold positions with :mkview and load with :loadview Automatically create folds based on indent :set foldmethod=indent

You can hide copy right sections of other comments.

" .vimrc
" https://stackoverflow.com/questions/2250011/can-i-have-vim-ignore-a-license-block-at-the-top-of-a-file
function! FoldCopyright()
  if !exists( "b:foldedCopyright" )
    let b:foldedCopyright = 1
    silent! 1,/# Copyright/;/USA\.$/fold
  endif
endfunction
autocmd BufNewFile,BufRead *.rb call FoldCopyright()

If you use autocmd FileType vim setlocal foldmethod=marker marker method than any lines that starts and ends with { { { …. }}} can be toggled with za

Database

Use https://github.com/tpope/vim-db and access with

:DB mysql://username:password@localhost/my_db_test

Tmux

Not using for now

  • strange characters instead of single quote I see <91> and <92> in vim. https://superuser.com/questions/199799/vim-shows-strange-characters-91-92 run :%s/[\x91\x92]/'/g to replace them

https://handbook.infinum.co/books/rails/Editors/Vim https://emily.st/2018/11/13/vim-in-the-future/ https://onivim.io/ https://neovim.io/doc/ https://github.com/neoclide/coc.nvim Visual studio plugins running on vim

# you need to install coc using yarn
cd ~/.vim/bundle/coc.nvim/
yarn

and you can install plugins

:CocInfo
:CocInstall coc-yaml
:CocConfig
# to edit `~/.vim/coc-settings.json`