I use the lazyvim.org distro, so my plugins and tips are optimized to be compatible with that the most, if using something different you might need to to a bit of tweaking, but you can grab the overall ideas and adapt them to your own config
I use macOS, so keep that in mind too
This is not a distribution, this is my personal setup, so one day I may use certain plugin, like neo-tree, and the following day I may completely disable it and instead switch to mini.files, in case you clone and pull, expect to see changes
Pre-requisites
My entire neobean setup is in my github repo, so you can grab it from there
I have a video in which I show you how to download and setup my neobean config, but also other neovim distributions, so I highly recommend you check it out:
If you don’t want to watch the video above, and you already have your own neovim config, and want to quickly get started and follow along in this tutorial
Run the commands below to clone my dotfiles in your .config directory and we will run my config below
I create and edit my videos in an m1 mac mini, and it’s starting to stay behind in the editing side of things, tends to slow me down a bit, I’d like to upgrade the machine I use for all my videos to a mac mini with these specs:
Apple M4 Pro chip with 14‑core CPU, 20‑core GPU, 16-core Neural Engine
24GB unified memory
1TB SSD storage
10 Gigabit Ethernet
If you want to help me reach my goal, you can donate here
Discord server
After following this guide or even watching the related video, you:
Have questions related to one of the tools, configs or scripts that I use
Would like me to expand a bit more on how something is done
Or simply would like to talk and meet other community members that share your same interests
All links to my YouTube videos in video description
All of the links will also be in my blogpost
The stuff you’ll see here, is the stuff that I use as of today
I may have way many additional keymaps in my ~/github/dotfiles-latest/neovim/neobean/lua/config/keymaps.lua file, some of which I don’t use often, I will only demo the stuff that I think is useful in this article
Where are all these files?
If you already downloaded my neobean config in the steps above, you’ll already have all these files
I’m not giving you a permalink, as my dotfiles change quite often
Markdown tips
These are sorted by my personal preference, most preferred ones at the top
Use snippets
Snippets is one of my favorite things
I use these in case I want to:
Add one of my YouTube videos
Add a code block
Create a link from a URL I have in the clipboard ;lincex
I’ll demo this later
Do you want to learn more about luasnip and how I configure my snippets? Watch the video below (just notice that we now use blink.cmp instead of nvim-cmp):
Folke moved us all in the LazyVim distro from nvim-cmp to blink.cmp as the completion engine, it’s working great for me, so if you’re using your own config and want to migrate to blink.cmp watch this video:
I like keeping track of the things that I have to do during the day, and the things I have done, I also like to have my video ideas stored and tracked in github, reminders, etc
I used the Apple reminder’s app in the past, but I’ve recently switched to skitty-notes, it’s basically this same neovim config running in kitty showing on the right hand side of my screen, always visible
I can switch to it by tapping the right arrow key, and I create and toggle tasks there
I use the daily note every day, usually for example if I need to upload a new video, I have a template in LuaSnip to get me started, and I do this in my daily note
I don’t keep a journal, like in The Princess Diaries movie, I just use my daily note as a temp location to edit stuff that needs to be placed somewhere else
When I press hyper+t+r it will:
Create a daily note with the date-day for example 2024-06-30-Sunday inside the obsidian_main/250-daily/2024/06-Jun directory
If the directories do not exist it will create them
If the daily note doesn’t exist it will create it
Create a new tmux session with the note name in detached mode and start neovim with the daily note
If a tmux session with that name already exists, just switch to it
I created a dedicated video explaining how the daily note works and how to set it up:
Make sure that the ~/github/dotfiles-latest/scripts/macos/mac/300-dailyNote.sh script is executable
How do I do the hyper+t+r and hyper+t+j
In case you’re wondering, what is this hyper+t+r keymap, why does it have like a sub layer?
I have a lot of keymaps and several sub layers, for example:
The sub layer to switch to each one of my apps is a, so hyper+a+j takes me to my terminal application
The sub layer to switch to my tmux sessions is t, so hyper+t+r takes me to my daily note tmux session or hyper+t+u takes me to my obsidian tmux session
There are several fold options worth knowing about
opt.foldlevel = 99
(default LazyVim)
Sets the initial fold level when opening a file.
With a high value like 99, it ensures that almost all folds are open when a file is opened.
opt.foldmethod = "expr"
(default LazyVim 0.10)
Sets the method for defining folds
Uses the expression defined in foldexpr to create folds. This method allows for highly customizable folding behavior based on the evaluated expression.
Do you want to learn more about luasnip and how I configure my snippets? Watch the video below (just remember that we now use blink.cmp instead of nvim-cmp):
Spell dictionary, I still don’t manually add entries
Fix undercurl in tmux
I recently switched from Kitty, to WezTerm and then to Ghostty
I’m not sure the config below is still needed in Ghostty when using Tmux, which was the case with Kitty
I removed the 2 terminal-overrides lines below, saved my tmux config, reloaded it and undercurl works in Ghostty
In case you’re using a different terminal, you also use tmux, and are having undercurl issues, try adding this to your tmux.conf file
1
2
3
4
5
6
7
8
9
10
11
# Undercurl support (works with kitty)# Fix found below in Folke's tokyonight theme :heart:# https://github.com/folke/tokyonight.nvim#fix-undercurls-in-tmux## After reloading the configuration, you also have to kill the tmux session for# these changes to take effectset-g default-terminal "${TERM}"# undercurl supportset-as terminal-overrides ',*:Smulx=\E[4::%p1%dm'# underscore colours - needs tmux-3.0set-as terminal-overrides ',*:Setulc=\E[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m'
I change the undercurl color and style in my neovim colorscheme settings, every time you make a change there you have to reload the tmux config, but also kill the tmux session or it won’t work
If you want to setup Ghostty the way I do, and learn why I chose it as my default terminal, check this video out:
There’s a default Auto Command (autocmd) in Folke’s lazyvim.org distro that is what enables spelling
Also the lazyvim.org comes preconfigured with the Optionopt.spelllang = { "en" } (English) but remember I have keymaps to set that above
UPDATE:
Wrap is set to true by default on this autocmd and I don’t want that, so added the autocmd to my ~/github/dotfiles-latest/neovim/neobean/lua/config/autocmds.lua file and removed that
1
2
3
4
5
6
7
8
9
10
11
12
-- wrap and check for spell in text filetypesvim.api.nvim_create_autocmd("FileType",{group=augroup("wrap_spell"),pattern={"text","plaintex","typst","gitcommit","markdown"},callback=function()-- -- By default wrap is set to true regardless of what I chose in my options.lua file,-- -- This sets wrapping for my skitty-notes and I don't want to have-- -- wrapping there, I want to decide this in the options.lua file-- vim.opt_local.wrap = falsevim.opt_local.spell=trueend,})
Use alt for keymaps
They keymaps that I use the most have been configured with alt, for example alt+g opens LazyGit
Before this, all my keymaps started with <leader>, and some of them with Ctrl but sometimes I need to start them when in insert mode and it’s also less keystrokes
I speak Spanish and sometimes write notes in Spanish, so the left alt key is used for something else, so I added this to my Ghostty config:
This config is also available for kitty and wezterm, see my config files
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# If `true`, the *Option* key will be treated as *Alt*. This makes terminal# sequences expecting *Alt* to work properly, but will break Unicode input# sequences on macOS if you use them via the *Alt* key. You may set this to# `false` to restore the macOS *Alt* key unicode sequences but this will break# terminal sequences expecting *Alt* to work.## The values `left` or `right` enable this for the left or right *Option*# key, respectively.## Note that if an *Option*-sequence doesn't produce a printable character, it# will be treated as *Alt* regardless of this setting. (i.e. `alt+ctrl+a`).## This does not work with GLFW builds.
macos-option-as-alt = right
If you want to setup Ghostty the way I do, and learn why I chose it as my default terminal, check this video out:
Upload images to my own imgur account (authenticated)
Sometimes you need to share an image, but through a link
<M-i>
This script uploads images to Imgur using an access token, and refreshes the token if it’s expired. It reads environment variables from a specified file and updates them as needed.
I have a video in which all of this is explained in detail:
You’ll see the pop-up, but a lot of times you will want to see them again
There’s a default lazyvim keymap <leader>snh (search noice history)
I use <M-h>
Close the window that shows below with <leader>wd (window delete)
Or use the command :NoiceHistory
Accept completion with ctrl+y instead of enter
I really hated this behaviour, maybe skill issue, but every time I was at the end of a line and hit enter, it would autocomplete a word instead of moving to the line below
I change this in the keymap section of the blink-cmp.lua file
Bold easily
This is still relevant and I use it sometimes
If I’m on a word and press <leader>mb it will toggle bold on the single word
If try to bold on a * it will let me know that I need to move the cursor
Can bold a paragraph in visual mode
If in a bold area (paragraph) and run <leader>mb will unbold that section
need to be on the first line
It needs the mini.surround plugin
By default if you want to bold some text, you select it and do 2gsa* or if you want to “unbold” it I normally do gsd*.
I configured keymap <leader>mb
This is just a random paragraph with random text in it, it doesn’t serve any purpose but I just want to use it to demonstrate how multi line bold and unbold works
This is just a single line of text
Inline code
I have 2 keymaps, one for normal mode and 1 for visual mode
If I’m on a word in normal mode and type gss formats is as inline code
By default this is done with
1
2
3
4
5
# In visual mode
gsa`
# For the word you're in
gsaiw`
But notice all the characters you need to press, and I just use this way too much
Remember to star my dots
⭐⭐⭐ If you like what you find in my dotfiles, including my neobean configuration and keymaps, star my dotfiles
Jump between markdown headings
Follow markdown convention and use a single H1 heading in your file for this to work
I tend to fold items and navigate that way, or use the outline plugin, but sometimes I do still use gj and gk when unfolded to navigate between headings
Some of these default keymaps are the better up/down ones found below:
1
2
3
4
5
6
7
8
9
-- better up/down-- If there is no count (v:count == 0), pressing j will execute gj-- Useful when dealing with wrapped lines in the buffer.-- If there is a count (v:count != 0), pressing j will execute j.-- For example, if you press 3j to move down three linesmap({"n","x"},"j","v:count == 0 ? 'gj' : 'j'",{expr=true,silent=true})map({"n","x"},"<Down>","v:count == 0 ? 'gj' : 'j'",{expr=true,silent=true})map({"n","x"},"k","v:count == 0 ? 'gk' : 'k'",{expr=true,silent=true})map({"n","x"},"<Up>","v:count == 0 ? 'gk' : 'k'",{expr=true,silent=true})
So by default my neovim “sends” gj when I press j and I can navigate through wrapped lines easily
You might think that gj and gk mappings I added would break the default keymaps, but for some reason it still keeps working
So with j and k I navigate through wrapped lines without issues
Fold with enter
Normally you fold with za but I changed it to use enter <CR>
Line wrapping at 80 characters
I don’t like my lines to be longer than 80 characters, helps me with readability and overall consistency of my files.
If I open an obsidian markdown file in neovim, line lengths are all over the place, so I prefer to follow the markdown guidelines.
To achieve this I do 2 things:
textwidth = 80
Set the option vim.opt.textwidth = 80 in lua/config/options.lua
When text reaches this limit, it automatically wraps to the next line.
This will automatically switch to the line below as you are typing and reach the 80 characters
This will NOT auto wrap:
Existing lines in a document after you enable the option
Long lines that you paste into a file
ProseWrap and .prettierrc.yaml
This requires the prettier plugin, we’ll install it later
Configure the proseWrap: "always" option in the .prettierrc.yaml file
This will autoformat existing lines over 80 characters and also long lines that you paste that exceed the 80 characters
You will see how to enable prettier in the LazyExtras section
I add the ~/github/dotfiles-latest/.prettierrc.yaml file, to my $HOME directory
I keep the file in my dotfiles and create a symlink in my home directory that points to the .prettierrc.yaml file
The configuration file will be resolved starting from the location of the file being formatted, and searching up the file tree until a config file is (or isn’t) found.
Prettier intentionally doesn’t support any kind of global configuration. This is to make sure that when a project is copied to another computer, Prettier’s behavior stays the same. Otherwise, Prettier wouldn’t be able to guarantee that everybody in a team gets the same consistent results.
Disable autoformatting in certain sections
Prettier is enabled and will autoformat your file, but there are some times that you don’t need prettier to autoformat, example below:
So make sure that plugin is installed, comes with lazyvim.org distro by default
<C-z><M-z>
Navigate the help pages
This hasn’t changed
If for example you’re setting up a keymap, or you want to understand what the commands on an existing keymap do, or basically, any command in neovim, use the help
<leader>sh
Then search for something pwd and navigate around “tags” with shift+k
To go back to where you were after navigating to a tag, use Ctrl-o
Close that pane with <leader>wd (window delete)
Paste with “p” in visual mode
This is not markdown specific, but overall neovim specific
DON’T use cmd+v (macOS) to paste or the line below will be deleted
Paste with p (lowercase) or P (uppercase)
1
2
3
4
5
6
7
8
Laborum aute consectetur sit reprehenderit.
Laborum aute consectetur sit reprehenderit.
Duis consectetur laborum deserunt.
Duis consectetur laborum deserunt.
Minim tempor ullamco do eu pariatur minim.
Minim tempor ullamco do eu pariatur minim.
Increase decrease all markdown headings
I have several old.md documents that do not follow markdown guidelines
Some have more than one H1 heading, so I want to add one more # to each heading
<leader>mhI and <leader>mhD
These 2 don’t ask for confirmation and just increase all the headings
Don’t indent with tab
Don’t try this, because if you use snippets, this will interfere with them and you won’t be able to jump to the next field using tab
If you use tab for something else, you’ll lose it
To indent use defaults:
In insert mode use <C-T> and <C-D>
In normal mode >> and <<
Open current file in finder
<leader>fO or <M-f> (uppercase O as in “Oscar”)
Update: I now open the file in ForkLift instead of finder
This is for macOS, not sure if works on Linux, but modify it
Dismiss all messages
If you open neovim on an old outdated machine, you will get hundreds of noice messages on the screen, sometimes occupying the entire screen and you won’t be able to read
Clear them all with <leader>snd<M-d> (search noice dismiss)
1
:lua local messages ={"System update available. System update available. System update available.","Backup completed successfully. Backup completed successfully. Backup completed successfully.","New email received. New email received. New email received.","Reminder: Meeting at 3 PM. Reminder: Meeting at 3 PM. Reminder: Meeting at 3 PM.","Low disk space on drive C:. Low disk space on drive C:. Low disk space on drive C:.","Software update installed. Software update installed. Software update installed.","Battery level critical. Battery level critical. Battery level critical.","File download completed. File download completed. File download completed.","New message from John. New message from John. New message from John.","Security scan completed. Security scan completed. Security scan completed.","Application crash detected. Application crash detected. Application crash detected.","Printer is out of paper. Printer is out of paper. Printer is out of paper.","Wi-Fi connection lost. Wi-Fi connection lost. Wi-Fi connection lost.","New friend request received. New friend request received. New friend request received.","Weather alert: Heavy rain expected. Weather alert: Heavy rain expected. Weather alert: Heavy rain expected.","VPN connection established. VPN connection established. VPN connection established.","System reboot required. System reboot required. System reboot required.","Bluetooth device connected. Bluetooth device connected. Bluetooth device connected.","Scheduled maintenance at midnight. Scheduled maintenance at midnight. Scheduled maintenance at midnight.","Password change reminder. Password change reminder. Password change reminder."}for _, message in ipairs(messages)do vim.api.nvim_echo(, false, {}) end
Paste github repo as link
<C-g>M-; (since you run it with alt, can run it in insert mode)
Make sure you have the main github repo link in your clipboard first
Select text in a bullet point
Press ctrl+space
Keep pressing it to keep selecting
To go back use backspace
[!WARNING] I still don’t know why this breaks
This breaks if you have a markdown comment below in the file, it will jump there, not sure why
If you know why this is, let me know down in the comments
Create headings and daily note
This is a good practice, but I haven’t been following it, I don’t add to much stuff to my obsidian notes these days, I document stuff closer to the code, or i the code itself, if you look at my dotfiles, you’ll understand
I’m leaving this here, as it’s still valid
I use this in my Obsidian vault
This is useful in case I want to have stuff linked to my daily note
I use markdown headings with date on a specific note XOA for example
Then in obsidian I can go to a specific note, and see which headings are linked to that note, just so that I can keep track of what did each day, some sort of journal
These keymaps besides adding the heading, will also create the daily note if it does not exist:
If you don’t want to create the daily note, comment that line
You like how my markdown file looks, with beautiful headings, icons on the links, beautiful code blocks with their respective icons depending on the language, etc?
This is what you’re looking for, I go over this plugin in a video:
I like that it allows me to preview the file I’m about to open
I created a few keymaps that allow me for example grab a directory, it could be a markdown file with images inside, zip it and copy it to the system clipboard that I can then share in another application, like slack for example.
This is a beauty, it comes installed with lazyvim.org by default, I think Folke disabled it once, and I almost died, so in case the following stop working, you know this is the plugin
viq or vaq select inside or around quotes
Text inside backticks
“Text inside double quotes”
‘Text inside single quotes’
vig or yig select entire file
vio or vao
I select text inside code blocks A LOT, and I mean A LOT
So this is definitely one of my personal favorites
vi or va to see what other options are useful for you
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env bash# Filename: ~/github/scripts/macos/mac/300-dailyNote.sh# Get current date componentscurrent_year=$(date +"%Y")current_month_num=$(date +"%m")current_month_abbr=$(date +"%b")current_day=$(date +"%d")current_weekday=$(date +"%A")# Construct the directory structure and filenamenote_dir=~/github/obsidian_main/250-daily/${current_year}/${current_month_num}-${current_month_abbr}note_name=${current_year}-${current_month_num}-${current_day}-${current_weekday}full_path=${note_dir}/${note_name}.md
# Use note name as the session nametmux_session_name=${note_name}
I like my cursor to always be in the middle, specially if I’m at the bottom of a file, yes, you can configure a keymap, but this plugin works great for me
I still use this plugin every single day, still love it
UPDATES:
My auto-save plugin debounce_delay used to be set to 750ms but I felt it slowed me down, I had to wait a bit for auto-save to kick in, which also auto-formats my files, so if I needed to quickly change stuff between 2 lines and I got out of insert mode, auto-save kicked in, now I have more time to go out of insert mode, edit stuff, go somewhere else and enter insert mode without autosave not kicking in
It’s configured to auto save when I leave a buffer or the focus is lost, but only if I’m not on insert mode
Otherwise it would cause issues when switching to a tutorial in insert mode and coming back
debounce_delay currently set to 5s and if need to save for a strange reason, maybe to auto-format faster I run M-w
This is a really controversial plugin, some people love autosave, some other ones hate it
Personally I like autosaving, this plugin will auto save for you when you exit insert mode
Also if you focus another app or you leave the buffer, even if you’re on insert mode, it will autosave
I have a video about this plugin, you can find it here
Paste images in neovim and save them in different formats, I prefer .avif or .webp as their size is way smaller compared to .png when dealing with images with transparent backgrounds
I use this plugin always with 3rd/image.nvim
I go over a demo on how and what I use this plugin for in the video:
I navigate my buffers using telescope, they’re also sorted by MRU, I can close buffers from telescope with d and the best thing, is that I can get a preview of the buffers:
I can scroll up or down the preview with S-j and S-k
By default, in lazyvim with <S-h> and <S-l> you navigate between the prev and next buffers, but I changed both of those:
Telescope Frecency gives each file a score, depending on how much that file is opened, so let’s say I have 2 files with the same name, the more I open one of them, the higher the score will be, so when I bring up telescope, that file will show at the top
I have a video in which I go over frecency and how I set it up:
If on a markdown file, and you’re inside a level 4 heading, this plugin shows you the level 2 and 3 heading that you’re under at the top of the screen Really useful to know where you’re at
This plugin used to be enabled by default in lazyvim, but it was moved to extras
You can manage these in the lua/config/lazy.lua file or with :LazyExtras
I’m not sure if you can also manage them in the lazyvim.json file as well
I prefer to configure the extras in the lazy.lua file, because I want to have the settings on each machine, but if that’s not your case, you can enable the extras on each machine with :LazyExtras
Using LSP protocol it provides completion, goto definition, find references, rename refactoring, diagnostics, and more. In addition to regular Markdown, it also supports wiki-link-style references that enable Zettelkasten-like, note taking
Go to the obsidian XOA file under Create Windows 11 VM
K (uppercase k) over a link allow me to hover
KK (press it twice) and you can navigate that file in the hover menu
gd (go to definition) allows me to go the file that a link points to
In combination with blink.cmp this is quite useful for linking notes together
formatting.prettier
This includes:
mason.nvim conform.nvim none-ls.nvim
If you go to the lazyvim.org website in the extras -> formatting -> prettier section (notice it matches the Extra’s name)
You’ll be able to see which plugins Mason will install, which is only prettier
Prettier is the one that automatically formats my markdown files
It removes extra blank lines
Removes blank spaces at the end of a line
But also messes up my chirpy tips because it format things
You can ignore some parts from formatting, will show you how below
I like following markdown guidelines, so I don’t like my lines to be longer than 80 characters, I like to enable wrapping for them