# Vim Tips [gregorymcintyre.com](https://gregorymcintyre.com) 2017 ==== ## Vim Tips * Beginner * Intermediate * Advanced ==== ## Beginner Vim ```js f(world, hello); ``` ```vim <Right><Right> xxxxxihello<Esc> <Right><Right><Right> xxxxxiworld<Esc> ``` ==== ## Beginner Vim * `<Right>` = move cursor right * `x` = delete character * `i` = enter insert mode * `<Esc>` = exit insert mode ==== ## Beginner Vim * Lots of keystrokes (or use the mouse!) * Lots of repetition ==== ## Vim Tips * ~~Beginner~~ * Intermediate * Advanced ==== ## Intermediate Vim ```js f(world, hello); ``` ```vim wwcwhello<Esc>wwcwworld<Esc> ``` ==== ## Intermediate Vim ```js class MyClass { myMethod() { return subRoutine(); // wcwgreeting<Esc> } // jjb subRoutine() { // . return "Hello World"; } } ``` ==== ## Intermediate Vim * `h/j/k/l` = move cursor left/down/up/right * `c` = change (delete the next cursor movement, enter insert mode) * `w` = word (move cursor forward by one word) * `j` = move cursor down * `b` = move back one word * `.` = repeat last "edit" ==== ## Intermediate Vim * Command + movement = edit! * Repeat as necessary * Fewer keystrokes * Try combinations of commands/movements * Command vocabulary * Movement vocabulary ==== ## Intermediate Vim | commands | | | ---- | ----------------------------- | | `c` | change | | `d` | delete (also cut) | | `y` | copy | | `p`/`P` | paste on previous/next line | | `v`/`V` | select text/line | ==== ## Intermediate Vim | motions | | | ---- | ----------------------------- | | `b`/`w` | prev/next word | | `{`/`}` | prev/next blank line | ==== ## Quiz `{d}` ==== ## Vim Tips * ~~Beginner~~ * ~~Intermediate~~ * Advanced ==== ## Advanced Vim * Higher level commands & motions * Text objects * Modeline * Plugins * Faster navigation * Tool integration * Windows/tabs/buffers * Learning ==== ## Advanced Commands | commands | | | ---- | ----------------------------- | | `=` | indent | | `==` | indent current line | | `>`/`<` | indent/unindent | | `>>`/`<<`| indent/unindent current line | | `gq` | format text with hard wrap | | `J` | join (remove newlines) | | `10j` | repeat j 10 times | ==== ## Quiz * `{gq}` * `gqq` * `V10>` ==== ## Advanced Motions | motions | | | ---- | ----------------------------- | | `fx` | forward until the next letter "x" | | `^`/`$` | start/end of line | | `gg`/`G` | start/end of file | | `?`/`/` | search back/forwards | ==== ## Quiz * `gg=G` * `d?Quiz<Return>` ==== ## Text Objects | apply to... | | | ---- | ----------------------------- | | `iw`/`aw` | word | | `is`/`as` | sentence | | `ip`/`ap` | paragraph | | `i"`/`a"` | double quoted text | | `i(`/`a(` | text in brackets | | `it`/`at` | text in HTML tag | ==== ## Quiz * `dap` * `ci"Hello World<Esc>` ==== ## Modeline The Vim command prompt ```vim :<Tab> ``` ==== ## Modeline Example ```js // :bufdo %s/\<subRoutine\>/newName/gc class MyCode { main() { subRoutine(); // y } subRoutine() { // y return "Yay"; } } // y/n for other files ``` ==== ## Modeline Example ```vim :bufdo %s/\<subRoutine\>/newName/gc ``` * `bufdo` = repeat on all open files * `%` = select the whole file * `s` = substitute using regex * `\<` = beginning of a word (regex) * `\>` = end of a word (regex) * `g` = all occurances on each line * `c` = confirmation prompt * `:help bufdo` * `:help substitute` ==== ## Plugins * Themes * Syntax rules * Text objects * Commands * Other... ==== ## Plugins ```vim call plug#begin('~/.vim/plugged') " ... Plug 'elixir-lang/vim-elixir' " ... call plug#end() ``` [https://github.com/junegunn/vim-plug](https://github.com/junegunn/vim-plug) ==== ## Plugins * New text objects * `dii` = delete everything at current indent level * `daa` = delete a comma separated argument neatly * `dar` = delete a Ruby expression neatly ```vim Plug 'michaeljsmith/vim-indent-object' Plug 'wellle/targets.vim' Plug 'nelstrom/vim-textobj-rubyblock' ``` ==== ## Plugins * New commands * `ysiw"`/`ds"` = quote/unquote word * `gcar` = comment out Ruby expression ```vim Plug 'tpope/vim-surround' Plug 'tpope/vim-commentary' ``` ==== ## Quiz * What are some syntactic objects you already work with? * What do you do to them? ==== ## Faster Navigation Measure how many seconds you spend finding the right code to edit ==== ## Faster Navigation | method | time | questions | | ---- | --- | --- | | `:NERDTree` | 5-20 seconds | dir? file? lineno? | | `:CtrlP` | 2-15 seconds | file? lineno? | | `gf` | 2-10 seconds | lineno? | | `:tag` | 1-3 seconds | which name? | | `<C-]>` | <1 second | - | ==== ## Faster Navigation ```vim if has("gui_macvim") " D- is Command on Mac nnoremap <D-p> :CtrlP<CR> nnoremap <D-r> :CtrlPMRUFiles<CR> nnoremap <D-b> :CtrlPBuffer<CR> endif ``` ```vim Plug 'kien/ctrlp.vim' ``` ==== ## Faster Navigation (Command-R) <img class="borderless" src="mru.png" alt=":CtrlP MRU"> ==== ## Faster Navigation File in the same directory? ```vim cnoremap %/ <C-R>=expand("%:p:h")."/"<CR> nnoremap ,e :e \ <C-R>= \ substitute(expand("%:p:h"), ' ', '\\ ', 'g') \ .'/'<CR><BS>/ ``` <!-- .element: class="small" --> ==== ## Faster Navigation (,e) <img class="borderless" src="comma-e.png" alt=",e"> ==== ## Faster Navigation ```vim Plug 'airblade/vim-rooter' ``` * `<Command-R>` * Select file in another project * `:pwd` will always set appropriately ==== ## Tools (RSpec, Mix, etc.) ```bash $ cat ~/bin/v exec gvim --remote-expr "expand('%').':'.line('.')" $ cat ~/bin/vf exec gvim --remote-expr "expand('%')" $ v /Users/greg/project/spec/models/user_spec.rb:38 $ vf /Users/greg/project/spec/models/user_spec.rb ``` <!-- .element: class="small" --> ==== ## RSpec ```bash $ bundle exec rspec `v` . Finished in 0.53 seconds 1 example, 0 failures ``` ==== ## Mix ```bash $ mix test `v` AppSignal disabled.Including tags: [line: "9"] Excluding tags: [:test] . Finished in 0.06 seconds 2 tests, 0 failures, 1 skipped Randomized with seed 697624 ``` <!-- .element: class="small" --> ==== ## Potentially ```bash $ cucumber `v` $ mocha `v` $ rubocop `vf` $ mix credo --read-from-stdin < `vf` $ ember test `vf` # :-( $ next-cool-tool `v` ``` ==== ## Typing \`v\` in iTerm <img class="borderless" src="iterm-prefs.png" alt="iTerm Preferences"> ==== ## Typing \`v` ```bash $ be rspec <Command-R><Return> ``` ==== ## Expanding \`v` ```bash $ be rspec <Command-R><C-M-e> # bash % be rspec <Command-R><Tab> # zsh ``` ==== ## Windows, Tabs, Buffers Oh my! ==== ## Windows * `<Command-N>` for a new window (MacVim) * I don't use it * Messes with my \`v\` thing ==== ## Tabs * Change buffer in tab = `:e`, `:close` * New tab = `:tabedit`, `:tabclose` * I don't use it * Too confusing ==== ## Buffers * `:e`, `,e`, `<Command-R>`, `<Command-P>` * But I don't use `:b` or `:CtrlPBuffer` * Which files are open? * Too much mental load ==== ## Splits * `:split` or `<C-W>s` or `<C-W>v` * Then `<C-W>o` * I very rarely use it * Spatial awareness? * Too much mental load ==== ## So What DO I Use? * `<C-]>` and `:tag <Tab>` when possible * Forget files and directory structures * Huge mental load vanishes * Ultra fast ==== ## So What DO I Use? * `<C-o>` and `<C-i>` * Works across files * Forget files and directory structures * Re-opens old files if necessary ==== ## So What DO I Use? * `<Command-P>` or `<Command-R>` * Slower backup plan ==== ## How Did I Learn? * Pair programming * Years of incremental improvements ==== ## Take Home Messages * Prefer repeatable edits * Get faster incrementally * Files and directories are slow * Pair program and ask * "Do you know a better way to...?" * "How did you just do that?" ==== [gregorymcintyre.com/slides/vim-tips/](https://gregorymcintyre.com/slides/vim-tips/#/)