mirror of
https://oauth2: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@github.com/m1ngsama/chopsticks.git
synced 2026-06-26 05:54:37 +08:00
Compare commits
8 commits
002bc7bd3e
...
e5412e464e
| Author | SHA1 | Date | |
|---|---|---|---|
| e5412e464e | |||
| 7f7a200b85 | |||
| f0c662fd5c | |||
| fc5cac570e | |||
| 5156543702 | |||
| 74cc479a0e | |||
| debcdd33c4 | |||
| d6df4fee3e |
8 changed files with 150 additions and 29 deletions
4
.github/demo.tape
vendored
4
.github/demo.tape
vendored
|
|
@ -24,8 +24,8 @@ Type "vim server.py"
|
|||
Enter
|
||||
Sleep 3.5s
|
||||
|
||||
# ── 2. Fuzzy find files (Ctrl+p → type → select) ──────────────────────────
|
||||
Ctrl+p
|
||||
# ── 2. Fuzzy find files (,ff → type → select) ────────────────────────────
|
||||
Type ",ff"
|
||||
Sleep 1.5s
|
||||
Type "route"
|
||||
Sleep 2.5s
|
||||
|
|
|
|||
29
CHANGELOG.md
29
CHANGELOG.md
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
## Unreleased
|
||||
|
||||
## 2.2.0 — 2026-05-17
|
||||
|
||||
### Added
|
||||
|
||||
- `~/.config/chopsticks.vim` local pre-load config for profile and user choices
|
||||
|
|
@ -23,6 +25,30 @@
|
|||
|
||||
### Fixed
|
||||
|
||||
- Built-in plugin guards for `gzip`, `logiPat`, `rrhelper`, and
|
||||
`spellfile_plugin` are now set in both `g:`-prefixed and unscoped
|
||||
forms — those four old-style runtime plugins check `loaded_X` (no
|
||||
`g:`), so the previous `g:loaded_X` lines did nothing. Saves ~270μs
|
||||
total at startup, mostly from gzip
|
||||
- `install.sh` interactive menu and QUICKSTART now show `,ff` (current
|
||||
fuzzy-find binding) instead of the stale `Ctrl+p` left over from the
|
||||
native-first cleanup; `.github/demo.tape` updated to match (the
|
||||
binary GIF still shows `Ctrl+p` until someone regenerates it from a
|
||||
fresh fixture)
|
||||
- README badge and `install.sh` recommend Vim 8.1+ instead of 8.0+ —
|
||||
the runtime conditionally relies on patches `8.1.0360` (diffopt) and
|
||||
`8.1.1517` (completeopt+=popup), so 8.0 users hit option errors
|
||||
- `ttimeoutlen` is now 50ms when `g:is_tty` (was 10ms unconditionally);
|
||||
fixes F-keys, arrow keys, and Alt-prefixes fragmenting on SSH where
|
||||
one-way latency exceeds 10ms. Local terminals keep the 10ms snappy
|
||||
default
|
||||
- `install.sh` no longer silently `PlugClean!`s user-added plugins from
|
||||
`~/.vim/plugged`; it now lists undeclared plugin directories first and
|
||||
asks before removing them (`--yes` skips the removal entirely)
|
||||
- `install.sh` Python tools now prefer `pipx` and `pip3 --user` over
|
||||
`pip3 install --break-system-packages`; the break-system path is gated
|
||||
behind `CHOPSTICKS_ALLOW_BREAK_SYSTEM=1` so PEP 668 distros are no
|
||||
longer silently polluted
|
||||
- `g:loaded_logipat` typo → `g:loaded_logiPat` — logiPat was loading fully (0.478ms wasted)
|
||||
- `get.sh` now refuses to update an existing `~/.vim` git repo unless its
|
||||
origin is chopsticks
|
||||
|
|
@ -33,6 +59,9 @@
|
|||
|
||||
### Changed
|
||||
|
||||
- `install.sh` "First steps inside Vim" block now leads with `,?`
|
||||
(cheat sheet) — the single best onboarding asset is now the first
|
||||
thing a new user sees after install, not the fourth
|
||||
- `set exrc`/`set secure` are now opt-in via `g:chopsticks_enable_exrc = 1`;
|
||||
Vim no longer sources project-local `.vimrc`/`.exrc` from the working
|
||||
directory by default
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ Esc back to Normal
|
|||
## Find things
|
||||
|
||||
```
|
||||
Ctrl+p fuzzy find file (git-aware)
|
||||
,ff fuzzy find file (git-aware)
|
||||
,rg ripgrep project
|
||||
,b search buffers
|
||||
,fh recent files
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<p align="center">
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square" alt="MIT License"></a>
|
||||
<a href="https://www.vim.org/"><img src="https://img.shields.io/badge/Vim-8.0%2B-brightgreen?style=flat-square" alt="Vim 8.0+"></a>
|
||||
<a href="https://www.vim.org/"><img src="https://img.shields.io/badge/Vim-8.1%2B-brightgreen?style=flat-square" alt="Vim 8.1+"></a>
|
||||
<a href="#install"><img src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey?style=flat-square" alt="Platform"></a>
|
||||
<a href="https://github.com/m1ngsama/chopsticks/actions"><img src="https://img.shields.io/github/actions/workflow/status/m1ngsama/chopsticks/test.yml?style=flat-square&label=tests" alt="Tests"></a>
|
||||
<a href="https://github.com/m1ngsama/chopsticks/releases"><img src="https://img.shields.io/github/v/release/m1ngsama/chopsticks?style=flat-square&color=orange" alt="Release"></a>
|
||||
|
|
|
|||
105
install.sh
105
install.sh
|
|
@ -519,7 +519,7 @@ fi
|
|||
[[ -n "$VIM_BIN" ]] || die "vim installed but not found in PATH"
|
||||
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.1+ recommended for full async/LSP support — some features may not work"
|
||||
|
||||
# Node.js (optional — vim-lsp needs no Node.js; only npm formatters do)
|
||||
HAS_NODE=0; command -v node >/dev/null 2>&1 && HAS_NODE=1
|
||||
|
|
@ -656,10 +656,59 @@ VIMEOF
|
|||
fi
|
||||
}
|
||||
|
||||
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"
|
||||
# Echoes one name per line for each directory under ~/.vim/plugged that no
|
||||
# chopsticks profile/flag combination would declare. The detection script
|
||||
# bypasses local config and forces every opt-in on, so a plugin that's only
|
||||
# loaded inside tmux or behind a flag does NOT show up as "extra". Empty
|
||||
# output means PlugClean would be a no-op for the user's tree.
|
||||
list_extra_plugins() {
|
||||
local declared_file="$_TMPDIR/declared-plugins.txt"
|
||||
local declare_script="$_TMPDIR/declared-plugins.vim"
|
||||
local plugged="$HOME/.vim/plugged"
|
||||
[[ -d "$plugged" ]] || return 0
|
||||
|
||||
cat > "$declare_script" <<'VIMEOF'
|
||||
let g:chopsticks_local_config = '/dev/null'
|
||||
let $TMUX = '1'
|
||||
let g:chopsticks_profile = 'full'
|
||||
let g:chopsticks_enable_auto_pairs = 1
|
||||
let g:chopsticks_enable_terminal_keymaps = 1
|
||||
execute 'source ' . fnameescape($CHOPSTICKS_VIMRC)
|
||||
if !exists('g:plugs')
|
||||
cquit
|
||||
endif
|
||||
call writefile(sort(keys(g:plugs)), $CHOPSTICKS_DECLARED_PLUGINS)
|
||||
qa!
|
||||
VIMEOF
|
||||
CHOPSTICKS_VIMRC="$SCRIPT_DIR/.vimrc" \
|
||||
CHOPSTICKS_DECLARED_PLUGINS="$declared_file" \
|
||||
"$VIM_BIN" -u NONE -i NONE -es -N -S "$declare_script" >/dev/null 2>&1 || return 1
|
||||
[[ -e "$declared_file" ]] || return 0
|
||||
|
||||
local plugin name
|
||||
while IFS= read -r plugin; do
|
||||
[[ -d "$plugin" ]] || continue
|
||||
name="$(basename "$plugin")"
|
||||
if ! grep -Fxq "$name" "$declared_file"; then
|
||||
printf '%s\n' "$name"
|
||||
fi
|
||||
done < <(find "$plugged" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort)
|
||||
}
|
||||
|
||||
extras="$(list_extra_plugins || true)"
|
||||
if [[ -n "$extras" ]]; then
|
||||
warn "Plugins under ~/.vim/plugged that the active profile does not declare:"
|
||||
while IFS= read -r ex; do
|
||||
[[ -n "$ex" ]] && echo " - $ex"
|
||||
done <<< "$extras"
|
||||
if [[ $AUTO_YES -eq 1 ]]; then
|
||||
info "Leaving them in place (--yes mode). Run :PlugClean inside Vim to remove."
|
||||
elif ask "Remove these directories with PlugClean!?"; then
|
||||
_vim_run 'PlugClean!' || true # plug.vim may exit non-zero after removal; harmless
|
||||
else
|
||||
info "Leaving them in place. Run :PlugClean inside Vim if you change your mind."
|
||||
fi
|
||||
fi
|
||||
_vim_run 'PlugClean!' || true # remove plugins no longer in vimrc; ignore exit code (none expected)
|
||||
_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."
|
||||
|
|
@ -699,11 +748,11 @@ fi
|
|||
# ── System tools ─────────────────────────────────────────────────────────────
|
||||
if [[ $HAS_PKG_MGR -eq 1 ]]; then
|
||||
_I_RIPGREP=$_idx
|
||||
_ITEMS+=("ripgrep|,rg / ,rG project-wide search · powers Ctrl+p preview|1")
|
||||
_ITEMS+=("ripgrep|,rg / ,rG project-wide search · powers FZF preview|1")
|
||||
: $(( _idx++ ))
|
||||
|
||||
_I_FZF=$_idx
|
||||
_ITEMS+=("fzf|Ctrl+p fuzzy file search · ,b buffers · ,rt tag search|1")
|
||||
_ITEMS+=("fzf|,ff fuzzy file search · ,b buffers · ,rt tag search|1")
|
||||
: $(( _idx++ ))
|
||||
|
||||
_I_CTAGS=$_idx
|
||||
|
|
@ -966,19 +1015,45 @@ elif [[ $_I_PYTHON -lt 0 ]] || ! _selected "$_I_PYTHON"; then
|
|||
skip "Python tool suite (skipped by user)"
|
||||
SKIPPED+=("black" "isort" "flake8" "pylint" "yamllint" "sqlfluff")
|
||||
else
|
||||
# Prefer pipx (isolated per-tool venvs, the recommended path on PEP 668
|
||||
# distros like Debian 12+/Ubuntu 23.04+). Bootstrap pipx via the system
|
||||
# package manager if missing. Only fall back to --break-system-packages
|
||||
# if the user explicitly opts in.
|
||||
if ! command -v pipx >/dev/null 2>&1; then
|
||||
if pkg_install pipx pipx python-pipx pipx 2>/dev/null; then
|
||||
ok "pipx (recommended Python CLI installer)"
|
||||
else
|
||||
warn "pipx not available — falling back to pip3 --user"
|
||||
fi
|
||||
fi
|
||||
|
||||
case ":$PATH:" in
|
||||
*":$HOME/.local/bin:"*) ;;
|
||||
*) warn "\$HOME/.local/bin is not on PATH — pipx/pip --user tools will not be found"
|
||||
info "Add to your shell rc: export PATH=\"\$HOME/.local/bin:\$PATH\"" ;;
|
||||
esac
|
||||
|
||||
pip_install() {
|
||||
local pkg="$1" check="${2:-$1}"
|
||||
if command -v "$check" >/dev/null 2>&1; then
|
||||
ok "$pkg (already installed)"; return
|
||||
fi
|
||||
if pip3 install --quiet "$pkg" 2>/dev/null; then
|
||||
ok "$pkg"; INSTALLED+=("$pkg")
|
||||
elif pip3 install --quiet --break-system-packages "$pkg" 2>/dev/null; then
|
||||
warn "$pkg installed with --break-system-packages (consider using a virtualenv)"
|
||||
ok "$pkg"; INSTALLED+=("$pkg")
|
||||
else
|
||||
fail "$pkg"; FAILED+=("$pkg")
|
||||
if command -v pipx >/dev/null 2>&1 && pipx install --quiet "$pkg" 2>/dev/null; then
|
||||
ok "$pkg (via pipx)"; INSTALLED+=("$pkg")
|
||||
return
|
||||
fi
|
||||
if pip3 install --quiet --user "$pkg" 2>/dev/null; then
|
||||
ok "$pkg (via pip --user)"; INSTALLED+=("$pkg")
|
||||
return
|
||||
fi
|
||||
if [[ "${CHOPSTICKS_ALLOW_BREAK_SYSTEM:-0}" == "1" ]] && \
|
||||
pip3 install --quiet --break-system-packages "$pkg" 2>/dev/null; then
|
||||
warn "$pkg installed with --break-system-packages (CHOPSTICKS_ALLOW_BREAK_SYSTEM=1)"
|
||||
INSTALLED+=("$pkg")
|
||||
return
|
||||
fi
|
||||
fail "$pkg — install pipx, or set CHOPSTICKS_ALLOW_BREAK_SYSTEM=1 to bypass PEP 668"
|
||||
FAILED+=("$pkg")
|
||||
}
|
||||
pip_install black
|
||||
pip_install isort
|
||||
|
|
@ -1126,10 +1201,10 @@ echo -e " ${CYAN}vim .${NC} Open dashboard in current directory"
|
|||
echo -e " ${CYAN}vim myfile${NC} Edit a specific file"
|
||||
echo ""
|
||||
echo -e "${BOLD} First steps inside Vim${NC}"
|
||||
echo -e " ${CYAN},?${NC} Open cheat sheet — your map of every keybinding"
|
||||
echo -e " ${CYAN}Esc${NC} Exit insert mode → back to Normal"
|
||||
echo -e " ${CYAN}:q!${NC} + Enter Emergency quit without saving"
|
||||
echo -e " ${CYAN},x${NC} Save and quit"
|
||||
echo -e " ${CYAN},?${NC} Open cheat sheet"
|
||||
echo -e " ${CYAN}:q!${NC} + Enter Emergency quit without saving"
|
||||
if [[ $CONFIG_PROFILE != "minimal" ]]; then
|
||||
echo -e " ${CYAN}:LspInstallServer${NC} Install LSP for current filetype"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -42,7 +42,10 @@ set noerrorbells
|
|||
set novisualbell
|
||||
set t_vb=
|
||||
set ttimeout
|
||||
set ttimeoutlen=10
|
||||
" Wait long enough on SSH/TTY for multi-byte key codes to arrive intact —
|
||||
" 10ms fragments F-keys, arrows, and Alt-prefixes when one-way latency > 10ms.
|
||||
" 50ms is well under perceptible <Esc>→Normal delay locally.
|
||||
let &ttimeoutlen = g:is_tty ? 50 : 10
|
||||
|
||||
if $COLORTERM ==# 'gnome-terminal'
|
||||
set t_Co=256
|
||||
|
|
|
|||
|
|
@ -42,16 +42,18 @@ let g:chopsticks_markdown_conceal = get(g:, 'chopsticks_markdown_conceal',
|
|||
let g:chopsticks_lsp_virtual_text = get(g:, 'chopsticks_lsp_virtual_text',
|
||||
\ s:profile_full && !g:is_tty)
|
||||
|
||||
" Skip built-in plugins we never use
|
||||
" Skip built-in plugins we never use.
|
||||
" Modern plugins check g:loaded_X; older ones (gzip, logiPat, rrhelper,
|
||||
" spellfile) check the unscoped loaded_X form, so we set both.
|
||||
let g:loaded_2html_plugin = 1
|
||||
let g:loaded_getscriptPlugin = 1
|
||||
let g:loaded_gzip = 1
|
||||
let g:loaded_logiPat = 1
|
||||
let g:loaded_rrhelper = 1
|
||||
let g:loaded_gzip = 1 | let loaded_gzip = 1
|
||||
let g:loaded_logiPat = 1 | let loaded_logiPat = 1
|
||||
let g:loaded_rrhelper = 1 | let 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_spellfile_plugin = 1 | let loaded_spellfile_plugin = 1
|
||||
let g:loaded_openPlugin = 1
|
||||
let g:loaded_manpager_plugin = 1
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ check_vim() {
|
|||
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u "$TMP_ROOT/chopsticks path/.vimrc" \
|
||||
-i NONE -es -N -c 'qa!' 2>&1
|
||||
|
||||
vim -u NONE -i NONE -es -N \
|
||||
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u NONE -i NONE -es -N \
|
||||
-c 'let g:chopsticks_profile = "minimal"' \
|
||||
-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") || has_key(g:plugs, "auto-pairs") | cquit | endif' \
|
||||
|
|
@ -257,6 +257,18 @@ check_vim() {
|
|||
-c 'if maparg(",F", "n") !~# "gg=G" | cquit | endif' \
|
||||
-c 'qa!' 2>&1
|
||||
|
||||
TERM=xterm-256color XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N \
|
||||
-c 'if g:is_tty || &ttimeoutlen != 10 | cquit | endif' \
|
||||
-c 'qa!' 2>&1
|
||||
|
||||
TERM=linux XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N \
|
||||
-c 'if !g:is_tty || &ttimeoutlen != 50 | cquit | endif' \
|
||||
-c 'qa!' 2>&1
|
||||
|
||||
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N \
|
||||
-c 'if !exists("loaded_gzip") || !exists("loaded_logiPat") || !exists("loaded_rrhelper") || !exists("loaded_spellfile_plugin") | 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' \
|
||||
|
|
@ -267,7 +279,7 @@ check_vim() {
|
|||
-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 \
|
||||
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u NONE -i NONE -es -N \
|
||||
-c 'let g:chopsticks_profile = "minimal"' \
|
||||
-c 'source .vimrc' \
|
||||
-c 'ChopsticksStatus' \
|
||||
|
|
@ -322,7 +334,7 @@ check_vim() {
|
|||
exit 1
|
||||
fi
|
||||
|
||||
vim -u NONE -i NONE -es -N \
|
||||
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u NONE -i NONE -es -N \
|
||||
-c 'let g:chopsticks_profile = "minimal"' \
|
||||
-c 'source .vimrc' \
|
||||
-c 'normal ,?' \
|
||||
|
|
@ -347,7 +359,7 @@ check_vim() {
|
|||
-c 'if !&swapfile || !&writebackup || &directory !~# "\.vim/.swap" | cquit | endif' \
|
||||
-c 'qa!' 2>&1
|
||||
|
||||
vim -u NONE -i NONE -es -N \
|
||||
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u NONE -i NONE -es -N \
|
||||
-c 'let g:ale_fix_on_save = 0' \
|
||||
-c 'source .vimrc' \
|
||||
-c 'if g:ale_fix_on_save != 0 | cquit | endif' \
|
||||
|
|
|
|||
Loading…
Reference in a new issue