name: inverse layout: true class: center, middle, inverse --- # Vim The editor that withstood the test of time .footnote[Marek Šuppa
Ondrej Jariabka
Adrián Matejov] --- layout: false # Why learn UNIX today? Despite what it may look like, it is still being used rather extensively. See for yourself: https://insights.stackoverflow.com/survey/2020#technology-platforms --- # Vim - A text editor ubiquitous on *NIX systems - An extension of the `vi` editor, part of the original UNIX - Simple at its core, but very extensible - User friendly to programmers and system administrators - The 5th most popular development environment in 2019 (according to [StackOverflow survey](https://insights.stackoverflow.com/survey/2019#technology)) -- Opening it (with a file) is very easy, just run ```bash vim file.txt ``` from your shell ??? StackOverflow survey: https://insights.stackoverflow.com/survey/2019#technology --- # Warning: Vim has a steep learning curve .center[ ![:scale 80%](images/editor_learning_curves.jpg) .font-small[Image from https://devrant.com/rants/83706/few-text-editors-learning-curves-emacs-won-the-competition] ] --- # Exiting Vim .center[ ![:scale 80%](images/close_vim_tweet.png) ] .center[.font-small[From [What I’ve Learned After Using Vim 15 Days Straight](https://towardsdatascience.com/what-ive-learned-after-using-vim-15-days-straight-ceda7e773a6d)]] --- # Exiting Vim II Despite what the internet says, it's not that difficult. Here are a few options: -- - `:q` or `:q!` - `q` stands for "quit" (you can also run `:quit` if you want) - by default, Vim won't quit if there are unsaved changes - you can force it to do so by appending `!` to the command -- - `:wq`, `:x` and `:wq!` - `w` stands for "write" and makes Vim write the changes to the opened file - `wq` is a combination of the "write" and "quit" commands - `x` is a quick shortcut for `wq` - appending `!` makes Vim ignore warnings about overwriting --- # Vim philosophy 1. Optimize for reading code/text, not writing 2. Be programmable by itself (keystrokes are composable commands) 3. Avoid the mouse (too slow) or even the arrow keys (too much hand movement) -- In practice this means using different "modes of operation" for different kinds of tasks -- There are 12 of them in total but we'll only go through the most important ones. ??? - Vim can be profoundly alien to people who only used "standard programming tools" - Many of the ideas encapsuled in it are very valuable outside of it as well (similar to UNIX) -- that's why we teach it --- # Vim modes - **NORMAL** - the default mode the editor starts in - each keypress is equivalent to an editor command -- - **INSERT** - the "normal" mode of other editors - each keypress actually inserts a character to a given file -- - **VISUAL** - allows you to take a selection of text and apply various transformations -- - **COMMAND** - lets you run commands that control the whole editor in its "command line" - commands start with `:`, for instance `:q!` - technically known as _Command-line_ or _Cmdline_ mode --- # Vim modes II .center[![:scale 80%](images/vim-modes.png)] Everything starts and ends in the **NORMAL** mode. From there you can -- - Press `i` to start the **INSERT** mode - Press `v` to start the **VISUAL** mode - Press `:` to start the **COMMAND** mode -- To get back to the **NORMAL** mode, press `ESC` key (twice in the **COMMAND** mode). .center[ .font-small[Image from [CS61a article on Vim](https://cs61a.org/articles/vim.html)] ] --- class: inverse, middle, center # Normal mode --- # Movement in **NORMAL** mode - Instead of arrow keys, Vim uses `h`, `j`, `k` and `l` .center[![:scale 50%](images/vim.png)] -- - The reason why is efficiency: they are directly on your home row: .center[![:scale 50%](images/normal_position.png)] .center[.font-small[Images from https://tonsky.me/blog/cursor-keys/]] ??? The history is rather simple: the terminal Bill Joy wrote `vi` on did not have any arrow keys... https://catonmat.net/why-vim-uses-hjkl-as-arrow-keys --- # Movement in **NORMAL** mode II Movement on line level: - `^`, `0` or `
` - Jump to the beginning of the line - `^` goes to the first non-blank character - `$` or `
` - Jump to the end of the line -- Movement on word level: - `w` - Jump forward to the beginning of a word - `b` - Jump backwards to the beginning of a word -- .left-eq-column[ _The cursor is on `r`:_ ``` This is a ve`r`y nice sentence! ``` ] .right-eq-column[ _After pressing `w`:_ ``` This is a very `n`ice sentence! ``` _After pressing `b`:_ ``` This is a `v`ery nice sentence! ``` ] --- # Movement in **NORMAL** mode III Movement on character level: - `h` or `
` - Move one character to the _left_ - `l` or `
` - Move one character to the _right_ -- Movement to a specific character: - `fx` - Jump to the next occurence of character `x` - `Fx` - Jump to the previous occurence of character `x` -- _The cursor is on `r`:_ ``` This is a ve`r`y nice sentence! ``` _After pressing `ft`:_ ``` This is a very nice sen`t`ence! ``` --- # Movement in **NORMAL** mode IV Movement across lines: - `k` or `
` - Move to the line _above_ - `l` or `
` - Move to the line _below_ - `gg` - Move to the _first_ line of the file - `G` - Move to the _last_ line of the file --- # Editing in **NORMAL** mode Edit commands are the equivalent of text edit you'd do with a mouse. It is here where Vim starts to look like a programming language. - `o` / `O` - Insert line below / above - `d{motion}` - delete `{motion}` - for instance `dw` is delete word and `d$` is delete to end of line - `c{motion}` - change `{motion}` (like `cw` -- change word) - a shortcut for pressing `d{motion}` and then `i` - `x` / `X` - delete character after / before (same as `dl` / `dh`) - `s` - substitute character (same as `xi`) - `y{motion}` - "yank" (copy) everything until `{motion}` to the _"register"_ - delete and copy also put the changed text to the _"register"_ - `p` / `P` - paste from the _"register"_ after / before cursor --- # More edit commands in **NORMAL** mode - `cc` / `dd` / `yy` - change (remove and edit), delete (cut) or "yank" (copy) the _entire line_ - `xp` - swap two adjacent characters 1. delete character under cursor and move to the next 2. put deleted character to register 3. paste deleted character from register - `rx` - replace current character with `x` - `u` / `
` - undo / redo a change - `.` - repeat last change --- # Vim's **NORMAL** commands as a language Movements are "_nouns_" because they refer to a specific part of the text. -- Edits are "_verbs_" because they act on nouns. -- Combined with "_modifiers_" like counts, they comprise a powerful language. -- .left-eq-column[ - `8l` - Move eight characters to the left - `2w` - Move two words forward - `5k` - Move 5 lines down - `14gg` - Go to the 14th line ] .right-eq-column[ - `d2w` - Delete two words - `df)` - Delete until you find `)` - `yG` - "Yank" (copy) everything until the end of the file - `3dd` - Delete tree lines (below) - `4u` - Undo the last 4 changes ] --- # Lookup in **NORMAL** mode The lookup capabilities are based on **regular expressions**. `
` basically means pressing `Enter`. -- - `/{regexp}
` / `?{regexp}
` - look up `{regex}` from the current line downwards / upwards - `n` - repeat the search in _the same_ direction - `N` - repeat the search in _the opposite_ direction --- # Lookup-supported regular expressions .pure-table.pure-table-striped.mkdown-table[ | expr | description | |-----------|------------------------------| | `.` | any character | | `[ ]` | character class (or `[^ ]`) | | `^` | beginning of the line | | `$` | end of the line | | `\?` | match once or not at all | | `\+` | match one and more times | | `*` | match zero or more times | | `\{2,7}` | two to seven matches | ] --- class: inverse, middle, center # Insert mode --- # **INSERT** mode You can switch to it in multiple ways: - At the character you are currently at (`i`) - Move cursor to the right (`a` for _append_) - Move cursor at the beginning of the line (`A`) -- You can move in it with arrow keys. But it is much more effective to go back to **NORMAL** mode and move in there. -- To get out of it (and get back to **NORMAL** mode), you can use - `Esc` - `Ctrl+C` - `Ctrl+[` --- class: center, inverse, middle # Visual mode --- # Visual mode It can operate on various levels: - Characters (by pressing `v`) - Lines (by pressing `
`) - Blocks (by pressing `
`) -- The selection itself can be changed using movement commands. -- With `o` you can swap the position from which the selection is moving. --- # **VISUAL** mode commands Most of them are the same as in the **NORMAL** mode. - `I` / `A` - insert / append typed text to each line of the selection - `d` / `c` / `y` - delete / change (delete and insert) / yank (copy) the selection - deleted or yanked (copied) text can then be pasted with `p` or `P` - `u` / `U` / `~` - uppercase / lowercase / swap the case of the selection - `rx` - replace app characters in the selection with character `x` - `>` / `<` - increase / decrease the indent ("TAB-ization") of the selection --- class: center, inverse, middle # Command (Cmdline) mode --- # **COMMAND** (Cmdline) mode - `:` / `
` (twice) - Get in / out of the **COMMAND** mode -- - Up / Down arrows let you go through the command history - `
` does autocompletion -- Some helpful commands: - `:history` shows the complete history in a listing - `:help command` shows the help page for a given `command` - `:syntax on` / `:syntax off` turns on / off syntax highlighting --- # Text substitution in **COMMAND** mode - When coming from the **VISUAL** mode, the command is applied on the selection -- otherwise on the whole text. -- **`:s/{regexp}/{string}/{mod}`** - substitutes matched `{regexp}` for `{string}` - also works on text selected in **VISUAL** mode `:'<,'>s/{regexp}/{string}/` - and on the whole text using `%`, for instance `:%s/{regexp}/{string}/` - and from the 5th to the last line `:5,$s/{regexp}/{string}/` -- - `{mod}` modifies the replace behavior - `g` replaces all, not just first occurrence - `c` makes Vim ask you to confirm the substitution - `i` makes the regular expression case-insensitive -- - `&` can be used to repeat the last substitution --- # Shell commands in **COMMAND** mode - `:!{cmd}` - execute `{cmd}` in a shell - `:r!{cmd}` - execute `{cmd}` and paste its stdout to the currently opened file (buffer) -- Similar concept can be used to _filter_ the file we are editing: - `:3,5!{cmd}` - pass lines 3 to 5 to the stdin of `{cmd}` and replace them with the output - `:%!{cmd}` - pass the contents of the whole file (`%`) through `{cmd}` - `:'<,'>!{cmd}` - pass the contents of the selection through `{cmd}` - happens automatically when `!` is pressed in **VIRTUAL** mode --- class: inverse, middle, center # Useful commands --- # `nl` Adds line numbers to each input line - `-s` sets the separator (`
` by default) - for instance `nl -s :` - `-w` sets how many columns are used for line numbers (6 by default) - for instance `nl -w 1` .left-eq-column[ ```bash $ cat file.txt Adam Beatrice Cynthia David Emma $ nl file.txt 1 Adam 2 Beatrice 3 Cynthia 4 David 5 Emma ``` ] .right-eq-column[ ```bash $ nl -w 1 file.txt 1 Adam 2 Beatrice 3 Cynthia 4 David 5 Emma $ nl -w 1 -s ":" file.txt 1:Adam 2:Beatrice 3:Cynthia 4:David 5:Emma ``` ] --- # `shuf` - outputs a random permutation of the input lines - `-r` **r**epeat lines from the input - `-n` print out at most **n** lines ```bash $ cat file.txt 1 Adam 2 Beatrice 3 Cynthia 4 David 5 Emma $ shuf file.txt 2 Beatrice 3 Cynthia 1 Adam 5 Emma 4 David $ shuf -n 6 file.txt 2 Beatrice 3 Cynthia 1 Adam 5 Emma 4 David ```