Compare commits

..

No commits in common. "259744b5e3bbcaa67f6be2783d5d7a9b4ee6a3c9" and "1b9e8b39998e99ead0987ba2682f53ec94c574e5" have entirely different histories.

4 changed files with 148 additions and 279 deletions

View file

@ -51,19 +51,157 @@ jobs:
} }
done done
- name: Run Vim smoke tests - name: Test startup
run: scripts/test.sh vim run: |
vim -u .vimrc -i NONE -es -N -c 'qa!' 2>&1
echo "Vim exited cleanly"
- name: Verify modules load
run: |
vim -u .vimrc -i NONE -es -N \
-c 'redir! > /tmp/test.txt' \
-c 'silent echo len(g:plugs)' \
-c 'redir END' \
-c 'qa!' 2>/dev/null
PLUGS=$(cat /tmp/test.txt | tr -d '[:space:]')
echo "Plugins registered: $PLUGS"
if [ "$PLUGS" -lt 20 ]; then
echo "FAIL: expected 20+ plugins, got $PLUGS"
exit 1
fi
- name: Verify path-safe module loading
run: |
mkdir -p "/tmp/chopsticks path/modules"
cp .vimrc "/tmp/chopsticks path/.vimrc"
cp modules/*.vim "/tmp/chopsticks path/modules/"
vim -u "/tmp/chopsticks path/.vimrc" -i NONE -es -N -c 'qa!' 2>&1
- name: Verify minimal profile
run: |
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") | cquit | endif' \
-c 'qa!' 2>&1
- name: Verify local config hook
run: |
mkdir -p /tmp/chopsticks-ci
printf "%s\n" "let g:chopsticks_profile = 'minimal'" > /tmp/chopsticks-ci/local.vim
vim -u NONE -i NONE -es -N \
-c 'let g:chopsticks_local_config = "/tmp/chopsticks-ci/local.vim"' \
-c 'source .vimrc' \
-c 'if g:chopsticks_profile !=# "minimal" || has_key(g:plugs, "ale") || has_key(g:plugs, "vim-lsp") | cquit | endif' \
-c 'qa!' 2>&1
- name: Verify XDG local config hook
run: |
mkdir -p /tmp/chopsticks-xdg
printf "%s\n" "let g:chopsticks_profile = 'minimal'" > /tmp/chopsticks-xdg/chopsticks.vim
XDG_CONFIG_HOME=/tmp/chopsticks-xdg vim -u NONE -i NONE -es -N \
-c 'source .vimrc' \
-c 'if g:chopsticks_profile !=# "minimal" || has_key(g:plugs, "ale") || has_key(g:plugs, "vim-lsp") | cquit | endif' \
-c 'qa!' 2>&1
- name: Verify profile-aware cheat sheet
run: |
vim -u NONE -i NONE -es -N \
-c 'let g:chopsticks_profile = "minimal"' \
-c 'source .vimrc' \
-c 'normal ,?' \
-c 'redir! > /tmp/chopsticks-cheat.txt' \
-c 'silent %print' \
-c 'redir END' \
-c 'qa!' 2>&1
if grep -Eq 'definition|LspInstallServer|ALE errors|undo tree|markdown preview' /tmp/chopsticks-cheat.txt; then
cat /tmp/chopsticks-cheat.txt
exit 1
fi
grep -q ',cr run file' /tmp/chopsticks-cheat.txt
- name: Verify Markdown quiet defaults
run: |
vim -u .vimrc -i NONE -es -N README.md \
-c 'set filetype=markdown' \
-c 'if &l:spell || &l:conceallevel != 0 || &l:signcolumn !=# "no" || exists("g:lsp_settings_filetype_markdown") | cquit | endif' \
-c 'qa!' 2>&1
- name: Verify ergonomic defaults
run: |
vim -u .vimrc -i NONE -es -N \
-c 'if maparg("s", "n") !=# "" | cquit | endif' \
-c 'if maparg(",w", "n") =~# "!" | cquit | endif' \
-c 'if !&swapfile || !&writebackup || &directory !~# "\.vim/.swap" | cquit | endif' \
-c 'qa!' 2>&1
- name: Verify local ALE override
run: |
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' \
-c 'qa!' 2>&1
- name: Verify large file protection
run: |
truncate -s 11000000 /tmp/chopsticks-large.py
vim -u .vimrc -i NONE -es -N /tmp/chopsticks-large.py \
-c 'set filetype=python' \
-c 'if &l:syntax !=# "" || &l:undolevels != -1 || &l:swapfile || get(b:, "ale_enabled", 1) != 0 | cquit | endif' \
-c 'qa!' 2>&1
- name: Measure startup time
run: |
vim -u .vimrc -i NONE --startuptime /tmp/startup.log -es -N -c 'qa!' 2>/dev/null
tail -1 /tmp/startup.log
STARTUP_MS=$(tail -1 /tmp/startup.log | awk '{print $1}')
awk -v ms="$STARTUP_MS" 'BEGIN { if (ms > 150) exit 1 }'
shellcheck: shellcheck:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Check test runner CLI - name: Shellcheck install.sh
run: shellcheck install.sh get.sh
- name: Verify installer profile-only modes
run: | run: |
scripts/test.sh --help XDG_CONFIG_HOME=/tmp/chopsticks-dry ./install.sh --dry-run --profile=full \
scripts/test.sh list | tee /tmp/chopsticks-dry-run.txt
- name: Run shell and installer tests grep -q 'Profile: full' /tmp/chopsticks-dry-run.txt
run: scripts/test.sh shell installer bootstrap test ! -e /tmp/chopsticks-dry/chopsticks.vim
XDG_CONFIG_HOME=/tmp/chopsticks-config ./install.sh --configure-only --profile=minimal
grep -q "let g:chopsticks_profile = 'minimal'" /tmp/chopsticks-config/chopsticks.vim
XDG_CONFIG_HOME=/tmp/chopsticks-config ./install.sh --configure-only --profile=full
grep -q "let g:chopsticks_profile = 'full'" /tmp/chopsticks-config/chopsticks.vim
XDG_CONFIG_HOME=/tmp/chopsticks-default ./install.sh --configure-only --yes
grep -q "let g:chopsticks_profile = 'engineer'" /tmp/chopsticks-default/chopsticks.vim
- name: Verify bootstrap dry-run safety
run: |
CHOPSTICKS_DEST=/tmp/chopsticks-bootstrap ./get.sh --dry-run --profile=minimal \
| tee /tmp/chopsticks-get-dry-run.txt
grep -q 'Would clone' /tmp/chopsticks-get-dry-run.txt
test ! -e /tmp/chopsticks-bootstrap
mkdir -p /tmp/not-chopsticks
git init /tmp/not-chopsticks
git -C /tmp/not-chopsticks remote add origin https://github.com/example/not-chopsticks.git
if CHOPSTICKS_DEST=/tmp/not-chopsticks ./get.sh --dry-run; then
echo "Expected get.sh to reject non-chopsticks repo"
exit 1
fi
mkdir -p /tmp/chopsticks-existing
git init /tmp/chopsticks-existing
git -C /tmp/chopsticks-existing remote add origin https://github.com/m1ngsama/chopsticks.git
touch /tmp/chopsticks-existing/install.sh /tmp/chopsticks-existing/.vimrc
CHOPSTICKS_DEST=/tmp/chopsticks-existing ./get.sh --dry-run --yes \
| tee /tmp/chopsticks-get-existing.txt
grep -q 'Would update existing chopsticks repo' /tmp/chopsticks-get-existing.txt
docs: docs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -72,4 +210,4 @@ jobs:
- name: Install markdownlint - name: Install markdownlint
run: npm install -g markdownlint-cli run: npm install -g markdownlint-cli
- name: Lint Markdown - name: Lint Markdown
run: scripts/test.sh docs run: markdownlint README.md QUICKSTART.md CONTRIBUTING.md CHANGELOG.md

View file

@ -18,8 +18,6 @@
- `install.sh --configure-only` to update local profile config without reinstalling - `install.sh --configure-only` to update local profile config without reinstalling
- `get.sh --dry-run` for safe bootstrap previews before clone/update/install - `get.sh --dry-run` for safe bootstrap previews before clone/update/install
- `CHOPSTICKS_DEST=/absolute/path` to test or install the bootstrap target elsewhere - `CHOPSTICKS_DEST=/absolute/path` to test or install the bootstrap target elsewhere
- `scripts/test.sh` local test runner reused by GitHub Actions
- `scripts/test.sh quick`, `--help`, and `list` for easier local test discovery
### Fixed ### Fixed
@ -58,9 +56,6 @@
update it without appending duplicate bindings update it without appending duplicate bindings
- Installer cleanup now restores the cursor after interrupted checkbox menus - Installer cleanup now restores the cursor after interrupted checkbox menus
- Bootstrap dry-run now refuses unrelated existing git repos before any writes - Bootstrap dry-run now refuses unrelated existing git repos before any writes
- CI now shares shell, installer, bootstrap, docs, and Vim smoke checks with
the local test runner
- CI now checks the test runner help and group-list commands
- Skip 2 more built-in plugins: openPlugin, manpager (10 → 12 total) - Skip 2 more built-in plugins: openPlugin, manpager (10 → 12 total)
- Remove deprecated `set ttyfast` (no-op since Vim 8) - Remove deprecated `set ttyfast` (no-op since Vim 8)
- Add `grepprg=rg --vimgrep``:grep` now uses ripgrep + quickfix - Add `grepprg=rg --vimgrep``:grep` now uses ripgrep + quickfix

View file

@ -13,20 +13,7 @@
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. Update the cheat sheet in `modules/tools.vim` if you add keybindings
5. Run `scripts/test.sh vim` locally after installing plugins 5. Test on both macOS and Linux
6. Test on both macOS and Linux when changing terminal or package-manager behavior
## Local tests
```bash
scripts/test.sh --help
scripts/test.sh quick
scripts/test.sh vim
```
`scripts/test.sh quick` runs shell, docs, installer, and bootstrap checks without requiring Vim plugins.
`scripts/test.sh vim` expects plugins to be installed under `~/.vim/plugged`.
Use `STARTUP_LIMIT_MS=150 scripts/test.sh vim` to match CI's startup threshold.
## Reporting bugs ## Reporting bugs
@ -41,4 +28,4 @@ Open an issue. Include:
- Named augroups with `autocmd!` - Named augroups with `autocmd!`
- No comments explaining _what_ — only _why_ - No comments explaining _what_ — only _why_
- `exists('g:plugs["..."]')` guards for plugin-dependent config - `exists('g:plugs["..."]')` guards for plugin-dependent config
- Test with `scripts/test.sh vim` - Test with `vim -u .vimrc -i NONE --startuptime /tmp/s.log -es -N -c qa!`

View file

@ -1,251 +0,0 @@
#!/usr/bin/env bash
# Project test runner. CI calls the same groups that maintainers can run locally.
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
TMP_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/chopsticks-test-XXXXXX")"
EMPTY_XDG="$TMP_ROOT/xdg-empty"
STARTUP_LIMIT_MS="${STARTUP_LIMIT_MS:-150}"
cleanup() {
rm -rf "$TMP_ROOT"
}
trap cleanup EXIT
cd "$ROOT"
mkdir -p "$EMPTY_XDG"
step() {
printf '\n==> %s\n' "$1"
}
need() {
command -v "$1" >/dev/null 2>&1 || {
echo "Missing required command: $1" >&2
exit 1
}
}
usage() {
cat <<'EOF'
Usage: scripts/test.sh [group...]
Groups:
quick shell, docs, installer, and bootstrap checks
shell shell syntax, executability, and shellcheck
docs markdownlint for project docs
installer install.sh dry-run/configure-only profile checks
bootstrap get.sh dry-run safety checks
vim Vim smoke tests; requires plugins in ~/.vim/plugged
all quick plus vim
Options:
-h, --help show this help
list print group names, one per line
EOF
}
list_groups() {
printf '%s\n' quick shell docs installer bootstrap vim all
}
check_shell() {
step "Shell syntax and lint"
need bash
bash -n install.sh
bash -n get.sh
bash -n scripts/test.sh
test -x install.sh
test -x get.sh
test -x scripts/test.sh
need shellcheck
shellcheck install.sh get.sh scripts/test.sh
}
check_docs() {
step "Markdown lint"
need markdownlint
markdownlint README.md QUICKSTART.md CONTRIBUTING.md CHANGELOG.md
}
check_installer_modes() {
step "Installer profile-only modes"
XDG_CONFIG_HOME="$TMP_ROOT/dry" ./install.sh --dry-run --profile=full \
| tee "$TMP_ROOT/install-dry-run.txt"
grep -q 'Profile: full' "$TMP_ROOT/install-dry-run.txt"
test ! -e "$TMP_ROOT/dry/chopsticks.vim"
XDG_CONFIG_HOME="$TMP_ROOT/config" ./install.sh --configure-only --profile=minimal
grep -q "let g:chopsticks_profile = 'minimal'" "$TMP_ROOT/config/chopsticks.vim"
XDG_CONFIG_HOME="$TMP_ROOT/config" ./install.sh --configure-only --profile=full
grep -q "let g:chopsticks_profile = 'full'" "$TMP_ROOT/config/chopsticks.vim"
XDG_CONFIG_HOME="$TMP_ROOT/default" ./install.sh --configure-only --yes
grep -q "let g:chopsticks_profile = 'engineer'" "$TMP_ROOT/default/chopsticks.vim"
}
check_bootstrap() {
step "Bootstrap dry-run safety"
CHOPSTICKS_DEST="$TMP_ROOT/bootstrap" ./get.sh --dry-run --profile=minimal \
| tee "$TMP_ROOT/get-dry-run.txt"
grep -q 'Would clone' "$TMP_ROOT/get-dry-run.txt"
test ! -e "$TMP_ROOT/bootstrap"
mkdir -p "$TMP_ROOT/not-chopsticks"
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
if CHOPSTICKS_DEST="$TMP_ROOT/not-chopsticks" ./get.sh --dry-run; then
echo "Expected get.sh to reject non-chopsticks repo" >&2
exit 1
fi
mkdir -p "$TMP_ROOT/chopsticks-existing"
git -c init.defaultBranch=main init "$TMP_ROOT/chopsticks-existing" >/dev/null
git -C "$TMP_ROOT/chopsticks-existing" remote add origin https://github.com/m1ngsama/chopsticks.git
touch "$TMP_ROOT/chopsticks-existing/install.sh" "$TMP_ROOT/chopsticks-existing/.vimrc"
CHOPSTICKS_DEST="$TMP_ROOT/chopsticks-existing" ./get.sh --dry-run --yes \
| tee "$TMP_ROOT/get-existing.txt"
grep -q 'Would update existing chopsticks repo' "$TMP_ROOT/get-existing.txt"
}
check_plugin_dirs() {
step "Plugin directories"
for plugin in \
fzf fzf.vim vim-fugitive vim-gitgutter ale vim-lsp vim-lsp-settings \
asyncomplete.vim asyncomplete-lsp.vim vim-markdown
do
test -d "$HOME/.vim/plugged/$plugin" || {
echo "Missing plugin directory: $plugin" >&2
exit 1
}
done
}
check_vim() {
step "Vim smoke tests"
need vim
check_plugin_dirs
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N -c 'qa!' 2>&1
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N \
-c "redir! > $TMP_ROOT/plugs.txt" \
-c 'silent echo len(g:plugs)' \
-c 'redir END' \
-c 'qa!' 2>/dev/null
PLUGS="$(tr -d '[:space:]' < "$TMP_ROOT/plugs.txt")"
echo "Plugins registered: $PLUGS"
if [ "$PLUGS" -lt 20 ]; then
echo "Expected 20+ plugins, got $PLUGS" >&2
exit 1
fi
mkdir -p "$TMP_ROOT/chopsticks path/modules"
cp .vimrc "$TMP_ROOT/chopsticks path/.vimrc"
cp modules/*.vim "$TMP_ROOT/chopsticks path/modules/"
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 \
-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") | cquit | endif' \
-c 'qa!' 2>&1
mkdir -p "$TMP_ROOT/local"
printf "%s\n" "let g:chopsticks_profile = 'minimal'" > "$TMP_ROOT/local/config.vim"
vim -u NONE -i NONE -es -N \
-c "let g:chopsticks_local_config = '$TMP_ROOT/local/config.vim'" \
-c 'source .vimrc' \
-c 'if g:chopsticks_profile !=# "minimal" || has_key(g:plugs, "ale") || has_key(g:plugs, "vim-lsp") | cquit | endif' \
-c 'qa!' 2>&1
mkdir -p "$TMP_ROOT/xdg"
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 \
-c 'source .vimrc' \
-c 'if g:chopsticks_profile !=# "minimal" || has_key(g:plugs, "ale") || has_key(g:plugs, "vim-lsp") | cquit | endif' \
-c 'qa!' 2>&1
vim -u NONE -i NONE -es -N \
-c 'let g:chopsticks_profile = "minimal"' \
-c 'source .vimrc' \
-c 'normal ,?' \
-c "redir! > $TMP_ROOT/cheat.txt" \
-c 'silent %print' \
-c 'redir END' \
-c 'qa!' 2>&1
if grep -Eq 'definition|LspInstallServer|ALE errors|undo tree|markdown preview' "$TMP_ROOT/cheat.txt"; then
cat "$TMP_ROOT/cheat.txt"
exit 1
fi
grep -q ',cr run file' "$TMP_ROOT/cheat.txt"
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N README.md \
-c 'set filetype=markdown' \
-c 'if &l:spell || &l:conceallevel != 0 || &l:signcolumn !=# "no" || exists("g:lsp_settings_filetype_markdown") | cquit | endif' \
-c 'qa!' 2>&1
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N \
-c 'if maparg("s", "n") !=# "" | cquit | endif' \
-c 'if maparg(",w", "n") =~# "!" | cquit | endif' \
-c 'if !&swapfile || !&writebackup || &directory !~# "\.vim/.swap" | cquit | endif' \
-c 'qa!' 2>&1
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' \
-c 'qa!' 2>&1
truncate -s 11000000 "$TMP_ROOT/large.py"
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE -es -N "$TMP_ROOT/large.py" \
-c 'set filetype=python' \
-c 'if &l:syntax !=# "" || &l:undolevels != -1 || &l:swapfile || get(b:, "ale_enabled", 1) != 0 | cquit | endif' \
-c 'qa!' 2>&1
XDG_CONFIG_HOME="$EMPTY_XDG" vim -u .vimrc -i NONE --startuptime "$TMP_ROOT/startup.log" \
-es -N -c 'qa!' 2>/dev/null
tail -1 "$TMP_ROOT/startup.log"
STARTUP_MS="$(awk 'END { print $1 }' "$TMP_ROOT/startup.log")"
awk -v ms="$STARTUP_MS" -v limit="$STARTUP_LIMIT_MS" \
'BEGIN { if (ms > limit) exit 1 }'
}
run_group() {
case "$1" in
quick)
check_shell
check_docs
check_installer_modes
check_bootstrap
;;
shell) check_shell ;;
docs) check_docs ;;
installer) check_installer_modes ;;
bootstrap) check_bootstrap ;;
vim) check_vim ;;
all)
run_group quick
check_vim
;;
list | --list) list_groups ;;
-h | --help) usage ;;
*)
echo "Unknown test group: $1" >&2
echo >&2
usage >&2
exit 1 ;;
esac
}
if [[ $# -eq 0 ]]; then
set -- all
fi
for group in "$@"; do
run_group "$group"
done