Compare commits

...

23 commits

Author SHA1 Message Date
8e6dcc6e97
Fix opt-in keymap install messaging (#61)
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
test / docs (push) Has been cancelled
2026-05-13 18:28:31 +08:00
2514d2e803
Fix noninteractive plugin installation (#59) 2026-05-13 18:22:12 +08:00
b2835d3cae
Make terminal keymaps opt-in (#57) 2026-05-13 17:24:45 +08:00
23f6ed98ec
Make auto-pairs opt-in (#55) 2026-05-13 17:18:01 +08:00
043e8e4a58
Make completion keymaps opt-in (#53) 2026-05-13 17:08:21 +08:00
8f89939a57
Make sudo-save mapping opt-in (#51) 2026-05-13 15:47:59 +08:00
ea8c3054e1
Move visual selection search to leader mapping (#49) 2026-05-13 15:01:45 +08:00
2aa28304ca
Restore command-line Ctrl-P and Ctrl-N (#47) 2026-05-13 14:50:27 +08:00
ff0de570de
Move last-change selection to leader mapping (#45) 2026-05-13 14:44:58 +08:00
fd081a2397
Make Ctrl-S save opt-in (#42)
* Make Ctrl-S save opt in

* Avoid hanging CI Vim installation

* Keep Homebrew Vim on macOS CI
2026-05-13 14:32:50 +08:00
76aa3efd72
Make jk escape opt in (#40) 2026-05-13 14:05:22 +08:00
f278e9f3b6
Restore native Ctrl window keys (#38) 2026-05-13 13:56:28 +08:00
d03f7129d8
Move file search to leader mapping (#36) 2026-05-13 13:50:27 +08:00
e1c2ea3888
Restore native Space motion behavior (#34) 2026-05-13 13:39:59 +08:00
861e18b86c
Restore native Q behavior (#32) 2026-05-13 13:32:35 +08:00
8e2505bfca
Restore native Y yank behavior (#30) 2026-05-13 13:28:21 +08:00
49aae12415
Restore native zero motion (#28) 2026-05-13 13:24:04 +08:00
2f7d488c8c
Move LSP navigation to native-first mappings (#26) 2026-05-13 13:18:08 +08:00
5544b74545
Improve first-time LSP setup guidance (#25) 2026-05-13 12:45:53 +08:00
c98d04200c
Document native-first keymap policy (#23) 2026-05-13 12:39:40 +08:00
9fde301a2c
Use temp output for C file runner (#21) 2026-05-13 12:39:08 +08:00
097c8abcd7
Report LSP status without autoload false negatives (#20) 2026-05-13 12:38:32 +08:00
1c54077487
Make bootstrap dry-run avoid git installation (#19) 2026-05-13 12:37:46 +08:00
14 changed files with 396 additions and 115 deletions

View file

@ -16,11 +16,15 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install Vim - name: Install Vim
timeout-minutes: 5
run: | run: |
if [ "$(uname)" = "Darwin" ]; then if [ "$(uname)" = "Darwin" ]; then
brew install vim brew install vim
elif command -v vim >/dev/null 2>&1; then
vim --version | head -1
else else
sudo apt-get update && sudo apt-get install -y vim sudo apt-get update
sudo apt-get install -y vim
fi fi
- name: Install vim-plug - name: Install vim-plug

2
.vimrc
View file

@ -11,6 +11,8 @@ endif
if exists('g:chopsticks_loaded') | finish | endif if exists('g:chopsticks_loaded') | finish | endif
let g:chopsticks_loaded = 1 let g:chopsticks_loaded = 1
let g:surround_no_insert_mappings = get(g:, 'surround_no_insert_mappings', 1)
function! s:load(mod) abort function! s:load(mod) abort
execute 'source ' . fnameescape(g:chopsticks_dir . '/modules/' . a:mod . '.vim') execute 'source ' . fnameescape(g:chopsticks_dir . '/modules/' . a:mod . '.vim')
endfunction endfunction

View file

@ -5,16 +5,18 @@
1. **No Node.js dependencies.** The LSP engine is pure VimScript. Some language servers need Node — that's fine. The config itself must not. 1. **No Node.js dependencies.** The LSP engine is pure VimScript. Some language servers need Node — that's fine. The config itself must not.
2. **Startup matters.** Run `vim -u .vimrc -i NONE --startuptime /tmp/s.log -es -N -c qa!` before and after. If your change adds >1ms, it needs a good reason. 2. **Startup matters.** Run `vim -u .vimrc -i NONE --startuptime /tmp/s.log -es -N -c qa!` before and after. If your change adds >1ms, it needs a good reason.
3. **Works on TTY.** Test over SSH. If it breaks in a terminal without true color, fix it or gate it behind `g:is_tty`. 3. **Works on TTY.** Test over SSH. If it breaks in a terminal without true color, fix it or gate it behind `g:is_tty`.
4. **One module, one concern.** Don't put git config in lsp.vim. 4. **Native-first keymaps.** Enhance Vim's native behavior instead of replacing it. Do not override built-in motions, operators, text objects, or help-oriented keys for discoverability alone; prefer leader-prefixed or otherwise non-conflicting ergonomic mappings.
5. **One module, one concern.** Don't put git config in lsp.vim.
## Adding a plugin ## Adding a plugin
1. Add the `Plug` line to `modules/plugins.vim` 1. Add the `Plug` line to `modules/plugins.vim`
2. If it's not needed at startup, lazy-load it: `Plug 'foo/bar', { 'on': 'FooCommand' }` 2. If it's not needed at startup, lazy-load it: `Plug 'foo/bar', { 'on': 'FooCommand' }`
3. Put config in the appropriate module 3. Put config in the appropriate module
4. Update the cheat sheet in `modules/tools.vim` if you add keybindings 4. Check new mappings against native Vim behavior before adding them
5. Run `scripts/test.sh vim` locally after installing plugins 5. Update the cheat sheet in `modules/tools.vim` if you add keybindings
6. Test on both macOS and Linux when changing terminal or package-manager behavior 6. Run `scripts/test.sh vim` locally after installing plugins
7. Test on both macOS and Linux when changing terminal or package-manager behavior
## Local tests ## Local tests

View file

@ -29,17 +29,16 @@ cd ~/.vim && ./install.sh --configure-only --profile=full
| Mode | Enter | Leave | | Mode | Enter | Leave |
| ------ | --------------- | ------------- | | ------ | --------------- | ------------- |
| Normal | startup default | — | | Normal | startup default | — |
| Insert | `i` / `a` / `o` | `Esc` or `jk` | | Insert | `i` / `a` / `o` | `Esc` |
| Visual | `v` / `V` | `Esc` | | Visual | `v` / `V` | `Esc` |
## Survival ## Survival
``` ```
Esc / jk back to Normal Esc back to Normal
,w save ,w save
,x save + quit ,x save + quit
:q! force quit :q! force quit
Ctrl+s save from any mode
,? cheat sheet (toggle sidebar) ,? cheat sheet (toggle sidebar)
``` ```
@ -57,8 +56,8 @@ Ctrl+p fuzzy find file (git-aware)
## Write code ## Write code
``` ```
gd go to definition ,dd go to definition
K hover docs ,dk hover docs
,rn rename symbol ,rn rename symbol
,ca code action ,ca code action
,f format ,f format
@ -92,7 +91,7 @@ Alt+j / Alt+k move line
## Navigate ## Navigate
``` ```
Ctrl+h/j/k/l splits + tmux panes <C-w>h/j/k/l splits
,h / ,l prev / next buffer ,h / ,l prev / next buffer
,z maximize window ,z maximize window
,tv / ,th terminal ,tv / ,th terminal

View file

@ -81,6 +81,12 @@ profile or uses `engineer`.
let g:chopsticks_profile = 'minimal' " core navigation/editing/git/markdown let g:chopsticks_profile = 'minimal' " core navigation/editing/git/markdown
let g:chopsticks_profile = 'engineer' " default: LSP, ALE, syntax extras let g:chopsticks_profile = 'engineer' " default: LSP, ALE, syntax extras
let g:chopsticks_profile = 'full' " engineer + heavier Markdown feedback let g:chopsticks_profile = 'full' " engineer + heavier Markdown feedback
let g:chopsticks_enable_jk_escape = 1 " optional: insert-mode jk exits insert
let g:chopsticks_enable_ctrl_s_save = 1 " optional: Ctrl-S saves
let g:chopsticks_enable_sudo_save_bang = 1 " optional: :w!! sudo save
let g:chopsticks_enable_completion_keymaps = 1 " optional: Tab/Enter completion
let g:chopsticks_enable_auto_pairs = 1 " optional: automatic pair insertion
let g:chopsticks_enable_terminal_keymaps = 1 " optional: terminal Esc/Ctrl navigation
``` ```
`minimal` avoids LSP, ALE, completion plugins, extra language syntax plugins, `minimal` avoids LSP, ALE, completion plugins, extra language syntax plugins,
@ -96,12 +102,12 @@ active profile and only shows keys for enabled features.
Leader: `,` Leader: `,`
``` ```
Ctrl+p fuzzy find file gd go to definition ,ff fuzzy find file ,dd go to definition
,rg ripgrep project K hover docs ,rg ripgrep project ,dk hover docs
,e toggle file sidebar ,cr run current file ,e toggle file sidebar ,cr run current file
,gs git status ,f format ,gs git status ,f format
,w save ,q quit ,w save ,q quit
jk exit insert mode ,? cheat sheet Esc exit insert mode ,? cheat sheet
``` ```
<details> <details>
@ -109,11 +115,11 @@ jk exit insert mode ,? cheat sheet
### Files ### Files
`Ctrl+p` find | `,b` buffers | `,rg` grep | `,rG` grep word | `,fh` recent | `,fl` lines | `,e` browser | `,E` browser (file dir) | `,,` last file `,ff` find | `,b` buffers | `,rg` grep | `,rG` grep word | `,fh` recent | `,fl` lines | `,e` browser | `,E` browser (file dir) | `,,` last file
### Code ### Code
`gd` def | `gy` type | `gi` impl | `gr` refs | `K` docs | `[g` `]g` diagnostics | `[e` `]e` ALE errors | `,rn` rename | `,ca` action | `,o` outline | `,cr` run `,dd` def | `,dt` type | `,di` impl | `,dr` refs | `,dk` docs | `,dp` `,dn` diagnostics | `[e` `]e` ALE errors | `,rn` rename | `,ca` action | `,o` outline | `,cr` run
### Edit ### Edit
@ -125,7 +131,7 @@ jk exit insert mode ,? cheat sheet
### Windows ### Windows
`Ctrl+hjkl` navigate (+ tmux) | `,z` maximize | `,h` `,l` buffers | `,bd` close buffer | `,=` `,` resize | `,tv` `,th` terminal | `Esc Esc` exit terminal `<C-w>hjkl` navigate | `,z` maximize | `,h` `,l` buffers | `,bd` close buffer | `,=` `,` resize | `,tv` `,th` terminal
### Markdown ### Markdown
@ -216,7 +222,7 @@ Each module is self-contained. Comment out one line in `.vimrc` to disable it. A
| Plugins not loading | `:PlugInstall` then `:PlugUpdate` | | Plugins not loading | `:PlugInstall` then `:PlugUpdate` |
| LSP not starting | `:LspInstallServer` for current filetype | | LSP not starting | `:LspInstallServer` for current filetype |
| Colors wrong | `export COLORTERM=truecolor` in shell rc | | Colors wrong | `export COLORTERM=truecolor` in shell rc |
| `Ctrl+s` freezes | `stty -ixon` in shell rc | | Optional `Ctrl+s` freezes | `stty -ixon` in shell rc |
| Everything slow | Large file? Auto-disabled >10MB | | Everything slow | Large file? Auto-disabled >10MB |
| What's installed? | `:ChopsticksStatus` shows tools, LSP, linters | | What's installed? | `:ChopsticksStatus` shows tools, LSP, linters |

33
get.sh
View file

@ -79,7 +79,13 @@ echo " Dest: $DEST"
# ── git ─────────────────────────────────────────────────────────────────────── # ── git ───────────────────────────────────────────────────────────────────────
step "Checking for git" step "Checking for git"
if ! command -v git >/dev/null 2>&1; then HAS_GIT=0
command -v git >/dev/null 2>&1 && HAS_GIT=1
if [[ $HAS_GIT -eq 0 ]]; then
if [[ $DRY_RUN -eq 1 ]]; then
warn "git not found — would need to install git before a real install"
else
warn "git not found — attempting to install" warn "git not found — attempting to install"
if command -v apt-get >/dev/null 2>&1; then sudo apt-get install -y git >/dev/null 2>&1 if command -v apt-get >/dev/null 2>&1; then sudo apt-get install -y git >/dev/null 2>&1
elif command -v pacman >/dev/null 2>&1; then sudo pacman -S --noconfirm git >/dev/null 2>&1 elif command -v pacman >/dev/null 2>&1; then sudo pacman -S --noconfirm git >/dev/null 2>&1
@ -87,8 +93,31 @@ if ! command -v git >/dev/null 2>&1; then
elif command -v brew >/dev/null 2>&1; then brew install git >/dev/null 2>&1 elif command -v brew >/dev/null 2>&1; then brew install git >/dev/null 2>&1
else die "git is required. Install it manually then re-run."; fi else die "git is required. Install it manually then re-run."; fi
command -v git >/dev/null 2>&1 || die "git install failed. Try: sudo apt install git" command -v git >/dev/null 2>&1 || die "git install failed. Try: sudo apt install git"
HAS_GIT=1
fi
fi
if [[ $HAS_GIT -eq 1 ]]; then
ok "git $(git --version | awk '{print $3}')"
elif [[ $DRY_RUN -eq 1 ]]; then
info "Would require: git"
else
die "git is required. Install it manually then re-run."
fi
if [[ $DRY_RUN -eq 1 && $HAS_GIT -eq 0 ]]; then
step "Setting up $DEST"
if [[ -d "$DEST/.git" ]]; then
info "Would inspect existing git repo at $DEST"
info "Would update it only if its origin is $REPO"
elif [[ -d "$DEST" ]]; then
die "$DEST exists but git is unavailable, so dry-run cannot verify whether it is chopsticks.
Install git and re-run dry-run for the full safety check."
else
info "Would clone $REPO to $DEST"
fi
info "Would run: bash install.sh ${INSTALLER_ARGS[*]:-(no installer options)}"
exit 0
fi fi
ok "git $(git --version | awk '{print $3}')"
# ── Clone or update ─────────────────────────────────────────────────────────── # ── Clone or update ───────────────────────────────────────────────────────────
step "Setting up $DEST" step "Setting up $DEST"

View file

@ -493,10 +493,21 @@ fi
# vim # vim
[ -f "$SCRIPT_DIR/.vimrc" ] || die ".vimrc not found in $SCRIPT_DIR — is this the chopsticks repo?" [ -f "$SCRIPT_DIR/.vimrc" ] || die ".vimrc not found in $SCRIPT_DIR — is this the chopsticks repo?"
if ! command -v vim >/dev/null 2>&1; then resolve_vim() {
if [[ $OS == "macos" ]]; then
for vim_path in /opt/homebrew/bin/vim /usr/local/bin/vim; do
[[ -x "$vim_path" ]] && { echo "$vim_path"; return; }
done
fi
command -v vim 2>/dev/null || true
}
VIM_BIN="$(resolve_vim)"
if [[ -z "$VIM_BIN" ]]; then
warn "vim not found — attempting to install" warn "vim not found — attempting to install"
if pkg_install vim vim vim vim 2>/dev/null; then if pkg_install vim vim vim vim 2>/dev/null; then
ok "vim installed" ok "vim installed"
VIM_BIN="$(resolve_vim)"
else else
die "vim not found and could not be installed automatically. die "vim not found and could not be installed automatically.
Ubuntu/Debian: sudo apt install vim Ubuntu/Debian: sudo apt install vim
@ -505,8 +516,9 @@ if ! command -v vim >/dev/null 2>&1; then
macOS: brew install vim" macOS: brew install vim"
fi fi
fi fi
ok "Found: $(vim --version | head -n1)" [[ -n "$VIM_BIN" ]] || die "vim installed but not found in PATH"
vim --version | grep -q 'Vi IMproved 8\|Vi IMproved 9' || \ ok "Found: $("$VIM_BIN" --version | head -n1) ($VIM_BIN)"
"$VIM_BIN" --version | grep -q 'Vi IMproved 8\|Vi IMproved 9' || \
warn "Vim 8.0+ recommended for full async/LSP support — some features may not work" warn "Vim 8.0+ recommended for full async/LSP support — some features may not work"
# Node.js (optional — vim-lsp needs no Node.js; only npm formatters do) # Node.js (optional — vim-lsp needs no Node.js; only npm formatters do)
@ -596,14 +608,15 @@ fi
step "Installing Vim plugins" step "Installing Vim plugins"
_vim_run() { _vim_run() {
if { true </dev/tty; } 2>/dev/null; then local vim_cmd="$1" batch_script
if [[ -t 1 ]] && { true </dev/tty; } 2>/dev/null; then
# Interactive terminal: vim uses alternate screen; user sees progress # Interactive terminal: vim uses alternate screen; user sees progress
vim "$@" </dev/tty "$VIM_BIN" -u "$SCRIPT_DIR/.vimrc" +"$vim_cmd" +qall </dev/tty
else else
# No TTY (SSH batch, CI): do NOT redirect stdin (causes "Error reading input" exit) # Batch/agent/CI: avoid vim-plug's screen UI, which may try to read input.
# or stdout (breaks async job callbacks — partial install). batch_script="$_TMPDIR/vim-run.vim"
# Redirect only stderr; escape sequences appear on stdout but installation succeeds. printf '%s\nqa!\n' "$vim_cmd" > "$batch_script"
vim --not-a-term "$@" 2>/dev/null "$VIM_BIN" -u "$SCRIPT_DIR/.vimrc" -i NONE -n -es -N -S "$batch_script"
fi fi
} }
@ -628,7 +641,7 @@ qa!
VIMEOF VIMEOF
CHOPSTICKS_REQUIRED_PLUGINS="$required_file" \ CHOPSTICKS_REQUIRED_PLUGINS="$required_file" \
vim -u "$SCRIPT_DIR/.vimrc" -i NONE -es -N -S "$verify_script" >/dev/null 2>&1 || return 1 "$VIM_BIN" -u "$SCRIPT_DIR/.vimrc" -i NONE -es -N -S "$verify_script" >/dev/null 2>&1 || return 1
[[ -s "$required_file" ]] || return 1 [[ -s "$required_file" ]] || return 1
while IFS= read -r dir; do while IFS= read -r dir; do
@ -646,8 +659,8 @@ VIMEOF
if [[ -d "$HOME/.vim/plugged" ]] && [[ -n "$(find "$HOME/.vim/plugged" -mindepth 1 -maxdepth 1 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" 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!' || true # remove plugins no longer in vimrc; ignore exit code (none expected)
_vim_run +'PlugInstall --sync' +qall || true # fzf post-install hook may exit non-zero; harmless _vim_run 'PlugInstall --sync' || true # fzf post-install hook may exit non-zero; harmless
verify_plugins || die "Plugin installation failed — retry with a stable network connection." verify_plugins || die "Plugin installation failed — retry with a stable network connection."
@ -1062,14 +1075,18 @@ fi
# ============================================================================ # ============================================================================
step "LSP language servers" step "LSP language servers"
info "vim-lsp installs language servers on demand — no action needed here." if [[ $CONFIG_PROFILE == "minimal" ]]; then
info "" skip "LSP disabled by minimal profile"
info "To install a server: open a source file in Vim and run:" else
info " :LspInstallServer" info "vim-lsp installs language servers on demand — no action needed here."
info "" info ""
info "Supported: Python, JS/TS, Go, Rust, C/C++, Shell, HTML, CSS, JSON, YAML, Markdown, SQL" info "To install a server: open a source file in Vim and run:"
info "" info " :LspInstallServer"
info "For Markdown LSP (marksman), the installer already handled it above." info ""
info "Supported: Python, JS/TS, Go, Rust, C/C++, Shell, HTML, CSS, JSON, YAML, Markdown, SQL"
info ""
info "For Markdown LSP (marksman), the installer already handled it above."
fi
# ============================================================================ # ============================================================================
# Summary # Summary
@ -1109,13 +1126,18 @@ echo -e " ${CYAN}vim .${NC} Open dashboard in current directory"
echo -e " ${CYAN}vim myfile${NC} Edit a specific file" echo -e " ${CYAN}vim myfile${NC} Edit a specific file"
echo "" echo ""
echo -e "${BOLD} First steps inside Vim${NC}" echo -e "${BOLD} First steps inside Vim${NC}"
echo -e " ${CYAN}Esc${NC} or ${CYAN}jk${NC} Exit insert mode → back to Normal" echo -e " ${CYAN}Esc${NC} Exit insert mode → back to Normal"
echo -e " ${CYAN}:q!${NC} + Enter Emergency quit without saving" echo -e " ${CYAN}:q!${NC} + Enter Emergency quit without saving"
echo -e " ${CYAN},x${NC} Save and quit" echo -e " ${CYAN},x${NC} Save and quit"
echo -e " ${CYAN},?${NC} Open cheat sheet" echo -e " ${CYAN},?${NC} Open cheat sheet"
echo -e " ${CYAN}:LspInstallServer${NC} Install LSP for current filetype" if [[ $CONFIG_PROFILE != "minimal" ]]; then
echo "" echo -e " ${CYAN}:LspInstallServer${NC} Install LSP for current filetype"
echo -e "${YELLOW}[!]${NC} Ctrl+s is mapped to save in Vim." fi
echo " If it freezes your terminal, add this to ~/.bashrc or ~/.zshrc:" if [[ -f "$LOCAL_CONFIG" ]] && \
echo -e " ${CYAN}stty -ixon${NC}" grep -Eq '^[[:space:]]*let[[:space:]]+g:chopsticks_enable_ctrl_s_save[[:space:]]*=[[:space:]]*1([[:space:]]|$)' "$LOCAL_CONFIG"; then
echo ""
echo -e "${YELLOW}[!]${NC} Ctrl+s is mapped to save in Vim."
echo " If it freezes your terminal, add this to ~/.bashrc or ~/.zshrc:"
echo -e " ${CYAN}stty -ixon${NC}"
fi
echo "" echo ""

View file

@ -108,12 +108,7 @@ nnoremap <leader>h :bprevious<cr>
nnoremap <leader>cd :lcd %:p:h<cr>:pwd<cr> nnoremap <leader>cd :lcd %:p:h<cr>:pwd<cr>
nnoremap 0 ^ nnoremap <leader>v `[v`]
vnoremap 0 ^
nnoremap gV `[v`]
cnoremap <C-p> <Up>
cnoremap <C-n> <Down>
nnoremap <M-j> :m .+1<CR>== nnoremap <M-j> :m .+1<CR>==
nnoremap <M-k> :m .-2<CR>== nnoremap <M-k> :m .-2<CR>==
@ -127,12 +122,9 @@ nnoremap <silent> <F3> :set invnumber<CR>:echo 'Line numbers: ' . (&number ? 'ON
nnoremap <silent> <F4> :set invrelativenumber<CR>:echo 'Relative numbers: ' . (&relativenumber ? 'ON' : 'OFF')<CR> nnoremap <silent> <F4> :set invrelativenumber<CR>:echo 'Relative numbers: ' . (&relativenumber ? 'ON' : 'OFF')<CR>
nnoremap <silent> <F6> :set list!<CR>:echo 'List chars: ' . (&list ? 'ON' : 'OFF')<CR> nnoremap <silent> <F6> :set list!<CR>:echo 'List chars: ' . (&list ? 'ON' : 'OFF')<CR>
nnoremap <space> za if get(g:, 'chopsticks_enable_jk_escape', 0)
inoremap jk <Esc>
nnoremap Y y$ endif
nnoremap Q <nop>
inoremap jk <Esc>
vnoremap < <gv vnoremap < <gv
vnoremap > >gv vnoremap > >gv
@ -140,10 +132,12 @@ vnoremap > >gv
nnoremap n nzzzv nnoremap n nzzzv
nnoremap N Nzzzv nnoremap N Nzzzv
vnoremap // y/\V<C-r>=escape(@",'/\')<CR><CR> vnoremap <leader>/ y/\V<C-r>=escape(@",'/\')<CR><CR>
nnoremap <silent> <C-s> :w<CR> if get(g:, 'chopsticks_enable_ctrl_s_save', 0)
inoremap <silent> <C-s> <C-o>:w<CR> nnoremap <silent> <C-s> :w<CR>
inoremap <silent> <C-s> <C-o>:w<CR>
endif
nnoremap <C-d> <C-d>zz nnoremap <C-d> <C-d>zz
vnoremap <C-d> <C-d>zz vnoremap <C-d> <C-d>zz

View file

@ -24,6 +24,10 @@ let g:chopsticks_enable_ui_extras = get(g:, 'chopsticks_enable_ui_extras',
\ !s:profile_minimal) \ !s:profile_minimal)
let g:chopsticks_enable_markdown_preview = get(g:, let g:chopsticks_enable_markdown_preview = get(g:,
\ 'chopsticks_enable_markdown_preview', !s:profile_minimal) \ 'chopsticks_enable_markdown_preview', !s:profile_minimal)
let g:chopsticks_enable_auto_pairs = get(g:,
\ 'chopsticks_enable_auto_pairs', 0)
let g:chopsticks_enable_terminal_keymaps = get(g:,
\ 'chopsticks_enable_terminal_keymaps', 0)
let g:chopsticks_markdown_lint = get(g:, 'chopsticks_markdown_lint', let g:chopsticks_markdown_lint = get(g:, 'chopsticks_markdown_lint',
\ s:profile_full) \ s:profile_full)

View file

@ -51,9 +51,11 @@ let g:asyncomplete_auto_popup = 1
let g:asyncomplete_auto_completeopt = 0 let g:asyncomplete_auto_completeopt = 0
let g:asyncomplete_popup_delay = 50 let g:asyncomplete_popup_delay = 50
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>" if get(g:, 'chopsticks_enable_completion_keymaps', 0)
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>" inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <CR> pumvisible() ? asyncomplete#close_popup() : "\<CR>" inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <expr> <CR> pumvisible() ? asyncomplete#close_popup() : "\<CR>"
endif
" ── Buffer Keymaps ────────────────────────────────────────────────────────── " ── Buffer Keymaps ──────────────────────────────────────────────────────────
@ -63,14 +65,14 @@ function! s:on_lsp_buffer_enabled() abort
setlocal signcolumn=yes setlocal signcolumn=yes
endif endif
nmap <buffer> gd <plug>(lsp-definition) nmap <buffer> <leader>dd <plug>(lsp-definition)
nmap <buffer> gy <plug>(lsp-type-definition) nmap <buffer> <leader>dt <plug>(lsp-type-definition)
nmap <buffer> gi <plug>(lsp-implementation) nmap <buffer> <leader>di <plug>(lsp-implementation)
nmap <buffer> gr <plug>(lsp-references) nmap <buffer> <leader>dr <plug>(lsp-references)
nmap <buffer> [g <plug>(lsp-previous-diagnostic) nmap <buffer> <leader>dp <plug>(lsp-previous-diagnostic)
nmap <buffer> ]g <plug>(lsp-next-diagnostic) nmap <buffer> <leader>dn <plug>(lsp-next-diagnostic)
nmap <buffer> K <plug>(lsp-hover) nmap <buffer> <leader>dk <plug>(lsp-hover)
nmap <buffer> <leader>rn <plug>(lsp-rename) nmap <buffer> <leader>rn <plug>(lsp-rename)
nmap <buffer> <leader>ca <plug>(lsp-code-action) nmap <buffer> <leader>ca <plug>(lsp-code-action)

View file

@ -47,7 +47,7 @@ function! s:SmartFiles() abort
endfunction endfunction
if exists('g:plugs["fzf.vim"]') if exists('g:plugs["fzf.vim"]')
nnoremap <C-p> :call <SID>SmartFiles()<CR> nnoremap <leader>ff :call <SID>SmartFiles()<CR>
nnoremap <leader>b :Buffers<CR> nnoremap <leader>b :Buffers<CR>
nnoremap <leader>rg :Rg<CR> nnoremap <leader>rg :Rg<CR>
nnoremap <leader>rG :RgWord<CR> nnoremap <leader>rG :RgWord<CR>
@ -86,15 +86,6 @@ command! -bang -nargs=* RgWord
\ .shellescape(expand('<cword>')), 1, s: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) 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 ────────────────────────────────────────────────── " ── Window Maximize Toggle ──────────────────────────────────────────────────
function! s:ToggleMaximize() abort function! s:ToggleMaximize() abort
@ -115,9 +106,11 @@ nnoremap <silent> <leader>z :call <SID>ToggleMaximize()<CR>
if has('terminal') if has('terminal')
nnoremap <leader>tv :terminal<CR> nnoremap <leader>tv :terminal<CR>
nnoremap <leader>th :terminal ++rows=10<CR> nnoremap <leader>th :terminal ++rows=10<CR>
if g:chopsticks_enable_terminal_keymaps
tnoremap <Esc><Esc> <C-\><C-n> tnoremap <Esc><Esc> <C-\><C-n>
tnoremap <C-h> <C-\><C-n><C-w>h tnoremap <C-h> <C-\><C-n><C-w>h
tnoremap <C-j> <C-\><C-n><C-w>j tnoremap <C-j> <C-\><C-n><C-w>j
tnoremap <C-k> <C-\><C-n><C-w>k tnoremap <C-k> <C-\><C-n><C-w>k
tnoremap <C-l> <C-\><C-n><C-w>l tnoremap <C-l> <C-\><C-n><C-w>l
endif
endif endif

View file

@ -26,9 +26,12 @@ Plug 'tpope/vim-commentary'
Plug 'tpope/vim-repeat' Plug 'tpope/vim-repeat'
Plug 'tpope/vim-sleuth' Plug 'tpope/vim-sleuth'
Plug 'wellle/targets.vim' Plug 'wellle/targets.vim'
Plug 'jiangmiao/auto-pairs'
Plug 'easymotion/vim-easymotion', { 'on': '<Plug>(easymotion' } Plug 'easymotion/vim-easymotion', { 'on': '<Plug>(easymotion' }
if g:chopsticks_enable_auto_pairs
Plug 'jiangmiao/auto-pairs'
endif
if g:chopsticks_enable_lint if g:chopsticks_enable_lint
" ── Linting & Formatting ──────────────────────────────────────────────── " ── Linting & Formatting ────────────────────────────────────────────────
Plug 'dense-analysis/ale' Plug 'dense-analysis/ale'

View file

@ -113,7 +113,11 @@ function! s:RunFile() abort
elseif l:ft ==# 'go' | execute '!go run ' . l:file elseif l:ft ==# 'go' | execute '!go run ' . l:file
elseif l:ft ==# 'rust' | execute '!cargo run' elseif l:ft ==# 'rust' | execute '!cargo run'
elseif l:ft ==# 'sh' | execute '!bash ' . l:file elseif l:ft ==# 'sh' | execute '!bash ' . l:file
elseif l:ft ==# 'c' | execute '!gcc -o /tmp/a.out ' . l:file . ' && /tmp/a.out' elseif l:ft ==# 'c'
let l:out_path = tempname()
let l:out = shellescape(l:out_path)
execute '!gcc -o ' . l:out . ' ' . l:file . ' && ' . l:out
call delete(l:out_path)
elseif l:ft ==# 'lua' | execute '!lua ' . l:file elseif l:ft ==# 'lua' | execute '!lua ' . l:file
elseif l:ft ==# 'ruby' | execute '!ruby ' . l:file elseif l:ft ==# 'ruby' | execute '!ruby ' . l:file
elseif l:ft ==# 'perl' | execute '!perl ' . l:file elseif l:ft ==# 'perl' | execute '!perl ' . l:file
@ -124,7 +128,9 @@ nnoremap <leader>cr :call <SID>RunFile()<CR>
" ── Sudo Save ─────────────────────────────────────────────────────────────── " ── Sudo Save ───────────────────────────────────────────────────────────────
cnoremap w!! w !sudo tee > /dev/null % if get(g:, 'chopsticks_enable_sudo_save_bang', 0)
cnoremap w!! w !sudo tee > /dev/null %
endif
" ── QuickFix ──────────────────────────────────────────────────────────────── " ── QuickFix ────────────────────────────────────────────────────────────────
@ -147,12 +153,58 @@ function! s:Off(name, reason) abort
return ' off ' . a:name . ' (' . a:reason . ')' return ' off ' . a:name . ' (' . a:reason . ')'
endfunction endfunction
function! s:LspCheck(ft, server) abort function! s:PlugDir(name) abort
if !get(g:, 'chopsticks_enable_lsp', 1) if !exists('g:plugs') || !has_key(g:plugs, a:name)
return s:Off(a:ft, 'LSP disabled by profile') return ''
endif endif
if !exists('*lsp#get_server_names') return fnamemodify(get(g:plugs[a:name], 'dir', ''), ':p')
return ' -- ' . a:ft . ' (vim-lsp not loaded)' endfunction
function! s:PlugInstalled(name) abort
let l:dir = s:PlugDir(a:name)
return !empty(l:dir) && isdirectory(l:dir)
endfunction
function! s:LspStackIssue() abort
if !get(g:, 'chopsticks_enable_lsp', 1)
return 'LSP disabled by profile'
endif
if empty(s:PlugDir('vim-lsp'))
return 'vim-lsp not declared by this profile'
endif
if !s:PlugInstalled('vim-lsp')
return 'vim-lsp not installed; run :PlugInstall'
endif
if empty(s:PlugDir('vim-lsp-settings'))
return 'vim-lsp-settings not declared by this profile'
endif
if !s:PlugInstalled('vim-lsp-settings')
return 'vim-lsp-settings not installed; run :PlugInstall'
endif
return ''
endfunction
function! s:LspStackCheck() abort
let l:issue = s:LspStackIssue()
if l:issue ==# 'LSP disabled by profile'
return s:Off('vim-lsp stack', l:issue)
endif
if !empty(l:issue)
return ' -- vim-lsp stack (' . l:issue . ')'
endif
if exists(':LspStatus') == 2 || exists(':LspInstallServer') == 2
return ' OK vim-lsp stack (installed)'
endif
return ' OK vim-lsp stack (installed; not loaded yet)'
endfunction
function! s:LspCheck(ft, server) abort
let l:issue = s:LspStackIssue()
if l:issue ==# 'LSP disabled by profile'
return s:Off(a:ft, l:issue)
endif
if !empty(l:issue)
return ' -- ' . a:ft . ' (' . l:issue . ')'
endif endif
let l:dir = expand('~/.local/share/vim-lsp-settings/servers/' . a:server) let l:dir = expand('~/.local/share/vim-lsp-settings/servers/' . a:server)
if isdirectory(l:dir) if isdirectory(l:dir)
@ -178,6 +230,11 @@ function! s:ChopsticksStatus() abort
call add(l:lines, '') call add(l:lines, '')
call add(l:lines, '── lsp servers ── (:LspInstallServer to install)') call add(l:lines, '── lsp servers ── (:LspInstallServer to install)')
call add(l:lines, s:LspStackCheck())
if get(g:, 'chopsticks_enable_lsp', 1)
call add(l:lines, ' LSP actions are buffer-local and start after a server attaches.')
call add(l:lines, ' Missing one? Open that filetype and run :LspInstallServer once.')
endif
call add(l:lines, s:LspCheck('python', 'pylsp')) call add(l:lines, s:LspCheck('python', 'pylsp'))
call add(l:lines, s:LspCheck('go', 'gopls')) call add(l:lines, s:LspCheck('go', 'gopls'))
call add(l:lines, s:LspCheck('rust', 'rust-analyzer')) call add(l:lines, s:LspCheck('rust', 'rust-analyzer'))
@ -271,7 +328,7 @@ function! s:CheatSheet() abort
\ ' ─────────────────────────────', \ ' ─────────────────────────────',
\ '', \ '',
\ ' ── files ──────────────────', \ ' ── files ──────────────────',
\ ' Ctrl+p find file', \ ' ,ff files',
\ ' ,b buffers', \ ' ,b buffers',
\ ' ,rg grep project', \ ' ,rg grep project',
\ ' ,rG grep word', \ ' ,rG grep word',
@ -288,17 +345,18 @@ function! s:CheatSheet() abort
if l:has_lsp if l:has_lsp
call extend(l:lines, [ call extend(l:lines, [
\ ' gd definition', \ ' ,dd definition',
\ ' gy type definition', \ ' ,dt type definition',
\ ' gi implementation', \ ' ,di implementation',
\ ' gr references', \ ' ,dr references',
\ ' K hover docs', \ ' ,dk hover docs',
\ ' ,rn rename', \ ' ,rn rename',
\ ' ,ca code action', \ ' ,ca code action',
\ ' ,f format', \ ' ,f format',
\ ' ,o outline', \ ' ,o outline',
\ ' [g ]g LSP diagnostics', \ ' ,dp ,dn LSP diagnostics',
\ ' :LspInstallServer setup LSP', \ ' :LspInstallServer setup LSP',
\ ' :ChopsticksStatus check LSP setup',
\ ]) \ ])
endif endif
@ -346,7 +404,7 @@ function! s:CheatSheet() abort
\ ' [x ]x conflict markers', \ ' [x ]x conflict markers',
\ '', \ '',
\ ' ── windows ───────────────', \ ' ── windows ───────────────',
\ ' Ctrl+hjkl navigate splits', \ ' <C-w>hjkl navigate splits',
\ ' ,h ,l prev / next buf', \ ' ,h ,l prev / next buf',
\ ' ,bd close buffer', \ ' ,bd close buffer',
\ ' ,z maximize toggle', \ ' ,z maximize toggle',
@ -366,9 +424,7 @@ function! s:CheatSheet() abort
\ ' ,w save', \ ' ,w save',
\ ' ,q quit', \ ' ,q quit',
\ ' ,x save + quit', \ ' ,x save + quit',
\ ' Ctrl+s save (any mode)', \ ' Esc exit insert',
\ ' jk exit insert',
\ ' :w!! sudo save',
\ ' ,ev edit vimrc', \ ' ,ev edit vimrc',
\ ' ,sv reload vimrc', \ ' ,sv reload vimrc',
\ ' :ChopsticksStatus health', \ ' :ChopsticksStatus health',

View file

@ -94,6 +94,22 @@ check_bootstrap() {
grep -q 'Would clone' "$TMP_ROOT/get-dry-run.txt" grep -q 'Would clone' "$TMP_ROOT/get-dry-run.txt"
test ! -e "$TMP_ROOT/bootstrap" test ! -e "$TMP_ROOT/bootstrap"
mkdir -p "$TMP_ROOT/no-git-bin"
printf '%s\n' \
'#!/usr/bin/env bash' \
"echo \"brew was called\" >> \"\$BREW_LOG\"" \
'exit 42' > "$TMP_ROOT/no-git-bin/brew"
chmod +x "$TMP_ROOT/no-git-bin/brew"
BREW_LOG="$TMP_ROOT/no-git-brew.log" \
PATH="$TMP_ROOT/no-git-bin" \
CHOPSTICKS_DEST="$TMP_ROOT/no-git-bootstrap" \
/bin/bash ./get.sh --dry-run --profile=full \
| tee "$TMP_ROOT/get-no-git-dry-run.txt"
grep -q 'Would require: git' "$TMP_ROOT/get-no-git-dry-run.txt"
grep -q 'Would clone' "$TMP_ROOT/get-no-git-dry-run.txt"
test ! -e "$TMP_ROOT/no-git-brew.log"
test ! -e "$TMP_ROOT/no-git-bootstrap"
mkdir -p "$TMP_ROOT/not-chopsticks" mkdir -p "$TMP_ROOT/not-chopsticks"
git -c init.defaultBranch=main init "$TMP_ROOT/not-chopsticks" >/dev/null git -c init.defaultBranch=main init "$TMP_ROOT/not-chopsticks" >/dev/null
git -C "$TMP_ROOT/not-chopsticks" remote add origin https://github.com/example/not-chopsticks.git git -C "$TMP_ROOT/not-chopsticks" remote add origin https://github.com/example/not-chopsticks.git
@ -152,7 +168,7 @@ check_vim() {
vim -u NONE -i NONE -es -N \ vim -u NONE -i NONE -es -N \
-c 'let g:chopsticks_profile = "minimal"' \ -c 'let g:chopsticks_profile = "minimal"' \
-c 'source .vimrc' \ -c 'source .vimrc' \
-c 'if has_key(g:plugs, "ale") || has_key(g:plugs, "vim-lsp") || has_key(g:plugs, "vim-lsp-settings") || has_key(g:plugs, "asyncomplete.vim") | cquit | endif' \ -c 'if has_key(g:plugs, "ale") || has_key(g:plugs, "vim-lsp") || has_key(g:plugs, "vim-lsp-settings") || has_key(g:plugs, "asyncomplete.vim") || has_key(g:plugs, "auto-pairs") | cquit | endif' \
-c 'qa!' 2>&1 -c 'qa!' 2>&1
mkdir -p "$TMP_ROOT/local" mkdir -p "$TMP_ROOT/local"
@ -160,16 +176,131 @@ check_vim() {
vim -u NONE -i NONE -es -N \ vim -u NONE -i NONE -es -N \
-c "let g:chopsticks_local_config = '$TMP_ROOT/local/config.vim'" \ -c "let g:chopsticks_local_config = '$TMP_ROOT/local/config.vim'" \
-c 'source .vimrc' \ -c 'source .vimrc' \
-c 'if g:chopsticks_profile !=# "minimal" || has_key(g:plugs, "ale") || has_key(g:plugs, "vim-lsp") | cquit | endif' \ -c 'if g:chopsticks_profile !=# "minimal" || has_key(g:plugs, "ale") || has_key(g:plugs, "vim-lsp") || has_key(g:plugs, "auto-pairs") | cquit | endif' \
-c 'qa!' 2>&1 -c 'qa!' 2>&1
mkdir -p "$TMP_ROOT/xdg" mkdir -p "$TMP_ROOT/xdg"
printf "%s\n" "let g:chopsticks_profile = 'minimal'" > "$TMP_ROOT/xdg/chopsticks.vim" printf "%s\n" "let g:chopsticks_profile = 'minimal'" > "$TMP_ROOT/xdg/chopsticks.vim"
XDG_CONFIG_HOME="$TMP_ROOT/xdg" vim -u NONE -i NONE -es -N \ XDG_CONFIG_HOME="$TMP_ROOT/xdg" vim -u NONE -i NONE -es -N \
-c 'source .vimrc' \ -c 'source .vimrc' \
-c 'if g:chopsticks_profile !=# "minimal" || has_key(g:plugs, "ale") || has_key(g:plugs, "vim-lsp") | cquit | endif' \ -c 'if g:chopsticks_profile !=# "minimal" || has_key(g:plugs, "ale") || has_key(g:plugs, "vim-lsp") || has_key(g:plugs, "auto-pairs") | cquit | endif' \
-c 'qa!' 2>&1 -c 'qa!' 2>&1
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N \
-c 'ChopsticksStatus' \
-c "redir! > $TMP_ROOT/status-default.txt" \
-c 'silent %print' \
-c 'redir END' \
-c 'qa!' 2>&1
if grep -Fq 'vim-lsp not loaded' "$TMP_ROOT/status-default.txt"; then
cat "$TMP_ROOT/status-default.txt"
exit 1
fi
grep -Fq 'OK vim-lsp stack (installed)' "$TMP_ROOT/status-default.txt"
grep -Fq 'python (:LspInstallServer in a python file)' "$TMP_ROOT/status-default.txt"
grep -Fq 'LSP actions are buffer-local and start after a server attaches.' "$TMP_ROOT/status-default.txt"
grep -Fq 'Open that filetype and run :LspInstallServer once.' "$TMP_ROOT/status-default.txt"
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N \
-c 'let last_change_map = nr2char(96) . "[v" . nr2char(96) . "]"' \
-c 'if maparg("0", "n") !=# "" || maparg("0", "v") !=# "" || maparg("Y", "n") !=# "" || maparg("Q", "n") !=# "" || maparg("<Space>", "n") !=# "" || maparg("//", "v") !=# "" || maparg("gV", "n") !=# "" || maparg("jk", "i") !=# "" || maparg("<C-s>", "n") !=# "" || maparg("<C-s>", "i") !=# "" || maparg("<C-h>", "n") !=# "" || maparg("<C-j>", "n") !=# "" || maparg("<C-k>", "n") !=# "" || maparg("<C-l>", "n") !=# "" || maparg("<C-p>", "n") !=# "" || maparg("<C-p>", "c") !=# "" || maparg("<C-n>", "c") !=# "" || maparg("w!!", "c") !=# "" | cquit | endif' \
-c 'if has_key(g:plugs, "auto-pairs") || maparg("<Tab>", "i") =~# "pumvisible" || maparg("<S-Tab>", "i") =~# "pumvisible" || maparg("<CR>", "i") =~# "asyncomplete#close_popup" || maparg("<CR>", "i") =~# "AutoPairs" | cquit | endif' \
-c 'if maparg("<Esc><Esc>", "t") !=# "" || maparg("<C-h>", "t") !=# "" || maparg("<C-j>", "t") !=# "" || maparg("<C-k>", "t") !=# "" || maparg("<C-l>", "t") !=# "" | cquit | endif' \
-c 'if maparg(",/", "v") !~# "escape" || maparg(",v", "n") !=# last_change_map || maparg(",ff", "n") !~# "SmartFiles" | cquit | endif' \
-c 'qa!' 2>&1
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u NONE -i NONE -es -N \
-c 'let g:chopsticks_enable_jk_escape = 1' \
-c 'source .vimrc' \
-c 'if maparg("jk", "i") !~# "<Esc>" | cquit | endif' \
-c 'qa!' 2>&1
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u NONE -i NONE -es -N \
-c 'let g:chopsticks_enable_ctrl_s_save = 1' \
-c 'let g:chopsticks_enable_sudo_save_bang = 1' \
-c 'let g:chopsticks_enable_completion_keymaps = 1' \
-c 'source .vimrc' \
-c 'if maparg("<C-s>", "n") !~# ":w" || maparg("<C-s>", "i") !~# ":w" || maparg("w!!", "c") !~# "sudo tee" | cquit | endif' \
-c 'if maparg("<Tab>", "i") !~# "pumvisible" || maparg("<S-Tab>", "i") !~# "pumvisible" || maparg("<CR>", "i") !~# "asyncomplete#close_popup" | cquit | endif' \
-c 'qa!' 2>&1
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u NONE -i NONE -es -N \
-c 'let g:chopsticks_enable_auto_pairs = 1' \
-c 'source .vimrc' \
-c 'if !has_key(g:plugs, "auto-pairs") | cquit | endif' \
-c 'qa!' 2>&1
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u NONE -i NONE -es -N \
-c 'let g:chopsticks_enable_terminal_keymaps = 1' \
-c 'source .vimrc' \
-c 'if has("terminal") && (maparg("<Esc><Esc>", "t") !~# "<C-\\\\><C-N>" || maparg("<C-h>", "t") !~# "<C-W>h" || maparg("<C-j>", "t") !~# "<C-W>j" || maparg("<C-k>", "t") !~# "<C-W>k" || maparg("<C-l>", "t") !~# "<C-W>l") | cquit | endif' \
-c 'qa!' 2>&1
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N \
-c 'silent! delcommand LspStatus' \
-c 'silent! delcommand LspInstallServer' \
-c 'ChopsticksStatus' \
-c "redir! > $TMP_ROOT/status-lsp-not-loaded.txt" \
-c 'silent %print' \
-c 'redir END' \
-c 'qa!' 2>&1
grep -Fq 'OK vim-lsp stack (installed; not loaded yet)' "$TMP_ROOT/status-lsp-not-loaded.txt"
vim -u NONE -i NONE -es -N \
-c 'let g:chopsticks_profile = "minimal"' \
-c 'source .vimrc' \
-c 'ChopsticksStatus' \
-c "redir! > $TMP_ROOT/status-minimal.txt" \
-c 'silent %print' \
-c 'redir END' \
-c 'qa!' 2>&1
grep -Fq 'off vim-lsp stack (LSP disabled by profile)' "$TMP_ROOT/status-minimal.txt"
grep -Fq 'off python (LSP disabled by profile)' "$TMP_ROOT/status-minimal.txt"
if grep -Fq 'LSP actions are buffer-local' "$TMP_ROOT/status-minimal.txt"; then
cat "$TMP_ROOT/status-minimal.txt"
exit 1
fi
mkdir -p "$TMP_ROOT/missing-home/.vim/autoload"
cp "$HOME/.vim/autoload/plug.vim" "$TMP_ROOT/missing-home/.vim/autoload/plug.vim"
HOME="$TMP_ROOT/missing-home" XDG_CONFIG_HOME="$EMPTY_XDG" \
vim -u .vimrc -i NONE -es -N \
-c 'ChopsticksStatus' \
-c "redir! > $TMP_ROOT/status-missing-plugin.txt" \
-c 'silent %print' \
-c 'redir END' \
-c 'qa!' 2>&1
grep -Fq 'vim-lsp not installed; run :PlugInstall' "$TMP_ROOT/status-missing-plugin.txt"
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N \
-c 'doautocmd User lsp_buffer_enabled' \
-c 'if maparg("gd", "n") !=# "" || maparg("K", "n") !=# "" || maparg("gi", "n") !=# "" || maparg("gr", "n") !=# "" | cquit | endif' \
-c 'if maparg(",dd", "n") !~# "lsp-definition" | cquit | endif' \
-c 'if maparg(",dt", "n") !~# "lsp-type-definition" | cquit | endif' \
-c 'if maparg(",di", "n") !~# "lsp-implementation" | cquit | endif' \
-c 'if maparg(",dr", "n") !~# "lsp-references" | cquit | endif' \
-c 'if maparg(",dk", "n") !~# "lsp-hover" | cquit | endif' \
-c 'if maparg(",dp", "n") !~# "lsp-previous-diagnostic" | cquit | endif' \
-c 'if maparg(",dn", "n") !~# "lsp-next-diagnostic" | cquit | endif' \
-c 'qa!' 2>&1
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N \
-c 'normal ,?' \
-c "redir! > $TMP_ROOT/cheat-default.txt" \
-c 'silent %print' \
-c 'redir END' \
-c 'qa!' 2>&1
grep -Fq ':ChopsticksStatus check LSP setup' "$TMP_ROOT/cheat-default.txt"
grep -Fq ',ff files' "$TMP_ROOT/cheat-default.txt"
grep -Fq ',dd definition' "$TMP_ROOT/cheat-default.txt"
grep -Fq ',dk hover docs' "$TMP_ROOT/cheat-default.txt"
grep -Fq ',dp ,dn LSP diagnostics' "$TMP_ROOT/cheat-default.txt"
grep -Fq '<C-w>hjkl navigate splits' "$TMP_ROOT/cheat-default.txt"
if grep -Eq 'Ctrl\\+p find file|Ctrl\\+hjkl navigate splits|Ctrl\\+s save|jk exit insert|gd definition|K hover docs|\\[g \\]g LSP diagnostics' "$TMP_ROOT/cheat-default.txt"; then
cat "$TMP_ROOT/cheat-default.txt"
exit 1
fi
vim -u NONE -i NONE -es -N \ vim -u NONE -i NONE -es -N \
-c 'let g:chopsticks_profile = "minimal"' \ -c 'let g:chopsticks_profile = "minimal"' \
-c 'source .vimrc' \ -c 'source .vimrc' \
@ -207,6 +338,40 @@ check_vim() {
-c 'if &l:syntax !=# "" || &l:undolevels != -1 || &l:swapfile || get(b:, "ale_enabled", 1) != 0 | cquit | endif' \ -c 'if &l:syntax !=# "" || &l:undolevels != -1 || &l:swapfile || get(b:, "ale_enabled", 1) != 0 | cquit | endif' \
-c 'qa!' 2>&1 -c 'qa!' 2>&1
mkdir -p "$TMP_ROOT/fake-bin" "$TMP_ROOT/c runner"
cat > "$TMP_ROOT/fake-bin/gcc" <<'GCCEOF'
#!/usr/bin/env bash
set -eu
printf '%s\n' "$@" > "$GCC_ARGS"
out=""
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
shift
out="$1"
fi
shift || true
done
test -n "$out"
printf '%s\n' '#!/usr/bin/env bash' 'exit 0' > "$out"
chmod +x "$out"
GCCEOF
chmod +x "$TMP_ROOT/fake-bin/gcc"
c_file="$TMP_ROOT/c runner/main.c"
c_file_real="$(cd "$TMP_ROOT/c runner" && pwd -P)/main.c"
printf '%s\n' 'int main(void) { return 0; }' > "$c_file"
GCC_ARGS="$TMP_ROOT/gcc-args.txt" \
PATH="$TMP_ROOT/fake-bin:$PATH" \
XDG_CONFIG_HOME="$EMPTY_XDG" \
vim -u .vimrc -i NONE -es -N "$c_file" \
-c 'set filetype=c' \
-c 'normal ,cr' \
-c 'qa!' 2>&1
c_out="$(sed -n '2p' "$TMP_ROOT/gcc-args.txt")"
test -n "$c_out"
test "$c_out" != "/tmp/a.out"
test ! -e "$c_out"
grep -Fxq "$c_file_real" "$TMP_ROOT/gcc-args.txt"
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE --startuptime "$TMP_ROOT/startup.log" \ XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE --startuptime "$TMP_ROOT/startup.log" \
-es -N -c 'qa!' 2>/dev/null -es -N -c 'qa!' 2>/dev/null
tail -1 "$TMP_ROOT/startup.log" tail -1 "$TMP_ROOT/startup.log"