Vim

Table of Contents
│ └── Vim vs Neovim
│ ├── Neovim
│ └── Clipboard Support
│ └── Reloading Config
├── THE MODAL MODEL
│ ├── Character Motions
│ ├── Word Motions
│ ├── Composed Examples
│ └── The Dot Command
├── TEXT OBJECTS
│ └── Text Object Examples
├── INSERT MODE
│ └── Insert Mode Commands
├── VISUAL MODE
│ └── Block Visual Mode
│ ├── Ranges
│ ├── Global Command (:g)
│ └── Filter Command (:!)
│ ├── Search
│ └── Substitute
├── REGISTERS
├── MACROS
│ ├── Windows
│ ├── Buffers
│ └── Tabs
├── Core Settings
└── Plugins
├── Theme: Flexoki

🔗PHILOSOPHY AND MODAL EDITING

Vim's defining characteristic is that it is a modal editor. There is no persistent insert state. You are always in one mode, and that mode determines exactly what every keystroke means.

The payoff: once you internalise the grammar, editing becomes a composable language. d3w (delete three words), ci" (change inside quotes), gUip (uppercase inner paragraph) — these are statements in a grammar you can extend indefinitely.

Core ideas:

  • Keep your hands on the home row. The mouse is a context switch.
  • Spend most of your time in Normal mode — it is the command mode, not a waiting state.
  • Every operator + motion combination is a sentence. You do not need to remember two hundred commands; you learn a vocabulary of ~30 and combine them.
  • The dot (.) command repeats the last change. Design your edits so they are repeatable.
  • Use text objects, not character-by-character selection. ci( is faster than going to the first char, visually selecting, then deleting.

🔗Vim vs Neovim

FeatureVimNeovim
Config languageVimscriptLua (first class), Vimscript (supported)
AsyncLimitedFull async via libuv
Built-in LSPNoYes
Built-in TreesitterNoYes
Built-in terminalYesYes (better integration)
RPC/remote pluginsVia Python/RubyVia msgpack-RPC
Floating windowsNoYes
Default optionsConservativeMore sensible defaults
Active developmentMaintenance modeActive

For a modern installation, Neovim is the optimal choice. It offers native Lua support, integrated language server capabilities, and advanced UI features.


🔗INSTALL AND UPGRADE

🔗Neovim

Arch Linux:

sudo pacman -S neovim

Ubuntu / Debian (Latest Stable):

sudo add-apt-repository ppa:neovim-ppa/stable
sudo apt update && sudo apt install neovim

Build from source:

sudo pacman -S base-devel cmake ninja unzip gettext curl
git clone [https://github.com/neovim/neovim.git](https://github.com/neovim/neovim.git)
cd neovim
git checkout stable
make CMAKE_BUILD_TYPE=Release
sudo make install

🔗Clipboard Support

Neovim delegates clipboard tasks to external tools. Your configuration uses unnamedplus for Wayland integration.

# Wayland
sudo pacman -S wl-clipboard            # provides wl-copy, wl-paste

# X11
sudo pacman -S xclip                   # or xsel

# check Neovim sees it
nvim -c ':checkhealth' -c ':only'

🔗CONFIG PATHS AND LAUNCH

Neovim follows the XDG Base Directory Specification. Your main configuration file is ~/.config/nvim/init.lua.

PathPurpose
~/.config/nvim/init.luaMain config (Lua)
~/.config/nvim/lua/Lua modules directory
~/.local/share/nvim/Data: plugins, undo history, swap files
~/.local/share/nvim/lazy/lazy.nvim plugin store
~/.local/state/nvim/Log files, shada
~/.cache/nvim/Cache

🔗Reloading Config

To reload your configuration dynamically inside Neovim:

:source $MYVIMRC

🔗THE MODAL MODEL

Vim has several modes. Understanding each and how to enter and exit them is the foundation of everything else.

ModeIndicatorEntryExit
Normal(none)Escape, Ctrl-[, Ctrl-c— (this is home)
Insert-- INSERT --i, a, o, s, c, R...Escape
Visual (char)-- VISUAL --vEscape or v
Visual (line)-- VISUAL LINE --VEscape or V
Visual (block)-- VISUAL BLOCK --Ctrl-vEscape or Ctrl-v
Command-line: or / or ?:, /, ?, !Enter or Escape
Replace-- REPLACE --REscape
Terminal-- TERMINAL --:terminal, i in term bufCtrl-\ then Ctrl-n

🔗Why Normal Mode is Home

Every other editor puts you in an insert state by default. Vim inverts this: Normal mode is the resting state. Text editing breaks down into navigating to the edit, making the change, and returning to Normal to navigate again. Vim optimises for navigating.


🔗NORMAL MODE — MOTIONS

Motions move the cursor. Every motion can be preceded by a count. Motions combined with operators form the editing grammar.

🔗Character Motions

KeyMovement
hLeft one character
jDown one line
kUp one line
lRight one character
0Column zero (start of line, including whitespace)
^First non-blank character of line
$End of line (after last character)
g_Last non-blank character of line

🔗Word Motions

A word is a sequence of alphanumeric characters and underscores. A WORD is any sequence of non-whitespace characters.

KeyMovement
wStart of next word
WStart of next WORD
bStart of previous word
BStart of previous WORD
eEnd of current/next word
EEnd of current/next WORD

🔗Find and To (Character Search on Line)

KeyMovement
f{c}Forward to next occurrence of character c on line
F{c}Backward to previous occurrence of c on line
t{c}Forward to just before next c
T{c}Backward to just after previous c
;Repeat last f/F/t/T in same direction
,Repeat last f/F/t/T in opposite direction

🔗Line Number and Document Motions

KeyMovement
ggFirst line of file
GLast line of file
{N}GLine N
%Matching bracket/paren/brace/HTML tag
{Start of previous paragraph
}Start of next paragraph

🔗NORMAL MODE — OPERATORS

Operators act on the text covered by a following motion or text object. The pattern is: [count] {operator} [count] {motion}.

KeyAction
dDelete (cut — goes into register)
yYank (copy)
cChange (delete then enter Insert mode)
>Indent right
<Indent left
=Auto-indent (format indentation)
gqFormat lines (wrap to textwidth)
gUUppercase
guLowercase
~Toggle case of character under cursor

🔗Composed Examples

  • d3w -- delete 3 words
  • d$ -- delete to end of line
  • dd -- delete current line
  • dG -- delete to end of file
  • yap -- yank around paragraph
  • ci" -- change inside double quotes
  • gUiw -- uppercase inner word

🔗The Dot Command

. repeats the last change — not the last command. A change is any action that modified text: insert, delete, replace, etc. Design your edits for repeatability. For example: ciw<new text><Esc>, then press . on the next word to apply the identical change.


🔗TEXT OBJECTS

Text objects allow selecting structured regions of text without navigating to their boundaries. They only work after an operator or in visual mode. Format: {i|a}{object}i = inner (without delimiters), a = around (with delimiters).

ObjectInner (i)Around (a)
wWordWord + surrounding whitespace
WWORDWORD + surrounding whitespace
sSentenceSentence + whitespace
pParagraphParagraph + blank lines
"Inside double quotesIncluding double quotes
'Inside single quotesIncluding single quotes
( or )Inside parenthesesIncluding parentheses
[ or ]Inside square bracketsIncluding brackets
{ or }Inside curly bracesIncluding braces
tInside HTML/XML tagIncluding the tags

🔗Text Object Examples

  • diw -- delete inner word (leaves whitespace)
  • daw -- delete around word (removes word + space)
  • ci( -- change inside parentheses
  • yi' -- yank inside single quotes

🔗INSERT MODE

Insert mode is where you type text. The goal is to enter it, type the minimum, and leave.

KeyEntry Point
iBefore the cursor
IBefore first non-blank character of line
aAfter the cursor
AAfter the last character of line (end of line)
oOpen new line below and enter insert
OOpen new line above and enter insert
sDelete character under cursor and enter insert
SDelete entire line content and enter insert
c{motion}Delete through motion, enter insert

🔗Insert Mode Commands

KeyAction
Ctrl-[Exit Insert mode (same as Escape)
Ctrl-wDelete word before cursor
Ctrl-uDelete all characters before cursor on current line
Ctrl-oExecute one Normal mode command, return to Insert
Ctrl-r {reg}Insert contents of register

🔗VISUAL MODE

Visual mode lets you select a region and then apply an operator to it.

KeyMode
vCharacter-wise visual
VLine-wise visual
Ctrl-vBlock visual
gvReselect last visual selection
oToggle cursor to opposite end of selection

🔗Block Visual Mode

Block visual (Ctrl-v) selects a rectangular region. Operations apply to each line of the block independently. This is extremely powerful for prepending text to multiple lines simultaneously (Ctrl-v, select lines, I, type text, Escape).


🔗COMMAND-LINE MODE

Command-line mode is entered with :, /, ?, or !. It accepts Ex commands, search patterns, and shell commands.

🔗Ranges

Ranges prefix Ex commands to specify which lines they operate on.

  • % Entire file (same as 1,$)
  • '<,'> Last visual selection (auto-populated when pressing : in Visual mode)
  • 1,10 Lines 1 to 10
  • .,+5 Current line to 5 lines below

🔗Global Command (:g)

:g/{pattern}/{command} runs a command on every line matching a pattern.

  • :g/TODO/d " delete all TODO lines
  • :g/^$/d " delete blank lines
  • :v/pattern/d " delete all non-matching lines

🔗Filter Command (:!)

  • :%!sort " sort entire file
  • :'<,'>!python3 " run visual selection through python

🔗SEARCH AND SUBSTITUTE

  • /pattern " search forward
  • ?pattern " search backward
  • n " next match (same direction)
  • N " previous match (opposite direction)
  • * " search word under cursor forward (whole word)

Your configuration ensures searches are fast and ergonomic:

  • ignorecase is enabled so lowercase inputs match both cases.
  • smartcase is enabled so queries containing uppercase letters strictly match case.

🔗Substitute

  • :s/old/new/ " replace first match on current line
  • :%s/old/new/g " replace all matches in file
  • :%s/old/new/gc " replace all, confirm each
  • :'<,'>s/old/new/g " replace in visual selection

🔗REGISTERS

Registers store text. They are accessed with " followed by the register name.

RegisterNameDescription
""UnnamedLast deleted, changed, or yanked text
"0YankMost recent yank only (not affected by delete)
"1"9NumberedRolling history of deletes and changes
"a"zNamedUser-controlled, explicitly named
"+ClipboardSystem clipboard
"_Black holeDiscard — no register is affected
"/SearchLast search pattern

🔗The Unnamed and Yank Registers

The most common confusion: "1 through "9 shift on every delete. But "0 only updates on explicit yanks, never on deletes. Always use "0p to paste a yank after subsequent deletes.


🔗MACROS

Macros record a sequence of Normal, Insert, and Command-line mode actions into a register and replay them.

  • q{register} " begin recording into register (e.g. qq)
  • q " stop recording
  • @{register} " execute macro once
  • {N}@{register} " execute macro N times
  • @@ " repeat last executed macro

🔗WINDOWS, BUFFERS, AND TABS

🔗Windows

A window is a viewport onto a buffer.

  • Ctrl-w v Vertical split
  • Ctrl-w s Horizontal split
  • Ctrl-w h/j/k/l Move between windows
  • Ctrl-w = Equalise all window sizes
  • Ctrl-w c Close window

🔗Buffers

A buffer is a file loaded into memory. It exists whether or not it is currently displayed in a window.

  • :ls " list all listed buffers
  • :b{N} " switch to buffer N
  • :bn / :bp " next / previous buffer
  • :bd " unload and remove current buffer

🔗Tabs

Tabs in Vim are not like editor tabs — they are separate window layouts, each containing their own set of splits. Use tabs for distinct working contexts, not for individual files.

  • :tabnew " open new tab
  • gt / gT " Next / previous tab

🔗NEOVIM LUA ESSENTIALS

Neovim exposes its API through the vim global Lua object.

vim.opt.number = true          -- set an option
vim.g.mapleader = " "          -- set a global variable
vim.fn.expand("%")             -- call a Vim built-in function
vim.cmd("w")                   -- execute Ex commands
vim.api.nvim_get_current_buf() -- interact with the Neovim C API

🔗Neovim Lua Autocommands

vim.api.nvim_create_autocmd("FileType", {
  pattern = { "lua", "sh", "markdown" },
  callback = function()
    -- action to perform
  end,
})

🔗NEOVIM — THIS CONFIG DEEP-DIVE

Your init.lua sets up a highly tailored, keyboard-driven development environment, leaning on modern Lua plugins rather than legacy Vimscript.

🔗Core Settings

Your environment establishes standard editor behaviors and aesthetics natively:

  • The mapleader and maplocalleader are bound to the Space key.
  • Absolute line numbers (number = true) and relative line numbering (relativenumber = true) are both enabled to facilitate rapid vertical jumping.
  • Full mouse support is active across all modes (mouse = "a").
  • Case-insensitive searching is enabled (ignorecase = true), which intelligently becomes case-sensitive if you type an uppercase character (smartcase = true).
  • The updatetime is lowered to 250 milliseconds, ensuring diagnostics and plugin updates feel responsive.
  • True 24-bit color is enforced with termguicolors = true.
  • System clipboard integration is handled seamlessly using the unnamedplus register.
  • The spelllang is strictly set to "en_gb".

🔗Package Management: Lazy.nvim

The setup utilizes lazy.nvim as its package manager. It dynamically bootstraps itself via git clone into stdpath("data") .. "/lazy/lazy.nvim" if the directory does not exist. It targets the stable branch and enforces a blobless clone (--filter=blob:none) for speed.

🔗Plugins

🔗Theme: Flexoki

  • The kepano/flexoki-neovim plugin is loaded with top priority (priority = 1000).
  • It executes the colorscheme flexoki-dark command immediately upon loading.
  • It explicitly overrides the Normal and NormalFloat highlight groups, painting their backgrounds with the #100F0F hex code to mesh perfectly with your broader Sway/system aesthetic.

🔗Syntax and Parsing: Nvim-Treesitter

  • nvim-treesitter/nvim-treesitter is configured to download and compile parsers natively.
  • It is explicitly instructed to install parsers for lua, bash, markdown, and markdown_inline.
  • A FileType autocommand triggers vim.treesitter.start() automatically whenever you open lua, sh, or markdown files.

🔗Autocompletion: Nvim-Cmp

  • The hrsh7th/nvim-cmp plugin handles code completion, relying strictly on two local dependencies: cmp-path and cmp-buffer.
  • The sources configuration limits data aggregation to local file paths ({ name = "path" }) and current text buffers ({ name = "buffer" }).
  • Key mappings are explicitly structured around standard control keys: <C-b> scrolls docs up, <C-f> scrolls docs down, <C-Space> manually triggers the menu, <C-e> aborts the operation, and <CR> confirms the selection.

🔗Buffer Navigation: Bufferline.nvim

  • akinsho/bufferline.nvim requires nvim-web-devicons to function correctly in your setup.
  • The bar is configured in buffers mode, rendering background buffers at the top of the terminal.
  • It displays ordinal numbers on the tabs and hides all graphical closing icons (show_buffer_close_icons = false, show_close_icon = false) for a cleaner visual profile.
  • It enforces regular tabs (enforce_regular_tabs = true), a thin separator (separator_style = "thin"), and ensures the bar is always visible.
  • Custom keymaps are defined for navigation: <S-h> calls <cmd>BufferLineCyclePrev<CR>, <S-l> calls <cmd>BufferLineCycleNext<CR>, and <leader>x terminates the active buffer with <cmd>bdelete<CR>.

🔗Markdown Enhancements: Render-Markdown

  • MeanderingProgrammer/render-markdown.nvim leverages both treesitter and devicons to paint Markdown files beautifully in the terminal.
  • Heading signs are disabled (sign = false), and heading icons are replaced with a custom array of specialized font characters ('󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ').
  • Code blocks disable the standard sign column, render natively as visual blocks (width = "block"), and inject a minor right-side padding (right_pad = 1).

🔗Writing Focus: Zen-mode.nvim

  • folke/zen-mode.nvim strips away terminal distractions.
  • The isolated window is restricted to a column width of 80 (width = 80).
  • Absolute and relative line numbers are forcefully disabled within the Zen pane (number = false, relativenumber = false).
  • It is triggered instantly via the <leader>z keybinding, invoking <cmd>ZenMode<CR>.