Compare commits

...

10 commits

Author SHA1 Message Date
01c67d841b fix: audit fixes — shellcheck, TTY signcolumn, matchdelete race, docs accuracy
Some checks failed
test / startup (macos-latest) (push) Has been cancelled
test / startup (ubuntu-latest) (push) Has been cancelled
test / shellcheck (push) Has been cancelled
- install.sh: ls -A → find (shellcheck SC2012)
- navigation.vim: GFiles -nargs=? to support :GFiles?
- lsp.vim: signcolumn=yes gated behind !g:is_tty
- editing.vim: matchdelete in timer wrapped with silent!
- README: gofmt → goimports, plugin count 24–25
- CHANGELOG: annotate removed features (ChopsticksLearn, vim . layout)
2026-04-22 18:31:08 +08:00
196e88c2c8 docs: demo GIF with live API curl — 40s, 5 clean scenes
Scenes: open → fuzzy find → ripgrep → curl running API (JSON) → cheat sheet.
Server runs in background, curl shows formatted /users response.
Fixed: port conflict, buffer state reset before cheat sheet.
2026-04-22 18:08:05 +08:00
4965b65041 docs: slow down demo GIF — 24s → 35s, 50ms typing, longer scene holds 2026-04-22 17:50:15 +08:00
2c7d190314 docs: re-record demo GIF — clean narrative, zero lint warnings
5-scene story: open → fuzzy find → ripgrep → run file → cheat sheet.
Demo project rewritten with functional dispatch (no class/stdlib method
name lint issues). All frames clean — no ALE warnings, no git markers.
2026-04-22 17:45:52 +08:00
a42c980d3e perf: remove ttyfast, add grepprg/diffopt, DRY FZF commands, conditional tmux-navigator
- Remove deprecated `set ttyfast` (no-op since Vim 8)
- Add grepprg=rg for :grep → quickfix integration
- Add diffopt with histogram algorithm
- Consolidate Rg/RgWord/GFiles (24 lines → 10, lazy preview)
- Load vim-tmux-navigator only inside tmux, Ctrl+hjkl fallback outside
2026-04-22 17:06:33 +08:00
f6631dfdf1 docs: re-record demo GIF — deterministic FZF handling, all 6 scenes clean 2026-04-22 16:51:52 +08:00
56c3917682 perf+feat: fix logiPat guard, skip 2 more built-ins, add git/format bindings
Performance:
- Fix g:loaded_logipat → g:loaded_logiPat (0.478ms → 0.017ms)
- Skip openPlugin + manpager (12 built-in plugins disabled total)

Features:
- ,af toggle format-on-save
- ,gL git log --oneline --graph
- ,gC FZF commits search, ,gB buffer commits
2026-04-22 16:30:28 +08:00
996b428809 docs: re-record demo GIF — clean viminfo, fix ALE warnings 2026-04-22 16:18:21 +08:00
ba39fca13b docs: re-record demo GIF — 7-scene feature showcase 2026-04-22 15:54:33 +08:00
ecf0a1b260 docs: rewrite demo tape — 7-scene "what can I do" narrative
Scenes: vim . dashboard, fuzzy find, ripgrep, run file, sidebar
toggle, git status, cheat sheet. Optional LSP section commented out.
2026-04-22 15:53:30 +08:00
14 changed files with 124 additions and 74 deletions

BIN
.github/demo.gif vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 460 KiB

After

Width:  |  Height:  |  Size: 990 KiB

72
.github/demo.tape vendored
View file

@ -1,47 +1,63 @@
# chopsticks demo — "what can I do with this?"
# Rule: NEVER use Escape to close FZF — always Enter (deterministic).
# Pacing: hold each scene long enough for the viewer to read.
Output .github/demo.gif
Set Shell bash
Set FontSize 14
Set Width 960
Set Height 540
Set Width 1080
Set Height 620
Set Theme "Builtin Solarized Dark"
Set TypingSpeed 50ms
Set Padding 10
Type "vim ~/.vim/modules/core.vim"
# ── 0. Start API server in background ──────────────────────────────────────
Type "cd /tmp/demo-project"
Enter
Sleep 0.5s
Type "python3 serve.py > /dev/null 2>&1 &"
Enter
Sleep 1s
# ── 1. Open file — syntax highlighting + statusline ────────────────────────
Type "vim server.py"
Enter
Sleep 3.5s
# ── 2. Fuzzy find files (Ctrl+p → type → select) ──────────────────────────
Ctrl+p
Sleep 1.5s
Type "route"
Sleep 2.5s
Enter
Sleep 3s
# ── 3. Ripgrep project search (,rg → query → select) ──────────────────────
Type ",rg"
Sleep 1.5s
Type "def "
Sleep 3s
Enter
Sleep 3s
# ── 4. Curl the running API from inside Vim ────────────────────────────────
Type ":!curl -s localhost:8080/users | python3 -m json.tool"
Enter
Sleep 4.5s
Enter
Sleep 1.5s
# Show the code with solarized theme and statusline
Sleep 1s
# Use Ctrl+p for fuzzy find
Type "\x10"
Sleep 1s
Type "lsp"
Sleep 1s
Escape
Sleep 0.5s
# Go to definition
Type "gg"
Sleep 0.3s
Type "/mapleader"
# ── 5. Cheat sheet (,?) ───────────────────────────────────────────────────
# Reset to server.py so cheat sheet shows code on left, keys on right.
Type ":edit server.py"
Enter
Sleep 1s
# Show cheat sheet
Type ",?"
Sleep 2s
Sleep 5.5s
Type "q"
Sleep 0.5s
# Open file browser
Type ",e"
Sleep 1.5s
Escape
Sleep 0.5s
# Quit
# ── done ───────────────────────────────────────────────────────────────────
Type ":qa!"
Enter
Sleep 0.5s

View file

@ -4,6 +4,21 @@
### Added
- `:ChopsticksStatus` diagnostic command — checks system tools, LSP servers, linters, formatters
- `,af` toggle format-on-save (ALE `fix_on_save`)
- `,gL` git log graph (last 20 commits)
- `,gC` FZF git commits search, `,gB` buffer commits
### Fixed
- `g:loaded_logipat` typo → `g:loaded_logiPat` — logiPat was loading fully (0.478ms wasted)
### Changed
- Skip 2 more built-in plugins: openPlugin, manpager (10 → 12 total)
- Remove deprecated `set ttyfast` (no-op since Vim 8)
- Add `grepprg=rg --vimgrep``:grep` now uses ripgrep + quickfix
- Add `diffopt` with histogram algorithm and indent-heuristic
- Consolidate FZF Rg/RgWord/GFiles commands (DRY refactor)
- vim-tmux-navigator: conditional load (only inside tmux), fallback `Ctrl+hjkl` mappings outside
- Add `Ctrl+hjkl` window navigation fallback when tmux-navigator not loaded
## 2.1.0 — 2025-04-22
@ -22,8 +37,8 @@
- Sidebar toggle (`,e` / `,E`) — left-side netrw with `topleft vertical`, winfixwidth, proper toggle
- Enriched statusline — SLMode, SLGit, SLAle, SLFlags
- Toggle feedback — F2/F3/F4/F6/`,ss` echo current state
- `vim .` layout — netrw left + Startify right, proper proportions
- Interactive tutorial (`:ChopsticksLearn`)
- `vim .` layout — netrw left + Startify right (removed in later refactor)
- Interactive tutorial (`:ChopsticksLearn` — removed in later release)
### Removed (Unix minimalism refactor)
- **565 lines** of dead code and bloat

View file

@ -5,7 +5,7 @@
<h1 align="center">chopsticks</h1>
<p align="center">
<strong>Vim for engineers. 25 plugins, works over SSH.</strong>
<strong>Vim for engineers. ~25 plugins, works over SSH.</strong>
</p>
<p align="center">
@ -30,14 +30,14 @@ You SSH into a server. You need to edit code. You want LSP, fuzzy find, git inte
chopsticks gives you a production-ready Vim config in one command. Pure VimScript — no Node.js for the core. Degrades gracefully on TTY. Works the same on your MacBook and your headless Arch box.
**25 plugins**, LSP, linting, and a hand-built statusline. No bloat, no decorations, just tools.
**2425 plugins** (tmux-navigator loads only inside tmux), LSP, linting, and a hand-built statusline. No bloat, no decorations, just tools.
## What's in the box
| Feature | Description |
|---------|-------------|
| **LSP** | completion, go-to-def, hover, rename, code actions — pure VimScript ([vim-lsp](https://github.com/prabirshrestha/vim-lsp)) |
| **Lint + format** | [ALE](https://github.com/dense-analysis/ale) runs black, prettier, gofmt, rustfmt on save |
| **Lint + format** | [ALE](https://github.com/dense-analysis/ale) runs black, prettier, goimports, rustfmt on save |
| **Fuzzy find** | files, buffers, grep, tags, marks, commands — [FZF](https://github.com/junegunn/fzf.vim) |
| **Git** | status, diff, blame, push, pull, conflict markers — [fugitive](https://github.com/tpope/vim-fugitive) + [gitgutter](https://github.com/airblade/vim-gitgutter) |
| **Run file** | `,cr` — auto-detects Python, Go, Rust, JS, C, Shell, and more |
@ -92,7 +92,7 @@ jk exit insert mode ,? cheat sheet
### Git
`,gs` status | `,gd` diff | `,gb` blame | `,gc` commit | `,gp` push | `,gl` pull | `]x` `[x` conflict
`,gs` status | `,gd` diff | `,gb` blame | `,gc` commit | `,gp` push | `,gl` pull | `,gL` log graph | `,gC` FZF commits | `,gB` buffer commits | `]x` `[x` conflict
### Windows
@ -104,7 +104,7 @@ jk exit insert mode ,? cheat sheet
### Toggle
`F2` paste | `F3` line numbers | `F4` relative numbers | `F6` invisible chars | `,ss` spell check
`F2` paste | `F3` line numbers | `F4` relative numbers | `F6` invisible chars | `,ss` spell check | `,af` format on save
### Utilities
@ -131,7 +131,7 @@ ALE and vim-lsp coexist cleanly (`ale_disable_lsp=1`). ALE handles linting + for
├── .vimrc thin loader
├── modules/
│ ├── env.vim TTY detection, truecolor, skip built-in plugins
│ ├── plugins.vim vim-plug + 25 plugins
│ ├── plugins.vim vim-plug + 2425 plugins
│ ├── core.vim settings, keymaps, performance
│ ├── ui.vim solarized, statusline, startify
│ ├── editing.vim easymotion, yank highlight, blank lines
@ -150,7 +150,7 @@ Each module is self-contained. Comment out one line in `.vimrc` to disable it. A
| Metric | Value |
|--------|-------|
| Lazy-loaded | 7 plugins (on command or filetype) |
| Built-in plugins skipped | 10 (gzip, tar, zip, vimball, etc.) |
| Built-in plugins skipped | 12 (gzip, tar, zip, vimball, logiPat, etc.) |
| Large file threshold | 10MB (auto-disables syntax + undo) |
| TTY large file | 500KB (syntax disabled) |

View file

@ -423,7 +423,7 @@ _vim_run() {
vim --not-a-term "$@" 2>/dev/null
fi
}
if [[ -d "$HOME/.vim/plugged" ]] && [[ -n "$(ls -A "$HOME/.vim/plugged" 2>/dev/null)" ]]; then
if [[ -d "$HOME/.vim/plugged" ]] && [[ -n "$(find "$HOME/.vim/plugged" -mindepth 1 -maxdepth 1 2>/dev/null)" ]]; then
warn "PlugClean: removing plugins not listed in .vimrc from ~/.vim/plugged"
fi
_vim_run +'PlugClean!' +qall || true # remove plugins no longer in vimrc; ignore exit code (none expected)

View file

@ -160,9 +160,13 @@ augroup END
" ── Performance ─────────────────────────────────────────────────────────────
set synmaxcol=200
set ttyfast
set lazyredraw
set complete-=i
if executable('rg')
set grepprg=rg\ --vimgrep\ --smart-case
set grepformat=%f:%l:%c:%m
endif
set updatetime=300
set shortmess+=cI
@ -183,6 +187,10 @@ set exrc
set secure
set sessionoptions=blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal
if has("patch-8.1.0360")
set diffopt=filler,internal,context:3,algorithm:histogram,indent-heuristic
endif
" ── Format Options ──────────────────────────────────────────────────────────
augroup ChopstickFormatOptions

View file

@ -25,7 +25,7 @@ if exists('##TextYankPost') && has('timers')
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)})
call timer_start(150, {-> execute('silent! call matchdelete(' . l:m . ')')})
endfunction
augroup ChopstickYankHL
autocmd!

View file

@ -10,10 +10,12 @@ let g:has_true_color = ($COLORTERM ==# 'truecolor' || $COLORTERM ==# '24bit')
let g:loaded_2html_plugin = 1
let g:loaded_getscriptPlugin = 1
let g:loaded_gzip = 1
let g:loaded_logipat = 1
let g:loaded_logiPat = 1
let g:loaded_rrhelper = 1
let g:loaded_tarPlugin = 1
let g:loaded_vimballPlugin = 1
let g:loaded_zipPlugin = 1
let g:loaded_tutor_mode_plugin = 1
let g:loaded_spellfile_plugin = 1
let g:loaded_openPlugin = 1
let g:loaded_manpager_plugin = 1

View file

@ -18,6 +18,7 @@ if exists('g:plugs["vim-fugitive"]')
nnoremap <leader>gl :Git pull<CR>
nnoremap <leader>gd :Gdiffsplit<CR>
nnoremap <leader>gb :Git blame<CR>
nnoremap <leader>gL :Git log --oneline --graph -20<CR>
endif
" ── Conflict Navigation ────────────────────────────────────────────────────

View file

@ -50,4 +50,6 @@ if exists('g:plugs["ale"]')
nnoremap <silent> [e :ALEPrevious<cr>
nnoremap <silent> ]e :ALENext<cr>
nnoremap <silent> <leader>aD :ALEDetail<cr>
nnoremap <silent> <leader>af :let g:ale_fix_on_save = !g:ale_fix_on_save
\ <bar> echo 'Format on save: ' . (g:ale_fix_on_save ? 'ON' : 'OFF')<cr>
endif

View file

@ -52,7 +52,9 @@ inoremap <expr> <CR> pumvisible() ? asyncomplete#close_popup() : "\<CR>"
function! s:on_lsp_buffer_enabled() abort
setlocal omnifunc=lsp#complete
if !g:is_tty
setlocal signcolumn=yes
endif
nmap <buffer> gd <plug>(lsp-definition)
nmap <buffer> gy <plug>(lsp-type-definition)

View file

@ -60,6 +60,8 @@ if exists('g:plugs["fzf.vim"]')
nnoremap <leader>fL :Lines<CR>
nnoremap <leader>f/ :History/<CR>
nnoremap <leader>f: :History:<CR>
nnoremap <leader>gC :Commits<CR>
nnoremap <leader>gB :BCommits<CR>
endif
let g:fzf_layout = { 'down': '40%' }
@ -70,30 +72,27 @@ else
let g:fzf_preview_window = ['right:50%', 'ctrl-/']
endif
if g:is_tty
command! -bang -nargs=* Rg
\ call fzf#vim#grep(
\ 'rg --column --line-number --no-heading --color=always --smart-case -- '
\ .shellescape(<q-args>), 1, <bang>0)
command! -bang GFiles call fzf#vim#gitfiles('', <bang>0)
else
command! -bang -nargs=* Rg
\ call fzf#vim#grep(
\ 'rg --column --line-number --no-heading --color=always --smart-case -- '
\ .shellescape(<q-args>), 1, fzf#vim#with_preview(), <bang>0)
command! -bang GFiles call fzf#vim#gitfiles('', fzf#vim#with_preview(), <bang>0)
endif
function! s:Preview() abort
return g:is_tty ? {} : fzf#vim#with_preview()
endfunction
if g:is_tty
command! -bang -nargs=* Rg
\ call fzf#vim#grep(
\ 'rg --column --line-number --no-heading --color=always --smart-case -- '
\ .shellescape(<q-args>), 1, s:Preview(), <bang>0)
command! -bang -nargs=* RgWord
\ call fzf#vim#grep(
\ 'rg --column --line-number --no-heading --color=always --smart-case -F -- '
\ .shellescape(expand('<cword>')), 1, <bang>0)
else
command! -bang -nargs=* RgWord
\ call fzf#vim#grep(
\ 'rg --column --line-number --no-heading --color=always --smart-case -F -- '
\ .shellescape(expand('<cword>')), 1, fzf#vim#with_preview(), <bang>0)
\ .shellescape(expand('<cword>')), 1, s:Preview(), <bang>0)
command! -bang -nargs=? GFiles call fzf#vim#gitfiles(<q-args>, s:Preview(), <bang>0)
" ── Window Navigation ───────────────────────────────────────────────────────
if empty($TMUX)
nnoremap <C-h> <C-w>h
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-l> <C-w>l
endif
" ── Window Maximize Toggle ──────────────────────────────────────────────────

View file

@ -49,6 +49,8 @@ Plug 'fatih/vim-go', { 'for': 'go' }
Plug 'mbbill/undotree', { 'on': 'UndotreeToggle' }
Plug 'mhinz/vim-startify'
Plug 'lifepillar/vim-solarized8'
if !empty($TMUX)
Plug 'christoomey/vim-tmux-navigator'
endif
call plug#end()

View file

@ -248,6 +248,7 @@ function! s:CheatSheet() abort
\ ' ,mt table of contents',
\ ' [g ]g LSP diagnostics',
\ ' [e ]e ALE errors',
\ ' ,af format on save',
\ ' :LspInstallServer setup LSP',
\ '',
\ ' ── edit ──────────────────',
@ -268,6 +269,8 @@ function! s:CheatSheet() abort
\ ' ,gc commit',
\ ' ,gp push',
\ ' ,gl pull',
\ ' ,gL log graph',
\ ' ,gC FZF commits',
\ ' [x ]x conflict markers',
\ '',
\ ' ── windows ───────────────',