LazyVim Notes are based on this resource https://lazyvim-ambitious-devs.phillips.codes/course/chapter-1/ Tutor :Tutor launch tutor Verb, count, motion count + verb + count + motion navigation is the default verb, can be omitted Motions w jump forward to the start of a word e jump forward to the end of a word b jump back to the start of a word ge jump back to the end of a word $ jump forward to the end of a line 0 jump backwards to the start of a line ^ jump backwards to the first non-white char W E B gE works the same, but splits words by white space, while lowercased versions split works also with dot, paren, quote Count + motion = Repeat motion 3w jump forward to the start of a word 3 times Insert mode (text) a put caret after cursor A put caret at the end of the line i put caret before cursor I put caret at the start of the line o add line below and put caret O add line above and put caret gi go to the last insertion point Esc normal mode (navigate and manipulate text) Ctrl+o go back into Normal mode for one operation only Ctrl+u undo for current line in Insert mode Select v granule text selection in Visual mode V line text selection in Visual mode Ctrl+v block vertical text selection (handy for csv data), $ - expands the selection to the longest line Or just click and drag mouse Esc / v exit Visual mode gv go back to prev selection o in Visual mode - jump to the start/end of selection S select with Seeking Surrounding Objects Expand selection there is no native vim way, but can use treesitter plugin Create or edit ~/.config/nvim/lua/plugins/treesitter.lua return { "nvim-treesitter/nvim-treesitter", opts = function(_, opts) opts.incremental_selection = vim.tbl_deep_extend("force", opts.incremental_selection or {}, { enable = true, keymaps = { init_selection = "gnn", -- start at node under cursor node_incremental = "grn", -- expand outward node_decremental = "grm", -- shrink inward scope_incremental = "grc", -- expand to scope (func/class) }, }) end, } Run :Lazy sync, then restart NeoVim Put cursor inside some code. Type: gnn selection starts. Then: grn expand outward. Again: grn expand more. grm shrink back. Registers Registers are different named clipboards where you copy text " open register list "ayy copy line into named a register "ap paste from the a register you may also delete and replace into the register adding again to the same named register replaces the content "Ay copy into upper-cased named A register appends text into existing a register System clipboard is synched with + and * registers Space s" show all registers and add content to + register with Enter Ctrl+r show same registers menu in Insert mode last copied text is always available at 0 register and you may paste it with "0p Last typed text goes into . register Last deleted small text goes into - register The name of the file that you are currently editing goes into % register :let @c=@. copy . register to named c register Copy (yank) y copy highlighted text (yank) yy copy whole line Y copy to the end of the line yw copy to the word's end yiq / yaq copy inside nearest quotes / including quotes yib / yab copy inside nearest brackets / including brackets yiw / yaw copy nearest word / word and whitespaces around yig copy whole file Paste p paste deleted text after cursor 5p paste 5 times P paste deleted text before cursor In Insert mode to paste Ctrl+r followed by + Yanky.nvim Plugin Install it from :LazyExtras and pushing x in front of it, then reload NeoVim Space p opens the clipboard history list p[y[y[y… / p]y]y]y… pastes previous/next clipboard entries in cycle [p / ]p pastes indented above/below current line >p / <p / P / <P put after/before and indent right/left Undo, Redo u undo the last command U undo all for the line Ctrl+r redo Ctrl+u undo in Insert mode Command mode : command mode :q! exit without save Open project in NeoVim Navigate to you project in terminal with cd Type nvim Save :w write :w TEST.txt write under TEST name :write TEST.txt same v motion :w FILENAME saves the Visually selected lines in file FILENAME. Exit :q quite :wq write & quit :x write & quit :q! quit without save Navigate in list Tab move down in list Ctrl+y accept Arrow Down accept Cursor movement j down k up h left l right Cursor history Ctrl+o jump back in history location Ctrl+i jump forward in history location Ctrl+g show cursor position + file name Jump by line (go to) 15G jumps to line #15 :15 jumps to line #15 gg jumps to first line G jumps to last line Jump by sentence ( / ) jump to start/end of the sentence Jump by paragraph { / } jump to start/end of the paragraph Jump by bracket [ / ] open go to prev/next menu ]) go to block's ) ]} go to block's } ]> go to block's > ]% go to block's brace (universal, works for <>()[]{} ) Jump to matching bracket Place cursor on bracket % jumps to closing bracket Jump by variable instance [[ / ]] jumps to prev/next variable instances Jump by function [f / ]f jumps to prev/next function start [F / ]F jumps to prev/next function end Jump by parameter [a / ]a jumps to prev/next parameter start [A / ]A jumps to prev/next parameter end Jump by method [m / ]m jumps to prev/next method start [M / ]M jumps to prev/next method end Jump by class [c / ]c jumps to prev/next class start [C / ]C jumps to prev/next class end Jump by scope [i / ]i jumps to start/end of scope Jump by error, warning, spell, diagnostic [e / ]e jumps to prev/next error [w / ]w jumps to prev/next warning [s / ]s jumps to prev/next spell issue ( Space us to enable spell check) [d / ]d jumps to prev/next diagnostic message [t / ]t jumps to prev/next TODO or FIXME comment Space cd show full error message under cursor Jump by hunk (changes) Hunk - modifications that haven't been staged or committed yet [h / ]h jumps to prev/next changes Go back/forward Ctrl+o/i go back/forward Go to definition gd go to definition Go to reference gr go to reference, shows the list of all files which uses the variable Space sR resumes your previous list Alt+t open all results in Trouble Go to symbol Space ss show list of symbols in file Space cs same, but another view, on the right side Space sS show list of symbols in project Show context info K show info (for ex. function signature from LSP) Marks ma mark line with a 'a jump to the mark a within the file mA mark line globally with A , can jump to it from any file ' open list with marks Space sm same, but different view with search :delmarks a delete the mark a :delm a same, delete the mark a '. jumps to the last place I inserted or changed text Jump to last edited text '. jumps to the last place I inserted or changed text Find fx puts you in Find mode and jumps to the nearest x ; / , jumps to the next/prev one 3fx jumps to the 3rd x from you F searches backwards To t same as Find mode, but puts cursor before the found char t searches for next char Seek s seek mode you may jump to any visible text simply by typing part of it and press green label character Seek in object May seek inside text object where your cursor is vS / dS / cS / yS select/delete/change/copy & enter into SEEK mode Green labels will surround the text part, a,b,c,d,e... from the inner to outer Seek remote May for ex copy (yank) something from remote place r yr (enters into Seek mode) + phrase + ib (inside brackets) Cursor comes back to the initial place Seek remote object Copy something from remote object with R (capital) Cursor comes back to original position yR (enters into Seek mode) + phrase + a (tag) Personally did not understand why it is helpful, better to jump to place, select & yank Surrounding Pair To change quotation marks or brackets, or content inside enable mini.surround extra plugin Select some text gsa add surrounding to selection " / ' / ` add quotation mark around ( / { / [ add braces with empty spaces ) / } / ] add braces without empty spaces Instead of selecting the text first may do directly gsaiB" to add quotation marks inside braces at your cursor gsa$" will surround text between the cursor and the end of the line with double quotation marks gsaSb' will surround text that you select with the label b after an S operation with single quotation marks gsdb delete surrounding braces gsdq delete surrounding quotes gsd[ delete surrounding square brackets 2gsd{ delete the second set of curly braces from cursor position gsr"' replace double quotes with single gsfb / gsFb jump to next/prev bracket gsfb highlight paired braces gsat add tags around selection Scroll Ctrl+d/u scroll down/up 50% Ctrl+f/b scroll down/up 100% 5 Ctrl+f scroll down 5 screens Ctrl+e/y scroll down/up 1 line z t/b scroll up/down to move active line almost to the top/bottom zz scroll to move active line to the middle Delete (verb) d [number] motion - delete operator dh / dl delete the character to the left/right of the cursor. dw delete to the beginning of next word d2w delete 2 words de delete to the end of the word db delete to the start of the word d0 delete to the start of the line d$ delete to the end of the line dd delete whole line (shortcut) 2dd delete 2 lines d2fe delete to the second e , including e d2ta delete to the second a dsfoos the label s that pops up when you use Seek mode to seek to foo . Note that Seek mode jumps to the beginning of the word D delete to the end of the line (shortcut) diq / daq delete inside nearest quotes / including quotes dib / dab delete inside nearest brackets / including brackets diw / daw delete nearest word / word and whitespaces around Delete char (verb) x delete char under cursor 5x delete 5 chars X delete char before cursor Change (verb) c - deletes and inters into Insert mode same as d + motion + i cw deletes to the end of the word & enters into Insert mode cc changes whole line (shortcut) C changes to the end of the line (shortcut) ciq / caq changes inside nearest quotes / including quotes cib / cab changes inside nearest brackets / including brackets ciw / caw changes nearest word / word and whitespaces around cag changes whole file Replace char (verb) r go into replace mode of single char, then a to replace with a R go into global replace mode Join lines J join lines merging white spaces gJ join lines keeping white spaces UpperCase & LowerCase ~ inverts case under the cursor gU / gu upper/lower case mode gUU / guu same, for whole line Dot repeat . repeats the verb 2. repeats the verb two times (if you removed 3 lines with 3dd , 2. will not remove 6 lines, but 2) Record command qq start recording and store commands into q named register q stop recording qQ continue recording (append commands to q register) Q play most recent recording @a play back recording stored at a register saved previously by qa @@ replay whichever register you most recently played To edit the recording just past it from the register by "qp if it was written to the named q register, then modify the text and copy it back to the q register by "qyiw Search in file / phrase search prompt, then Enter to jump to the first found match, or Esc to cancel it ? phrase search prompt in backwards direction n find next N find next in reverse direction Ctrl+o go back to older position Ctrl+i go back to newer position Search is case insensitive until you put uppercase letter Include \C in your search phrase to make search case sensitive when you are interested only in lower cased results for ex. Regexp in search RegExp in Vim is strange . any char, load..g finds loading \. searches for . dot char \S not whitespace char .* match any string \S\+ match any word without spaces \= optional, for ex https\=: will match http & https \V disable regexp for following search string Search and replace in file with Nvim-rip-substitute It is the plugin which has familiar dialog and easy to use Create ~/.config/nvim/lua/plugins/rip-substitute.lua and restart NeoVim return { "chrisgrieser/nvim-rip-substitute", keys = { { "g/", function() require("rip-substitute").sub() end, mode = { "n", "x" }, desc = "Rip Substitute", }, }, } g/ open dialog in the lower right corner First line is for search, second line is for replace, use j/k to jump between them Enter in Normal mode or the Ctrl+Enter in Insert mode to perform the substitution Use up/down arrows in Norma mode to select a previous substitution It supports RegExp by default ba(r|z|n) will find bar , baz , ban Search in project Telescope and RipGrep to be installed Maybe need to enable Telescope plugin via :LazyExtras brew install ripgrep install, it was not installed for me Space / open search prompt Space sg same Find and replace in file Vim way :substitute / :s enter into substitute mode :s/old/new replaces "old" with "new" first occurrence in line where your cursor is :.s/old/new same, but specifically indicate that operation is done on the same line, can be ommited as it is the default behaivor :s/old/new/g replaces "old" with "new" all occurrences in line where your cursor is :%s/old/new replaces first occurrences in every line of "old" with "new" in whole file :%s/old/new/g same, but all occurrences :5s/old/new/g replaces "old" with "new" at line 5 5G maybe it is easier to jump to line 5 and then make replacement :2,5s/old/new/g replaces "old" with "new" all occurrences in 2...5 lines :,50s/old/new/g replaces "old" with "new" all occurrences from current line to line #50 :,/text/s/old/new/g replaces "old" with "new" from current line to the first line with text including the line :%s/old/new/gc replaces "old" with "new" in file with prompt, useful when you need to skip some replacements :%s/old/new/gc c prompt flag, replaces "old" with "new" in file with prompt, useful when you need to skip some replacements :%s/old/new/gI I case sensitive flag :s//new if you omit search phrase, it replaces whatever pattern you last searched with "new" :s without any pattern or replacement, it will repeat the last pattern and replacement you did, but it will not use any previous flags, so most useful would be :%sg which means “repeat the last substitution on the entire file, globally.” Find and replace project wise Space sr open 'ripgrep' dialog j / k jump between fields As you type you get instant live update with proposed changes To accept changes you need to go back into normal mode with Esc and then \r to apply replacement You may modify replacement in preview window or even skip some replacements by deleting the preview line by dd . After that \s to sync changes. Press Enter over like in preview to jump to a source file \t open search history and Enter to reuse it External command :!ls show files :!rm FILENAME remove FILENAME file Read content and paste :r TEST reads content from the file TEST and pastes below the cursor :r !ls reads content from external command and pastes below the cursor Search file Search files in Current Working Directory Current Working Directory (CWD) is the directory where your terminal was in when you typed nvim Space fF files fuzzy search in (CWD) To check where you are, type :pwd (Print Working Directory) To change CWD :cd path/to/directory To change CWD just in one tab :lcd path/to/directory Search files in Root Directory Root Directory is where package.json or tsconfig.json Space Space files fuzzy search in current project Space ff same Root Directory may be confusing, coz they may change silently. Imagine you are in a monorepo with multiple tsconfig.json files and you will have different Current Working Directory depending on which file you are working on. In this case you may want to search relative to CWD Search gotchas Search is case insensitive, until you type a capital letter phrase1 phrase2 - type phrase1 first, get search results, hit Space , type second phrase2 , already visible results will be narrowed by fuzzy search with second phrase, super convenient Alt+s seek mode (may need to enable Alt first iTerm2 → Preferences → Profiles → [your profile] → Keyboard and set Left Option Key to: Esc+ ) Ctrl+j Ctrl+k move down/up in the list Ctrl+h backspace Tab select multiple results Enter confirm selection Esc Esc exit from search mode Explorer Space e open file explorer at Root Directory Space E open file explorer at CWD j / k down/up 3j jump down 3 lines Enter expand/collapse folder Backspace go to parent folder Enter expand/collapse folder Tab multiple select Ctrl+f/b scroll down/up i jump to search field in Insert mode to search for a specific file Alt+s seek mode during Insert mode s seek mode also covers the explorer window d delete file a add file/folder r rename y / p copy/paste m move file ? being focused on explorer - help window with other useful shortcuts mini.files Like explorer, but more Vim-ish mini.files Installation Go to LazyVim extras by x from the dashboard Move your cursor to the line that contains mini.files Press x to install, then restart NeoVim mini.files Usage Space fm open dir of current file at explorer Space fM open the directory where your terminal was in when you typed nvim (CWD) j / k move up/down h / l move out/in o add file/folder dd delete i go to Insert mode to rename yy copy p paste q close the explorer view = save changes Useful vim plugin for vscode learn vim plugin for vscode vimtutor terminal app to learn vim on most Unix operating systems cheatsheet NeoVim https://neovim.io/ is Vim-based text editor LazyVim is opinionated popular Neovim setup LazyVim keybindings Font https://www.nerdfonts.com/font-downloads Download FiraCode Nerd Font, unzip, install all fonts Open iTerm2, then Preferences, then Profiles, then Text, pick FiraCode Nerd Font Restart the terminal Dashboard :lua Snacks.dashboard() open dashboard from editor Plugins The Lazy Extras mode can be accessed by pressing x from the dashboard or :LazyExtras from the editor Navigate and press x to pick Relaunch NeoVim Space cm open Mason, some other plugin list, alternative to LazyExtras Buffers H / L switch buffers visible in the currently active window [b / ]b same, switch buffers Space , open current buffer list Ctrl+x close buffer from the list Space ` switch to previous buffer Space bb same, switch to previous buffer Space bd close (delete) buffer Space bD close (delete) buffer & window split Space bp pin a buffer Space bl/br/bo/bP close to left/right/others/pinned buffers split Space . open scratch buffer where you may write notes. Scratch buffers are tied to the current working directory. Space S open scratch buffer list Windows Window in Vim is a pane or split Space w v/s split vertically/horizontally Same works in mini.files plugin Ctrl+v/s open in vertically/horizontally split from explorer Ctrl+h/j/k/l move between windows Space w h/j/k/l same, move between windows Space wq close window Space wd same, close window Space wo close other windows Resize split with mouse by dragging middle bar Space w </>/+/- same, resize split window Space w= reset split windows to equal size Space w Space go into Hydra mode, it will keep the menu open, now you may keep pressing >>>>> to continuously resize Space uz go into Zen mode, center the window and dim all around Tabs Skipped, did not understand why it is needed... Fold z c/a fold / unfold za toggle folding zR unfold all zO unfold all folds under cursor Session Session keeps information about windows, splits and tabs Space qq to exit LazyVim cd to the project and open NeoVim by nvim s to restore the last session Space qs same, restore session Space qS open session list, can be useful to see last opened projects Space qd close without saving the session, useful when you temporarily opened NeoVim and close it Language server :LspRestart restart the language server :checkhealth / :LazyHealth health of various installed plugins (do not expect all to be green) (there are overlaps, LazyHealth is easier to read) Space xx/xX show diagnostic window with list of errors Code action Space ca open code actions Notice NeoVim has a notice window in the top right corner where some important messages pops up once in a while Space cna show list of messages ESLint Lint plugin for NeoVim nvim-lint Add file ~/.config/nvim/lua/plugins/nvim-lint.lua return { "mfussenegger/nvim-lint", event = { "BufReadPre", "BufNewFile" }, config = function() local lint = require("lint") lint.linters_by_ft = { javascript = { "eslint" }, typescript = { "eslint" }, javascriptreact = { "eslint" }, typescriptreact = { "eslint" }, } -- Always use the project's local eslint lint.linters.eslint = lint.linters.eslint or {} lint.linters.eslint.prefer_local = "node_modules/.bin" -- Prefer the nearest folder that actually has the eslint binary; -- otherwise fall back to a folder with an ESLint config; else git root. lint.linters.eslint.cwd = function(bufnr) local bufpath = vim.api.nvim_buf_get_name(bufnr) local start = vim.fs.dirname(bufpath) -- 1) nearest node_modules/.bin/eslint local bin = vim.fs.find("node_modules/.bin/eslint", { path = start, upward = true })[1] if bin then -- strip trailing /node_modules/.bin/eslint -> project root return (bin:gsub("/node_modules/.bin/eslint$", "")) end -- 2) nearest ESLint config local cfg = vim.fs.find({ "eslint.config.js", "eslint.config.cjs", ".eslintrc", ".eslintrc.json", ".eslintrc.js", ".eslintrc.cjs", }, { path = start, upward = true })[1] if cfg then return vim.fs.dirname(cfg) end -- 3) git root, then current cwd local git = vim.fs.find(".git", { path = start, upward = true })[1] return git and vim.fs.dirname(git) or vim.loop.cwd() end vim.api.nvim_create_autocmd({ "BufWritePost", "BufEnter", "InsertLeave" }, { callback = function() lint.try_lint() end, }) end, } Formatter Lint plugin for NeoVim conform Add file ~/.config/nvim/lua/plugins/conform.lua return { "stevearc/conform.nvim", opts = { formatters_by_ft = { javascript = { "prettier" }, javascriptreact = { "prettier" }, typescript = { "prettier" }, typescriptreact = { "prettier" }, json = { "prettier" }, css = { "prettier" }, html = { "prettier" }, yaml = { "prettier" }, markdown = { "prettier" }, -- add more filetypes if needed }, }, } Commenting gcc comment/uncomment line gc5j comment 5 lines below 5gcc same, comment 5 lines below, bit easier gcap comment out an entire block separated by newlines gcSh comment out the function surrounded by the h labels after the S is invoked V5jgc commenting can be applied on visual mode, select 5 lines and then comment them gco / gcO add comment below/above Indent >> / << indent the line where cursor is Select text and > / < to indent Indentation is always applied automatically with formatting on save gqag format the entire file Also may select text and hit = to apply indentation In Insert mode Ctrl+t/d to indent (“add tab” and “dedent”) Wrap gww wrap line to 80 chars gwip wrap paragraph gwig wrap file :set textwidth=<number> set wrap width Spell check Space us enable/disable spell check [s / ]s next/prev misspelled word z= show suggestion Snippets & Abbreviations check later... Terminal in vim Ctrl+/ open Vim's terminal (Vim has it's own terminal) Esc exit from Insert to Normal mode (that is how zsh is configured) a / i go into Insert mode Git integration Space gs opens list of changed files Space gc opens list of commits Space ghs stage hunk Space ghS stage file Space ghr reset hunk Space ghR reset file Space ghu unstage hunk Space ghb git blame, check commit for the active line Space ghp preview the hunk, what has been changed Space ghd show diff between the current file (right) and the staging index file (left) Space ghD show diff between the current file and the last commit :diffoff disable diff mode, then Space bd to close the buffer brew install lazygit install and learn LazyGit, useful plugin to work with Git Space gg open LazyGit (after installation) Continue reading about Git...