Neovim Tips & Tricks


This chapter compiles many of the best tips and tricks that the Neovim community has developed over the years to turbo-charge your Neovim workflow.

Filed In:navigating

Neovim provides many ways to navigate within documents, and this tip creates a simple keymap that makes it quick and easy to jump between markdown headings, which can be a big speed boost in longer markdown documents. Create a markdown directory under ftplugin if it doesn't already exist, then add a file containing the following keymaps : vim.keymap.set("n","<A-j>","/^#\\+ <CR>") vim.keymap.set("n","<A-k>","?^#\\+ <CR>") These keymaps take advantage of the search operators / and ? to search forward and backward from the current cursor position, respectively. In each case, Neovim searches for the pattern ^#\\+, which matches any line that starts with one or more # characters followed by a space. While this is a fairly naive pattern that may produce some false matches, it is very simple to implement and works quite well for most markdown documents. As a quick demo, let's take the following Markdown file. Starting from the top, in steps 1 and 2 we hit <A-j> to step forward through the headings, then finally in step 3 we use <A-k> to jump back up to the previous heading: Start Before # Heading 1 Text ## Heading 2 Text ### Heading 3 NORMAL Top 1:1 1 Jump to Next Heading<A-j> # Heading 1 Text ## Heading 2 Text ### Heading 3 NORMAL 50% 5:1 2 Jump to Next Heading (Again)<A-j> # Heading 1 Text ## Heading 2 Text ### Heading 3 NORMAL 90% 9:1 3 Jump to Previous Heading<A-k> # Heading 1 Text ## Heading 2 Text ### Heading 3 NORMAL 50% 5:1 This keymap also supports counts , allowing you to navigate even faster by jumping multiple headings at a time. If you would like to see another way to implement the same function but using Treesitter, take a look at this tip.
Filed In:navigating

We previously looked at how to create a keymap that makes it quick and easy to navigate between Markdown headings. Although that tip was simple to create, there is potential for false-positives. In this tip we take a look at how to implement the same keymap with Treesitter so that we can more-accurately target Markdown headings. Create a markdown directory under ftplugin if it doesn't already exist, then add a file containing the following keymaps : localts_utils=require("nvim-treesitter.ts_utils") localM={ -- define the query query=vim.treesitter.query.parse("markdown","((atx_heading) @header)"), } M.init=function() -- search the current buffer M.buffer=0 -- references to lines within the buffer M.first_line=0 M.current_line=vim.fn.line(".") M.previous_line=M.current_line-1 M.next_line=M.current_line+1 M.last_line=-1 -- default count M.count=1 ifvim.v.count>1then M.count=vim.v.count end -- list of captures M.captures={} -- get the parser M.parser=vim.treesitter.get_parser() -- parse the tree M.tree=M.parser:parse()[1] -- get the root of the resulting tree M.root=M.tree:root() end M.next_heading=function() M.init() -- populate captures with all matching nodes from the next line to -- the last line of the buffer for_,node,_,_in M.query:iter_captures(M.root,M.buffer,M.next_line,M.last_line) do table.insert(M.captures,node) end -- get the node at the specified index ts_utils.goto_node(M.captures[M.count]) end M.previous_heading=function() M.init() -- if we are already at the top of the buffer -- there are no previous headings ifM.current_line==M.first_line+1then return end -- populate captures with all matching nodes from the first line -- of the buffer to the previous line for_,node,_,_in M.query:iter_captures(M.root,M.buffer,M.first_line,M.previous_line) do table.insert(M.captures,node) end -- get the node at the specified index ts_utils.goto_node(M.captures[#M.captures-M.count+1]) end -- define the keymaps vim.keymap.set("n","<A-j>",M.next_heading) vim.keymap.set("n","<A-k>",M.previous_heading) This is a bit more complicated, but still fairly simple. We start by creating a lua module, followed by an initialization function that collects information about the buffer , cursor , and count . Finally, separate functions are created to implement jumping in the forward and reverse directions, respectively. Finally, we create the keymaps . As a quick demo, let's follow the same steps we did in the previous tip. Starting from the top, in steps 1 and 2 we hit <A-j> to step forward through the headings, then finally in step 3 we use <A-k> to jump back up to the previous heading: Start Before # Heading 1 Text ## Heading 2 Text ### Heading 3 NORMAL Top 1:1 1 Jump to Next Heading<A-j> # Heading 1 Text ## Heading 2 Text ### Heading 3 NORMAL 50% 5:1 2 Jump to Next Heading (Again)<A-j> # Heading 1 Text ## Heading 2 Text ### Heading 3 NORMAL 90% 9:1 3 Jump to Previous Heading<A-k> # Heading 1 Text ## Heading 2 Text ### Heading 3 NORMAL 50% 5:1