Vim

Vim is a terminal-native, modal text editor with over three decades of active development. It runs on any POSIX system, requires no graphical environment, and produces no telemetry. Neovim is a refactored fork of Vim that introduces Lua as a first-class configuration language, an embedded LSP client, and a maintained plugin API. Both operate without licencing fees, vendor lock-in, or mandatory account registration.

Proprietary editors including VS Code, JetBrains IDEs, and Sublime Text collect usage data, enforce update channels, and tie configuration to corporate-controlled extension marketplaces. Vim and Neovim place all configuration, all data, and all tooling decisions under the user's direct control. The configuration is a plaintext file. The environment is fully reproducible. The toolchain is yours.

This manual covers both editors in parallel. The configuration section presents my working Neovim init.lua and a functionally equivalent Vim .vimrc.


Installation

Neovim

Platform Command
Arch Linux sudo pacman -S neovim
Alpine Linux apk add neovim
Ubuntu / Debian (PPA) sudo add-apt-repository ppa:neovim-ppa/unstable && sudo apt update && sudo apt install neovim
Rocky Linux / RHEL sudo dnf install epel-release && sudo dnf install neovim
AppImage (universal) curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim-linux-x86_64.appimage && chmod +x nvim-linux-x86_64.appimage && sudo mv nvim-linux-x86_64.appimage /usr/local/bin/nvim

Arch Linux is the preferred platform. The package is current, the AUR provides any supplementary tooling, and the system remains under direct user control.

Vim

Vim ships with most base system installations. When installation is required:

Platform Command
Arch Linux sudo pacman -S vim
Alpine Linux apk add vim
Ubuntu / Debian sudo apt install vim
Rocky Linux / RHEL sudo dnf install vim-enhanced

Post-Install Verification

Editor Command Expected Output
Neovim nvim --version NVIM vX.X.X
Vim vim --version VIM - Vi IMproved X.X

Run :checkhealth inside Neovim after first launch. The output identifies missing clipboard providers, Python support, and Node binaries. Install only what your workflow requires.


The Modal Editing Model

Vim operates across distinct modes. Each mode governs how the editor interprets keyboard input.

Mode Reference

Mode Entry Function
Normal Escape or Ctrl-[ Command input. The default and resting state. Every key executes an operation.
Insert i, a, o, and variants Text entry. Characters typed appear in the buffer.
Visual v, V, Ctrl-v Text selection. Operators apply to the selected region.
Command-line : Ex command execution. File operations, settings, search-replace, shell access.
Replace R Overstrike entry. Typed characters overwrite existing text at the cursor position.

Normal mode is the primary state. Insert mode serves a single purpose: entering text. Return to Normal immediately after each edit. Remaining in Insert mode removes access to all motion commands and operators.

Insert Mode Entry Points

Key Behaviour
i Insert before cursor
I Insert at first non-blank character of line
a Append after cursor
A Append at end of line
o Open new line below, enter Insert
O Open new line above, enter Insert
s Delete character under cursor, enter Insert
S Delete entire line content, enter Insert
c{motion} Delete through motion, enter Insert

Navigation in Vim is compositional. Motions combine with operators to construct precise edit operations. Learning the motion atoms enables construction of any compound move.

Character Movement

Key Direction
h Left
j Down
k Up
l Right

Word Motions

Vim distinguishes between a word (alphanumeric characters and underscores) and a WORD (any sequence of non-whitespace characters). The string foo.bar constitutes two words and one WORD.

Key Behaviour
w Start of next word
W Start of next WORD
b Start of previous word
B Start of previous WORD
e End of current or next word
E End of current or next WORD
ge End of previous word

Line Navigation

Key Behaviour
0 Column zero (hard line start)
^ First non-blank character of line
$ End of line
g_ Last non-blank character of line
f{char} Jump to next occurrence of char on current line
F{char} Jump to previous occurrence of char on current line
t{char} Jump to one column before next occurrence of char
T{char} Jump to one column after previous occurrence of char
; Repeat last f, F, t, or T in same direction
, Repeat last f, F, t, or T in reverse direction

Document Navigation

Key Behaviour
gg First line of file
G Last line of file
{N}G Line N
{N}gg Line N
Ctrl-d Scroll down half a screen
Ctrl-u Scroll up half a screen
Ctrl-f Scroll down one full screen
Ctrl-b Scroll up one full screen
H Cursor to top of visible screen
M Cursor to middle of visible screen
L Cursor to bottom of visible screen
zz Centre screen on cursor line
zt Scroll so cursor line is at top of screen
zb Scroll so cursor line is at bottom of screen

Jump List

The jump list records significant cursor positions across files. It is session-persistent.

Key Behaviour
Ctrl-o Jump to previous position in jump list
Ctrl-i Jump to next position in jump list
:jumps Display full jump list

Editing — Operators, Motions, and Text Objects

The Grammar

Vim editing follows a consistent composable grammar:

[count] {operator} {motion or text-object}

Operators define the action. Motions or text objects define the range. Counts multiply either.

Composed Command Result
d3w Delete three words
ci" Change contents inside double quotes
ya( Yank everything inside and including parentheses
>ip Indent the inner paragraph
gUiw Uppercase the inner word

Operators

Key Action
d Delete (cut to register)
y Yank (copy to register)
c Change (delete then enter Insert mode)
> Indent right
< Indent left
= Auto-indent
~ Toggle case
gu Lowercase
gU Uppercase

Doubling an operator applies it to the current line. dd deletes the line. yy yanks the line. cc changes the line.

Text Objects

Text objects describe a structural region of the buffer, independent of cursor position. The prefix i selects the inner region. The prefix a selects around (includes delimiters or surrounding whitespace).

Key Object
iw / aw Inner word / around word
is / as Inner sentence / around sentence
ip / ap Inner paragraph / around paragraph
i" / a" Inner double quotes / including quotes
i' / a' Inner single quotes / including quotes
i) / a) Inner parentheses / including parentheses
i] / a] Inner square brackets / including brackets
i} / a} Inner curly braces / including braces
it / at Inner HTML tag content / including tags

Common Single-Key Edits

Key Action
x Delete character under cursor
X Delete character before cursor
r{char} Replace character under cursor with char
R Enter Replace mode
J Join current line with line below
gJ Join lines without whitespace adjustment
u Undo
Ctrl-r Redo
. Repeat last change
p Paste register contents after cursor
P Paste register contents before cursor

The . command repeats the last change at the current cursor position. The efficient editing pattern is: make one change, move, repeat with ..


Visual Mode

Visual mode selects a region of the buffer before applying an operator.

Entry

Key Selection Type
v Character-wise
V Line-wise
Ctrl-v Block (column-wise)
gv Reselect previous visual selection

Operators in Visual Mode

Any operator applied in Visual mode acts on the selected region.

Key Action on Selection
d Delete
y Yank
c Change
> / < Indent right / left
~ Toggle case
u / U Lowercase / uppercase

Block Visual Editing

Block visual mode (Ctrl-v) enables column-level operations across multiple lines.

Procedure for inserting text at start of a column:

Step Action
1 Enter block visual with Ctrl-v
2 Select the column across target lines
3 Press I to insert at block start
4 Type the text
5 Press Escape to apply across all selected lines

This procedure comments out multiple lines with # or // in a single operation.


Search and Replace

Key Behaviour
/{pattern} Search forward
?{pattern} Search backward
n Next match
N Previous match
* Search forward for word under cursor
# Search backward for word under cursor
:noh Clear search highlights

Vim uses its own regular expression flavour.

Pattern Meaning
. Any single character
\w Word character (alphanumeric or underscore)
\d Digit
\s Whitespace character
^ Start of line
$ End of line
\<word\> Whole word boundary match
.* Any sequence of characters (greedy)

With ignorecase set, search is case-insensitive. With smartcase additionally set, a pattern containing any uppercase character becomes case-sensitive automatically.

Substitution Syntax

:{range}s/{pattern}/{replacement}/{flags}
Component Options
Range (empty) = current line, % = whole file, 5,10 = lines 5 to 10, '<,'> = visual selection
Flags g = all occurrences per line, i = case-insensitive, c = confirm each, e = suppress no-match error

Common substitutions:

Command Effect
:%s/foo/bar/g Replace all occurrences in file
:%s/foo/bar/gc Replace with per-match confirmation
:%s/\s\+$//e Strip trailing whitespace from all lines
:%s/ubuntu/alpine/gi Case-insensitive global replace
:g/^$/d Delete all blank lines

Global Command

The :g command executes an ex command on every line matching a pattern.

Command Effect
:g/TODO/d Delete every line containing TODO
:g/error/p Print every line containing error
:g/^#/m$ Move all lines beginning with # to end of file

Buffers, Windows, and Tabs

These three constructs are distinct.

Construct Definition
Buffer A file loaded into memory. It exists regardless of whether it is displayed.
Window A viewport onto a buffer. Multiple windows display simultaneously. Multiple windows can show the same buffer.
Tab A named collection of window layouts. Tabs preserve split arrangements, not individual files.

Buffer Commands

Command Action
:ls or :buffers List all open buffers
:b{N} Switch to buffer N
:b {name} Switch to buffer by partial name match
:bn Next buffer
:bp Previous buffer
:bd Unload current buffer
:bd{N} Unload buffer N
:ba Open all buffers in split windows

Window Commands

Command Action
:sp or Ctrl-w s Horizontal split
:vsp or Ctrl-w v Vertical split
Ctrl-w h/j/k/l Move focus to adjacent window
Ctrl-w H/J/K/L Move window to screen edge
Ctrl-w = Equalise all window sizes
Ctrl-w _ Maximise current window height
Ctrl-w \| Maximise current window width
Ctrl-w + / - Increase / decrease window height
Ctrl-w > / < Increase / decrease window width
:q Close current window
:only Close all windows except current

Tab Commands

Command Action
:tabnew Open a new empty tab
:tabnew {file} Open file in a new tab
gt Next tab
gT Previous tab
{N}gt Go to tab N
:tabclose Close current tab
:tabonly Close all other tabs
:tabs List all open tabs

The Command Line

: enters Command-line mode from Normal mode. Ex commands govern file operations, settings, shell access, and plugin interfaces.

File Operations

Command Action
:w Write current buffer to disk
:w {name} Write to a new filename
:wa Write all modified buffers
:q Close current window
:qa Close all windows
:wq or :x Write and close
:q! Close without writing
:e {file} Open a file into a buffer
:e! Reload current file from disk, discarding changes
:r {file} Insert file contents below cursor
:r !{cmd} Insert shell command output below cursor

Shell Access

Command Action
:!{cmd} Execute shell command, display output
:r !{cmd} Execute command, insert output into buffer
:terminal Open embedded terminal buffer (Neovim)

Runtime Option Changes

Command Action
:set number Enable line numbers
:set number! Toggle line numbers
:set number? Query current value
:set spell Enable spellcheck
:set spelllang=en_gb Set spellcheck language

Marks, Registers, and Macros

Marks

Marks store cursor positions for recall. Lowercase marks are file-local. Uppercase marks are global and persist across files.

Command Action
m{a-z} Set local mark
m{A-Z} Set global mark
`{mark} Jump to exact position of mark
'{mark} Jump to line of mark
`. Jump to position of last change
`^ Jump to position of last Insert mode exit
`[ Start of last yanked or changed text
`] End of last yanked or changed text
:marks List all marks
:delmarks {mark} Delete a mark

Registers

Registers are named storage locations for text. Vim maintains multiple registers simultaneously.

Register Contents
"" Unnamed register. Receives all d, y, c output.
"0 Last yank. Unaffected by delete operations.
"1 to "9 Rolling delete history.
"a to "z Named registers under user control.
"A to "Z Append variants of named registers.
"+ System clipboard.
"* Primary selection (X11 / Wayland).
". Last inserted text.
"% Current buffer filename.
": Last executed ex command.
"/ Last search pattern.

Usage:

Command Action
"ayy Yank current line into register a
"ap Paste from register a
"+yy Yank current line to system clipboard
"+p Paste from system clipboard
:registers Display all register contents

Setting clipboard=unnamedplus routes the unnamed register through the system clipboard. y and p then operate on the system clipboard without any register prefix. This requires wl-clipboard on Wayland or xclip / xsel on X11.

Macros

Macros record a sequence of Normal mode operations into a register and replay them.

Recording and Playback:

Command Action
q{a-z} Begin recording into register
q Stop recording
@{a-z} Execute macro from register
{N}@{a-z} Execute macro N times
@@ Repeat last executed macro

A macro stops automatically when it encounters an error, such as a failed search or end of file. Supplying a count larger than the number of remaining targets is safe: the macro halts cleanly.


Configuration

Neovim — init.lua Annotated

Configuration file location: ~/.config/nvim/init.lua

-- CORE SETTINGS

-- leader key: space is reachable with either thumb
-- all custom keymaps use this as their prefix
vim.g.mapleader = " "
vim.g.maplocalleader = " "

-- absolute line numbers give fixed references
-- relative numbers show motion counts to any visible line
vim.opt.number = true
vim.opt.relativenumber = true

-- mouse support in all modes
-- useful for resizing splits without disrupting keyboard flow
vim.opt.mouse = "a"

-- ignorecase: search is case-insensitive by default
-- smartcase: pattern with any uppercase letter becomes case-sensitive
vim.opt.ignorecase = true
vim.opt.smartcase = true

-- updatetime: milliseconds before CursorHold fires
-- affects diagnostic display latency across plugins
vim.opt.updatetime = 250

-- termguicolors: enables 24-bit rgb colour in the terminal
-- required for accurate colourscheme rendering
vim.opt.termguicolors = true

-- clipboard: routes the unnamed register through the system clipboard
-- requires wl-clipboard on wayland: pacman -S wl-clipboard
vim.opt.clipboard = "unnamedplus"

-- spelllang: english dictionary for spellcheck
-- activate per session with :set spell
vim.opt.spelllang = "en_gb"


-- PACKAGE MANAGER

-- lazy.nvim bootstraps itself from github on first run
-- subsequent launches load it from the local data directory
-- lazy-lock.json pins every plugin to an exact commit hash,
-- making the environment fully reproducible across machines
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    "--branch=stable",
    lazypath,
  })
end
vim.opt.rtp:prepend(lazypath)


-- PLUGINS

require("lazy").setup({

  -- COLOURSCHEME
  -- flexoki-dark is a warm, low-contrast dark theme
  -- priority = 1000 loads it before all other plugins
  -- background is overridden to pure black for high-contrast output
  {
    "kepano/flexoki-neovim",
    name = "flexoki",
    priority = 1000,
    config = function()
      vim.cmd("colorscheme flexoki-dark")
      vim.api.nvim_set_hl(0, "Normal",      { bg = "#000000" })
      vim.api.nvim_set_hl(0, "NormalFloat", { bg = "#000000" })
    end,
  },

  -- SYNTAX
  -- treesitter parses source into an abstract syntax tree
  -- highlighting derives from structure, not regex pattern matching
  -- build = ":TSUpdate" keeps parsers current on plugin update
  {
    "nvim-treesitter/nvim-treesitter",
    build = ":TSUpdate",
    config = function()
      require("nvim-treesitter").install({ "lua", "bash", "markdown", "markdown_inline" })

      -- attach treesitter highlighting when neovim identifies the filetype
      vim.api.nvim_create_autocmd("FileType", {
        pattern = { "lua", "sh", "markdown" },
        callback = function()
          vim.treesitter.start()
        end,
      })
    end,
  },

  -- COMPLETION
  -- nvim-cmp is a completion engine with pluggable sources
  -- sources here are local only: filesystem paths and open buffer text
  -- no network calls, no corporate api endpoints, no telemetry
  {
    "hrsh7th/nvim-cmp",
    dependencies = {
      "hrsh7th/cmp-path",
      "hrsh7th/cmp-buffer",
    },
    config = function()
      local cmp = require("cmp")
      cmp.setup({
        mapping = cmp.mapping.preset.insert({
          ["<C-b>"]     = cmp.mapping.scroll_docs(-4),
          ["<C-f>"]     = cmp.mapping.scroll_docs(4),
          ["<C-Space>"] = cmp.mapping.complete(),
          ["<C-e>"]     = cmp.mapping.abort(),
          ["<CR>"]      = cmp.mapping.confirm({ select = true }),
        }),
        sources = cmp.config.sources({
          { name = "path" },
          { name = "buffer" },
        })
      })
    end,
  },

  -- BUFFER LINE
  -- renders open buffers as a top bar with ordinal numbering
  -- shift-h and shift-l cycle through buffers
  -- leader-x unloads the current buffer from memory
  {
    "akinsho/bufferline.nvim",
    config = function()
      require("bufferline").setup({
        options = {
          mode = "buffers",
          numbers = "ordinal",
          show_buffer_close_icons = false,
          show_close_icon = false,
          separator_style = "thin",
          enforce_regular_tabs = true,
          always_show_bufferline = true,
        }
      })

      vim.keymap.set("n", "<S-h>",     "<cmd>BufferLineCyclePrev<CR>", { desc = "previous buffer" })
      vim.keymap.set("n", "<S-l>",     "<cmd>BufferLineCycleNext<CR>", { desc = "next buffer" })
      vim.keymap.set("n", "<leader>x", "<cmd>bdelete<CR>",             { desc = "close buffer" })
    end,
  },

  -- MARKDOWN RENDERING
  -- renders markdown structure visually inside neovim
  -- headings display as weighted blocks, code fences receive backgrounds
  -- sign = false removes sign column decoration
  -- code.width = "block" extends fence background to window width
  {
    "MeanderingProgrammer/render-markdown.nvim",
    dependencies = { "nvim-treesitter/nvim-treesitter" },
    opts = {
      heading = {
        sign = false,
        icons = { "H1 ", "H2 ", "H3 ", "H4 ", "H5 ", "H6 " },
      },
      code = {
        sign = false,
        width = "block",
        right_pad = 1,
      },
    },
  },

  -- ZEN MODE
  -- removes all chrome and centres text at 80 columns
  -- leader-z toggles the mode
  {
    "folke/zen-mode.nvim",
    config = function()
      require("zen-mode").setup({
        window = {
          width = 80,
          options = {
            number = false,
            relativenumber = false,
          }
        },
      })
      vim.keymap.set("n", "<leader>z", "<cmd>ZenMode<CR>", { desc = "toggle zen mode" })
    end
  }

})

Vim — .vimrc Equivalent

Configuration file location: ~/.vimrc

Install vim-plug first:

curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

Open Vim and run :PlugInstall to install all declared plugins.

" CORE SETTINGS

" leader key: space, consistent with neovim config
let mapleader = " "
let maplocalleader = " "

" line numbers: absolute and relative simultaneously
set number
set relativenumber

" mouse support in all modes
set mouse=a

" case-insensitive search with smart-case override
set ignorecase
set smartcase

" reduce key code timeout delay
set updatetime=250

" 24-bit colour support
set termguicolors

" route unnamed register through system clipboard
" requires wl-clipboard on wayland or xclip/xsel on x11
set clipboard=unnamedplus

" english spellcheck dictionary
" activate with :set spell
set spelllang=en_gb


" QUALITY OF LIFE

" display command being constructed in the status area
set showcmd

" status line always visible
set laststatus=2

" faster terminal redraws
set ttyfast

" write swap data to memory only; version control is the recovery mechanism
set noswapfile

" soft wrap at word boundaries
set wrap
set linebreak

" INDENTATION

set autoindent
set smartindent
set expandtab
set tabstop=2
set shiftwidth=2
set softtabstop=2

" SCROLLING

" maintain context lines above and below the cursor
set scrolloff=8
set sidescrolloff=8

" SPLITS

" new splits open to the right and below
set splitright
set splitbelow

" UNDO

" persistent undo survives session boundaries
set undofile
set undodir=~/.vim/undodir

" create the undo directory if it does not exist
silent !mkdir -p ~/.vim/undodir

" COMMAND LINE COMPLETION

set wildmenu
set wildmode=longest:full,full


" PLUGINS

call plug#begin('~/.vim/plugged')

  " COLOURSCHEME
  " flexoki-neovim is compatible with Vim
  Plug 'kepano/flexoki-neovim'

  " BUFFER LINE
  " vim-airline renders a buffer bar and status line
  " operates without nerd fonts; icon dependency removed
  Plug 'vim-airline/vim-airline'
  Plug 'vim-airline/vim-airline-themes'

  " ZEN MODE
  " goyo centres text at a fixed column width
  " limelight dims inactive paragraphs during composition
  Plug 'junegunn/goyo.vim'
  Plug 'junegunn/limelight.vim'

  " COMPLETION
  " asyncomplete provides async buffer and path completion
  " all sources are local; no external api calls
  Plug 'prabirshrestha/asyncomplete.vim'
  Plug 'prabirshrestha/asyncomplete-buffer.vim'
  Plug 'prabirshrestha/asyncomplete-file.vim'

  " MARKDOWN SYNTAX
  " vim-markdown extends native markdown highlighting and folding
  Plug 'preservim/vim-markdown'

call plug#end()


" COLOURSCHEME

colorscheme flexoki-dark

" override background to pure black
highlight Normal      guibg=#000000
highlight NormalFloat guibg=#000000


" AIRLINE

" enable the buffer tab bar
let g:airline#extensions#tabline#enabled = 1

" display buffer numbers for :b{N} navigation
let g:airline#extensions#tabline#buffer_nr_show = 1

" plain separators; no powerline glyphs required
let g:airline#extensions#tabline#left_sep     = ' '
let g:airline#extensions#tabline#left_alt_sep = '|'
let g:airline_theme = 'dark'

" buffer cycling: shift-h and shift-l, consistent with neovim config
nnoremap <S-h> :bprevious<CR>
nnoremap <S-l> :bnext<CR>

" leader-x closes current buffer
nnoremap <leader>x :bdelete<CR>


" GOYO

" 80 column writing window
let g:goyo_width = 80

" limelight activates and deactivates with goyo
autocmd! User GoyoEnter Limelight
autocmd! User GoyoLeave Limelight!

" leader-z toggles zen mode, consistent with neovim config
nnoremap <leader>z :Goyo<CR>


" ASYNCOMPLETE

call asyncomplete#register_source(asyncomplete#sources#buffer#get_source_options({
    \ 'name': 'buffer',
    \ 'allowlist': ['*'],
    \ 'completor': function('asyncomplete#sources#buffer#completor'),
    \ }))

call asyncomplete#register_source(asyncomplete#sources#file#get_source_options({
    \ 'name': 'file',
    \ 'allowlist': ['*'],
    \ 'completor': function('asyncomplete#sources#file#completor')
    \ }))

" tab and shift-tab navigate the completion popup
inoremap <expr> <Tab>   pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <expr> <CR>    pumvisible() ? asyncomplete#close_popup() : "\<CR>"


" MARKDOWN

" folding disabled
let g:vim_markdown_folding_disabled = 1

" strikethrough syntax enabled
let g:vim_markdown_strikethrough = 1


" KEY MAPS

" clear search highlights
nnoremap <leader>n :noh<CR>

" file operations
nnoremap <leader>w :w<CR>
nnoremap <leader>q :q<CR>
nnoremap <leader>Q :qa!<CR>

" split navigation
nnoremap <leader>h <C-w>h
nnoremap <leader>j <C-w>j
nnoremap <leader>k <C-w>k
nnoremap <leader>l <C-w>l

" open splits
nnoremap <leader>v :vsp<CR>
nnoremap <leader>s :sp<CR>

" toggle spellcheck
nnoremap <leader>p :set spell!<CR>

The Plugin Ecosystem

lazy.nvim

lazy.nvim is the Neovim package manager. It defers plugin loading until the plugin is triggered, keeping startup time constant regardless of plugin count. The lazy-lock.json file records the exact commit hash of every installed plugin. This makes the environment fully reproducible: cloning the config repository and running :Lazy restore produces an identical setup on any machine.

Command Action
:Lazy Open the lazy.nvim interface
:Lazy update Update all plugins to latest commits
:Lazy restore Sync all plugins to lockfile hashes
:Lazy clean Remove plugins no longer declared

kepano/flexoki-neovim

Flexoki is a warm, paper-derived colour palette. It provides accurate highlighting across a wide range of filetypes without relying on the terminal's 16-colour palette. The background override in the config sets it to pure black (#000000) for maximum contrast in terminal environments.

nvim-treesitter

Treesitter constructs a concrete syntax tree from source code and derives highlighting from structural nodes. It correctly handles edge cases that break regex-based highlighting: strings containing quote characters, heredoc blocks, nested interpolations, and multiline constructs. Adding parsers is straightforward.

Command Action
:TSInstall {language} Install a parser
:TSUpdate Update all installed parsers
:TSBufToggle highlight Toggle treesitter highlighting for current buffer

nvim-cmp

nvim-cmp is a completion framework. It accepts sources as dependencies and routes their output through a unified completion popup. The configuration here uses two offline sources: cmp-buffer draws words from open buffers, cmp-path completes filesystem paths. Both operate without network access. No AI completion endpoints. No data leaves the machine.

bufferline.nvim

bufferline renders the open buffer list as a styled top bar with ordinal numbering. nvim-web-devicons has been removed from the dependency list; icon fonts are decorative and introduce a font dependency that creates inconsistency across terminal environments.

render-markdown.nvim

render-markdown.nvim applies visual structure to markdown files inside the editor. Headings render as weighted labels. Code fences receive a filled background at block width. The plugin depends on treesitter for its markdown parser. The Nerd Font heading glyphs from the original config have been replaced with plain text labels (H1 through H6) to remove the font dependency.

zen-mode.nvim / goyo.vim

Both plugins remove editor chrome and centre the buffer at a fixed column width. zen-mode.nvim operates in Neovim. goyo.vim is the equivalent for Vim. Both are triggered by Space-z. The 80-column width enforces typographic discipline for long-form writing.


Cheatsheet

Modes

Key Mode
i Insert before cursor
I Insert at line start
a Append after cursor
A Append at line end
o New line below, Insert
O New line above, Insert
v Visual character
V Visual line
Ctrl-v Visual block
R Replace
: Command line
Escape Return to Normal
Key Action
h j k l Left, down, up, right
w / W Next word / WORD
b / B Previous word / WORD
e / E End of word / WORD
0 Line start (column 0)
^ First non-blank character
$ Line end
f{c} / F{c} Find char forward / backward on line
t{c} / T{c} To char forward / backward on line
; / , Repeat f/t forward / reverse
gg / G File start / end
{N}G Line N
Ctrl-d / Ctrl-u Scroll half-screen down / up
Ctrl-f / Ctrl-b Scroll full-screen down / up
H / M / L Screen top / middle / bottom
zz / zt / zb Centre / top / bottom screen on cursor
Ctrl-o / Ctrl-i Jump back / forward in jump list
* / # Search word under cursor forward / backward

Operators

Key Action
d Delete
y Yank
c Change
> / < Indent right / left
= Auto-indent
gU / gu Uppercase / lowercase
~ Toggle case

Text Objects

Key Object
iw / aw Word / word with space
ip / ap Paragraph inner / around
i" / a" Double quotes inner / around
i' / a' Single quotes inner / around
i) / a) Parentheses inner / around
i] / a] Brackets inner / around
i} / a} Braces inner / around
it / at Tag inner / around

Composed Commands

Command Action
dw Delete word
d$ Delete to end of line
ci" Change inside double quotes
yip Yank inner paragraph
da( Delete including parentheses
>ip Indent paragraph
gUiw Uppercase inner word

Common Edits

Key Action
x Delete character
r{c} Replace character
J Join line with line below
u Undo
Ctrl-r Redo
. Repeat last change
p / P Paste after / before cursor
dd / yy / cc Delete / yank / change line

Search and Replace

Command Action
/{pat} Search forward
?{pat} Search backward
n / N Next / previous match
:noh Clear highlights
:%s/a/b/g Replace all in file
:%s/a/b/gc Replace with confirmation
:'<,'>s/a/b/g Replace in selection
:g/{pat}/d Delete all matching lines

Buffers and Windows

Command Action
:ls List buffers
:b{N} Go to buffer N
:bn / :bp Next / previous buffer
:bd Unload buffer
Ctrl-w s / v Horizontal / vertical split
Ctrl-w h/j/k/l Navigate splits
Ctrl-w = Equalise splits
:only Close other windows
Shift-h / Shift-l Previous / next buffer (this config)
Space-x Close buffer (this config)

Marks and Registers

Command Action
m{a} Set mark
`{a} Jump to mark
'{a} Jump to mark's line
:marks List marks
"ayy Yank line to register a
"ap Paste from register a
"+yy / "+p Yank to / paste from system clipboard
:registers List all registers

Macros

Command Action
q{a} Begin recording into register a
q Stop recording
@{a} Execute macro
{N}@{a} Execute macro N times
@@ Repeat last macro

File and Session Commands

Command Action
:w Write buffer
:wa Write all buffers
:q / :q! Close / force close
:wq Write and close
:e {file} Open file
:e! Reload from disk
:r !{cmd} Insert command output
:checkhealth Neovim diagnostic report
:Lazy Plugin manager interface
:Lazy update Update all plugins
:Lazy restore Sync to lockfile

This Config's Custom Keymaps

Key Action
Space-z Toggle zen mode
Space-x Close current buffer
Shift-h Previous buffer
Shift-l Next buffer
Space-w Write file (Vim)
Space-q Quit (Vim)
Space-n Clear search highlights (Vim)
Space-v / Space-s Vertical / horizontal split (Vim)
Space-h/j/k/l Navigate splits (Vim)
Space-p Toggle spellcheck (Vim)