LazyVim


Summary

Notes taken on my learnings and usage of LazyVim.

Sources

LazyVim for Ambitious Developers

Dashboard Mode (lazyvim only)

The menu mode that opens when you open up Lazyvim without a file.

Normal Mode

<count><verb><count><motion> - structure of standard command

" - Open the registers mini-mode for pasting from
s - seek mode, select text that is visible
f - find mode
F - backwards find mode
t - To mode

Movement

CTRL-d - move window half-page down, keeping cursor in same location on the window
CTRL-u - move window half-page up, keeping cursor in same location on the window
CTRL-f - move forwards a full page
CTRL-b - move backwards a full page
0 - go to start of line
w - beginning of next word
e - end of current word (or next word if already on end)
b - beginning of current word (or previous word if already on end)
W - beginning of next word, only consider whitespace as word boundaries
% - jump to matching part of pair. Jumps to nearest pair if not on one (only works with brackets, not quotes)
(/) - backwards/forwards by a sentence (not very useful in code)
{/} - backwards/forwards by a paragraph (useful in code for going between things separated by empty lines)

prev/next [/]

[( - jump to previous ( of structure we’re in
[< - jump to previous < of structure we’re in
[{ - jump to previous { of structure we’re in
[%/]% - jump to whatever is bracketing me
[[/]] - jump to other references of thing under cursor (variable, function, etc. Usually depends on LSP)
[i/]i - jump to beginning/end of indentation
[s/]s - jump to prev/next misspelled word
[d/]d - jump to prev/next diagnostic (squiggly line under code)
[e/]e jump to prev/next error diagnostic
[w/]w jump to prev/next warning diagnostic
[t/]t jump to prev/next TODO
[h/]h jump to prev/next git hunk

Marks (Bookmarks)

Lazyvim helpfully will show you marks in the gutter bar.

m<letter> - mark line with letter
'<letter> - jump to where letter is marked

Capital letters are used to set global marks that do not depend on files

' - open marks menu
:delmarks <letter> - delete mark denoted by letter
'. - jump to last place where you inserted or changed text
'< - jump to beginning of most recent selection
'> - jump to end of most recent selection

Jump history

CTRL-o - move to previous location in jump history
CTRL-i - move to next location in jump history

z mode

zt - move cursor to top of screen
zb - move cursor to bottom of screen
zz - move cursor to middle of screen

Open Insert Mode

i - insert before
a - insert after
I - insert at beginning of line
A - insert at end of line
o - insert on newline below
O - insert on newline above
gi - insert at previous insert location

Open Visual Mode

v - enter Visual Character Mode
V - enter Visual Line Mode
CTRL-v - enter Visual Block Mode
gv - go to last visual selection

Editing

d - delete
c - change (delete text and enter Insert Mode)
dd - delete entire line
cc - delete entire line and enter Insert Mode
x - delete character at cursor
X - delete character before cursor
r - replace one character
J - Join lines
gJ - join without modifying whitespace
gu - lowercase everything in motion
guu - lowercase entire line
gU - uppercase everything in motion
gUU - uppercase entire line
~ - invert case of character
u - undo
CTRL-r - redo
recommended plugin for undoing - undotree

Helpful Combos

xp - swap character with character to the right

Objects

Grammar - <verb><context><object>

Context

a - around
i - inside

a usually selects everything that i does, with a little extra surrounding context

Seek Mode

S - seek mode, added by flash.nvim plugin
Lets you select what you want to seek to based on labels, therefore the grammar is just <verb><Seek mode command>
R - Remote seek mode
r - remote seek mode but puts you back in Operator-Pending mode after seeking

Object Types

Pausing after typing the verb and context will give you a helper menu showing different object types you can use.

( - matched parentheses, a includes the parens, i is just the inside

Text Objects

a/i changes whether surrounding whitespace is affected as well

w - word
s - sentence
p - paragraph
g - entire buffer
l - last text object
n - next text object

Quotes and Brackets

a includes the brackets, i does not

" - double quotes
' - single quotes
` - backticks
[ - square brackets
{ - curly braces
( - parens

Language Features

c - class or type
f - function or method
o - act on “objects” such as blocks, loops, conditionals
t - act on HTML-like tags
i - act on “scope”, which is basically indentation level

Examples

di( - delete all text inside matched pair of parentheses
da( - delete all text inside parentheses and the parens as well

Copy Pasting

Any text deleted with d or c gets added to the system clipboard by default.

This can be turned off by setting vim.opt.clipboard = ""

p - paste system clipboard after current position
P - paste system clipboard before current position

y - yank text
yy - yank entire line
Y - yank until end of line
yR<search><label>p - copy text you search for and paste to current position

Registers

Hitting " and waiting will pop up a menu showing the contents of all the registers at the moment

<space>s" - open a picker dialog for registers (CTRL-r in Insert or Command mode)

Named Registers

"<register-name><action> - operate on register named register-name

Using the capital version of the register name will have you append to the register contents instead of replacing them.

Blackhole Register

"_ - register that doesn’t actually store things. Useful for deleting text without ruining your current registers

Last-used Registers

"0 - the most recent yanked text
"<number> - most recently yanked texts. 0 is most recent, 9 is oldest
". - the most recently inserted text

Current Filename Register

"% - contains the name of the current file

Copying Registers

:let @b = @+ - copy the system clipboard into register b

Recording Macros

q<name> - record a macro in <name> register
Q - replay most recent macro
@<name> - replay macro in <name> register
@@ - replay most recently replayed macro

Use the capital letter version of the name to append to the macro

The sequence of macro commands are just stored in the regular registers also used for copy pasting. This means you can paste the commands, edit them, yank them back into the register, then play the modified macro

Searching and Replacing

/ - search in current file
? - search backwards in current file

[!NOTE]
In regular vim these commands change direction based on which direction you started searching. In Neovim, they always map to downwards/upwards

n - jump to next match downwards
N - jump to next match upwards

Vim searches use regex by default, but they are not the PCRE-style regexes most languages use.

Case Sensitivity

In LazyVim, lowercase search strings will ignore case by default.

To make it only match lowercase strings, add a \C anywhere in the search string. This can be anywhere because it lets you add it once you realize you are matching things you don’t want to.

[!NOTE]
This requires ripgrep installed on your system.
It also behaves differently from built-in vim search because ripgrep uses PCRE regexes instead of Vim-style

<space>/ - search entire project in live_grep mode.

This is a picker window, see that section for more commands.

Replace

Substitute Command

:<range>s[ubstitute]/<pattern>/<replace>/<flags>

[!NOTE]
You don’t have to use / as the separator. Instead you can use other punctuation. This is useful if you are trying to type something with a lot of /s in it and don’t want to have to escape them every time.

Patterns

If the first pattern is blank, it will default to the last pattern you searched for or substituted

Example:

/foo # search for foo
:s//bar # replace foo with bar 
:s/baz/bar # replace baz with bar
:s//fizz # replace baz with fizz

If both patterns are blank, it will use the same patterns but will not use the same range or flags as before.

Capture Groups

If you want to use whatever you matched in the first pattern in the second pattern, refer to it by \0

Example:

:%s/Hello\s*\w*/\0, welcome to Seaworld/g

Would turn

Hello User1!
Hello User2!
Goodbye User1!
Hello User3!

into

Hello User1, welcome to Seaworld!
Hello User2, welcome to Seaworld!
Goodbye User1!
Hello User3, welcome to Seaworld!

You can also use \( and \) in your first pattern to create other capture groups. These are referred to by number.

Example:

'<,'>s/\[\(\S*\)\]\s*\(\S*\)\s*-\s*\(.*\)/Level: \1, Date: \2, Message: \3/

Would turn

[INFO] 2026-02-05 - All of my bones hurt
[DEBUG] 2026-02-05 - Not enough calcium
[WARNING] 2026-02-05 - Need to drink more water
[ERROR] 2026-02-06 - Not enough sleep, starting migraine

into

Level: INFO, Date: 2026-02-05, Message: All of my bones hurt
Level: DEBUG, Date: 2026-02-05, Message: Not enough calcium
Level: WARNING, Date: 2026-02-05, Message: Need to drink more water
Level: ERROR, Date: 2026-02-06, Message: Not enough sleep, starting migraine
Ranges

. - current line. This is the default range and will be used if you don’t set a range
5 - line 5
3,8 - lines 3-8 (inclusive)
'a,'b - from mark a to mark b
/foo/,/bar/ - from where “foo” is found to where “bar” is found
% - whole buffer

Flags

g - every instance of the pattern in the line instead of only the first occurrence
i - ignore case (defaults to true in LazyVim)
I - don’t ignore case
c - autoconfirm replacements

Norm Command

The :norm command allows you to preform a sequence of arbitrary Normal Mode commands across multiple lines

You can enter Insert Mode, but hitting <ESC> will close the command window instead of entering the keystroke. To get around that, use <CTRL-v><ESC>.

<CTRL-v> signals to vim that it should enter the next keypress literally instead of running a command

This might be hard to use, so you should use the Command Line Editor

Using Recordings with Norm

:<range>norm @q - run the q register on every line in the range
:<range>norm <Control-r>q - pastes the contents of register q into the cmdline window (which will then run it for every line)

Global Command

Runs a command for every line that matches a pattern.

:<range>g[lobal]/<pattern>/<command>

Commands are ex mode commands, but you can turn that into Normal Mode commands by using norm

Example:

%g/^hello/norm A world

would add “world” After every line that starts with “hello”

You can also invert the selection by using g!

Example:

%g!/^\[DEBUG\]/norm dd

would delete every line that starts with “[DEBUG]”

Project-wide Replacing

Uses the Grug-far.nvim plugin.

[!NOTE]
This requires the ripgrep CLI tool to be installed.

<space>sr - open the Grug-far UI

Since this uses ripgrep under the hood, it uses normal PCRE syntax instead of Vim regex syntax.

It also allows you to filter which files to run the search/replace on.

Navigate through the UI with normal vim commands, and it will show you a preview as you type in Insert Mode.

To accept your change, hit \r in Normal Mode

You can also move down to the preview window. This allows you to delete selections you don’t want to change, and also edit the replacements if they are not exactly how you want them.

\s - sync files with the preview window
\t - open recent search/replace operations menu
g? - help menu

text-case.nvim

Allows you to change the case your selection. Includes options for snake-case, CamelCase, CONSTANT_CASE, etc.

Requires manual installation:
~/.config/nvim/lua/plugins/text-case.lua

return {
  "johmsalas/text-case.nvim",
  lazy = false,
  config = true,
  cmd = {
    "Subs",
    "TextCaseStartReplacingCommand"
  }
}

ga - open case change menu
gac - camelCase
gad - dash-case
gal - lower case
gan - CONSTANT_CASE
gap - PascalCase
gas - snake_case
gau - UPPER CASE

The capital letter versions of these commands will use the LSP rename feature to change all instances, not just the current one.

gao<case><motion> - operator-pending mode. Allows you to use a motion to select text after you have selected your case

Subs Command

This plugin also includes a :Subs command. It works similar to the normal :s[ubstitute] command, but keeps the case of the entries it is operating on.

nvim-rip-substitute

Find/replace dialogue plugin that is closer to traditional IDEs

Requires manual installation:
~/.config/nvim/lua/plugins/rip-substitute.lua

return {
  "chrisgrieser/nvim-rip-substitute",
  keys = {
    {
      "g/",
      function()
        require("rip-substitute").sub()
      end,
      mode = { "n", "x" },
      desc = "Rip Substitute",
    },
  },
}

g/ - open Rip Substitute

This will open a window in the lower right that gives you Search/Replace fields. The Search field uses actual PCRE regex syntax instead of vim regex so can often be easier to use.

Normal Mode:
R - open the current regular expression on regex101
<ENTER> - Perform the substitution
<UP>/<DOWN> - go through search history

Insert mode:
<CTRL-ENTER> - perform the substitution

Misc Tips

Word Count

g<CTRL-g> - spits out current cursor position, includes the word/line/byte count of the file

Commenting

gc<motion|object> - toggle code comment/uncomment
gcc - toggle comment on current line
gco - start comment on new line below
gcO - start comment on new line above

Incrementing/Decrementing

<CTRL-a> - add one to number
<CTRL-x> - subtract one from number
g<CTRL-a> - increment numbers in area, with each line having a large number

dial.nvim

LazyExtra that enhances the incrementing/decrementing features

  • Swaps true/false
  • Months
  • Days of the week
  • ordinal words (first -> second, etc)
  • Version number
  • Markdown headers - works in this document!

Reflowing Text

gw - wrap text according to the textwidth setting
gww - wrap current line
gw<movement> - use any arbitrary vim movement to select text
gwip - wrap entire paragraph
gwig - wrap entire file

Spell Check

<space>us - toggle spellcheck
[s/]s - move to prev/next misspelled word
z= - show spellcheck suggestions for misspelling

Seek Mode

Allows you to search for text that is on the screen and jump to it using a label that seek mode adds after every match

Find Mode

Jumps to location after target search

f - jump to next match
F - jump to previous match

To Mode

Similar to Find mode, but it jumps to before the target space instead of after

Insert Mode

CTRL-r - Open the registers mini-mode for pasting from
CTRL-r + - Paste from system clipboard
<CTRL-t> - add indention (add tab)
<CTRL-d> - dedent
<CTRL-a> - paste what was last inserted - i.e. ". register
<CTRL-U> - remove all character on current line added since you entered Insert Mode

Visual Mode

After selecting text, using a verb will do the action and return to Normal Mode

o - move cursor to other end of selected block

Visual Block Mode

Select blocks of text.

Use I or A to add content to every line of the selection

CTRL-V$ - Visual Block Mode that automatically extends to the length of the furthest line instead of just the currently selected one.

Sending Selections Through Other Programs

While something is selected, hit ! to open up the command window. Your selection will be passed in as stdin and the stdout will be pasted in its place.

Examples

!jq - format json text you have selected
!pandoc -f markdown -t html - transform markdown into HTML

Command (ex) Mode

:help CTRL-r - open help for CTRL-r keybinding

Command Line Editor

Starting

In Normal Mode:
q:
While command window is focused:
<CTRL-f>

Using

You can look/navigate back through your previous commands and use normal vim commands to edit them.
<Enter> - Execute the command on the current line

Closing

<CTRL-c> - keybinding for closing window
<Space>wq - generic keybinding for closing current window
:q - closes current window so this also works to escape this window

Completion/Picker menus

Tab/SHIFT-Tab - select entries forwards/backwards
DOWN - move into selected directory
CTRL-y - confirm the selection
ALT-s - display labels next to completion entries to fast select
CTRL-d/CTRL-u - scroll results window down/up
CTRL-f/CTRL-b - scroll preview window down/up

CTRL-q - turn picker window into Quick Fix entries. Can also use <Tab> to only select certain files instead of sending them all
ALT-t - send file to a Trouble window

Space Mode (lazyvim only)

Opens up a menu of common actions
<space> f - Open the file/find submenu
<space> g - Open the git submenu
<space> <space> - Open Files in Current Project (root directory)
<space> f F - Open files in Current Working Directory
<space> e - Explore Mode (root directory)
<space> E - Explore Mode (CWD)
<space> f m - Open mini.files (Directory of current file)
<space> f M - Open mini.files (cwd)
<space> f c - Find Config File

Explorer Mode

For browsing directory trees.

i - enter Insert mode to use the search bar
a - add a file (give filename a trailing slash to make a directory)
r - rename a file
d - delete a file
y - yank file
p - put file
m - move file
? - display help

Diff Mode

[!WARNING]
When a file is opened in Diff mode, it stays that way until you turn it off with :diffoff

In this mode you can edit the files, but you should only edit the file displayed on the right to not confuse the internal state.

:diffp[ut] - make the other file the same as this one
:diffg[et] - make this file the same as the other one

[c/]c - jump between changes - useful when your diff isn’t git-based and so doesn’t have hunks

Using Diff Mode as a Merge Tool

[diff]
  tool = vimdiff
[merge]
  tool = vimdiff
  conflictstyle = zdiff3
[mergetool "vimdiff"]
  cmd = nvim -d $LOCAL $BASE $REMOTE $MERGED \
          -c '$wincmd w' -c 'wincmd J'
git mergetool

This will open neovim in diff mode with four windows open.

  1. Top Left - the changes of what you are merging onto
  2. Top Middle - Show the common ancestor of the changes
  3. Top Right - the changes that are being merged in
  4. Bottom - Current state of the file with the conflict markers

You should only edit the Bottom window.

Most flows start with making the bottom buffer equal to a top buffer with :diffg <window>

Window Management

The Stack

Server - instance of NeoVim
Client - connection to NeoVim. Usually client:server is 1:1, but you can connect to another server
Tab - fullscreen layout that are independent. Only one can be displayed at the same time
Window - section of the screen dedicated to viewing a buffer. Every tab has 1 or more windows. Windows can be scrolled to view different parts of buffers if buffers are too large
Buffer - a file that is currently open and can be viewed and/or edited (there are read-only buffers). Multiple windows can be looking into the same buffer, but their contents will be the same. Only 1 buffer is open per file, no matter how many views into it
Fold - collapsed section of a buffer
File - file that exists on disk. Buffers are linked to at most one file, but can be free-floating (“scratch”) buffers. Buffers may differ from file contents if the buffer has not been saved.

Buffers

H/L - move to buffer left/right
<space>, - open buffer picker
<space>b - open buffer menu
<space>. - open scratch buffer
<space>S - select a scratch buffer

Windows

<space>w - open window menu, same as CTRL-w

Creating Splits

<space>wv - vertical split

   |
 1 | 2
   |

<space>ws - horizontal split

   1
-------
   2

[!NOTE]
These keybindings also work in mini.files

Moving Between Windows

<space>w<hjkl> - move between windows

Manipulating Windows

<space>wq - close window, quit Neovim if last window
<space>wd - delete this window
<space>wo - close all other windows except currently active one

[!NOTE]
These will leave the buffer open. Only the window closes

<space>w+/<space>w- - increase/decrease height of current window by 1 column
<space>w>/<space>w< - increase/decrease width of current window by 1 row

Prefix these with numbers to actually make them useful

<space>w= - make all windows the same size

Hydra Mode

Mode that allows you to do many window commands in a row until you hit Escape

<space>w<space> - enter Hydra Mode

Zen Mode

Dim all other windows and focus on current one
<space>uz - enter Zen Mode

Tabs

<space><tab> - open Tab menu
<space><tab><tab> - create new tab
<space>wT - close current window split, create new tab with just that buffer
gt/gT - go to next/previous tab
<space><tab>d - close all windows in tab and the tab

Folds

zc - collapse fold under cursor
zo - open fold under cursor
za - toggle fold under cursor
zr - reduce folding (open a fold)
zR - open all folds
zO - open folds recursively

Sessions

<space>qq - close Neovim and save session
<space>qs - restore Neovim to last session in current directory
<space>qS - restore Neovim to a previous session, showing all directories that have saved sessions
<space>qd - close Neovim without saving session

Abbreviations and Snippets

Abbreviations are the original Vim method of inserting larger parts of code using shorter key combos. Snippets are newer and compatible with the VSCode format of defining snippets.

Abbreviations

:iabbr <shortcut> <expansion>

:iabbr ifmain if __name__ == "__main__":<Enter>main()<Left>

This abbreviation will expand to the standard Python main invocation and then move the cursor back to the parens

Snippets

Supplied by blink.nvim - will automatically pop up suggestions as you type.

Custom snippets

Formatting

Snippets are based on the VSCode Snippet format

Adding to Neovim

~/.config/nvim/snippets/package.json needs to know about your snippet file.

{
  "name": "personal-snippets",
  "contributes": {
    "snippets": [
      { "language": "svelte", "path": "./svelte.json" }
    ]
  }
}

Then create a file with this syntax:

{
  "Boilerplate Component": {
    "prefix": "<scri",
    "description": "Basic svelte boilerplate",
    "body": [
      "<script lang=\"ts\">",
      "  $1",
      "</script>",
      "",
      "${2:<div></div>}",
      "",
      "<style>",
      "  $3",
      "</style>"
    ]
  }
}

LSPs

Installing

Either done via LazyExtras or by using Mason.nvim

Debugging

<space>cl - show list of LSPs and their statuses
:lsp restart - restart the current LSP
:checkhealth - shows the entire health of the editor and plugins
:checkhealth vim.lsp - check health of LSPs
:checkhealth mason - check health of mason.nvim
:LazyHealth - Lazyvim specific debugging. Less extensive than :checkhealth, but can be easier to read

Code-enabled actions

gd - go to definition of item under cursor
gr - go to references
<space>ss - search for symbols in the current file
<space>sS - search for symbols in current workspace (not fully supported by all LSPs and tends to be very slow even when it is supported)
<space>cs - open a Trouble window for browsing symbols

Context

nvim-treesitter-context is an Extra that provides context to the currently selected line by showing class names/function names above it.
<space>ut - turn off treesitter context

Diagnostics

]d - jump to next diagnostic
]w - jump to next warning
]e - jump to next error
]t - jump to next TODO
]s - jump to next spellcheck
]q - jump to next quick fix location
<space>cd - show diagnostic under cursor
K - show full help text of diagnostic under cursor

Quick Fix/Trouble

Trouble is a plugin that aims to provide a better Quick Fix Menu than what is built into Neovim by default.

<space>x - open “Fix” menu
<space>xt - todos menu
<space>xx - diagnostics for current buffer
<space>xX - diagnostics for entire workspace

Code Actions

<space>ca - open code action picker menu

Linting

Usually handled by a different application than the LSP, but Lazyvim does a good job of hiding that distinction and throwing everything into the same Diagnostics menus

Formatting

Most linting is handled automatically by the nvim-lint plugin.
It should automatically run when you save a file.
<space>cf - run formatting manually

Source Control

Staging

<space>gh - open Git Hunks menu
<space>ghS - stage entire file
[h/]h - move between hunks
<space>ghs - stage currently selected hunk
<space>ghu - unstage currently selected hunk
<space>ghr - reset hunk to state before changes (destructive, but can but undone with u)

Blames

<space>ghb - shows commit that last changed the currently selected line
<space>ghp - diff the original and changed hunk in a view with them on top of each other
<space>ghd - diff the current file and the staging index in vim’s Diff mode
<space>ghD - diff the current file and the last commit in vim’s Diff mode

git-conflict.nvim

Syntax highlighting for conflict markers in files.

Requires manual installation:

~/.config/nvim/lua/plugins/git-conflict.lua

return {
  "akinsho/git-conflict.nvim",
  lazy = false,
  opts = {
    default_mappings = {
      ours = "<leader>gho",
      theirs = "<leader>ght",
      none = "<leader>gh0",
      both = "<leader>ghb",
      next = "]x",
      prev = "[x",
    },
  },
  keys = {
    {
      "<leader>gx",
      "<cmd>GitConflictListQf<cr>",
      desc = "List Conflicts",
    },
    {
      "<leader>gr",
      "<cmd>GitConflictRefresh<cr>",
      desc = "Refresh Conflicts",
    },
  },
}

Debugging

Debugging is covered by the dap.core LazyExtra that is not enabled by default.
If there is a LazyExtra for your language, then debugging support might be built in.

<space>d - open debugging menu
<space>dc - continue debugger or start debugger
<space>db - toggle breakpoint on current line
<space>di - step into
<space>do - step out
<space>dO - step Over

Testing

Testing is covered by the neotest LazyExtra that is not enabled by default.
If there is a LazyExtra for your language, then testing support might be built-in.

<space>t - open testing menu
<space>tt - run all tests in file
<space>tT - run all tests in project
<space>tr - run nearest test (usually the currently selected one)
<space>tw - toggle watch - auto rerun test when file changes
<space>to - toggle output window
<space>tO - toggle output pane
<space>ts - open summary pane

Plugin Management

There are three types of plugins in LazyVim:

  1. Preinstalled
  2. Lazy Extras
  3. Third-party

Any file in the <nvim_config>/lua/plugins directory will be automatically loaded. Typically you add Lua files that return Tables defining additional or modified plugins. These tables will be merged with the default LazyVim ones.

Disabling Preinstalled Plugins

Set enabled to false in the config

<nvim_config>/lua/plugins/disabled.lua

return {
  { "akinsho/bufferline.nvim", enabled = false}
}

Disabling Keybindings

return {
  { 
    "folke/snacks.nvim",
    keys = {
      { "<leader>e", false },
      { "<leader>E", false },
    },
  },
}

Changing Keybindings

Opts

Some plugins provide an opts field you can define in their configuration. This is sometimes used to simplify keybindings by letting you set a prefix or rebind a specific part of the command structure.

For example:

return {
  "nvim-mini/mini.files",
  opts = {
    mappings = {
      go_in = "<Right>",
      go_out = "<Left>",
    }
  }
}

The opts field can also be a function that takes in the previous opts table configured by LazyVim. This function must modify the passed in table, not return a new one.

Keys

Structure:

return {
  "example/plugin.nvim",
  keys = {
    {
      "<leader>e",
      function()
        require("plugin.nvim").foobar()
      end,
      desc = "Run foobar"
    }
  }
}

Installing Third-Party Plugins

Add a file to <nvim_config>/lua/plugins/ and return a Lua table defining the plugin.

Example:

return {
  "nmac427/guess-indent.nvim",
  opts = {
    auto_cmd = true,
    override_editorconfig = true
  },
}

Plugin Location

Using an unlabeled string at the beginning of the table will cause LazyVim to assume that is a user/repo pair for Github and attempt to download from there.

Instead of that you can provide one of these fields:
dir - install from a local directory
url - install from a URL

If you need to pin your Github-based plugin to something other than the default branch, you can provide the branch, tag, commit, or version fields.

opts

Configure options for the plugin.

You can figure out the available options by looking at what the plugin documents as the arguments to the setup function in nvim

Customization

Vim Options

Vim options are normally stored in lua/config/options.lua

Set vim options with vim.opt.option = value

Example:

vim.opt.wrap = true

Color Schemes

<space>uC - change color scheme

To permanently change colors schemes, set the opts on the LazyVim/LazyVim plugin:

<nvim_config>/lua/plugins/core.lua

return {
  -- Install other color scheme from Github
  { "ellisonleao/gruvbox.nvim" },
  {
    "LazyVim/LazyVim",
    opts = {
      -- Set it here
      colorscheme = "gruvbox",
    },
  },
}

Filetype-specific Configuration

<nvim_config>/lua/autocmds.lua

vim.api.nvim_create_autocmd(
  { "BufRead", "BufNewFile" },
  { pattern = "\*.svx",
    command = "setlocal filetype=markdown",
  }
)

The first argument is the list of events to trigger on, while the rest is self-explanatory.

Pattern is a Vim regex, hence the wonky \* needed

For a full list of events, see :help autocmd-events

Project-Specific Configuration

Add a .lazy.lua to your project root to change options only for a specific project.

LazyVim Recipes

Collection of helpful common configs:

https://www.lazyvim.org/configuration/recipes

Plugins

editor.mini-files

Normal mode-like navigation for dealing with files/directories
= - commit changes to filesystem

<space>wv - open in vertical split
<space>ws - open in horizontal split

editor.mini-surround

“Operate only on surrounding braces. Change quotes to parens, etc.”

Adding

gsa<motion><char> - Add surrounding pair (e.g. gsa$" - will surround the line in quotes from current cursor position to end of line)

Deleting

gsd<char> - will remove the next surrounding pair of char
3gsd<char> - will remove the third innermost layer of pairs

Replacing

gsr<in-char><out-char> - replace surrounding pair from in-char to out-char (e.g. gsr'" will change single quotes to double quotes)

Highlighting

gsh<char> - highlight the surrounding pairs

HTML Tags

Using t as the type of character you would like to use will open up a little prompt allowing you to easily create HTML tags. Tags also support attributes like defining the class in the prompt and it will format properly.
gsaapt - Add surrounding gsa around paragraph ap using a tag t

yanky.nvim

<space>p - pops up a menu of recent clipboard entries
[y - go backwards in clipboard history
]y - go forwards in clipboard history
[p/]p - paste text above/below current line

Mason.nvim

Collection of plugins that are mainly used for programming language specific tasks. (e.g. adding a different Markdown viewing plugin)

i - install package
U - update all installed tools
g? - show keybindings for Mason

Noice

Plugin that provides the pop-up notifications in the upper corner.
<space>sn - open the Noice search menu
<space>sna - show all notifications
<space>snl - show last notification

My Customizations

My Snippets

~/.config/nvim/snippets/package.json

{
  "name": "personal-snippets",
  "contributes": {
    "snippets": [
      {
        "language": "python",
        "path": "./python.json"
      },
      {
        "language": "json",
        "path": "./json.json"
      }
    ]
  }
}

~/.config/nvim/snippets/python.json

{
  "logger": {
    "prefix": "logger",
    "description": "Basic snippet to create a logger for the current module",
    "body": [
      "logger = logging.getLogger(__name__)"
    ]
  },
  "NOIMPL": {
    "prefix": "NOIMPL",
    "description": "Raises a NotImplementedError",
    "body": [
      "raise NotImplementedError(\"${1:msg}\")"
    ]
  },
  "New dataclass": {
    "prefix": "dataclass",
    "description": "Creates an empty dataclass definition",
    "body": [
      "@dataclass",
      "class ${1:name}:",
      "\tpass"
    ]
  }
}

~/.config/nvim/snippets/json.json

{
  "snippet": {
    "prefix": "snippet",
    "description": "Creating a new snippet",
    "body": [
      "\"${1:name}\": {",
      "\t\"prefix\": \"${2:prefix}\",",
      "\t\"description\": \"${3:description}\",",
      "\t\"body\": [",
      "\t\t${4:body}",
      "\t]",
      "}"
    ]
  }
}

Related Notes