feat: major feature upgrade — zen mode, run file, smart search, and more

New plugins (3):
- vim-sleuth: auto-detect indentation from existing files
- goyo.vim + limelight.vim: zen mode for focused writing (,zen)

New built-in features (8):
- Run current file (,cr) — auto-detects Python/Go/Rust/JS/C/Shell/etc.
- Yank highlight — flashes yanked text for visual feedback
- Auto-clear search highlight after cursor stops moving
- Git conflict marker navigation ([x / ]x)
- Window maximize toggle (,z)
- Sudo save (:w!!)
- QuickFix auto-open + ]q/[q navigation
- ALE error/warning count in statusline

More FZF mappings:
- ,fh recent files, ,fl buffer lines, ,fL all lines
- ,fc commands, ,fm marks, ,f/ search history, ,f: command history

README rewritten with compelling feature showcase (30 plugins).
Cheat sheet and QUICKSTART updated with all new features.
This commit is contained in:
m1ngsama 2026-04-21 23:42:41 +08:00
parent cc328cebf2
commit 84d999f91f
3 changed files with 355 additions and 396 deletions

242
.vimrc
View file

@ -117,6 +117,7 @@ Plug 'tpope/vim-surround'
Plug 'tpope/vim-commentary'
Plug 'tpope/vim-repeat'
Plug 'tpope/vim-unimpaired'
Plug 'tpope/vim-sleuth'
Plug 'wellle/targets.vim'
Plug 'jiangmiao/auto-pairs'
Plug 'easymotion/vim-easymotion'
@ -136,8 +137,10 @@ Plug 'HerringtonDarkholme/yats.vim'
Plug 'preservim/vim-markdown'
Plug 'fatih/vim-go'
" ── Markdown Preview ──────────────────────────────────────────────────────────
" ── Markdown Preview & Writing ────────────────────────────────────────────────
Plug 'previm/previm'
Plug 'junegunn/goyo.vim'
Plug 'junegunn/limelight.vim'
" ── UI ────────────────────────────────────────────────────────────────────────
Plug 'mbbill/undotree'
@ -359,12 +362,19 @@ function! s:SmartFiles() abort
endfunction
if exists('g:plugs["fzf.vim"]')
nnoremap <C-p> :call <SID>SmartFiles()<CR>
nnoremap <leader>b :Buffers<CR>
nnoremap <C-p> :call <SID>SmartFiles()<CR>
nnoremap <leader>b :Buffers<CR>
nnoremap <leader>rg :Rg<CR>
nnoremap <leader>rG :RgWord<CR>
nnoremap <leader>rt :Tags<CR>
nnoremap <leader>gF :GFiles<CR>
nnoremap <leader>fh :History<CR>
nnoremap <leader>fc :Commands<CR>
nnoremap <leader>fm :Marks<CR>
nnoremap <leader>fl :BLines<CR>
nnoremap <leader>fL :Lines<CR>
nnoremap <leader>f/ :History/<CR>
nnoremap <leader>f: :History:<CR>
endif
let g:fzf_layout = { 'down': '40%' }
@ -595,6 +605,34 @@ if exists('g:plugs["previm"]')
endif
let g:previm_enable_realtime = 1
" ============================================================================
" => Goyo + Limelight (zen mode for focused writing)
" ============================================================================
if exists('g:plugs["goyo.vim"]')
let g:goyo_width = 80
let g:goyo_height = '85%'
nnoremap <leader>zen :Goyo<CR>
function! s:goyo_enter()
if exists('g:plugs["limelight.vim"]') | Limelight | endif
set wrap linebreak scrolloff=999
endfunction
function! s:goyo_leave()
if exists('g:plugs["limelight.vim"]') | Limelight! | endif
set nowrap nolinebreak scrolloff=10
endfunction
augroup ChopstickGoyo
autocmd!
autocmd User GoyoEnter nested call s:goyo_enter()
autocmd User GoyoLeave nested call s:goyo_leave()
augroup END
endif
let g:limelight_conceal_ctermfg = 240
let g:limelight_conceal_guifg = '#586e75'
" ============================================================================
" => EasyMotion
" ============================================================================
@ -746,6 +784,16 @@ function! SLGit() abort
return empty(l:b) ? '' : ' ' . l:b . ' '
endfunction
" ALE error/warning count
function! SLAle() abort
if !exists('*ale#statusline#Count') | return '' | endif
let l:c = ale#statusline#Count(bufnr(''))
let l:e = l:c.error + l:c.style_error
let l:w = l:c.warning + l:c.style_warning
if l:e == 0 && l:w == 0 | return '' | endif
return printf(' E:%d W:%d ', l:e, l:w)
endfunction
" Assemble the statusline on every redraw
function! SLBuild() abort
let [l:label, l:hl] = SLMode()
@ -753,6 +801,7 @@ function! SLBuild() abort
let l:s .= '%#SLBody# %f '
let l:s .= '%#SLFlag#%m%r'
let l:s .= '%#SLBody#%='
let l:s .= '%#SLFlag#' . SLAle()
let l:s .= '%#SLGit#' . SLGit()
let l:s .= '%#SLFtype# %y '
let l:s .= '%#SLRight# %l:%c %P '
@ -1041,89 +1090,71 @@ function! s:CheatSheet() abort
call setline(1, [
\ '=== chopsticks — Quick Reference ===',
\ '',
\ 'MODES',
\ ' Normal Default. Navigate and run commands.',
\ ' Insert Type text. Enter: i/a/o Leave: Esc or jk',
\ ' Visual Select. Enter: v/V Leave: Esc',
\ '',
\ 'SURVIVAL',
\ ' Esc / jk Exit insert or visual mode',
\ ' :q! + Enter Quit without saving',
\ ' ,x Save and quit | ,w Save',
\ ' Ctrl+s Save (normal + insert mode)',
\ ' ,x Save+quit ,w Save Ctrl+s Save (any mode)',
\ ' :w!! Sudo save (when you forgot to open as root)',
\ '',
\ 'FILES & NAVIGATION',
\ ' Ctrl+p Fuzzy find file (git-aware, FZF)',
\ ' ,e Open netrw file browser',
\ ' ,E Open netrw in vertical split',
\ ' ,b Search open buffers (FZF)',
\ 'FILES & SEARCH',
\ ' Ctrl+p Fuzzy find file (git-aware)',
\ ' ,e / ,E File browser / vertical split',
\ ' ,b Search open buffers',
\ ' ,rg Search project contents (ripgrep)',
\ ' ,rG Ripgrep word under cursor',
\ ' ,fh Recent files history',
\ ' ,fl / ,fL Search lines in buffer / all buffers',
\ ' ,fc Commands | ,fm Marks',
\ ' ,f/ / ,f: Search / command history',
\ ' ,, Switch to last file (Ctrl+^)',
\ ' Ctrl+o / i Jump back / forward in history',
\ '',
\ 'CODE INTELLIGENCE (vim-lsp)',
\ ' gd Go to definition',
\ ' gy Go to type definition',
\ ' gi Go to implementation',
\ ' gr Show references',
\ ' K Hover documentation',
\ ' [g / ]g Prev / next LSP diagnostic',
\ ' [e / ]e Prev / next ALE error',
\ ' ,ca Code action',
\ ' ,rn Rename symbol',
\ ' ,f Format buffer (or visual selection)',
\ ' ,o File outline (symbols)',
\ ' ,ws Workspace symbols',
\ ' gd Definition gy Type def gi Impl gr Refs',
\ ' K Hover documentation',
\ ' [g / ]g Prev / next LSP diagnostic',
\ ' [e / ]e Prev / next ALE error',
\ ' ,ca Code action ,rn Rename ,f Format',
\ ' ,o File outline ,ws Workspace symbols',
\ ' ,cr Run current file',
\ '',
\ 'MARKDOWN',
\ ' ,mp Open live browser preview (previm)',
\ 'MARKDOWN & WRITING',
\ ' ,mp Live browser preview (previm)',
\ ' ,mt Table of contents',
\ ' zr Unfold all headings',
\ ' zm Fold all headings',
\ ' ,zen Zen mode (Goyo + Limelight)',
\ ' zr / zm Unfold / fold all headings',
\ '',
\ 'EDITING',
\ ' gc Toggle comment (visual mode too)',
\ ' s + 2 chars EasyMotion — jump anywhere on screen',
\ ' ,j / ,k EasyMotion — line motions',
\ ' ,u / F5 Undo tree (visual branch history)',
\ ' ,y / ,Y Yank / yank line to system clipboard',
\ ' ,p / ,P Paste from system clipboard',
\ ' Alt+j / Alt+k Move line down / up (also visual mode)',
\ ' ,F Re-indent entire file',
\ ' ,W Strip trailing whitespace',
\ ' s + 2 chars EasyMotion jump anywhere',
\ ' ,u / F5 Undo tree',
\ ' ,y / ,Y Yank to system clipboard',
\ ' Alt+j / Alt+k Move line down / up',
\ ' ,F Re-indent file ,W Strip trailing whitespace',
\ ' ,* Search and replace word under cursor',
\ '',
\ 'SPELLING',
\ ' ,ss Toggle spell checking',
\ ' ,sn / ,sp Next / prev misspelling',
\ ' ,sa Add word to dictionary',
\ ' ,s? Suggest corrections',
\ '',
\ 'GIT',
\ ' ,gs Status ,gd Diff ,gb Blame',
\ ' ,gc Commit ,gp Push ,gl Pull',
\ ' [x / ]x Navigate git conflict markers',
\ '',
\ 'WINDOWS & PANES',
\ ' Ctrl+h/j/k/l Navigate Vim splits and tmux panes',
\ ' ,h / ,l Prev / next buffer',
\ ' ,bd Close buffer (keep layout)',
\ ' ,tn / ,tc New tab / close tab | ,tl Last tab',
\ ' ,tv / ,th Open terminal (vertical / horizontal)',
\ ' Ctrl+h/j/k/l Navigate splits and tmux panes',
\ ' ,h / ,l Prev / next buffer ,bd Close buffer',
\ ' ,z Maximize / restore current window',
\ ' ,tv / ,th Terminal (vertical / horizontal)',
\ ' Esc Esc Exit terminal mode',
\ ' ,= / ,- Resize height (grow / shrink)',
\ ' ,+ / ,_ Resize width (grow / shrink)',
\ ' ,= / ,- Resize height ,+ / ,_ Resize width',
\ '',
\ 'QUICKFIX',
\ ' ,qo / ,qc Open / close quickfix',
\ ' ]q / [q Next / prev quickfix entry',
\ '',
\ 'UTILITIES',
\ ' ,ev / ,sv Edit / reload ~/.vimrc',
\ ' ,cp / ,cf Copy file path / filename to clipboard',
\ ' ,ms Open scratch markdown buffer',
\ ' ,cd Change CWD to current file directory',
\ ' F2 Paste F3 Line# F4 Relative# F6 Invisible',
\ '',
\ 'SESSION',
\ ' :Obsess Start tracking session',
\ ' :Obsess! Stop tracking',
\ ' ,ms Scratch buffer ,cd CD to file dir',
\ ' ,ss Toggle spell ,so Source current vim file',
\ ' F2 Paste F3 Line# F4 Relative# F6 Invisible',
\ '',
\ '(press q to close)',
\ ])
@ -1132,11 +1163,100 @@ function! s:CheatSheet() abort
endfunction
nnoremap <silent> <leader>? :call <SID>CheatSheet()<CR>
" ============================================================================
" => Yank Highlight (flash yanked region for visual feedback)
" ============================================================================
if exists('##TextYankPost') && has('timers')
function! s:YankHighlight() abort
if v:event.operator !=# 'y' | return | endif
let l:m = matchadd('IncSearch',
\ printf('\%%>%dl\%%<%dl', line("'[") - 1, line("']") + 1))
call timer_start(150, {-> matchdelete(l:m)})
endfunction
augroup ChopstickYankHL
autocmd!
autocmd TextYankPost * call s:YankHighlight()
augroup END
endif
" ============================================================================
" => Auto-Clear Search Highlight (clear after idle)
" ============================================================================
augroup ChopstickSearchHL
autocmd!
autocmd CursorHold * if get(v:, 'hlsearch', 0) | let v:hlsearch = 0 | endif
augroup END
" ============================================================================
" => Run Current File (,cr)
" ============================================================================
function! s:RunFile() abort
write
let l:ft = &filetype
let l:file = shellescape(expand('%:p'))
if l:ft ==# 'python' | execute '!python3 ' . l:file
elseif l:ft ==# 'javascript' | execute '!node ' . l:file
elseif l:ft ==# 'typescript' | execute '!npx ts-node ' . l:file
elseif l:ft ==# 'go' | execute '!go run ' . l:file
elseif l:ft ==# 'rust' | execute '!cargo run'
elseif l:ft ==# 'sh' | execute '!bash ' . l:file
elseif l:ft ==# 'c' | execute '!gcc -o /tmp/a.out ' . l:file . ' && /tmp/a.out'
elseif l:ft ==# 'lua' | execute '!lua ' . l:file
elseif l:ft ==# 'ruby' | execute '!ruby ' . l:file
elseif l:ft ==# 'perl' | execute '!perl ' . l:file
else | echo 'No runner for filetype: ' . l:ft
endif
endfunction
nnoremap <leader>cr :call <SID>RunFile()<CR>
" ============================================================================
" => Git Conflict Navigation ([x / ]x)
" ============================================================================
nnoremap <silent> ]x /^\(<<<<<<<\\|=======\\|>>>>>>>\)<CR>
nnoremap <silent> [x ?^\(<<<<<<<\\|=======\\|>>>>>>>\)<CR>
" ============================================================================
" => Window Maximize Toggle (,z)
" ============================================================================
function! s:ToggleMaximize() abort
if exists('t:maximize_session')
execute t:maximize_session
unlet t:maximize_session
else
let t:maximize_session = winrestcmd()
resize | vertical resize
endif
endfunction
nnoremap <silent> <leader>z :call <SID>ToggleMaximize()<CR>
" ============================================================================
" => Sudo Save (:w!! when you forget to open as root)
" ============================================================================
cnoremap w!! w !sudo tee > /dev/null %
" ============================================================================
" => QuickFix Improvements
" ============================================================================
augroup ChopstickQF
autocmd!
autocmd QuickFixCmdPost [^l]* cwindow
autocmd QuickFixCmdPost l* lwindow
augroup END
nnoremap <silent> ]q :cnext<CR>
nnoremap <silent> [q :cprev<CR>
" ============================================================================
" => Debug Helpers
" ============================================================================
" Show syntax highlight stack for word under cursor
nnoremap <leader>sh :call <SID>SynStack()<CR>
function! <SID>SynStack()
if !exists("*synstack") | return | endif

View file

@ -142,13 +142,15 @@ K Show documentation
| `[g` | Jump to previous diagnostic |
| `K` | Read the error message |
| `,ca` | Apply code action / auto-fix |
| `,cr` | Run current file (auto-detects language) |
### Markdown
### Markdown & Writing
| Key | Action |
|-----|--------|
| `,mp` | Open live preview in browser |
| `,mt` | Table of contents (side window) |
| `,zen` | Zen mode (Goyo + Limelight) |
| `zr` / `zm` | Unfold / fold all headings |
Formatting in the buffer is live: `**bold**` renders as bold,
@ -164,6 +166,7 @@ the cursor enters that line.
,gc commit
,gp push
,gl pull
[x / ]x navigate conflict markers
```
---
@ -192,28 +195,31 @@ CODE
K Show documentation
[g / ]g Prev / next LSP diagnostic
[e / ]e Prev / next ALE error
,rn Rename symbol
,ca Code action
,f Format buffer / selection
MARKDOWN
,mp Live preview | ,mt Table of contents
GIT
,gs Status | ,gd Diff | ,gb Blame
,gc Commit | ,gp Push | ,gl Pull
WINDOWS / PANES
Ctrl+h/j/k/l Move between Vim windows or tmux panes
,h / ,l Prev / next buffer
,tv / ,th Terminal (vertical / horizontal)
Esc Esc Exit terminal mode
,u Undo tree
,rn Rename ,ca Code action ,f Format
,cr Run current file
SEARCH
,rg Ripgrep ,rG Ripgrep word ,fh Recent files
,fl Lines in buffer ,fc Commands ,fm Marks
/text Forward | ?text Backward | n next | N prev
// Search visually selected text
,* Replace word under cursor (file-wide)
MARKDOWN
,mp Preview | ,mt TOC | ,zen Zen mode
GIT
,gs Status ,gd Diff ,gb Blame
,gc Commit ,gp Push ,gl Pull
[x / ]x Navigate conflict markers
WINDOWS
Ctrl+h/j/k/l Navigate splits and tmux panes
,z Maximize / restore window
,h / ,l Prev / next buffer
,tv / ,th Terminal (vertical / horizontal)
Esc Esc Exit terminal mode
]q / [q Next / prev quickfix entry
```
---

467
README.md
View file

@ -1,14 +1,11 @@
# chopsticks
> Flowing vim for any machine — SSH servers included.
> Solarized · vim-lsp (no Node.js) · Markdown-first · One-command install.
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE)
[![Vim 8.0+](https://img.shields.io/badge/Vim-8.0%2B-brightgreen?style=flat-square)](https://www.vim.org/)
[![Platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey?style=flat-square)](#installation)
[![Release](https://img.shields.io/github/v/release/m1ngsama/chopsticks?style=flat-square&label=release&color=orange)](https://github.com/m1ngsama/chopsticks/releases)
[![Last Commit](https://img.shields.io/github/last-commit/m1ngsama/chopsticks?style=flat-square)](https://github.com/m1ngsama/chopsticks/commits/main)
[![Stars](https://img.shields.io/github/stars/m1ngsama/chopsticks?style=flat-square)](https://github.com/m1ngsama/chopsticks/stargazers)
```bash
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
@ -16,45 +13,26 @@ curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | b
---
## Contents
## What You Get
- [Design Principles](#design-principles)
- [Requirements](#requirements)
- [Installation](#installation)
- [LSP](#lsp)
- [Key Mappings](#key-mappings)
- [Markdown](#markdown)
- [Features](#features)
- [Plugins](#plugins)
- [Customization](#customization)
- [Troubleshooting](#troubleshooting)
**30 plugins. One command. Zero Node.js dependency.**
---
## Design Principles
| Principle | What it means |
|-----------|--------------|
| **Flowing writing** | Every plugin earns its place by reducing interruptions to thought |
| **No Node.js** | vim-lsp runs on pure VimScript — works on any machine, including SSH servers |
| **Solarized** | One palette, everywhere — vim statusline matches tmux bar exactly |
| **TTY-aware** | SSH and console environments degrade gracefully without breaking |
| **KISS** | No icon fonts, no Nerd Font glyphs — plain ASCII throughout |
---
## Requirements
| Tool | Role |
|------|------|
| Vim 8.0+ | Required — `install.sh` installs it if missing |
| git | Required |
| curl | Required |
| ripgrep | Recommended — enables `,rg` project search |
| fzf | Recommended — enables `Ctrl+p` fuzzy finder |
| Node.js | Optional — enables npm formatters (prettier, eslint) |
`install.sh` detects your environment and installs missing dependencies.
| Feature | What it does |
|---------|-------------|
| **LSP everywhere** | Completion, go-to-definition, hover docs, rename — pure VimScript, works over SSH |
| **Format on save** | ALE runs black, prettier, gofmt automatically. Errors show in statusline. |
| **Fuzzy everything** | Files, buffers, grep, tags, marks, command history — all via FZF with preview |
| **Zen mode** | Goyo + Limelight: distraction-free writing. `,zen` and the world disappears |
| **Run any file** | `,cr` detects filetype and runs it: Python, Go, Rust, JS, C, Shell, and more |
| **Smart indentation** | vim-sleuth auto-detects tabs vs spaces from existing files. No config needed. |
| **Yank highlight** | Yanked text flashes — instant visual feedback, never guess what you copied |
| **Search that clears** | Search highlights disappear after you stop moving. No more `,<cr>` spam. |
| **Git workflow** | Status, diff, blame, push, pull. Conflict marker navigation with `[x`/`]x`. |
| **Window maximize** | `,z` toggles current split to full screen and back. |
| **Sudo save** | `:w!!` when you forgot to open as root |
| **ALE in statusline** | Error and warning counts always visible — no surprises |
| **30+ key mappings** | Every common action is one or two keystrokes away. `,?` shows them all. |
| **TTY-aware** | SSH, console, slow connections — degrades gracefully, never breaks |
---
@ -66,12 +44,6 @@ curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | b
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
```
Non-interactive / CI:
```bash
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --yes
```
### Git clone
```bash
@ -79,95 +51,48 @@ git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
cd ~/.vim && ./install.sh
```
### What the installer does
1. Detects OS and package manager
2. Verifies or installs `curl`, `git`, `vim`
3. Backs up existing `~/.vimrc`, then symlinks `~/.vimrc → ~/.vim/.vimrc`
4. Installs vim-plug and runs `:PlugInstall`
5. Offers to install system tools (ripgrep, fzf, ctags, shellcheck, hadolint, marksman)
6. Offers to install npm formatters (prettier, eslint, etc.) — requires Node.js
7. Offers to install Python formatters/linters (black, isort, flake8, etc.)
8. Offers to install Go tools (gopls, goimports, staticcheck)
9. Offers to append vim-tmux-navigator bindings to `~/.tmux.conf`
**Supported platforms:** macOS (Homebrew), Debian/Ubuntu (apt), Arch (pacman), Fedora (dnf).
---
## LSP
Code intelligence is provided by **vim-lsp** — a pure VimScript LSP client with no
Node.js dependency. It works on any machine, including servers accessed via SSH.
Install a language server for the current file:
```vim
:LspInstallServer " auto-detects filetype and installs the correct server
:LspStatus " check server status
```
Supported languages and their servers:
| Language | Server |
|----------|--------|
| Python | pylsp |
| JavaScript / TypeScript | typescript-language-server |
| Go | gopls |
| Rust | rust-analyzer |
| C / C++ | clangd |
| Shell | bash-language-server |
| HTML | vscode-html-language-server |
| CSS / SCSS | vscode-css-language-server |
| JSON | vscode-json-language-server |
| YAML | yaml-language-server |
| Markdown | marksman |
| SQL | sqls |
**Note:** While vim-lsp itself needs no Node.js, some language servers (TypeScript,
HTML, CSS, JSON, YAML) are npm packages that require Node.js to run. Python (pylsp),
Go (gopls), and Rust (rust-analyzer) language servers do not need Node.js.
**Markdown LSP** requires `marksman` as a standalone binary:
### Non-interactive / CI
```bash
brew install marksman # macOS
sudo pacman -S marksman # Arch
# or: install.sh handles it automatically
curl -fsSL ... | bash -s -- --yes
```
**Supported:** macOS (Homebrew), Debian/Ubuntu (apt), Arch (pacman), Fedora (dnf).
The installer detects your environment, installs vim-plug, plugins, and offers
system tools (ripgrep, fzf, ctags, shellcheck, marksman) plus language-specific
formatters and linters.
---
## Key Mappings
**Leader key:** `,` (comma)
**Leader key:** `,` (comma). Press `,?` to open the built-in cheat sheet.
Press `,?` at any time to open the built-in cheat sheet.
### Files and Buffers
### Files and Search
| Key | Action |
|-----|--------|
| `Ctrl+p` | Fuzzy file search — git-aware (FZF) |
| `,e` | Open netrw file browser |
| `,E` | Open netrw in vertical split |
| `,b` | Search open buffers (FZF) |
| `,rg` | Project-wide search (ripgrep + FZF) |
| `,rG` | Ripgrep word under cursor (fixed-string) |
| `Ctrl+p` | Fuzzy file search — git-aware |
| `,b` | Search open buffers |
| `,rg` | Project-wide ripgrep search |
| `,rG` | Ripgrep word under cursor |
| `,fh` | Recent files history |
| `,fl` / `,fL` | Search lines in buffer / all buffers |
| `,fc` | Commands | `,fm` Marks |
| `,f/` / `,f:` | Search / command history |
| `,e` / `,E` | File browser / vertical split |
| `,,` | Switch to last file |
| `,l` / `,h` | Next / previous buffer |
| `,bd` | Close current buffer (preserves window layout) |
| `,wa` | Save all open buffers |
| `,cd` | Change working directory to current file's directory |
| `,cd` | Change CWD to current file's directory |
### Code Intelligence (vim-lsp)
| Key | Action |
|-----|--------|
| `gd` | Go to definition |
| `gy` | Go to type definition |
| `gi` | Go to implementation |
| `gr` | Show references |
| `gy` | Type definition |
| `gi` | Implementation |
| `gr` | References |
| `K` | Hover documentation |
| `[g` / `]g` | Previous / next LSP diagnostic |
| `[e` / `]e` | Previous / next ALE error |
@ -176,104 +101,91 @@ Press `,?` at any time to open the built-in cheat sheet.
| `,ca` | Code action |
| `,o` | File outline (symbols) |
| `,ws` | Workspace symbols |
| `Tab` / `Shift+Tab` | Navigate completion popup |
| `Enter` | Confirm completion |
| `,cr` | **Run current file** (auto-detects language) |
### Markdown
Install LSP servers on demand:
```vim
:LspInstallServer " auto-detects filetype
:LspStatus " check server status
```
| Language | Server |
|----------|--------|
| Python | pylsp |
| JS / TS | typescript-language-server |
| Go | gopls |
| Rust | rust-analyzer |
| C / C++ | clangd |
| Shell | bash-language-server |
| HTML / CSS / JSON / YAML | vscode-*-language-server |
| Markdown | marksman |
| SQL | sqls |
### Markdown and Writing
| Key | Action |
|-----|--------|
| `,mp` | Open live preview in browser (previm) |
| `,mt` | Table of contents (side window) |
| `,zen` | **Zen mode** — Goyo + Limelight, distraction-free |
| `,mp` | Live browser preview (previm) |
| `,mt` | Table of contents |
| `zr` / `zm` | Unfold / fold all headings |
### Git (vim-fugitive)
Markdown buffers automatically enable `wrap`, `spell`, and concealment
(bold renders as bold, headings hide `#` markers, raw syntax shows on cursor line).
### Git
| Key | Action |
|-----|--------|
| `,gs` | Git status |
| `,gc` | Git commit |
| `,gp` | Git push |
| `,gl` | Git pull |
| `,gd` | Git diff |
| `,gb` | Git blame |
| `,gs` | Status |
| `,gd` | Diff |
| `,gb` | Blame |
| `,gc` | Commit |
| `,gp` | Push |
| `,gl` | Pull |
| `[x` / `]x` | Navigate conflict markers |
### Editing
| Key | Action |
|-----|--------|
| `s` + 2 chars | EasyMotion — jump anywhere on screen |
| `gc` | Toggle comment (visual mode too) |
| `Space` | Toggle code fold |
| `gc` | Toggle comment (works in visual mode) |
| `Y` | Yank to end of line |
| `Ctrl+d` / `Ctrl+u` | Half-page scroll, cursor centred |
| `Alt+j` / `Alt+k` | Move line down / up (normal and visual) |
| `,y` / `,Y` | Yank to system clipboard |
| `Alt+j` / `Alt+k` | Move line down / up |
| `,u` | Undo tree (visual branch history) |
| `F2` | Toggle paste mode |
| `F3` / `F4` | Toggle line numbers / relative numbers |
| `F5` | Toggle undo tree |
| `F6` | Toggle invisible characters |
| `,F` | Re-indent entire file |
| `,W` | Strip trailing whitespace |
| `,*` | Search and replace word under cursor |
| `gV` | Reselect last paste |
| `//` | Search visual selection |
### Survival
| Key | Action |
|-----|--------|
| `jk` | Exit insert mode |
| `Esc` | Exit insert / visual mode |
| `jk` | Exit insert mode |
| `Ctrl+s` | Save (any mode) |
| `,w` | Save |
| `,x` | Save and quit |
| `,q` | Quit |
| `,?` | Open cheat sheet |
### Windows, Tabs, tmux
### Windows and Navigation
| Key | Action |
|-----|--------|
| `Ctrl+h/j/k/l` | Navigate Vim splits **and** tmux panes |
| `,tv` / `,th` | Open terminal (vertical / horizontal split) |
| `,z` | **Maximize / restore** current window |
| `,h` / `,l` | Previous / next buffer |
| `,bd` | Close buffer (keep window layout) |
| `,tv` / `,th` | Terminal (vertical / horizontal) |
| `Esc Esc` | Exit terminal mode |
| `,tn` / `,tc` | New tab / close tab |
| `,tl` | Toggle to last tab |
| `]q` / `[q` | Next / previous quickfix entry |
| `Ctrl+d` / `Ctrl+u` | Half-page scroll, cursor centred |
### Quick Reference
| Key | Action |
|-----|--------|
| `,?` | Open built-in cheat sheet |
| `jk` | Exit insert mode |
| `Ctrl+s` | Save (any mode) |
| `:w!!` | Sudo save |
| `,w` / `,x` / `,q` | Save / save+quit / quit |
| `,ev` / `,sv` | Edit / reload `~/.vimrc` |
| `,cp` / `,cf` | Copy file path / filename to clipboard |
| `,*` | Search and replace word under cursor |
| `,F` | Re-indent entire file |
| `,W` | Strip trailing whitespace |
| `,ms` | Open scratch markdown buffer |
| `,ss` | Toggle spell checking |
---
## Markdown
chopsticks treats Markdown as a first-class language.
### In-buffer rendering (concealment)
`vim-markdown` hides syntax markers and renders formatting inline:
- `**bold**` displays as bold text
- `# Heading` hides the `#` characters
- Tables align automatically
The raw syntax reappears when the cursor enters that line.
### Live browser preview (previm)
```vim
,mp " open rendered preview in browser — updates on every save
```
No Node.js required. Uses `open` (macOS) or `xdg-open` (Linux).
### Table of contents
```vim
,mt " open TOC in a side window — press Enter to jump to heading
```
| `,so` | Source current vim file |
| `F2` Paste | `F3` Line# | `F4` Relative# | `F6` Invisible chars |
---
@ -281,15 +193,24 @@ No Node.js required. Uses `open` (macOS) or `xdg-open` (Linux).
### Statusline
A native, hand-written statusline using the Solarized palette:
Native, hand-written. Solarized palette. Shows mode, file, git branch, filetype,
ALE error/warning count, and cursor position. Background matches tmux bar.
```
N ~/.vimrc [+] main [vim] 42:7 68%
N ~/.vimrc [+] E:1 W:3 main [vim] 42:7 68%
```
- Mode block changes colour by mode (Normal=yellow, Insert=blue, Visual=magenta, Replace=red)
- Git branch via vim-fugitive
- Background matches tmux status bar for a seamless bottom band
Mode block changes colour: Normal=yellow, Insert=blue, Visual=magenta, Replace=red.
### Smart Defaults
- **vim-sleuth** auto-detects indentation from existing files
- **Yank highlight** flashes copied text for 150ms
- **Search highlight** auto-clears after cursor stops moving
- **QuickFix** auto-opens after `:grep`, `:make`, or `:Rg`
- **Format on save** via ALE (black, prettier, gofmt, rustfmt, etc.)
- **Auto-create directories** on save — write to `new/path/file.txt` without `mkdir` first
- **Cursor restore** — reopens files at the last cursor position
### Session Management
@ -300,9 +221,20 @@ A native, hand-written statusline using the Solarized palette:
Sessions auto-restore when you open Vim in the same directory.
### Project-Local Config
### TTY / SSH Support
Drop a `.vimrc` in any project root to override settings:
Detected automatically. In TTY mode:
- True colour and cursorline disabled
- FZF preview windows disabled
- IndentLine guides disabled
- Simplified statusline
- Syntax column limit reduced
### Large File Handling
Files over 10 MB: syntax highlighting, undo history, and linting automatically disabled.
### Project-Local Config
```vim
" my-project/.vimrc
@ -310,143 +242,44 @@ set shiftwidth=2
let g:ale_python_black_options = '--line-length=100'
```
### tmux Integration
`Ctrl+h/j/k/l` navigates seamlessly between Vim splits and tmux panes.
Add to `~/.tmux.conf` (or let `install.sh` append it):
```tmux
is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\S+\/)?g?(view|n?vim?x?)(diff)?$'"
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L'
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D'
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U'
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R'
```
### TTY / SSH Support
Detected automatically when `$TERM` is unset, `dumb`, `linux`, `screen`, or contains `builtin`. In TTY mode:
- True colour and cursorline disabled
- FZF preview windows disabled
- IndentLine guides disabled
- Simplified statusline (no colour)
- Syntax column limit reduced to 120 characters
### Large File Handling
Files over 10 MB automatically disable syntax highlighting, undo history, and
linting to prevent stalling.
---
## Plugins
## Plugins (30)
### Navigation
- **fzf + fzf.vim** — fuzzy finder for files, buffers, tags, ripgrep
### Git
- **vim-fugitive** — full Git integration
- **vim-gitgutter** — diff signs in the sign column
### LSP and Completion
- **vim-lsp** — pure VimScript LSP client
- **vim-lsp-settings** — auto-configures language servers
- **asyncomplete.vim** — async completion engine
- **asyncomplete-lsp.vim** — LSP completion source
### Linting and Formatting
- **ALE** — async linting and format-on-save
### Markdown
- **vim-markdown** — folding, concealment, table alignment
- **previm** — live browser preview
### Language Syntax
- **vim-javascript** — enhanced JS syntax
- **yats.vim** — TypeScript syntax
- **vim-go** — Go syntax and tooling
### Editing
- **vim-surround** — change/delete/add surroundings
- **vim-commentary**`gc` to toggle comments
- **vim-repeat** — repeat plugin maps with `.`
- **vim-unimpaired** — bracket shortcut pairs
- **targets.vim** — additional text objects
- **auto-pairs** — auto-close brackets and quotes
- **vim-easymotion**`s` + 2 chars to jump anywhere
### UI
- **vim-solarized8** — color scheme (truecolor support)
- **undotree** — visual undo branch history
- **vim-startify** — startup dashboard and session list
- **indentLine** — indent guides (non-TTY)
### Session and Navigation
- **vim-obsession** — session tracking
- **vim-tmux-navigator** — seamless Vim/tmux pane navigation
| Category | Plugins |
|----------|---------|
| **Navigation** | fzf, fzf.vim |
| **Git** | vim-fugitive, vim-gitgutter |
| **LSP** | vim-lsp, vim-lsp-settings, asyncomplete.vim, asyncomplete-lsp.vim |
| **Lint/Format** | ALE |
| **Editing** | vim-surround, vim-commentary, vim-repeat, vim-unimpaired, vim-sleuth, targets.vim, auto-pairs, vim-easymotion |
| **Language** | vim-javascript, yats.vim, vim-markdown, vim-go |
| **Writing** | previm, goyo.vim, limelight.vim |
| **UI** | vim-solarized8, undotree, vim-startify, indentLine |
| **Session** | vim-obsession, vim-tmux-navigator |
---
## Customization
### Per-project overrides
Create `.vimrc` in your project root:
```vim
" project/.vimrc
set shiftwidth=2
let g:ale_python_black_options = '--line-length=120'
```
### Modify keybindings
Edit `~/.vimrc` directly (`,ev` opens it from inside Vim). Reload with `,sv`.
Edit `~/.vimrc` directly (`,ev` opens it, `,sv` reloads). Per-project overrides
go in a `.vimrc` at your project root.
---
## Troubleshooting
**Plugins not loading**
```vim
:PlugInstall " install missing plugins
:PlugUpdate " update all plugins
```
**LSP server not starting**
```vim
:LspInstallServer " install server for current filetype
:LspStatus " check server status
```
**Markdown preview not opening**
`previm` uses `open` (macOS) or `xdg-open` (Linux). Make sure a browser is
set as the default handler for HTML files.
**Colors look wrong**
```bash
export TERM=xterm-256color # add to ~/.bashrc or ~/.zshrc
export COLORTERM=truecolor # for true colour
```
**ALE linters not found**
```bash
which flake8 black prettier eslint # verify tools are on PATH
```
**`Ctrl+s` freezes the terminal**
Add `stty -ixon` to your `~/.bashrc`, `~/.zshrc`, or `~/.config/fish/config.fish`.
| Problem | Solution |
|---------|----------|
| Plugins not loading | `:PlugInstall` then `:PlugUpdate` |
| LSP not starting | `:LspInstallServer` for current filetype |
| Colors look wrong | `export COLORTERM=truecolor` in your shell rc |
| ALE linters missing | `which flake8 black prettier eslint` to verify PATH |
| `Ctrl+s` freezes terminal | Add `stty -ixon` to `~/.bashrc` or `~/.zshrc` |
| Markdown preview broken | Ensure `open` (macOS) or `xdg-open` (Linux) works |
---
## License
[MIT](LICENSE) © m1ng
[MIT](LICENSE)