Compare commits

..

No commits in common. "01c67d841b8ad2a158d58881b4020169911de531" and "565f2fc80b48f1e4f610c51b0aaec44ebfcd74f9" have entirely different histories.

14 changed files with 74 additions and 124 deletions

BIN
.github/demo.gif vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 990 KiB

After

Width:  |  Height:  |  Size: 460 KiB

72
.github/demo.tape vendored
View file

@ -1,63 +1,47 @@
# 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 Output .github/demo.gif
Set Shell bash Set Shell bash
Set FontSize 14 Set FontSize 14
Set Width 1080 Set Width 960
Set Height 620 Set Height 540
Set Theme "Builtin Solarized Dark" Set Theme "Builtin Solarized Dark"
Set TypingSpeed 50ms Set TypingSpeed 50ms
Set Padding 10 Set Padding 10
# ── 0. Start API server in background ────────────────────────────────────── Type "vim ~/.vim/modules/core.vim"
Type "cd /tmp/demo-project"
Enter 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 Sleep 0.5s
Type "python3 serve.py > /dev/null 2>&1 &"
# Go to definition
Type "gg"
Sleep 0.3s
Type "/mapleader"
Enter Enter
Sleep 1s Sleep 1s
# ── 1. Open file — syntax highlighting + statusline ──────────────────────── # Show cheat sheet
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
# ── 5. Cheat sheet (,?) ───────────────────────────────────────────────────
# Reset to server.py so cheat sheet shows code on left, keys on right.
Type ":edit server.py"
Enter
Sleep 1s
Type ",?" Type ",?"
Sleep 5.5s Sleep 2s
Type "q" Type "q"
Sleep 0.5s Sleep 0.5s
# ── done ─────────────────────────────────────────────────────────────────── # Open file browser
Type ",e"
Sleep 1.5s
Escape
Sleep 0.5s
# Quit
Type ":qa!" Type ":qa!"
Enter Enter
Sleep 0.5s Sleep 0.5s

View file

@ -4,21 +4,6 @@
### Added ### Added
- `:ChopsticksStatus` diagnostic command — checks system tools, LSP servers, linters, formatters - `: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 ## 2.1.0 — 2025-04-22
@ -37,8 +22,8 @@
- Sidebar toggle (`,e` / `,E`) — left-side netrw with `topleft vertical`, winfixwidth, proper toggle - Sidebar toggle (`,e` / `,E`) — left-side netrw with `topleft vertical`, winfixwidth, proper toggle
- Enriched statusline — SLMode, SLGit, SLAle, SLFlags - Enriched statusline — SLMode, SLGit, SLAle, SLFlags
- Toggle feedback — F2/F3/F4/F6/`,ss` echo current state - Toggle feedback — F2/F3/F4/F6/`,ss` echo current state
- `vim .` layout — netrw left + Startify right (removed in later refactor) - `vim .` layout — netrw left + Startify right, proper proportions
- Interactive tutorial (`:ChopsticksLearn` — removed in later release) - Interactive tutorial (`:ChopsticksLearn`)
### Removed (Unix minimalism refactor) ### Removed (Unix minimalism refactor)
- **565 lines** of dead code and bloat - **565 lines** of dead code and bloat

View file

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

View file

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

View file

@ -160,13 +160,9 @@ augroup END
" ── Performance ───────────────────────────────────────────────────────────── " ── Performance ─────────────────────────────────────────────────────────────
set synmaxcol=200 set synmaxcol=200
set ttyfast
set lazyredraw set lazyredraw
set complete-=i set complete-=i
if executable('rg')
set grepprg=rg\ --vimgrep\ --smart-case
set grepformat=%f:%l:%c:%m
endif
set updatetime=300 set updatetime=300
set shortmess+=cI set shortmess+=cI
@ -187,10 +183,6 @@ set exrc
set secure set secure
set sessionoptions=blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal 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 ────────────────────────────────────────────────────────── " ── Format Options ──────────────────────────────────────────────────────────
augroup ChopstickFormatOptions augroup ChopstickFormatOptions

View file

@ -25,7 +25,7 @@ if exists('##TextYankPost') && has('timers')
if v:event.operator !=# 'y' | return | endif if v:event.operator !=# 'y' | return | endif
let l:m = matchadd('IncSearch', let l:m = matchadd('IncSearch',
\ printf('\%%>%dl\%%<%dl', line("'[") - 1, line("']") + 1)) \ printf('\%%>%dl\%%<%dl', line("'[") - 1, line("']") + 1))
call timer_start(150, {-> execute('silent! call matchdelete(' . l:m . ')')}) call timer_start(150, {-> matchdelete(l:m)})
endfunction endfunction
augroup ChopstickYankHL augroup ChopstickYankHL
autocmd! autocmd!

View file

@ -7,15 +7,13 @@ let g:is_tty = empty($TERM) || $TERM ==# 'dumb' || $TERM =~# 'linux'
let g:has_true_color = ($COLORTERM ==# 'truecolor' || $COLORTERM ==# '24bit') let g:has_true_color = ($COLORTERM ==# 'truecolor' || $COLORTERM ==# '24bit')
" Skip built-in plugins we never use " Skip built-in plugins we never use
let g:loaded_2html_plugin = 1 let g:loaded_2html_plugin = 1
let g:loaded_getscriptPlugin = 1 let g:loaded_getscriptPlugin = 1
let g:loaded_gzip = 1 let g:loaded_gzip = 1
let g:loaded_logiPat = 1 let g:loaded_logipat = 1
let g:loaded_rrhelper = 1 let g:loaded_rrhelper = 1
let g:loaded_tarPlugin = 1 let g:loaded_tarPlugin = 1
let g:loaded_vimballPlugin = 1 let g:loaded_vimballPlugin = 1
let g:loaded_zipPlugin = 1 let g:loaded_zipPlugin = 1
let g:loaded_tutor_mode_plugin = 1 let g:loaded_tutor_mode_plugin = 1
let g:loaded_spellfile_plugin = 1 let g:loaded_spellfile_plugin = 1
let g:loaded_openPlugin = 1
let g:loaded_manpager_plugin = 1

View file

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

View file

@ -50,6 +50,4 @@ if exists('g:plugs["ale"]')
nnoremap <silent> [e :ALEPrevious<cr> nnoremap <silent> [e :ALEPrevious<cr>
nnoremap <silent> ]e :ALENext<cr> nnoremap <silent> ]e :ALENext<cr>
nnoremap <silent> <leader>aD :ALEDetail<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 endif

View file

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

View file

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

View file

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

View file

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