fix: correct non-TTY vim-plug install; add real plugin count check

- _vim_run non-TTY branch: remove </dev/null (caused "Error reading
  input, exiting" before downloads finished → 0 plugins installed) and
  >/dev/null (broke async job callbacks → partial install of ~13/26).
  Now only redirects stderr; stdin inherits from caller so vim's event
  loop runs to completion.
- Add post-install verification: count ~/.vim/plugged entries and die
  if empty, replacing the unconditional "ok Plugins installed" that
  masked failures silently.
- .vimrc, install.sh, QUICKSTART.md, README.md: carry forward the full
  v1.2 rewrite (checkbox module selection, solarized palette, LSP
  stack) that accumulated in the previous session.

Tested: macOS (27 plugins, exit 0) and Arch Linux SSH (26 plugins,
exit 0). shellcheck: zero warnings.
This commit is contained in:
m1ngsama 2026-04-10 18:43:52 +08:00
parent 716e7e5808
commit 0b3f631e98
4 changed files with 1363 additions and 1887 deletions

1591
.vimrc

File diff suppressed because it is too large Load diff

View file

@ -1,63 +1,47 @@
# Quick Start # Quick Start
Five minutes from zero to a working Vim engineering environment. Five minutes from zero to a working Vim environment.
> **New to Vim?** Read Step 0 first — it takes 2 minutes and prevents the most
> common beginner frustration. Already know how Vim modes work? [Skip to Step 1](#step-1-install).
--- ---
## Step 0: Vim Basics ## Step 0: Vim Basics (2 minutes)
> **When confused, press `Esc` until things feel normal again — then keep reading.** > **When confused, press `Esc` until things feel normal again.**
Vim is **modal**: the keyboard behaves differently depending on which mode you are in. Vim is **modal** — the keyboard behaves differently depending on which mode you are in.
Most people get stuck because they try to type text while in Normal mode.
### The Three Modes | Mode | Purpose | Enter | Leave |
|------|---------|-------|-------|
| **Normal** | Navigate and run commands | default on startup | — |
| **Insert** | Type text | `i` before / `a` after / `o` new line | `Esc` or `jk` |
| **Visual** | Select text | `v` char / `V` line | `Esc` |
| Mode | Purpose | How to enter | How to leave | ### 4 commands that get you out of any jam
|------|---------|--------------|--------------|
| **Normal** | Navigate and run commands | Startup default | — (you're already here) |
| **Insert** | Type text | `i` before cursor, `a` after, `o` new line below | `Esc` or `jk` |
| **Visual** | Select text | `v` char-by-char, `V` whole lines | `Esc` |
### 4 Survival Commands
Learn these before anything else. They will get you out of every stuck situation.
| Command | Action | | Command | Action |
|---------|--------| |---------|--------|
| `Esc` or `jk` | Exit insert/visual mode — return to Normal | | `Esc` or `jk` | Exit insert / visual mode → Normal |
| `:q!` then `Enter` | Force quit without saving (emergency exit) | | `:q!` then `Enter` | Force quit without saving |
| `,x` | Save and quit | | `,x` | Save and quit |
| `,w` or `Ctrl+s` | Save the file | | `,w` or `Ctrl+s` | Save |
Once in Normal mode, press `,?` to open a cheat sheet covering everything else. Once in Normal mode, press `,?` to open the cheat sheet.
--- ---
## Step 1: Install ## Step 1: Install
**One command — works on macOS and Linux:**
```bash ```bash
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
``` ```
This clones the repo to `~/.vim` and runs the full installer. Interactive prompts Traditional:
let you choose which optional tools to install (ripgrep, Node.js, Python tools, etc.).
The installer automatically handles missing dependencies — it will offer to install
`git`, Homebrew (macOS), or Node.js via nvm if they are not found.
**Traditional install:**
```bash ```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
cd ~/.vim && ./install.sh cd ~/.vim && ./install.sh
``` ```
**Non-interactive (CI / server / scripting):** Non-interactive / CI:
```bash ```bash
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --yes curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --yes
``` ```
@ -67,37 +51,14 @@ curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | b
## Step 2: Open Vim ## Step 2: Open Vim
```bash ```bash
vim vim # startup dashboard (recent files + sessions)
``` vim . # startup dashboard, current directory listed
vim myfile # edit a specific file
The startup screen (vim-startify) shows recent files and sessions.
Press `Ctrl+p` to find a file, or just type a path.
To open a project:
```bash
vim . # NERDTree on left, Startify on right
vim myfile # opens file directly
``` ```
--- ---
## Step 3: Set Up LSP (pick your path) ## Step 3: Set Up LSP
### Path A: With Node.js (CoC — full LSP)
```bash
node --version # must be >= 14.14
```
Inside Vim, install language servers for your stack:
```vim
:CocInstall coc-pyright coc-tsserver coc-go coc-rust-analyzer
```
Or let `install.sh` do it — it asks during setup.
### Path B: Without Node.js (vim-lsp — no dependencies)
Open a source file, then run: Open a source file, then run:
@ -105,26 +66,39 @@ Open a source file, then run:
:LspInstallServer :LspInstallServer
``` ```
This auto-detects and installs the correct language server for the current filetype. This auto-detects the filetype and installs the correct language server.
No Node.js required — vim-lsp runs on pure VimScript.
Check status:
```vim
:LspStatus
```
**Markdown LSP** (`marksman`) needs a standalone binary:
```bash
brew install marksman # macOS
sudo pacman -S marksman # Arch
# install.sh handles this automatically
```
--- ---
## The 12 Keys That Matter ## The Keys That Matter
``` ```
, (pause 500ms) Show all keybindings (which-key) ,? Open cheat sheet (all bindings in one place)
,? Open cheat sheet inside Vim Esc / jk Exit insert mode → Normal
Esc / jk Exit insert mode → Normal (memorize this) Ctrl+s Save
Ctrl+s Save (works in normal and insert mode) Ctrl+p Fuzzy find file
Ctrl+p Fuzzy find file ,e File browser (netrw)
Ctrl+n Toggle file tree gd Go to definition
gd Go to definition K Show documentation
K Show documentation [g / ]g Prev / next LSP diagnostic
[g / ]g Prev / next LSP diagnostic ,rn Rename symbol
,rn Rename symbol ,rG Search word under cursor (ripgrep)
,rG Search word under cursor (ripgrep) ,gs Git status
,gs Git status ,mp Markdown live preview in browser
,w / ,x Save / Save+quit ,w / ,x Save / Save+quit
``` ```
--- ---
@ -138,8 +112,8 @@ K Show documentation
| `gd` | Go to definition | | `gd` | Go to definition |
| `gy` | Go to type definition | | `gy` | Go to type definition |
| `gi` | Go to implementation | | `gi` | Go to implementation |
| `gr` | List all references | | `gr` | List references |
| `K` | Show docs for symbol under cursor | | `K` | Docs for symbol under cursor |
| `Ctrl+o` | Jump back | | `Ctrl+o` | Jump back |
| `Ctrl+i` | Jump forward | | `Ctrl+i` | Jump forward |
@ -152,23 +126,35 @@ K Show documentation
| `gc` | Toggle comment (visual mode too) | | `gc` | Toggle comment (visual mode too) |
| `cs"'` | Change surrounding `"` to `'` | | `cs"'` | Change surrounding `"` to `'` |
| `ds(` | Delete surrounding `(` | | `ds(` | Delete surrounding `(` |
| `s`+2ch | EasyMotion: jump anywhere | | `s` + 2 chars | EasyMotion: jump anywhere |
### Manage Errors ### Manage Errors
| Key | Action | | Key | Action |
|-----|--------| |-----|--------|
| `]g` | Jump to next diagnostic | | `]g` | Jump to next LSP diagnostic |
| `[g` | Jump to previous diagnostic | | `[g` | Jump to previous diagnostic |
| `K` | Read the error message | | `K` | Read the error message |
| `,ca` | Apply code action / auto-fix | | `,ca` | Apply code action / auto-fix |
### Markdown
| Key | Action |
|-----|--------|
| `,mp` | Open live preview in browser |
| `,mt` | Table of contents |
| `zr` / `zm` | Unfold / fold all headings |
Formatting in the buffer is live: `**bold**` renders as bold,
headings hide their `#` markers. Raw syntax reappears when
the cursor enters that line.
### Git Workflow ### Git Workflow
``` ```
,gs git status (stage with 's', commit with 'cc') ,gs git status (stage with 's', commit with 'cc')
,gd diff current file ,gd diff current file
,gb blame current file ,gb blame
,gc commit ,gc commit
,gp push ,gp push
,gl pull ,gl pull
@ -176,97 +162,36 @@ K Show documentation
--- ---
## Language Workflows
### Python
```bash
# tools installed by install.sh; or manually:
pip install black flake8 pylint isort
```
Auto-formats with `black` + `isort` on save. Lint errors show as `X`/`!` in the sign column.
### JavaScript / TypeScript
```bash
npm install -g prettier eslint typescript
```
Auto-formats with `prettier` on save.
### Go
```bash
# tools installed by install.sh; or manually:
go install golang.org/x/tools/gopls@latest
go install golang.org/x/tools/cmd/goimports@latest
go install honnef.co/go/tools/cmd/staticcheck@latest
```
`gofmt` + `goimports` run on save automatically.
### Markdown
Install `marksman` for LSP support (completions, link checking):
```bash
brew install marksman # macOS
sudo pacman -S marksman # Arch
# or: ./install.sh (handles it automatically)
```
---
## Customize
Edit config live:
```vim
,ev " opens ~/.vimrc in Vim
,sv " reloads config without restarting
```
Per-project settings: create `.vimrc` in your project root.
```vim
" project/.vimrc
set shiftwidth=2
let g:ale_python_black_options = '--line-length=100'
```
Change color scheme in `~/.vimrc`:
```vim
colorscheme dracula " or: gruvbox, solarized, onedark
```
---
## Quick Reference Card ## Quick Reference Card
``` ```
BASICS (learn these first) BASICS
Esc / jk Exit insert mode → Normal Esc / jk Exit insert mode → Normal
Ctrl+s Save (normal + insert mode) Ctrl+s Save
:q! + Enter Emergency quit without saving :q! + Enter Emergency quit
,? Open cheat sheet ,? Open cheat sheet
FILES FILES
Ctrl+n File tree toggle
Ctrl+p Fuzzy find file (git-aware) Ctrl+p Fuzzy find file (git-aware)
,e File browser (netrw)
,b Search open buffers ,b Search open buffers
,rg Search file contents (ripgrep) ,rg Search file contents (ripgrep)
,rG Ripgrep word under cursor ,rG Ripgrep word under cursor
,w Save | ,q Quit | ,x Save+quit ,w Save | ,q Quit | ,x Save+quit
,wa Save all buffers ,wa Save all buffers
,, Switch to last file ,, Switch to last file
CODE CODE
gd Go to definition gd Definition | gy Type def | gi Impl | gr References
K Show documentation K Show documentation
[g / ]g Prev/next LSP diagnostic [g / ]g Prev / next LSP diagnostic
[e / ]e Prev/next ALE error [e / ]e Prev / next ALE error
,rn Rename symbol ,rn Rename symbol
,ca Code action / auto-fix ,ca Code action
,f Format selection | ,F Format whole file ,f Format buffer / selection
MARKDOWN
,mp Live preview | ,mt Table of contents
GIT GIT
,gs Status | ,gd Diff | ,gb Blame ,gs Status | ,gd Diff | ,gb Blame
@ -275,19 +200,14 @@ GIT
WINDOWS / PANES WINDOWS / PANES
Ctrl+h/j/k/l Move between Vim windows or tmux panes Ctrl+h/j/k/l Move between Vim windows or tmux panes
,h / ,l Prev / next buffer ,h / ,l Prev / next buffer
,tv Open terminal (vertical) ,tv / ,th Terminal (vertical / horizontal)
,th Open terminal (horizontal) Esc Esc Exit terminal mode
Esc Exit terminal mode ,u Undo tree
,u Undo tree | ,tt Tag browser
SEARCH & REPLACE SEARCH
/text Search forward | ?text backward /text Forward | ?text Backward | n next | N prev
// Search for visually selected text // Search visually selected text
,* Replace word under cursor (file-wide) ,* Replace word under cursor (file-wide)
CLIPBOARD
,y / ,Y Yank / yank line to system clipboard
,p / ,P Paste from system clipboard (after / before)
``` ```
--- ---

566
README.md
View file

@ -1,7 +1,7 @@
# chopsticks # chopsticks
> A batteries-included Vim configuration for full-stack engineering. > Flowing vim for any machine — SSH servers included.
> Tiered LSP · 14 languages · TTY-aware · Zero icon fonts · One-command install. > 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) [![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/) [![Vim 8.0+](https://img.shields.io/badge/Vim-8.0%2B-brightgreen?style=flat-square)](https://www.vim.org/)
@ -9,18 +9,11 @@
[![Release](https://img.shields.io/github/v/release/m1ngsama/chopsticks?style=flat-square&label=release&color=orange)](https://github.com/m1ngsama/chopsticks/releases) [![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) [![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) [![Stars](https://img.shields.io/github/stars/m1ngsama/chopsticks?style=flat-square)](https://github.com/m1ngsama/chopsticks/stargazers)
[![Issues](https://img.shields.io/github/issues/m1ngsama/chopsticks?style=flat-square)](https://github.com/m1ngsama/chopsticks/issues)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen?style=flat-square)](https://github.com/m1ngsama/chopsticks/pulls)
[![Plugins](https://img.shields.io/badge/plugins-30%2B-blueviolet?style=flat-square)](#plugins)
[![Languages](https://img.shields.io/badge/languages-14-informational?style=flat-square)](#language-support)
```bash ```bash
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
``` ```
> **New to Vim?** Read [Step 0 in QUICKSTART.md](QUICKSTART.md#step-0-vim-basics) first —
> a 2-minute intro to modes and the 4 commands that get you out of any jam.
--- ---
## Contents ## Contents
@ -28,14 +21,13 @@ curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | b
- [Design Principles](#design-principles) - [Design Principles](#design-principles)
- [Requirements](#requirements) - [Requirements](#requirements)
- [Installation](#installation) - [Installation](#installation)
- [LSP: Tiered Backend](#lsp-tiered-backend) - [LSP](#lsp)
- [Key Mappings](#key-mappings) - [Key Mappings](#key-mappings)
- [Markdown](#markdown)
- [Features](#features) - [Features](#features)
- [Language Support](#language-support)
- [Plugins](#plugins) - [Plugins](#plugins)
- [Customization](#customization) - [Customization](#customization)
- [Troubleshooting](#troubleshooting) - [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
--- ---
@ -43,51 +35,44 @@ curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | b
| Principle | What it means | | Principle | What it means |
|-----------|--------------| |-----------|--------------|
| **KISS** | No icon fonts, no Nerd Font glyphs — plain ASCII everywhere | | **Flowing writing** | Every plugin earns its place by reducing interruptions to thought |
| **Tiered LSP** | CoC (full) when Node.js is available; vim-lsp (pure VimScript) otherwise | | **No Node.js** | vim-lsp runs on pure VimScript — works on any machine, including SSH servers |
| **TTY-aware** | Automatically detects SSH/console environments and degrades gracefully | | **Solarized** | One palette, everywhere — vim statusline matches tmux bar exactly |
| **Engineering-first** | Git workflow, persistent sessions, project-local config, large-file safety | | **TTY-aware** | SSH and console environments degrade gracefully without breaking |
| **Batteries included** | `install.sh` handles vim-plug, plugins, system tools, and language servers | | **KISS** | No icon fonts, no Nerd Font glyphs — plain ASCII throughout |
--- ---
## Requirements ## Requirements
| Tool | Minimum | Role | | Tool | Role |
|------|---------|------| |------|------|
| Vim | **8.0+** | Required — `install.sh` installs it if missing | | Vim 8.0+ | Required — `install.sh` installs it if missing |
| git | any | Required — `install.sh` installs it if missing | | git | Required |
| curl | any | Required — `install.sh` installs it if missing | | curl | Required |
| Node.js | 14.14+ | Optional — enables CoC LSP; `install.sh` offers nvm install | | ripgrep | Recommended — enables `,rg` project search |
| ripgrep | any | Optional — enables `,rg` / `,rG` project search | | fzf | Recommended — enables `Ctrl+p` fuzzy finder |
| fzf | any | Optional — enables `Ctrl+p` fuzzy finder | | Node.js | Optional — enables npm formatters (prettier, eslint) |
| ctags | any | Optional — enables `,tt` tag browser |
| tmux | 1.8+ | Optional — enables seamless pane navigation |
`install.sh` detects your environment and installs missing dependencies automatically. `install.sh` detects your environment and installs missing dependencies.
On macOS it will offer to install Homebrew if not present. On any platform it will
offer to install Node.js via nvm if missing.
--- ---
## Installation ## Installation
### One command (recommended) ### One command
```bash ```bash
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
``` ```
This bootstrap script clones the repo to `~/.vim`, then runs the full installer. Non-interactive / CI:
It works correctly even when piped from curl — interactive prompts use `/dev/tty`.
For non-interactive or CI environments:
```bash ```bash
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --yes curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --yes
``` ```
### Traditional (git clone) ### Git clone
```bash ```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
@ -96,77 +81,57 @@ cd ~/.vim && ./install.sh
### What the installer does ### What the installer does
1. **Preflight** — checks network, detects OS and package manager, verifies or installs `curl`, `git`, and `vim` 1. Detects OS and package manager
2. **sudo** — authenticates once upfront; gracefully skips system packages when unavailable 2. Verifies or installs `curl`, `git`, `vim`
3. **macOS** — offers to install Homebrew if `brew` is not found 3. Backs up existing `~/.vimrc`, then symlinks `~/.vimrc → ~/.vim/.vimrc`
4. **Node.js** — offers to install via nvm if not found (falls back to vim-lsp if declined) 4. Installs vim-plug and runs `:PlugInstall`
5. **Python** — offers to install Python 3 if missing; bootstraps pip3 if only python3 is present 5. Offers to install system tools (ripgrep, fzf, ctags, shellcheck, hadolint, marksman)
6. **Symlinks** — backs up any existing `~/.vimrc` with a timestamp, then symlinks `~/.vimrc → ~/.vim/.vimrc` 6. Offers to install Node.js via nvm (for npm formatters — optional)
7. **Plugins** — installs vim-plug and runs `:PlugInstall` (with a progress notice during the black-screen period) 7. Offers to install npm formatters (prettier, eslint, etc.)
8. **System tools** — ripgrep, fzf, ctags, shellcheck, hadolint, marksman (verified downloads) 8. Offers to install Python formatters/linters (black, isort, flake8, etc.)
9. **Language tools** — npm formatters, pip formatters/linters, Go tools 9. Offers to install Go tools (gopls, goimports, staticcheck)
10. **CoC extensions** — all language servers in one step 10. Offers to append vim-tmux-navigator bindings to `~/.tmux.conf`
11. **tmux** — optionally appends vim-tmux-navigator bindings to `~/.tmux.conf`
**Supported platforms:** macOS (Homebrew), Debian/Ubuntu (apt), Arch Linux (pacman), Fedora (dnf). **Supported platforms:** macOS (Homebrew), Debian/Ubuntu (apt), Arch (pacman), Fedora (dnf).
### Manual
```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
ln -sf ~/.vim/.vimrc ~/.vimrc
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
vim +PlugInstall +qall </dev/null
```
--- ---
## LSP: Tiered Backend ## LSP
Code intelligence is provided by one of two backends, chosen automatically at startup: 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.
| Condition | Backend | Capabilities | Install a language server for the current file:
|-----------|---------|-------------|
| Vim 8.0.1453+ **and** Node.js 14.14+ | **CoC** | Full LSP, snippets, extension ecosystem |
| Vim 8.0+ (no Node.js) | **vim-lsp** | LSP via language server binaries, asyncomplete |
| Any Vim | **ALE** | Async linting + auto-fix (always active, both backends) |
Both CoC and vim-lsp expose the same key mappings so switching backends is transparent.
### With Node.js (CoC)
Install language server extensions from inside Vim — or let `install.sh` do it automatically:
```vim ```vim
:CocInstall coc-pyright " Python :LspInstallServer " auto-detects filetype and installs the correct server
:CocInstall coc-tsserver " JavaScript / TypeScript
:CocInstall coc-go " Go
:CocInstall coc-rust-analyzer " Rust
:CocInstall coc-json coc-yaml " JSON, YAML
:CocInstall coc-html coc-css " HTML, CSS/SCSS
:CocInstall coc-sh " Shell
:CocInstall coc-sql " SQL
```
**Markdown LSP** uses `marksman` as an external binary (not a CoC extension):
```bash
brew install marksman # macOS
sudo pacman -S marksman # Arch
# or: ./install.sh handles it automatically
```
### Without Node.js (vim-lsp)
Open a source file, then run:
```vim
:LspInstallServer " detects filetype and installs the correct server
:LspStatus " check server status :LspStatus " check server status
``` ```
Supported: Python, Go, Rust, TypeScript/JavaScript, Shell, HTML, CSS/SCSS, JSON, YAML, Markdown, SQL. Supported languages and their servers:
| Language | Server |
|----------|--------|
| Python | pylsp / pyright |
| 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 |
**Markdown LSP** requires `marksman` as a standalone binary:
```bash
brew install marksman # macOS
sudo pacman -S marksman # Arch
# or: install.sh handles it automatically
```
--- ---
@ -174,172 +139,138 @@ Supported: Python, Go, Rust, TypeScript/JavaScript, Shell, HTML, CSS/SCSS, JSON,
**Leader key:** `,` (comma) **Leader key:** `,` (comma)
Press `,` and wait 500 ms to see an interactive guide to all bindings (vim-which-key). Press `,?` at any time to open the built-in cheat sheet.
Press `,?` to open the built-in cheat sheet at any time.
### Survival
| Key | Action |
|-----|--------|
| `jk` | Exit insert mode → Normal (ergonomic Escape) |
| `Esc` | Exit insert / visual mode (standard) |
| `Ctrl+s` | Save file (normal and insert mode) |
| `,w` | Save file |
| `,x` | Save and quit |
| `,q` | Quit |
| `,?` | Open cheat sheet |
> **`Ctrl+s` note:** some terminals freeze on `Ctrl+s` (XON/XOFF). Add `stty -ixon`
> to your `~/.bashrc` / `~/.zshrc` to disable this permanently.
### Files and Buffers ### Files and Buffers
| Key | Action | | Key | Action |
|-----|--------| |-----|--------|
| `Ctrl+p` | Fuzzy file search — git-aware (FZF) | | `Ctrl+p` | Fuzzy file search — git-aware (FZF) |
| `Ctrl+n` | Toggle file tree (NERDTree) | | `,e` | Open netrw file browser |
| `,n` | Reveal current file in NERDTree | | `,E` | Open netrw in vertical split |
| `,b` | Search open buffers (FZF) | | `,b` | Search open buffers (FZF) |
| `,rg` | Project-wide search (ripgrep + FZF) | | `,rg` | Project-wide search (ripgrep + FZF) |
| `,rG` | Ripgrep for word under cursor (literal match) | | `,rG` | Ripgrep for word under cursor |
| `,rt` | Search tags (FZF) |
| `,gF` | Search git-tracked files (FZF) |
| `,l` | Next buffer |
| `,h` | Previous buffer |
| `,bd` | Close current buffer (preserves window layout) |
| `,,` | Switch to last file | | `,,` | Switch to last file |
| `,l` / `,h` | Next / previous buffer |
| `,bd` | Close current buffer (preserves window layout) |
### Windows, Tabs, and tmux ### Code Intelligence (vim-lsp)
| Key | Action |
|-----|--------|
| `Ctrl+h/j/k/l` | Navigate between Vim splits **and** tmux panes |
| `,=` | Increase window height |
| `,-` | Decrease window height |
| `,+` | Increase window width |
| `,_` | Decrease window width |
| `,tn` | New tab |
| `,tc` | Close tab |
| `,tl` | Toggle to last tab |
| `,tv` | Open terminal (vertical split) |
| `,th` | Open terminal (horizontal split) |
| `Esc Esc` | Exit terminal mode |
### Code Intelligence (CoC / vim-lsp)
| Key | Action | | Key | Action |
|-----|--------| |-----|--------|
| `gd` | Go to definition | | `gd` | Go to definition |
| `gy` | Go to type definition | | `gy` | Go to type definition |
| `gi` | Go to implementation | | `gi` | Go to implementation |
| `gr` | Show all references | | `gr` | Show references |
| `K` | Hover documentation | | `K` | Hover documentation |
| `[g` | Previous diagnostic | | `[g` / `]g` | Previous / next LSP diagnostic |
| `]g` | Next diagnostic | | `[e` / `]e` | Previous / next ALE error |
| `,rn` | Rename symbol | | `,rn` | Rename symbol |
| `,f` | Format selection | | `,f` | Format buffer / selection |
| `,F` | Format whole file | | `,ca` | Code action |
| `,ca` | Code action (cursor position) |
| `,o` | File outline (symbols) | | `,o` | File outline (symbols) |
| `,ws` | Workspace symbols | | `,ws` | Workspace symbols |
| `,cD` | Diagnostics list | | `Tab` / `Shift+Tab` | Navigate completion popup |
| `,qf` | Quick-fix current line (CoC) |
| `Tab` | Next completion item |
| `Shift+Tab` | Previous completion item |
| `Enter` | Confirm completion | | `Enter` | Confirm completion |
Text objects (CoC): `if`/`af` (function inner/around), `ic`/`ac` (class inner/around). ### Markdown
### Linting (ALE — always active)
| Key | Action | | Key | Action |
|-----|--------| |-----|--------|
| `[e` | Previous error / warning | | `,mp` | Open live preview in browser (previm) |
| `]e` | Next error / warning | | `,mt` | Table of contents |
| `,aD` | Show error detail | | `zr` / `zm` | Unfold / fold all headings |
| `,ad` | Full diagnostics list |
Signs in the gutter: `X` = error, `!` = warning.
### Git (vim-fugitive) ### Git (vim-fugitive)
| Key | Action | | Key | Action |
|-----|--------| |-----|--------|
| `,gs` | Git status (stage with `s`, commit with `cc`) | | `,gs` | Git status |
| `,gc` | Git commit | | `,gc` | Git commit |
| `,gp` | Git push | | `,gp` | Git push |
| `,gl` | Git pull | | `,gl` | Git pull |
| `,gd` | Git diff | | `,gd` | Git diff |
| `,gb` | Git blame | | `,gb` | Git blame |
### Search and Replace ### Editing
| Key | Action |
|-----|--------|
| `n` / `N` | Next / previous match (cursor centered) |
| `//` | Search for visually selected text |
| `,*` | Search and replace word under cursor (file-wide) |
| `,rG` | Ripgrep word under cursor across project |
| `,<CR>` | Clear search highlight |
### Clipboard
| Key | Action |
|-----|--------|
| `,y` | Yank to system clipboard |
| `,Y` | Yank line to system clipboard |
| `,p` | Paste from system clipboard (after cursor) |
| `,P` | Paste from system clipboard (before cursor) |
### Editing and Navigation
| Key | Action | | Key | Action |
|-----|--------| |-----|--------|
| `s` + 2 chars | EasyMotion — jump anywhere on screen | | `s` + 2 chars | EasyMotion — jump anywhere on screen |
| `gc` | Toggle comment (visual mode too) |
| `Space` | Toggle code fold | | `Space` | Toggle code fold |
| `Y` | Yank to end of line (consistent with `D`, `C`) | | `Y` | Yank to end of line |
| `Ctrl+d/u` | Half-page scroll (cursor stays centered) | | `Ctrl+d` / `Ctrl+u` | Half-page scroll, cursor centred |
| `>` / `<` | Indent / dedent (keeps visual selection) | | `Alt+j` / `Alt+k` | Move line down / up |
| `Alt+j/k` | Move current line down / up | | `,u` | Undo tree (visual branch history) |
| `0` | Jump to first non-blank character |
| `[q` / `]q` | Previous / next quickfix entry (vim-unimpaired) |
| `,u` | Toggle undo tree (visual branch history) |
| `,tt` | Toggle tagbar (code structure) |
| `F2` | Toggle paste mode |
| `F3` | Toggle absolute line numbers |
| `F4` | Toggle relative line numbers |
### Config and Utilities ### Survival
| Key | Action | | Key | Action |
|-----|--------| |-----|--------|
| `,ev` | Edit `~/.vimrc` | | `jk` | Exit insert mode |
| `,sv` | Reload `~/.vimrc` | | `Esc` | Exit insert / visual mode |
| `,wa` | Save all open buffers | | `Ctrl+s` | Save |
| `,wd` | Change working directory to current file's location | | `,w` | Save |
| `,cp` | Copy absolute file path to clipboard | | `,x` | Save and quit |
| `,cf` | Copy filename to clipboard | | `,q` | Quit |
| `,qo` / `,qc` | Open / close quickfix list | | `,?` | Open cheat sheet |
### Windows, Tabs, tmux
| Key | Action |
|-----|--------|
| `Ctrl+h/j/k/l` | Navigate Vim splits **and** tmux panes |
| `,tv` / `,th` | Open terminal (vertical / horizontal split) |
| `Esc Esc` | Exit terminal mode |
| `,tn` / `,tc` | New tab / close tab |
| `,tl` | Toggle to last tab |
---
## 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 quickfix window — press Enter to jump to heading
```
--- ---
## Features ## Features
### Startup Dashboard ### Statusline
Running `vim` (no arguments) opens a full-screen Startify dashboard showing recent A native, hand-written statusline using the Solarized palette:
files, sessions, and bookmarks. Running `vim .` opens NERDTree on the left with
the dashboard on the right.
### Keybinding Guide ```
N ~/.vimrc [+] main [vim] 42:7 68%
```
Press `,` and pause for 500 ms. A popup (vim-which-key) lists all leader bindings - Mode block changes colour by mode (Normal=yellow, Insert=blue, Visual=magenta, Replace=red)
organized into groups. No need to memorize everything upfront. - Git branch via vim-fugitive
- Background matches tmux status bar for a seamless bottom band
### Built-in Cheat Sheet
Press `,?` to open an inline reference covering modes, survival commands, search,
code intelligence, git, and clipboard — without leaving Vim.
### Session Management ### Session Management
@ -348,29 +279,23 @@ code intelligence, git, and clipboard — without leaving Vim.
:Obsess! " stop tracking :Obsess! " stop tracking
``` ```
Sessions are stored in `~/.vim/sessions/` and automatically restored by vim-prosession Sessions auto-restore when you open Vim in the same directory.
the next time you open Vim in the same directory.
### Project-Local Config ### Project-Local Config
Drop a `.vimrc` in any project root to override settings for that project: Drop a `.vimrc` in any project root to override settings:
```vim ```vim
" project/.vimrc " my-project/.vimrc
set shiftwidth=2 set shiftwidth=2
let g:ale_python_black_options = '--line-length=100' let g:ale_python_black_options = '--line-length=100'
``` ```
Loaded automatically via `set exrc`. Restricted to safe options via `set secure`.
### tmux Integration ### tmux Integration
`Ctrl+h/j/k/l` navigates seamlessly between Vim splits and tmux panes — no prefix `Ctrl+h/j/k/l` navigates seamlessly between Vim splits and tmux panes.
key, no mode switch.
**Vim side:** handled by vim-tmux-navigator (installed automatically). Add to `~/.tmux.conf` (or let `install.sh` append it):
**tmux side:** add to `~/.tmux.conf` (or let `install.sh` append it):
```tmux ```tmux
is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\S+\/)?g?(view|n?vim?x?)(diff)?$'" is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\S+\/)?g?(view|n?vim?x?)(diff)?$'"
@ -380,123 +305,79 @@ 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' bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R'
``` ```
Then reload: `tmux source-file ~/.tmux.conf` ### TTY / SSH Support
> **Note:** the `C-l` binding replaces the terminal's screen-clear shortcut inside Detected automatically when `$TERM` is `linux` or `screen`. In TTY mode:
> tmux. To restore it, add `bind C-l send-keys 'C-l'` — then use `prefix + C-l`.
- 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 ### Large File Handling
Files over 10 MB automatically disable syntax highlighting, undo history, and Files over 10 MB automatically disable syntax highlighting, undo history, and
linting to prevent Vim from stalling. linting to prevent stalling.
### TTY / Console Support
Detected automatically when `$TERM` is `linux` or `screen`. In TTY mode:
- True color and cursorline disabled
- Powerline separators replaced with plain ASCII
- FZF preview windows disabled
- IndentLine guides disabled
- Syntax column limit reduced to 120 characters
- Simpler built-in status line used instead of airline
---
## Language Support
| Language | Indent | Formatter | Linter | LSP |
|----------|--------|-----------|--------|-----|
| Python | 4 sp | black, isort | flake8, pylint | coc-pyright |
| JavaScript | 2 sp | prettier | eslint | coc-tsserver |
| TypeScript | 2 sp | prettier | eslint, tsserver | coc-tsserver |
| Go | tab | gofmt, goimports | staticcheck | coc-go |
| Rust | 4 sp | rustfmt | cargo | coc-rust-analyzer |
| Shell | 2 sp | — | shellcheck | coc-sh |
| YAML | 2 sp | prettier | yamllint | coc-yaml |
| HTML | 2 sp | prettier | — | coc-html |
| CSS / SCSS | 2 sp | prettier | stylelint | coc-css |
| Less | 2 sp | prettier | — | — |
| JSON | 2 sp | prettier | — | coc-json |
| Markdown | 2 sp | prettier | markdownlint | marksman |
| SQL | 4 sp | sqlfluff | sqlfluff | — |
| Dockerfile | 2 sp | — | hadolint | — |
`install.sh` installs all formatters and linters automatically.
ALE runs them asynchronously; format-on-save is active for all supported languages.
--- ---
## Plugins ## Plugins
### Navigation ### Navigation
- **NERDTree** — file tree explorer - **fzf + fzf.vim** — fuzzy finder for files, buffers, tags, ripgrep
- **fzf + fzf.vim** — fuzzy finder for files, buffers, tags, and ripgrep
### Git ### Git
- **vim-fugitive** — full Git integration inside Vim - **vim-fugitive** — full Git integration
- **vim-gitgutter** — diff signs in the sign column - **vim-gitgutter** — diff signs in the sign column
### LSP and Completion ### LSP and Completion
- **coc.nvim** — full LSP + completion via Node.js (recommended) - **vim-lsp** — pure VimScript LSP client
- **vim-lsp** — pure VimScript LSP client (Node.js-free fallback) - **vim-lsp-settings** — auto-configures language servers
- **vim-lsp-settings** — auto-configures language servers for vim-lsp - **asyncomplete.vim** — async completion engine
- **asyncomplete.vim** — async completion engine (vim-lsp mode) - **asyncomplete-lsp.vim** — LSP completion source
### Linting ### Linting and Formatting
- **ALE** — asynchronous lint engine, always active regardless of LSP backend - **ALE** — async linting and format-on-save
### UI ### Markdown
- **vim-airline** — status line and tabline - **vim-markdown** — folding, concealment, table alignment
- **vim-startify** — startup dashboard with session management - **previm** — live browser preview
- **vim-which-key** — keybinding hint popup on leader pause
- **indentLine** — indent guide lines (non-TTY only) ### Language Syntax
- **undotree** — visual undo branch history - **vim-javascript** — enhanced JS syntax
- **tagbar** — code structure sidebar via ctags - **yats.vim** — TypeScript syntax
- **vim-go** — Go syntax and tooling
### Editing ### Editing
- **vim-surround** — change surrounding quotes, brackets, and tags - **vim-surround** — change/delete/add surroundings
- **vim-commentary**`gc` to toggle comments - **vim-commentary**`gc` to toggle comments
- **auto-pairs** — auto-close brackets and quotes - **vim-repeat** — repeat plugin maps with `.`
- **vim-easymotion** — jump anywhere on screen with 2 keystrokes (`s`) - **vim-unimpaired** — bracket shortcut pairs
- **vim-unimpaired** — bracket shortcut pairs (`[q`/`]q`, etc.)
- **targets.vim** — additional text objects - **targets.vim** — additional text objects
- **vim-snippets** — snippet library (used with CoC) - **auto-pairs** — auto-close brackets and quotes
- **vim-tmux-navigator** — seamless `Ctrl+h/j/k/l` across Vim and tmux - **vim-easymotion** — `s` + 2 chars to jump anywhere
### Language Packs ### UI
- **vim-polyglot** — syntax for 100+ languages - **vim-colors-solarized** — color scheme
- **vim-go** — Go syntax and tooling (LSP handled by coc-go) - **undotree** — visual undo branch history
- **vim-startify** — startup dashboard and session list
- **indentLine** — indent guides (non-TTY)
### Session ### Session and Navigation
- **vim-obsession** — continuous session saving - **vim-obsession** — session tracking
- **vim-prosession** — project-level session management - **vim-tmux-navigator** — seamless Vim/tmux pane navigation
### Color Schemes
- **gruvbox** (default), **dracula**, **solarized**, **onedark**
--- ---
## Customization ## Customization
### Change the color scheme
In `~/.vimrc`, find and update the `colorscheme` line:
```vim
colorscheme dracula " options: gruvbox, solarized, onedark
```
True color is enabled automatically when `$COLORTERM=truecolor`. Falls back to
256-color, then 16-color in TTY.
### Per-project overrides ### Per-project overrides
Create `.vimrc` in your project root. Anything placed here overrides the global Create `.vimrc` in your project root:
config for that directory:
```vim ```vim
" my-project/.vimrc " project/.vimrc
set shiftwidth=2 set shiftwidth=2
let g:ale_python_black_options = '--line-length=120' let g:ale_python_black_options = '--line-length=120'
``` ```
@ -512,100 +393,41 @@ Edit `~/.vimrc` directly (`,ev` opens it from inside Vim). Reload with `,sv`.
**Plugins not loading** **Plugins not loading**
```vim ```vim
:PlugInstall " install any missing plugins :PlugInstall " install missing plugins
:PlugUpdate " update all plugins :PlugUpdate " update all plugins
``` ```
**CoC not working** **LSP server not starting**
```bash
node --version # must be 14.14+
```
Inside Vim: `:CocInfo` for diagnostics, `:CocInstall <extension>` to add a language server.
**vim-lsp server not starting**
```vim ```vim
:LspInstallServer " install the correct server for the current filetype :LspInstallServer " install server for current filetype
:LspStatus " check server status :LspStatus " check server status
``` ```
**Markdown LSP not starting** **Markdown preview not opening**
`marksman` must be installed as a standalone binary (not a CoC extension): `previm` uses `open` (macOS) or `xdg-open` (Linux). Make sure a browser is
set as the default handler for HTML files.
```bash
brew install marksman # macOS
sudo pacman -S marksman # Arch
# or: ./install.sh handles it automatically
```
**Colors look wrong** **Colors look wrong**
```bash ```bash
export TERM=xterm-256color # add to ~/.bashrc or ~/.zshrc export TERM=xterm-256color # add to ~/.bashrc or ~/.zshrc
export COLORTERM=truecolor # for true colour
``` ```
For true color: `export COLORTERM=truecolor`.
**ALE linters not found** **ALE linters not found**
```bash ```bash
which flake8 black prettier eslint # verify tools are on PATH which flake8 black prettier eslint # verify tools are on PATH
``` ```
If tools were installed with `pip install --user` or `npm install -g`, make sure
the respective bin directories are on `$PATH`.
**`Ctrl+s` freezes the terminal** **`Ctrl+s` freezes the terminal**
Add `stty -ixon` to your `~/.bashrc`, `~/.zshrc`, or `~/.config/fish/config.fish`. Add `stty -ixon` to your `~/.bashrc`, `~/.zshrc`, or `~/.config/fish/config.fish`.
This disables XON/XOFF flow control permanently.
--- ---
## Contributing
Bug reports and pull requests are welcome. Please follow these guidelines:
### Reporting a bug
1. Search [existing issues](https://github.com/m1ngsama/chopsticks/issues) before opening a new one.
2. Include your Vim version (`vim --version`), OS, and a minimal reproduction.
3. If the bug is plugin-specific, check whether it reproduces with a minimal config
(`vim -u NONE`) or only with chopsticks loaded.
### Proposing a change
1. Open an issue first to discuss the change, especially for non-trivial additions.
2. Keep the scope focused — one feature or fix per PR.
3. Follow existing conventions: augroups for autocmds, TTY guards for visual features,
conditional plugin loading where appropriate.
4. Update `CHANGELOG.md` with a summary of the change.
### Scope
Chopsticks is an opinionated configuration. Changes should align with the design
principles above — in particular, KISS (no icon fonts, minimal dependencies) and
TTY-compatibility. Neovim-only features and Lua configs are out of scope.
---
## Acknowledgements
Inspired by [amix/vimrc](https://github.com/amix/vimrc).
Built with [vim-plug](https://github.com/junegunn/vim-plug),
[coc.nvim](https://github.com/neoclide/coc.nvim),
[vim-lsp](https://github.com/prabirshrestha/vim-lsp),
and the broader Vim plugin community.
---
## Changelog
See [CHANGELOG.md](CHANGELOG.md).
## License ## License
[MIT](LICENSE) © m1ng [MIT](LICENSE) © m1ng

File diff suppressed because it is too large Load diff