Compare commits

..

No commits in common. "716e7e5808e84b0d1ae1e9e827aa08c470fb1e00" and "825633d62341d900d8bc346834d805a8797f1245" have entirely different histories.

6 changed files with 254 additions and 85 deletions

34
.vimrc
View file

@ -11,7 +11,7 @@
set nocompatible
" Detect terminal type and capabilities (must be early for conditional configs)
let g:is_tty = empty($TERM) || $TERM ==# 'dumb' || $TERM =~# 'linux' || $TERM =~# 'screen' || &term =~# 'builtin'
let g:is_tty = ($TERM =~ 'linux' || $TERM =~ 'screen' || &term =~ 'builtin')
let g:has_true_color = ($COLORTERM == 'truecolor' || $COLORTERM == '24bit')
" Enable type file detection. Vim will be able to try to detect the type of file in use
@ -1403,16 +1403,42 @@ endif
" ============================================================================
if exists('g:plugs["vim-startify"]')
" Static header — no system() calls so vim renders instantly on startup
let g:startify_custom_header = [
" Centered dashboard header — matches neovim startup aesthetic
function! StartifyHeader() abort
let l:art = [
\ '███╗ ███╗ ██╗███╗ ██╗ ██████╗ ███████╗ █████╗ ███╗ ███╗ █████╗ ',
\ '████╗ ████║███║████╗ ██║██╔════╝ ██╔════╝██╔══██╗████╗ ████║██╔══██╗',
\ '██╔████╔██║╚██║██╔██╗ ██║██║ ███╗███████╗███████║██╔████╔██║███████║ ',
\ '██║╚██╔╝██║ ██║██║╚██╗██║██║ ██║╚════██║██╔══██║██║╚██╔╝██║██╔══██║',
\ '██║ ╚═╝ ██║ ██║██║ ╚████║╚██████╔╝███████║██║ ██║██║ ╚═╝ ██║██║ ██║',
\ '╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝',
\ '',
\ ]
let l:art_w = 71
let l:pad = max([0, (winwidth(0) - l:art_w) / 2])
let l:indent = repeat(' ', l:pad)
let l:lines = []
for l:line in l:art
call add(l:lines, l:indent . l:line)
endfor
" Info subheader: vim version + cwd + git branch
let l:ver = 'Vim ' . (v:version / 100) . '.' . printf('%02d', v:version % 100)
let l:cwd = fnamemodify(getcwd(), ':t')
let l:git = ''
if executable('git')
let l:branch = system('git -C ' . shellescape(getcwd()) .
\ ' rev-parse --abbrev-ref HEAD 2>/dev/null')
if v:shell_error == 0
let l:git = ' [' . substitute(l:branch, '\n\+$', '', '') . ']'
endif
endif
let l:info = l:ver . ' ' . l:cwd . l:git
let l:info_pad = max([0, (winwidth(0) - len(l:info)) / 2])
call add(l:lines, '')
call add(l:lines, repeat(' ', l:info_pad) . l:info)
call add(l:lines, '')
return l:lines
endfunction
let g:startify_custom_header = 'StartifyHeader()'
" Sessions first, then recent files — mirrors dashboard plugin ordering
let g:startify_lists = [

173
CHANGELOG.md Normal file
View file

@ -0,0 +1,173 @@
# Changelog
All notable changes to chopsticks are documented here.
---
## [1.1.1] - 2026-04-09
Systematic absorption of best practices from amix/vimrc, tpope/vim-sensible,
ThePrimeagen, skwp/YADR, and spf13-vim — settings and mappings that appear
consistently across all top global configs but were missing here.
### Added
- **`set ttimeoutlen=10`** — eliminates the ~500ms ESC lag in terminal Vim; separates
keycode timeout from leader-key timeout (`timeoutlen` unchanged at 500ms)
- **`set display+=lastline`** — shows truncated long lines instead of replacing them with `@@@`
- **`set complete-=i`** — `Ctrl+n/p` no longer scans all included files; completion is instant
- **`set wildignorecase`** — case-insensitive filename completion in wildmenu and `:find`
- **`set path+=**`** — recursive `:find` across the project; wildignore excludes
`node_modules`, `__pycache__`, `dist`, `build`, `.git`
- **`set sessionoptions`** — removes `options` from saved sessions (prevents stale plugin
settings from contaminating restored sessions)
- **`set listchars`** — defines visible whitespace characters; TTY uses ASCII symbols,
modern terminals use Unicode (tab `→`, trail `·`, extends `▸`)
- **`F6`** — toggle visible whitespace on/off
- **`formatoptions-=cro`** on `BufEnter` — disables automatic comment-leader insertion
when pressing Enter or `o/O`; runs on BufEnter to override filetype plugins
- **`InsertLeave * set nopaste`** — auto-disables paste mode on leaving insert, preventing
permanently broken auto-indent
- **`colorcolumn=+1`** for all languages via `textwidth`:
Python 88, Go 120, JS/TS 100, Rust 100, Shell 80 (Markdown disabled)
- **`vnoremap J/K`** with `gv=gv` — move selected lines down/up and re-indent (ThePrimeagen)
- **`gV`** — re-select last pasted text (`\`[v\`]` — spf13, YADR)
- **`cnoremap <C-p>/<C-n>`** — navigate command-line history matching typed prefix (amix, spf13)
- **`<leader>e :Explore`** — open built-in Netrw file browser; works on any Vim without plugins
- **`<leader>cd`** — change window-local CWD to current file's directory (was `<leader>wd`)
- **`<leader>sv`** — reloads vimrc and echoes confirmation
### Changed
- `<leader>wd` renamed to `<leader>cd`; now uses `lcd` (window-local) instead of `cd` (global)
- `wildignore` expanded with `*/node_modules/*`, `*/__pycache__/*`, `*/dist/*`, `*/build/*`
---
## [1.1.0] - 2026-04-09
Ergonomics and automation overhaul: community-standard keybindings, seamless
tmux integration, an in-Vim cheat sheet, a beginner onboarding section, and
several correctness fixes from a systematic review.
### Added
- **`jk``Esc`** in insert mode — ergonomic escape without reaching for the key
- **`Ctrl+s` save** in normal and insert mode (add `stty -ixon` to shell rc to enable
in terminals that use XON/XOFF flow control)
- **`//` visual search** — search for visually selected text using `\V` very-nomagic escaping
- **`<leader>p` / `<leader>P`** — paste from system clipboard after/before cursor
- **`<leader>rG`** — ripgrep word under cursor with `-F` (literal, not regex)
- **`<leader>u`** — leader-key alias for UndoTree (complements `F5`)
- **`<leader>tt`** — leader-key alias for Tagbar (complements `F8`)
- **`,?` in-Vim cheat sheet** — opens a read-only buffer covering modes, survival
commands, search, code intelligence, git, and clipboard; press `q` to close
- **vim-tmux-navigator** plugin — `Ctrl+h/j/k/l` navigates seamlessly across Vim
splits and tmux panes without a prefix key
- **`install.sh` tmux step** — detects tmux and optionally appends the four
navigator `bind-key` lines to `~/.tmux.conf`; warns about `C-l`/screen-clear tradeoff
- **`install.sh` survival guide** — post-install output now shows the 4 essential
commands for first-time Vim users, plus the `stty -ixon` advisory
- **QUICKSTART.md Step 0** — new first section explaining Vim modes (Normal/Insert/Visual)
and 4 survival commands; makes the guide usable by users who have never opened Vim
- **`let b:ale_enabled = 0`** in `LargeFileSettings()` — ALE no longer spawns
linter subprocesses for files over 10 MB
### Changed
- **ALE lint triggers**`ale_lint_on_text_changed` changed from `'never'` to `'normal'`;
`ale_lint_on_insert_leave` and `ale_lint_on_enter` changed from `0` to `1` — diagnostics
now refresh on buffer enter and after edits settle in normal mode
- **`<C-h/j/k/l>` manual maps removed** — vim-tmux-navigator owns these keys at
plugin load time; the previous hand-rolled `<C-W>` maps were unreachable dead code
- **`<leader>pp` paste-mode toggle removed** — functionally identical to the existing
`F2` pastetoggle; its presence caused a 500 ms delay on every `<leader>p` paste
### Fixed
- **ALE navigation direction reversed**`[e` now correctly calls `ALEPrevious`
and `]e` calls `ALENext`, matching the vim-unimpaired `[`/`]` convention
- **`<leader>rG` regex metacharacter bug** — without `-F`, characters like `.` `*`
`(` in the cursor word were treated as regex, producing incorrect matches
---
## [1.0.0] - 2026-03-29
First stable release. Full-stack engineering environment out of the box — automatic
installation, tiered LSP, TTY fallback, and coverage for 14 languages.
### Added
- **Arch Linux support** in `install.sh` — pacman branch for all system tools
- **`hadolint`** added to system tools installation (Dockerfile linting)
- **`staticcheck`** added to Go tools (replaces archived `golint`)
- **`yamllint`** added to pip tools (YAML linting)
- **`coc-settings.json`** — configures `marksman` as Markdown LSP for CoC via
`languageserver` entry; symlinked automatically by `install.sh`
- **pip3 bootstrap** in `install.sh` — auto-installs pip3 when python3 is present
but pip3 is absent (common on Ubuntu minimal images)
- **9 named augroups** in `.vimrc` — all loose `autocmd` statements now wrapped
with `autocmd!` to prevent doubling on `:source $MYVIMRC`:
`ChopstickTabHistory`, `ChopstickResize`, `ChopstickStdin`, `CocHighlight`,
`ChopstickCleanup`, `ChopstickFiletype`, `ChopstickTTYLargeFile`,
`ChopstickWhichKey`, `ChopstickStartify`
- **TTY-safe plugin install**`vim +PlugInstall +qall </dev/null` prevents
Vim from blocking in non-interactive/piped environments
### Changed
- SQL tooling unified to **`sqlfluff`** (pip) — `sqlfmt` removed from npm section
- Go linter changed from `golint` (archived 2023) to **`staticcheck`**
- Markdown LSP changed from broken `coc-marksman` (npm) to **`marksman`** binary
configured via `coc-settings.json`
### Fixed
- **vim-go startup hang** on Arch Linux — removed `:GoUpdateBinaries` post-install
hook; set `g:go_gopls_enabled = 0` to prevent conflict with `coc-go`
- **E495 errors** (`<afile>` in special buffers) — all `<afile>` usages guarded
with `!empty(expand('<afile>'))` and `empty(&buftype)` checks
- **`g:go_def_mode` conflict** — now conditional: uses `gopls` when CoC active,
`godef` when vim-lsp active (avoids error when gopls is disabled)
- **vim startup UX** — NERDTree + Startify layout for `vim .` and bare `vim`
- **`coc-marksman` silent failure** — package does not exist on npm; replaced with
native `languageserver` configuration in `coc-settings.json`
- **CoC startup warning** in no-node environments — `g:coc_start_at_startup = 0`
and `g:coc_disable_startup_warning = 1` set when `g:use_coc = 0`
---
## [0.9.0] - 2026-02-21
### Added
- **Full-stack language coverage** — LSP, lint, and format for: Python,
JavaScript, TypeScript, Go, Rust, Shell, YAML, HTML, CSS/SCSS, Less,
JSON, Markdown, SQL, Dockerfile
- **`install.sh` overhaul** — automated installation of system tools, npm tools,
pip tools, Go tools, and CoC language server extensions with platform detection
and interactive prompts; `--yes` flag for non-interactive mode
- **vim-startify** startup screen with dynamic header (version, cwd, git branch)
- **vim-which-key** keybinding popup on `,` + 500ms pause
- **Startup layout**`vim .` opens NERDTree left + Startify right; bare `vim`
opens Startify with NERDTree alongside
- **Session management** via vim-obsession + vim-prosession
- **Large file handling** — syntax and undo disabled for files > 10 MB
- **Project-local config**`.vimrc` in project root auto-loaded via `set exrc`
- **Persistent undo**`~/.vim/.undo/` with `undolevels=1000`
### Changed
- Tiered LSP backend: CoC (Node.js) preferred, vim-lsp (no Node.js) as fallback
- All CoC and vim-lsp keybindings unified (`gd`, `K`, `[g`/`]g`, `,rn`, `,ca`)
- ALE `fix_on_save` disabled when vim-lsp active (prevents double-format)
- NERDTree autocmd wrapped in `augroup NERDTreeAutoClose`
### Fixed
- Multiple leader key conflicts resolved (`,ad`, `,cd`, `,cp`, `,sp`, `,t`)
- CtrlP removed (redundant with FZF)
- Duplicate `set` options cleaned up
- `<leader>A` dead mapping (no alternate-file plugin) removed
---
## [0.1.0] - 2024
Initial release — base Vim configuration with vim-plug, basic plugins, and
TTY/non-TTY detection.

View file

@ -39,27 +39,17 @@ Once in Normal mode, press `,?` to open a cheat sheet covering everything else.
## Step 1: Install
**One command — works on macOS and Linux:**
```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
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
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
cd ~/.vim && ./install.sh
```
**Non-interactive (CI / server / scripting):**
The script handles everything: symlinks, vim-plug, plugins, and all tools.
It detects your OS (macOS/Debian/Arch/Fedora) and installs what it can automatically.
**Non-interactive (CI / server):**
```bash
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --yes
./install.sh --yes
```
---

View file

@ -15,7 +15,8 @@
[![Languages](https://img.shields.io/badge/languages-14-informational?style=flat-square)](#language-support)
```bash
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
cd ~/.vim && ./install.sh
```
> **New to Vim?** Read [Step 0 in QUICKSTART.md](QUICKSTART.md#step-0-vim-basics) first —
@ -55,66 +56,54 @@ curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | b
| Tool | Minimum | Role |
|------|---------|------|
| Vim | **8.0+** | Required `install.sh` installs it if missing |
| git | any | Required — `install.sh` installs it if missing |
| curl | any | Required — `install.sh` installs it if missing |
| Node.js | 14.14+ | Optional — enables CoC LSP; `install.sh` offers nvm install |
| Vim | **8.0+** | Required |
| git | any | Cloning and vim-fugitive |
| curl | any | vim-plug bootstrap |
| Node.js | 14.14+ | Optional — enables CoC LSP (recommended) |
| ripgrep | any | Optional — enables `,rg` / `,rG` project search |
| fzf | any | Optional — enables `Ctrl+p` fuzzy finder |
| 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.
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.
All optional tools are installed automatically by `install.sh` when prompted.
---
## Installation
### One command (recommended)
```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.
It works correctly even when piped from curl — interactive prompts use `/dev/tty`.
For non-interactive or CI environments:
```bash
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --yes
```
### Traditional (git clone)
### Automatic (recommended)
```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
cd ~/.vim && ./install.sh
cd ~/.vim
./install.sh
```
### What the installer does
The installer handles everything in sequence:
1. **Preflight** — checks network, detects OS and package manager, verifies or installs `curl`, `git`, and `vim`
2. **sudo** — authenticates once upfront; gracefully skips system packages when unavailable
3. **macOS** — offers to install Homebrew if `brew` is not found
4. **Node.js** — offers to install via nvm if not found (falls back to vim-lsp if declined)
5. **Python** — offers to install Python 3 if missing; bootstraps pip3 if only python3 is present
6. **Symlinks** — backs up any existing `~/.vimrc` with a timestamp, then symlinks `~/.vimrc → ~/.vim/.vimrc`
7. **Plugins** — installs vim-plug and runs `:PlugInstall` (with a progress notice during the black-screen period)
8. **System tools** — ripgrep, fzf, ctags, shellcheck, hadolint, marksman (verified downloads)
9. **Language tools** — npm formatters, pip formatters/linters, Go tools
10. **CoC extensions** — all language servers in one step
11. **tmux** — optionally appends vim-tmux-navigator bindings to `~/.tmux.conf`
1. Verifies Vim 8.0+ and detects OS / package manager
2. Backs up any existing `~/.vimrc` with a timestamp
3. Symlinks `~/.vimrc → ~/.vim/.vimrc` and `~/.vim/coc-settings.json`
4. Installs vim-plug and runs `:PlugInstall`
5. Optionally installs system tools (ripgrep, fzf, ctags, shellcheck, hadolint, marksman)
6. Optionally installs language tools (npm, pip, Go)
7. Optionally installs CoC language server extensions
8. Optionally configures tmux for seamless pane navigation
**Supported platforms:** macOS (Homebrew), Debian/Ubuntu (apt), Arch Linux (pacman), Fedora (dnf).
Use `--yes` for non-interactive or CI environments:
```bash
./install.sh --yes
```
### Manual
```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
ln -sf ~/.vim/.vimrc ~/.vimrc
ln -sf ~/.vim/coc-settings.json ~/.vim/coc-settings.json
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
vim +PlugInstall +qall </dev/null

6
get.sh
View file

@ -59,10 +59,8 @@ step "Running installer"
cd "$DEST"
# exec replaces this process with install.sh and reconnects stdin to /dev/tty
# so interactive prompts work correctly even when this script was piped from curl.
# Use a test-open to check /dev/tty is actually accessible (it may exist but be
# unusable in non-interactive SSH sessions or container environments).
if { true </dev/tty; } 2>/dev/null; then
# so interactive prompts work correctly even when this script was piped from curl
if [[ -e /dev/tty ]]; then
exec bash install.sh "$@" </dev/tty
else
exec bash install.sh "$@"

View file

@ -40,7 +40,7 @@ ask() {
[[ $AUTO_YES -eq 1 ]] && return 0
if [[ -t 0 ]]; then
read -r -p "$1 [y/N] " reply
elif { true </dev/tty; } 2>/dev/null; then
elif [[ -e /dev/tty ]]; then
read -r -p "$1 [y/N] " reply </dev/tty
else
# No terminal available — default to no (safe)
@ -360,21 +360,14 @@ else
fi
step "Installing Vim plugins"
# Use /dev/tty when available so vim properly manages the terminal (alternate
# screen buffer, cursor, colours) and restores it cleanly on exit.
# Fall back to --not-a-term for non-interactive/CI environments.
_vim_run() {
if { true </dev/tty; } 2>/dev/null; then
# Interactive terminal: let vim manage the alternate screen properly
vim "$@" </dev/tty
info "(Vim will open fullscreen to install plugins — screen may go dark for 10-30s, this is normal)"
# </dev/null prevents Vim from reading stdin in non-interactive/piped environments
if ! vim +PlugInstall +qall </dev/null; then
warn "vim +PlugInstall exited non-zero — plugins may be partially installed"
warn "Run :PlugInstall manually inside Vim if something looks wrong"
else
# Non-interactive / CI: TERM=dumb suppresses all escape sequences;
# stdout+stderr redirected so nothing leaks into installer output
TERM=dumb vim "$@" </dev/null >/dev/null 2>&1
fi
}
_vim_run +PlugInstall +qall || true # post-install hooks (e.g. fzf) may exit non-zero; harmless
ok "Plugins installed"
fi
# ============================================================================
# 4. System Tools
@ -648,9 +641,9 @@ step "CoC language server extensions"
if [[ $HAS_NODE -eq 1 ]]; then
if ask "Install CoC language servers (LSP for all configured languages)?"; then
info "(Downloading CoC extensions via npm — this may take 1-3 minutes)"
info "(Downloading CoC extensions via npm — screen may go dark for 1-3 minutes, this is normal)"
# Note: coc-marksman doesn't exist on npm — markdown LSP is handled via coc-settings.json
_vim_run +'CocInstall -sync coc-json coc-tsserver coc-pyright coc-sh coc-html coc-css coc-yaml coc-go coc-rust-analyzer coc-sql' +qall
vim +'CocInstall -sync coc-json coc-tsserver coc-pyright coc-sh coc-html coc-css coc-yaml coc-go coc-rust-analyzer coc-sql' +qall </dev/null
ok "CoC language servers installed"
else
skip "CoC language servers"