mirror of
https://oauth2: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@github.com/m1ngsama/chopsticks.git
synced 2026-05-10 19:10:59 +08:00
Compare commits
No commits in common. "main" and "v1.2.0" have entirely different histories.
28 changed files with 2865 additions and 3181 deletions
23
.github/ISSUE_TEMPLATE/bug_report.md
vendored
23
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
|
@ -1,23 +0,0 @@
|
||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Something broken or unexpected
|
|
||||||
labels: bug
|
|
||||||
---
|
|
||||||
|
|
||||||
**What happened**
|
|
||||||
|
|
||||||
|
|
||||||
**What you expected**
|
|
||||||
|
|
||||||
|
|
||||||
**Steps to reproduce**
|
|
||||||
1.
|
|
||||||
2.
|
|
||||||
3.
|
|
||||||
|
|
||||||
**Environment**
|
|
||||||
- OS:
|
|
||||||
- Vim version (`vim --version | head -1`):
|
|
||||||
- Terminal:
|
|
||||||
- SSH: yes / no
|
|
||||||
- TTY mode (`echo g:is_tty` inside vim):
|
|
||||||
14
.github/ISSUE_TEMPLATE/feature_request.md
vendored
14
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
|
@ -1,14 +0,0 @@
|
||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest a plugin, mapping, or improvement
|
|
||||||
labels: enhancement
|
|
||||||
---
|
|
||||||
|
|
||||||
**What problem does this solve?**
|
|
||||||
|
|
||||||
|
|
||||||
**What does the solution look like?**
|
|
||||||
|
|
||||||
|
|
||||||
**Alternatives you considered**
|
|
||||||
|
|
||||||
13
.github/PULL_REQUEST_TEMPLATE.md
vendored
13
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
|
@ -1,13 +0,0 @@
|
||||||
## What
|
|
||||||
|
|
||||||
<!-- One sentence: what does this PR do? -->
|
|
||||||
|
|
||||||
## Why
|
|
||||||
|
|
||||||
<!-- Why is this change needed? -->
|
|
||||||
|
|
||||||
## Test
|
|
||||||
|
|
||||||
- [ ] `vim --startuptime` shows no regression
|
|
||||||
- [ ] Tested on macOS / Linux
|
|
||||||
- [ ] `,?` cheat sheet still accurate
|
|
||||||
BIN
.github/demo.gif
vendored
BIN
.github/demo.gif
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 990 KiB |
63
.github/demo.tape
vendored
63
.github/demo.tape
vendored
|
|
@ -1,63 +0,0 @@
|
||||||
# chopsticks demo — "what can I do with this?"
|
|
||||||
# Rule: NEVER use Escape to close FZF — always Enter (deterministic).
|
|
||||||
# Pacing: hold each scene long enough for the viewer to read.
|
|
||||||
|
|
||||||
Output .github/demo.gif
|
|
||||||
Set Shell bash
|
|
||||||
Set FontSize 14
|
|
||||||
Set Width 1080
|
|
||||||
Set Height 620
|
|
||||||
Set Theme "Builtin Solarized Dark"
|
|
||||||
Set TypingSpeed 50ms
|
|
||||||
Set Padding 10
|
|
||||||
|
|
||||||
# ── 0. Start API server in background ──────────────────────────────────────
|
|
||||||
Type "cd /tmp/demo-project"
|
|
||||||
Enter
|
|
||||||
Sleep 0.5s
|
|
||||||
Type "python3 serve.py > /dev/null 2>&1 &"
|
|
||||||
Enter
|
|
||||||
Sleep 1s
|
|
||||||
|
|
||||||
# ── 1. Open file — syntax highlighting + statusline ────────────────────────
|
|
||||||
Type "vim server.py"
|
|
||||||
Enter
|
|
||||||
Sleep 3.5s
|
|
||||||
|
|
||||||
# ── 2. Fuzzy find files (Ctrl+p → type → select) ──────────────────────────
|
|
||||||
Ctrl+p
|
|
||||||
Sleep 1.5s
|
|
||||||
Type "route"
|
|
||||||
Sleep 2.5s
|
|
||||||
Enter
|
|
||||||
Sleep 3s
|
|
||||||
|
|
||||||
# ── 3. Ripgrep project search (,rg → query → select) ──────────────────────
|
|
||||||
Type ",rg"
|
|
||||||
Sleep 1.5s
|
|
||||||
Type "def "
|
|
||||||
Sleep 3s
|
|
||||||
Enter
|
|
||||||
Sleep 3s
|
|
||||||
|
|
||||||
# ── 4. Curl the running API from inside Vim ────────────────────────────────
|
|
||||||
Type ":!curl -s localhost:8080/users | python3 -m json.tool"
|
|
||||||
Enter
|
|
||||||
Sleep 4.5s
|
|
||||||
Enter
|
|
||||||
Sleep 1.5s
|
|
||||||
|
|
||||||
# ── 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 ",?"
|
|
||||||
Sleep 5.5s
|
|
||||||
Type "q"
|
|
||||||
Sleep 0.5s
|
|
||||||
|
|
||||||
# ── done ───────────────────────────────────────────────────────────────────
|
|
||||||
Type ":qa!"
|
|
||||||
Enter
|
|
||||||
Sleep 0.5s
|
|
||||||
75
.github/workflows/test.yml
vendored
75
.github/workflows/test.yml
vendored
|
|
@ -1,75 +0,0 @@
|
||||||
name: test
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
pull_request:
|
|
||||||
branches: [main]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
startup:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, macos-latest]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Vim
|
|
||||||
run: |
|
|
||||||
if [ "$(uname)" = "Darwin" ]; then
|
|
||||||
brew install vim
|
|
||||||
else
|
|
||||||
sudo apt-get update && sudo apt-get install -y vim
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Install vim-plug
|
|
||||||
run: |
|
|
||||||
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
|
|
||||||
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
|
|
||||||
|
|
||||||
- name: Symlink config
|
|
||||||
run: |
|
|
||||||
ln -sf "$PWD" ~/.vim/chopsticks-src
|
|
||||||
ln -sf "$PWD/.vimrc" ~/.vimrc
|
|
||||||
mkdir -p ~/.vim/modules
|
|
||||||
cp modules/*.vim ~/.vim/modules/
|
|
||||||
|
|
||||||
- name: Install plugins
|
|
||||||
run: |
|
|
||||||
set +e
|
|
||||||
vim -i NONE -es -u .vimrc -N -c 'PlugInstall --sync' -c 'qa!' 2>&1
|
|
||||||
plug_status=$?
|
|
||||||
set -e
|
|
||||||
if [ "$plug_status" -ne 0 ]; then
|
|
||||||
echo "PlugInstall exited with $plug_status; validating plugin directories"
|
|
||||||
fi
|
|
||||||
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 "FAIL: missing plugin $plugin"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Run Vim smoke tests
|
|
||||||
run: scripts/test.sh vim
|
|
||||||
|
|
||||||
shellcheck:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Check test runner CLI
|
|
||||||
run: |
|
|
||||||
scripts/test.sh --help
|
|
||||||
scripts/test.sh list
|
|
||||||
- name: Run shell and installer tests
|
|
||||||
run: scripts/test.sh shell installer bootstrap
|
|
||||||
|
|
||||||
docs:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install markdownlint
|
|
||||||
run: npm install -g markdownlint-cli
|
|
||||||
- name: Lint Markdown
|
|
||||||
run: scripts/test.sh docs
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -1,8 +1,6 @@
|
||||||
|
*.json
|
||||||
|
!coc-settings.json
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Session.vim
|
Session.vim
|
||||||
autoload/
|
|
||||||
plugged/
|
|
||||||
.swap/
|
|
||||||
.undo/
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"default": true,
|
|
||||||
"MD013": false,
|
|
||||||
"MD022": false,
|
|
||||||
"MD024": {
|
|
||||||
"siblings_only": true
|
|
||||||
},
|
|
||||||
"MD032": false,
|
|
||||||
"MD033": false,
|
|
||||||
"MD040": false,
|
|
||||||
"MD041": false,
|
|
||||||
"MD060": false
|
|
||||||
}
|
|
||||||
320
CHANGELOG.md
320
CHANGELOG.md
|
|
@ -1,159 +1,211 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## Unreleased
|
All notable changes to chopsticks are documented here.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [1.2.0] - 2026-04-09
|
||||||
|
|
||||||
|
Installer robustness overhaul and one-command bootstrap.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `~/.config/chopsticks.vim` local pre-load config for profile and user choices
|
- **`get.sh`** — one-command bootstrap: `curl -fsSL .../get.sh | bash`
|
||||||
- `g:chopsticks_enable_markdown_preview` to control Previm independently
|
- Installs `git` if missing (apt / pacman / dnf / brew)
|
||||||
- `g:chopsticks_profile` with `minimal`, `engineer`, and `full` profiles
|
- Clones repo to `~/.vim`; `git pull` if already present
|
||||||
- `.markdownlint.json` aligned with the project's README/changelog style
|
- `exec bash install.sh </dev/tty` — interactive prompts work correctly even when piped from curl
|
||||||
- `:ChopsticksStatus` diagnostic command — checks system tools, LSP servers, linters, formatters
|
- **Network connectivity check** — warns early if `github.com` is unreachable
|
||||||
- `,af` toggle format-on-save (ALE `fix_on_save`)
|
- **`curl` preflight** — detects missing curl, auto-installs or dies with clear instructions
|
||||||
- `,gL` git log graph (last 20 commits)
|
- **`git` preflight** — same as curl
|
||||||
- `,gC` FZF git commits search, `,gB` buffer commits
|
- **`vim` auto-install** — attempts `pkg_install` before dying if vim is not found
|
||||||
- Interactive installer profile selection for `minimal`, `engineer`, and `full`
|
- **`sudo` availability check** — authenticates once upfront; `--yes` mode skips sudo gracefully with a warning
|
||||||
- `install.sh --profile=minimal|engineer|full` for scripted profile selection
|
- **macOS Homebrew installer** — offers to install Homebrew when `brew` is missing on macOS
|
||||||
- `install.sh --dry-run` to show the resolved profile/config path without writes
|
- **Node.js via nvm** — when Node.js is missing, offers to install nvm + Node.js LTS automatically
|
||||||
- `install.sh --configure-only` to update local profile config without reinstalling
|
- **Python 3 installer** — offers to install python3 via package manager when missing
|
||||||
- `get.sh --dry-run` for safe bootstrap previews before clone/update/install
|
- **`safe_download()`** helper — verifies downloads are non-empty and not HTML error pages (guards against GitHub 404 / rate-limit pages being silently treated as binaries)
|
||||||
- `CHOPSTICKS_DEST=/absolute/path` to test or install the bootstrap target elsewhere
|
- **`pkg_install()`** helper — unified cross-platform install (brew / apt / pacman / dnf)
|
||||||
- `scripts/test.sh` local test runner reused by GitHub Actions
|
- **`arch_github()` / `arch_linux_x64()`** helpers — normalize `uname -m` including `aarch64` → `arm64`
|
||||||
- `scripts/test.sh quick`, `--help`, and `list` for easier local test discovery
|
- **`trap on_error ERR`** — catches unexpected failures, shows line number and debug command
|
||||||
|
- **`trap EXIT`** — cleans up temp files (`/tmp/chopsticks-hadolint`, `/tmp/chopsticks-marksman`)
|
||||||
|
- **Symlink verification** — confirms `[[ -L ]]` after `ln -sf`
|
||||||
|
- **vim-plug fallback** — if curl download fails, falls back to `git clone`; verifies file is non-empty
|
||||||
|
- **`vim +PlugInstall` error handling** — warns on non-zero exit instead of silent continue
|
||||||
|
- **Screen-dark notice** — informs user before each Vim fullscreen step (PlugInstall, CocInstall)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `set -e` → `set -eo pipefail` — pipeline failures now propagate correctly
|
||||||
|
- `ask()` now reads from `/dev/tty` with a test-open check (`{ true </dev/tty; }`) — interactive prompts work under `curl | bash` and non-interactive SSH sessions fall back to "no" safely
|
||||||
|
- Binary downloads (hadolint, marksman) use named temp files and `safe_download()` instead of bare curl
|
||||||
|
- Arch architecture detection handles `aarch64` in addition to `arm64`
|
||||||
|
- System tools section checks `HAS_SUDO` before running apt / pacman / dnf commands
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [1.1.1] - 2026-04-09
|
||||||
|
|
||||||
|
Systematic absorption of best practices from amix/vimrc, tpope/vim-sensible,
|
||||||
|
ThePrimeagen, skwp/YADR, and spf13-vim — settings and mappings that appear
|
||||||
|
consistently across all top global configs but were missing here.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **`set ttimeoutlen=10`** — eliminates the ~500ms ESC lag in terminal Vim; separates
|
||||||
|
keycode timeout from leader-key timeout (`timeoutlen` unchanged at 500ms)
|
||||||
|
- **`set display+=lastline`** — shows truncated long lines instead of replacing them with `@@@`
|
||||||
|
- **`set complete-=i`** — `Ctrl+n/p` no longer scans all included files; completion is instant
|
||||||
|
- **`set wildignorecase`** — case-insensitive filename completion in wildmenu and `:find`
|
||||||
|
- **`set path+=**`** — recursive `:find` across the project; wildignore excludes
|
||||||
|
`node_modules`, `__pycache__`, `dist`, `build`, `.git`
|
||||||
|
- **`set sessionoptions`** — removes `options` from saved sessions (prevents stale plugin
|
||||||
|
settings from contaminating restored sessions)
|
||||||
|
- **`set listchars`** — defines visible whitespace characters; TTY uses ASCII symbols,
|
||||||
|
modern terminals use Unicode (tab `→`, trail `·`, extends `▸`)
|
||||||
|
- **`F6`** — toggle visible whitespace on/off
|
||||||
|
- **`formatoptions-=cro`** on `BufEnter` — disables automatic comment-leader insertion
|
||||||
|
when pressing Enter or `o/O`; runs on BufEnter to override filetype plugins
|
||||||
|
- **`InsertLeave * set nopaste`** — auto-disables paste mode on leaving insert, preventing
|
||||||
|
permanently broken auto-indent
|
||||||
|
- **`colorcolumn=+1`** for all languages via `textwidth`:
|
||||||
|
Python 88, Go 120, JS/TS 100, Rust 100, Shell 80 (Markdown disabled)
|
||||||
|
- **`vnoremap J/K`** with `gv=gv` — move selected lines down/up and re-indent (ThePrimeagen)
|
||||||
|
- **`gV`** — re-select last pasted text (`\`[v\`]` — spf13, YADR)
|
||||||
|
- **`cnoremap <C-p>/<C-n>`** — navigate command-line history matching typed prefix (amix, spf13)
|
||||||
|
- **`<leader>e :Explore`** — open built-in Netrw file browser; works on any Vim without plugins
|
||||||
|
- **`<leader>cd`** — change window-local CWD to current file's directory (was `<leader>wd`)
|
||||||
|
- **`<leader>sv`** — reloads vimrc and echoes confirmation
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `<leader>wd` renamed to `<leader>cd`; now uses `lcd` (window-local) instead of `cd` (global)
|
||||||
|
- `wildignore` expanded with `*/node_modules/*`, `*/__pycache__/*`, `*/dist/*`, `*/build/*`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [1.1.0] - 2026-04-09
|
||||||
|
|
||||||
|
Ergonomics and automation overhaul: community-standard keybindings, seamless
|
||||||
|
tmux integration, an in-Vim cheat sheet, a beginner onboarding section, and
|
||||||
|
several correctness fixes from a systematic review.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **`jk` → `Esc`** in insert mode — ergonomic escape without reaching for the key
|
||||||
|
- **`Ctrl+s` save** in normal and insert mode (add `stty -ixon` to shell rc to enable
|
||||||
|
in terminals that use XON/XOFF flow control)
|
||||||
|
- **`//` visual search** — search for visually selected text using `\V` very-nomagic escaping
|
||||||
|
- **`<leader>p` / `<leader>P`** — paste from system clipboard after/before cursor
|
||||||
|
- **`<leader>rG`** — ripgrep word under cursor with `-F` (literal, not regex)
|
||||||
|
- **`<leader>u`** — leader-key alias for UndoTree (complements `F5`)
|
||||||
|
- **`<leader>tt`** — leader-key alias for Tagbar (complements `F8`)
|
||||||
|
- **`,?` in-Vim cheat sheet** — opens a read-only buffer covering modes, survival
|
||||||
|
commands, search, code intelligence, git, and clipboard; press `q` to close
|
||||||
|
- **vim-tmux-navigator** plugin — `Ctrl+h/j/k/l` navigates seamlessly across Vim
|
||||||
|
splits and tmux panes without a prefix key
|
||||||
|
- **`install.sh` tmux step** — detects tmux and optionally appends the four
|
||||||
|
navigator `bind-key` lines to `~/.tmux.conf`; warns about `C-l`/screen-clear tradeoff
|
||||||
|
- **`install.sh` survival guide** — post-install output now shows the 4 essential
|
||||||
|
commands for first-time Vim users, plus the `stty -ixon` advisory
|
||||||
|
- **QUICKSTART.md Step 0** — new first section explaining Vim modes (Normal/Insert/Visual)
|
||||||
|
and 4 survival commands; makes the guide usable by users who have never opened Vim
|
||||||
|
- **`let b:ale_enabled = 0`** in `LargeFileSettings()` — ALE no longer spawns
|
||||||
|
linter subprocesses for files over 10 MB
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **ALE lint triggers** — `ale_lint_on_text_changed` changed from `'never'` to `'normal'`;
|
||||||
|
`ale_lint_on_insert_leave` and `ale_lint_on_enter` changed from `0` to `1` — diagnostics
|
||||||
|
now refresh on buffer enter and after edits settle in normal mode
|
||||||
|
- **`<C-h/j/k/l>` manual maps removed** — vim-tmux-navigator owns these keys at
|
||||||
|
plugin load time; the previous hand-rolled `<C-W>` maps were unreachable dead code
|
||||||
|
- **`<leader>pp` paste-mode toggle removed** — functionally identical to the existing
|
||||||
|
`F2` pastetoggle; its presence caused a 500 ms delay on every `<leader>p` paste
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- `g:loaded_logipat` typo → `g:loaded_logiPat` — logiPat was loading fully (0.478ms wasted)
|
- **ALE navigation direction reversed** — `[e` now correctly calls `ALEPrevious`
|
||||||
- `get.sh` now refuses to update an existing `~/.vim` git repo unless its
|
and `]e` calls `ALENext`, matching the vim-unimpaired `[`/`]` convention
|
||||||
origin is chopsticks
|
- **`<leader>rG` regex metacharacter bug** — without `-F`, characters like `.` `*`
|
||||||
- Large file protection now stays active after filetype and syntax autocommands
|
`(` in the cursor word were treated as regex, producing incorrect matches
|
||||||
- `g:ale_fix_on_save = 0` in local config is now respected
|
|
||||||
- Local config now respects absolute `XDG_CONFIG_HOME` instead of hardcoding
|
|
||||||
`~/.config`
|
|
||||||
|
|
||||||
### Changed
|
---
|
||||||
|
|
||||||
- `,?` cheat sheet is now profile-aware and hides LSP/ALE/preview/UndoTree keys
|
## [1.0.0] - 2026-03-29
|
||||||
when those features are disabled
|
|
||||||
- Module reload/source paths now use `fnameescape()` so installs in paths with
|
|
||||||
spaces are handled correctly
|
|
||||||
- CI now verifies path-safe module loading, the local config hook, and
|
|
||||||
minimal-profile cheat sheet output
|
|
||||||
- Markdown now opens in quiet writing mode by default: no real-time markdownlint,
|
|
||||||
no Marksman LSP, no spell noise, no conceal, no sign column, and no realtime preview
|
|
||||||
- Native `s` is no longer shadowed by EasyMotion; use `,S` for the two-character jump
|
|
||||||
- `,w` now uses a normal `:write` instead of forced `:write!`
|
|
||||||
- Swap files are enabled again and stored under `~/.vim/.swap` for crash recovery
|
|
||||||
- Installer defaults are slimmer: only core search tools stay selected by default;
|
|
||||||
language and lint suites are opt-in
|
|
||||||
- `:ChopsticksStatus` now respects disabled LSP/lint profiles instead of reporting
|
|
||||||
intentionally disabled tools as missing
|
|
||||||
- `,sv` now clears the load guard before sourcing `$MYVIMRC`
|
|
||||||
- CI now verifies key plugin directories, Markdown quiet defaults, markdownlint,
|
|
||||||
and an explicit startup-time threshold
|
|
||||||
- Installer plugin validation now checks every plugin required by the active profile
|
|
||||||
- The optional tool menu now hides LSP/lint suites in `minimal` and selects
|
|
||||||
Marksman by default in `full`
|
|
||||||
- tmux integration is written as a managed block so future installer runs can
|
|
||||||
update it without appending duplicate bindings
|
|
||||||
- Installer cleanup now restores the cursor after interrupted checkbox menus
|
|
||||||
- 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)
|
|
||||||
- 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
|
First stable release. Full-stack engineering environment out of the box — automatic
|
||||||
|
installation, tiered LSP, TTY fallback, and coverage for 14 languages.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
- **Arch Linux support** in `install.sh` — pacman branch for all system tools
|
||||||
- Cheat sheet (`,?`) — vertical sidebar, one key per line, section headers
|
- **`hadolint`** added to system tools installation (Dockerfile linting)
|
||||||
- Previm markdown preview restored (lazy-loaded, `,mp`)
|
- **`staticcheck`** added to Go tools (replaces archived `golint`)
|
||||||
- `:LspInstallServer` added to cheat sheet
|
- **`yamllint`** added to pip tools (YAML linting)
|
||||||
|
- **`coc-settings.json`** — configures `marksman` as Markdown LSP for CoC via
|
||||||
|
`languageserver` entry; symlinked automatically by `install.sh`
|
||||||
|
- **pip3 bootstrap** in `install.sh` — auto-installs pip3 when python3 is present
|
||||||
|
but pip3 is absent (common on Ubuntu minimal images)
|
||||||
|
- **9 named augroups** in `.vimrc` — all loose `autocmd` statements now wrapped
|
||||||
|
with `autocmd!` to prevent doubling on `:source $MYVIMRC`:
|
||||||
|
`ChopstickTabHistory`, `ChopstickResize`, `ChopstickStdin`, `CocHighlight`,
|
||||||
|
`ChopstickCleanup`, `ChopstickFiletype`, `ChopstickTTYLargeFile`,
|
||||||
|
`ChopstickWhichKey`, `ChopstickStartify`
|
||||||
|
- **TTY-safe plugin install** — `vim +PlugInstall +qall </dev/null` prevents
|
||||||
|
Vim from blocking in non-interactive/piped environments
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- SQL tooling unified to **`sqlfluff`** (pip) — `sqlfmt` removed from npm section
|
||||||
|
- Go linter changed from `golint` (archived 2023) to **`staticcheck`**
|
||||||
|
- Markdown LSP changed from broken `coc-marksman` (npm) to **`marksman`** binary
|
||||||
|
configured via `coc-settings.json`
|
||||||
|
|
||||||
- Plugin count: 25 (restored previm, dropped 5 bloat plugins)
|
### Fixed
|
||||||
- QUICKSTART updated — removed stale references, improved first-launch guidance
|
- **vim-go startup hang** on Arch Linux — removed `:GoUpdateBinaries` post-install
|
||||||
|
hook; set `g:go_gopls_enabled = 0` to prevent conflict with `coc-go`
|
||||||
|
- **E495 errors** (`<afile>` in special buffers) — all `<afile>` usages guarded
|
||||||
|
with `!empty(expand('<afile>'))` and `empty(&buftype)` checks
|
||||||
|
- **`g:go_def_mode` conflict** — now conditional: uses `gopls` when CoC active,
|
||||||
|
`godef` when vim-lsp active (avoids error when gopls is disabled)
|
||||||
|
- **vim startup UX** — NERDTree + Startify layout for `vim .` and bare `vim`
|
||||||
|
- **`coc-marksman` silent failure** — package does not exist on npm; replaced with
|
||||||
|
native `languageserver` configuration in `coc-settings.json`
|
||||||
|
- **CoC startup warning** in no-node environments — `g:coc_start_at_startup = 0`
|
||||||
|
and `g:coc_disable_startup_warning = 1` set when `g:use_coc = 0`
|
||||||
|
|
||||||
## 2.0.0 — 2025-04-21
|
---
|
||||||
|
|
||||||
|
## [0.9.0] - 2026-02-21
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
- **Full-stack language coverage** — LSP, lint, and format for: Python,
|
||||||
- Sidebar toggle (`,e` / `,E`) — left-side netrw with `topleft vertical`, winfixwidth, proper toggle
|
JavaScript, TypeScript, Go, Rust, Shell, YAML, HTML, CSS/SCSS, Less,
|
||||||
- Enriched statusline — SLMode, SLGit, SLAle, SLFlags
|
JSON, Markdown, SQL, Dockerfile
|
||||||
- Toggle feedback — F2/F3/F4/F6/`,ss` echo current state
|
- **`install.sh` overhaul** — automated installation of system tools, npm tools,
|
||||||
- `vim .` layout — netrw left + Startify right (removed in later refactor)
|
pip tools, Go tools, and CoC language server extensions with platform detection
|
||||||
- Interactive tutorial (`:ChopsticksLearn` — removed in later release)
|
and interactive prompts; `--yes` flag for non-interactive mode
|
||||||
|
- **vim-startify** startup screen with dynamic header (version, cwd, git branch)
|
||||||
### Removed (Unix minimalism refactor)
|
- **vim-which-key** keybinding popup on `,` + 500ms pause
|
||||||
|
- **Startup layout** — `vim .` opens NERDTree left + Startify right; bare `vim`
|
||||||
- **565 lines** of dead code and bloat
|
opens Startify with NERDTree alongside
|
||||||
- 5 plugins: Goyo, Limelight, vim-obsession, indentLine, vim-unimpaired
|
- **Session management** via vim-obsession + vim-prosession
|
||||||
- `modules/writing.vim` — folded into `languages.vim`
|
- **Large file handling** — syntax and undo disabled for files > 10 MB
|
||||||
- `tutor/chopsticks.tutor` — removed (269 lines)
|
- **Project-local config** — `.vimrc` in project root auto-loaded via `set exrc`
|
||||||
- Tab management keybindings (8 mappings), spell nav bindings (4 mappings)
|
- **Persistent undo** — `~/.vim/.undo/` with `undolevels=1000`
|
||||||
- Dead functions: HasPaste(), CleanExtraSpaces(), ToggleNumber(), SynStack
|
|
||||||
- TTY welcome message, `,so`, `,ms`, `,sh` mappings
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- Tiered LSP backend: CoC (Node.js) preferred, vim-lsp (no Node.js) as fallback
|
||||||
|
- All CoC and vim-lsp keybindings unified (`gd`, `K`, `[g`/`]g`, `,rn`, `,ca`)
|
||||||
|
- ALE `fix_on_save` disabled when vim-lsp active (prevents double-format)
|
||||||
|
- NERDTree autocmd wrapped in `augroup NERDTreeAutoClose`
|
||||||
|
|
||||||
- CI plugin threshold lowered to 20
|
### Fixed
|
||||||
- README: hero layout with demo GIF, badges, architecture diagram
|
- Multiple leader key conflicts resolved (`,ad`, `,cd`, `,cp`, `,sp`, `,t`)
|
||||||
- vim-markdown settings absorbed from writing.vim into languages.vim
|
- CtrlP removed (redundant with FZF)
|
||||||
|
- Duplicate `set` options cleaned up
|
||||||
|
- `<leader>A` dead mapping (no alternate-file plugin) removed
|
||||||
|
|
||||||
## 1.3.0 — 2025-04-20
|
---
|
||||||
|
|
||||||
### Changed
|
## [0.1.0] - 2024
|
||||||
|
|
||||||
- Startup: 39ms → 19ms (51% faster)
|
Initial release — base Vim configuration with vim-plug, basic plugins, and
|
||||||
- Dropped vim-unimpaired for performance
|
TTY/non-TTY detection.
|
||||||
- Runtime tuning across modules
|
|
||||||
|
|
||||||
## 1.2.0 — 2025-04-19
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Hero README with demo GIF, CI badges
|
|
||||||
- GitHub Actions CI (startup test on macOS + Ubuntu, shellcheck)
|
|
||||||
- Issue/PR templates
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Documentation rewrite — clean, short, for engineers
|
|
||||||
|
|
||||||
## 1.1.0 — 2025-04-18
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- 12-module architecture (env → plugins → core → ui → editing → navigation → lsp → lint → git → writing → languages → tools)
|
|
||||||
- Zen mode (Goyo + Limelight)
|
|
||||||
- Run file (`,cr`) with auto filetype detection
|
|
||||||
- Smart search (SmartFiles, Rg, RgWord)
|
|
||||||
- EasyMotion, yank highlight, undo tree
|
|
||||||
- Robust installer (`get.sh`) with preflight checks
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- `.vimrc` split into 12 self-contained modules
|
|
||||||
- Comprehensive bug audit (14 fixes)
|
|
||||||
|
|
||||||
## 1.0.0 — 2025-04-16
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Initial Vim configuration — migrated from Neovim
|
|
||||||
- vim-plug plugin manager
|
|
||||||
- vim-lsp + asyncomplete (pure VimScript LSP)
|
|
||||||
- ALE linting + format-on-save
|
|
||||||
- FZF fuzzy finder
|
|
||||||
- Fugitive + GitGutter
|
|
||||||
- Solarized colorscheme
|
|
||||||
- TTY detection and graceful degradation
|
|
||||||
- Platform installer (macOS, Debian, Arch, Fedora)
|
|
||||||
|
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
# Contributing
|
|
||||||
|
|
||||||
## Rules
|
|
||||||
|
|
||||||
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.
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Adding a plugin
|
|
||||||
|
|
||||||
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' }`
|
|
||||||
3. Put config in the appropriate module
|
|
||||||
4. Update the cheat sheet in `modules/tools.vim` if you add keybindings
|
|
||||||
5. Run `scripts/test.sh vim` locally after installing plugins
|
|
||||||
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
|
|
||||||
|
|
||||||
Open an issue. Include:
|
|
||||||
|
|
||||||
- OS and Vim version
|
|
||||||
- Whether you're on SSH/TTY
|
|
||||||
- Steps to reproduce
|
|
||||||
|
|
||||||
## Code style
|
|
||||||
|
|
||||||
- Named augroups with `autocmd!`
|
|
||||||
- No comments explaining _what_ — only _why_
|
|
||||||
- `exists('g:plugs["..."]')` guards for plugin-dependent config
|
|
||||||
- Test with `scripts/test.sh vim`
|
|
||||||
329
QUICKSTART.md
329
QUICKSTART.md
|
|
@ -1,120 +1,295 @@
|
||||||
# Quick Start
|
# Quick Start
|
||||||
|
|
||||||
Five minutes from zero to a working Vim setup.
|
Five minutes from zero to a working Vim engineering environment.
|
||||||
|
|
||||||
## Install
|
> **New to Vim?** Read Step 0 first — it takes 2 minutes and prevents the most
|
||||||
|
> common beginner frustration. Already know how Vim modes work? [Skip to Step 1](#step-1-install).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 0: Vim Basics
|
||||||
|
|
||||||
|
> **When confused, press `Esc` until things feel normal again — then keep reading.**
|
||||||
|
|
||||||
|
Vim is **modal**: the keyboard behaves differently depending on which mode you are in.
|
||||||
|
Most people get stuck because they try to type text while in Normal mode.
|
||||||
|
|
||||||
|
### The Three Modes
|
||||||
|
|
||||||
|
| Mode | Purpose | How to enter | How to leave |
|
||||||
|
|------|---------|--------------|--------------|
|
||||||
|
| **Normal** | Navigate and run commands | Startup default | — (you're already here) |
|
||||||
|
| **Insert** | Type text | `i` before cursor, `a` after, `o` new line below | `Esc` or `jk` |
|
||||||
|
| **Visual** | Select text | `v` char-by-char, `V` whole lines | `Esc` |
|
||||||
|
|
||||||
|
### 4 Survival Commands
|
||||||
|
|
||||||
|
Learn these before anything else. They will get you out of every stuck situation.
|
||||||
|
|
||||||
|
| Command | Action |
|
||||||
|
|---------|--------|
|
||||||
|
| `Esc` or `jk` | Exit insert/visual mode — return to Normal |
|
||||||
|
| `:q!` then `Enter` | Force quit without saving (emergency exit) |
|
||||||
|
| `,x` | Save and quit |
|
||||||
|
| `,w` or `Ctrl+s` | Save the file |
|
||||||
|
|
||||||
|
Once in Normal mode, press `,?` to open a cheat sheet covering everything else.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 1: Install
|
||||||
|
|
||||||
|
**One command — works on macOS and Linux:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
|
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
|
||||||
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --profile=minimal
|
|
||||||
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --dry-run --profile=full
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Open vim. First launch auto-installs plugins — **wait 30-60s, don't close vim**. Restart when done.
|
This clones the repo to `~/.vim` and runs the full installer. Interactive prompts
|
||||||
|
let you choose which optional tools to install (ripgrep, Node.js, Python tools, etc.).
|
||||||
|
|
||||||
Default profile is `engineer`. Interactive installs ask for a profile first;
|
The installer automatically handles missing dependencies — it will offer to install
|
||||||
`--profile=minimal`, `--profile=engineer`, or `--profile=full` selects it
|
`git`, Homebrew (macOS), or Node.js via nvm if they are not found.
|
||||||
without prompting. You can later put `let g:chopsticks_profile = 'minimal'` in
|
|
||||||
`${XDG_CONFIG_HOME:-~/.config}/chopsticks.vim` for a smaller core-only setup,
|
|
||||||
or use `full` for the heavier Markdown/LSP feedback.
|
|
||||||
|
|
||||||
To switch later without reinstalling anything:
|
**Traditional install:**
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
|
||||||
|
cd ~/.vim && ./install.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Non-interactive (CI / server / scripting):**
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --yes
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 2: Open Vim
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd ~/.vim && ./install.sh --configure-only --profile=full
|
vim
|
||||||
```
|
```
|
||||||
|
|
||||||
## Modes
|
The startup screen (vim-startify) shows recent files and sessions.
|
||||||
|
Press `Ctrl+p` to find a file, or just type a path.
|
||||||
|
|
||||||
| Mode | Enter | Leave |
|
To open a project:
|
||||||
| ------ | --------------- | ------------- |
|
```bash
|
||||||
| Normal | startup default | — |
|
vim . # NERDTree on left, Startify on right
|
||||||
| Insert | `i` / `a` / `o` | `Esc` or `jk` |
|
vim myfile # opens file directly
|
||||||
| Visual | `v` / `V` | `Esc` |
|
|
||||||
|
|
||||||
## Survival
|
|
||||||
|
|
||||||
```
|
|
||||||
Esc / jk back to Normal
|
|
||||||
,w save
|
|
||||||
,x save + quit
|
|
||||||
:q! force quit
|
|
||||||
Ctrl+s save from any mode
|
|
||||||
,? cheat sheet (toggle sidebar)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Find things
|
---
|
||||||
|
|
||||||
```
|
## Step 3: Set Up LSP (pick your path)
|
||||||
Ctrl+p fuzzy find file (git-aware)
|
|
||||||
,rg ripgrep project
|
### Path A: With Node.js (CoC — full LSP)
|
||||||
,b search buffers
|
|
||||||
,fh recent files
|
```bash
|
||||||
,e file browser
|
node --version # must be >= 14.14
|
||||||
,, last file
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Write code
|
Inside Vim, install language servers for your stack:
|
||||||
|
|
||||||
```
|
```vim
|
||||||
gd go to definition
|
:CocInstall coc-pyright coc-tsserver coc-go coc-rust-analyzer
|
||||||
K hover docs
|
|
||||||
,rn rename symbol
|
|
||||||
,ca code action
|
|
||||||
,f format
|
|
||||||
,cr run current file
|
|
||||||
Tab / S-Tab cycle completions
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**First time in a new language?** Run `:LspInstallServer` — it auto-detects filetype and installs the right server. Do this once per language.
|
Or let `install.sh` do it — it asks during setup.
|
||||||
|
|
||||||
## Git
|
### Path B: Without Node.js (vim-lsp — no dependencies)
|
||||||
|
|
||||||
|
Open a source file, then run:
|
||||||
|
|
||||||
|
```vim
|
||||||
|
:LspInstallServer
|
||||||
|
```
|
||||||
|
|
||||||
|
This auto-detects and installs the correct language server for the current filetype.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The 12 Keys That Matter
|
||||||
|
|
||||||
```
|
```
|
||||||
,gs status (s=stage, cc=commit)
|
, (pause 500ms) Show all keybindings (which-key)
|
||||||
,gd diff
|
,? Open cheat sheet inside Vim
|
||||||
,gb blame
|
Esc / jk Exit insert mode → Normal (memorize this)
|
||||||
|
Ctrl+s Save (works in normal and insert mode)
|
||||||
|
Ctrl+p Fuzzy find file
|
||||||
|
Ctrl+n Toggle file tree
|
||||||
|
gd Go to definition
|
||||||
|
K Show documentation
|
||||||
|
[g / ]g Prev / next LSP diagnostic
|
||||||
|
,rn Rename symbol
|
||||||
|
,rG Search word under cursor (ripgrep)
|
||||||
|
,gs Git status
|
||||||
|
,w / ,x Save / Save+quit
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Daily Use
|
||||||
|
|
||||||
|
### Navigate Code
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `gd` | Go to definition |
|
||||||
|
| `gy` | Go to type definition |
|
||||||
|
| `gi` | Go to implementation |
|
||||||
|
| `gr` | List all references |
|
||||||
|
| `K` | Show docs for symbol under cursor |
|
||||||
|
| `Ctrl+o` | Jump back |
|
||||||
|
| `Ctrl+i` | Jump forward |
|
||||||
|
|
||||||
|
### Edit Code
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `Tab` | Select next completion item |
|
||||||
|
| `Enter` | Confirm completion |
|
||||||
|
| `gc` | Toggle comment (visual mode too) |
|
||||||
|
| `cs"'` | Change surrounding `"` to `'` |
|
||||||
|
| `ds(` | Delete surrounding `(` |
|
||||||
|
| `s`+2ch | EasyMotion: jump anywhere |
|
||||||
|
|
||||||
|
### Manage Errors
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `]g` | Jump to next diagnostic |
|
||||||
|
| `[g` | Jump to previous diagnostic |
|
||||||
|
| `K` | Read the error message |
|
||||||
|
| `,ca` | Apply code action / auto-fix |
|
||||||
|
|
||||||
|
### Git Workflow
|
||||||
|
|
||||||
|
```
|
||||||
|
,gs git status (stage with 's', commit with 'cc')
|
||||||
|
,gd diff current file
|
||||||
|
,gb blame current file
|
||||||
|
,gc commit
|
||||||
,gp push
|
,gp push
|
||||||
]x / [x conflict markers
|
,gl pull
|
||||||
```
|
```
|
||||||
|
|
||||||
## Edit
|
---
|
||||||
|
|
||||||
```
|
## Language Workflows
|
||||||
,S + 2 chars EasyMotion jump
|
|
||||||
gc toggle comment
|
### Python
|
||||||
cs"' change surrounding " to '
|
|
||||||
Alt+j / Alt+k move line
|
```bash
|
||||||
,u undo tree
|
# tools installed by install.sh; or manually:
|
||||||
,y clipboard yank
|
pip install black flake8 pylint isort
|
||||||
```
|
```
|
||||||
|
|
||||||
## Navigate
|
Auto-formats with `black` + `isort` on save. Lint errors show as `X`/`!` in the sign column.
|
||||||
|
|
||||||
```
|
### JavaScript / TypeScript
|
||||||
Ctrl+h/j/k/l splits + tmux panes
|
|
||||||
,h / ,l prev / next buffer
|
```bash
|
||||||
,z maximize window
|
npm install -g prettier eslint typescript
|
||||||
,tv / ,th terminal
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Markdown
|
Auto-formats with `prettier` on save.
|
||||||
|
|
||||||
```
|
### Go
|
||||||
,mp preview in browser
|
|
||||||
,mt table of contents
|
```bash
|
||||||
|
# tools installed by install.sh; or manually:
|
||||||
|
go install golang.org/x/tools/gopls@latest
|
||||||
|
go install golang.org/x/tools/cmd/goimports@latest
|
||||||
|
go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||||
```
|
```
|
||||||
|
|
||||||
Markdown is quiet by default: no real-time lint, no spell noise, no concealed
|
`gofmt` + `goimports` run on save automatically.
|
||||||
syntax. Enable the heavier Markdown tools only when you want them.
|
|
||||||
|
|
||||||
## Health check
|
### Markdown
|
||||||
|
|
||||||
```
|
Install `marksman` for LSP support (completions, link checking):
|
||||||
:ChopsticksStatus see what's installed and what's missing
|
|
||||||
|
```bash
|
||||||
|
brew install marksman # macOS
|
||||||
|
sudo pacman -S marksman # Arch
|
||||||
|
# or: ./install.sh (handles it automatically)
|
||||||
```
|
```
|
||||||
|
|
||||||
The `,?` cheat sheet follows your active profile, so `minimal` users only see
|
---
|
||||||
keys for features that are actually loaded.
|
|
||||||
|
|
||||||
See [README](README.md) for the full reference. See the [wiki](https://github.com/m1ngsama/chopsticks/wiki) for deep dives.
|
## Customize
|
||||||
|
|
||||||
|
Edit config live:
|
||||||
|
```vim
|
||||||
|
,ev " opens ~/.vimrc in Vim
|
||||||
|
,sv " reloads config without restarting
|
||||||
|
```
|
||||||
|
|
||||||
|
Per-project settings: create `.vimrc` in your project root.
|
||||||
|
```vim
|
||||||
|
" project/.vimrc
|
||||||
|
set shiftwidth=2
|
||||||
|
let g:ale_python_black_options = '--line-length=100'
|
||||||
|
```
|
||||||
|
|
||||||
|
Change color scheme in `~/.vimrc`:
|
||||||
|
```vim
|
||||||
|
colorscheme dracula " or: gruvbox, solarized, onedark
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference Card
|
||||||
|
|
||||||
|
```
|
||||||
|
BASICS (learn these first)
|
||||||
|
Esc / jk Exit insert mode → Normal
|
||||||
|
Ctrl+s Save (normal + insert mode)
|
||||||
|
:q! + Enter Emergency quit without saving
|
||||||
|
,? Open cheat sheet
|
||||||
|
|
||||||
|
FILES
|
||||||
|
Ctrl+n File tree toggle
|
||||||
|
Ctrl+p Fuzzy find file (git-aware)
|
||||||
|
,b Search open buffers
|
||||||
|
,rg Search file contents (ripgrep)
|
||||||
|
,rG Ripgrep word under cursor
|
||||||
|
,w Save | ,q Quit | ,x Save+quit
|
||||||
|
,wa Save all buffers
|
||||||
|
,, Switch to last file
|
||||||
|
|
||||||
|
CODE
|
||||||
|
gd Go to definition
|
||||||
|
K Show documentation
|
||||||
|
[g / ]g Prev/next LSP diagnostic
|
||||||
|
[e / ]e Prev/next ALE error
|
||||||
|
,rn Rename symbol
|
||||||
|
,ca Code action / auto-fix
|
||||||
|
,f Format selection | ,F Format whole file
|
||||||
|
|
||||||
|
GIT
|
||||||
|
,gs Status | ,gd Diff | ,gb Blame
|
||||||
|
,gc Commit | ,gp Push | ,gl Pull
|
||||||
|
|
||||||
|
WINDOWS / PANES
|
||||||
|
Ctrl+h/j/k/l Move between Vim windows or tmux panes
|
||||||
|
,h / ,l Prev / next buffer
|
||||||
|
,tv Open terminal (vertical)
|
||||||
|
,th Open terminal (horizontal)
|
||||||
|
Esc Exit terminal mode
|
||||||
|
,u Undo tree | ,tt Tag browser
|
||||||
|
|
||||||
|
SEARCH & REPLACE
|
||||||
|
/text Search forward | ?text backward
|
||||||
|
// Search for visually selected text
|
||||||
|
,* Replace word under cursor (file-wide)
|
||||||
|
|
||||||
|
CLIPBOARD
|
||||||
|
,y / ,Y Yank / yank line to system clipboard
|
||||||
|
,p / ,P Paste from system clipboard (after / before)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
See [README.md](README.md) for the complete reference.
|
||||||
|
|
|
||||||
690
README.md
690
README.md
|
|
@ -1,231 +1,611 @@
|
||||||
<p align="center">
|
# chopsticks
|
||||||
<img src=".github/demo.gif" alt="chopsticks demo" width="720">
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h1 align="center">chopsticks</h1>
|
> A batteries-included Vim configuration for full-stack engineering.
|
||||||
|
> Tiered LSP · 14 languages · TTY-aware · Zero icon fonts · One-command install.
|
||||||
|
|
||||||
<p align="center">
|
[](LICENSE)
|
||||||
<strong>Vim for engineers. ~25 plugins, works over SSH.</strong>
|
[](https://www.vim.org/)
|
||||||
</p>
|
[](#installation)
|
||||||
|
[](https://github.com/m1ngsama/chopsticks/releases)
|
||||||
<p align="center">
|
[](https://github.com/m1ngsama/chopsticks/commits/main)
|
||||||
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square" alt="MIT License"></a>
|
[](https://github.com/m1ngsama/chopsticks/stargazers)
|
||||||
<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>
|
[](https://github.com/m1ngsama/chopsticks/issues)
|
||||||
<a href="#install"><img src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey?style=flat-square" alt="Platform"></a>
|
[](https://github.com/m1ngsama/chopsticks/pulls)
|
||||||
<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>
|
[](#plugins)
|
||||||
<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>
|
[](#language-support)
|
||||||
</p>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
|
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **New to Vim?** Read [Step 0 in QUICKSTART.md](QUICKSTART.md#step-0-vim-basics) first —
|
||||||
|
> a 2-minute intro to modes and the 4 commands that get you out of any jam.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Why
|
## Contents
|
||||||
|
|
||||||
You SSH into a server. You need to edit code. You want LSP, fuzzy find, git integration, format-on-save — not a 20-minute setup.
|
- [Design Principles](#design-principles)
|
||||||
|
- [Requirements](#requirements)
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [LSP: Tiered Backend](#lsp-tiered-backend)
|
||||||
|
- [Key Mappings](#key-mappings)
|
||||||
|
- [Features](#features)
|
||||||
|
- [Language Support](#language-support)
|
||||||
|
- [Plugins](#plugins)
|
||||||
|
- [Customization](#customization)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
- [Contributing](#contributing)
|
||||||
|
|
||||||
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.
|
---
|
||||||
|
|
||||||
**24–25 plugins** (tmux-navigator loads only inside tmux), LSP, linting, and a hand-built statusline. No bloat, no decorations, just tools.
|
## Design Principles
|
||||||
|
|
||||||
## What's in the box
|
| Principle | What it means |
|
||||||
|
|-----------|--------------|
|
||||||
|
| **KISS** | No icon fonts, no Nerd Font glyphs — plain ASCII everywhere |
|
||||||
|
| **Tiered LSP** | CoC (full) when Node.js is available; vim-lsp (pure VimScript) otherwise |
|
||||||
|
| **TTY-aware** | Automatically detects SSH/console environments and degrades gracefully |
|
||||||
|
| **Engineering-first** | Git workflow, persistent sessions, project-local config, large-file safety |
|
||||||
|
| **Batteries included** | `install.sh` handles vim-plug, plugins, system tools, and language servers |
|
||||||
|
|
||||||
| Feature | Description |
|
---
|
||||||
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| **LSP** | completion, go-to-def, hover, rename, code actions — pure VimScript ([vim-lsp](https://github.com/prabirshrestha/vim-lsp)) |
|
|
||||||
| **Lint + format** | [ALE](https://github.com/dense-analysis/ale) runs black, prettier, goimports, rustfmt on save |
|
|
||||||
| **Fuzzy find** | files, buffers, grep, tags, marks, commands — [FZF](https://github.com/junegunn/fzf.vim) |
|
|
||||||
| **Git** | status, diff, blame, push, pull, conflict markers — [fugitive](https://github.com/tpope/vim-fugitive) + [gitgutter](https://github.com/airblade/vim-gitgutter) |
|
|
||||||
| **Run file** | `,cr` — auto-detects Python, Go, Rust, JS, C, Shell, and more |
|
|
||||||
| **Markdown** | quiet writing defaults, browser preview (`,mp`), table of contents (`,mt`) |
|
|
||||||
| **Diagnostics** | `:ChopsticksStatus` — see what's installed, what's missing, how to fix it |
|
|
||||||
| **TTY-aware** | degrades gracefully on SSH, console, slow links — never breaks |
|
|
||||||
|
|
||||||
## Install
|
## Requirements
|
||||||
|
|
||||||
|
| Tool | Minimum | Role |
|
||||||
|
|------|---------|------|
|
||||||
|
| Vim | **8.0+** | Required — `install.sh` installs it if missing |
|
||||||
|
| git | any | Required — `install.sh` installs it if missing |
|
||||||
|
| curl | any | Required — `install.sh` installs it if missing |
|
||||||
|
| Node.js | 14.14+ | Optional — enables CoC LSP; `install.sh` offers nvm install |
|
||||||
|
| ripgrep | any | Optional — enables `,rg` / `,rG` project search |
|
||||||
|
| fzf | any | Optional — enables `Ctrl+p` fuzzy finder |
|
||||||
|
| ctags | any | Optional — enables `,tt` tag browser |
|
||||||
|
| tmux | 1.8+ | Optional — enables seamless pane navigation |
|
||||||
|
|
||||||
|
`install.sh` detects your environment and installs missing dependencies automatically.
|
||||||
|
On macOS it will offer to install Homebrew if not present. On any platform it will
|
||||||
|
offer to install Node.js via nvm if missing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### One command (recommended)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
|
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
|
||||||
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --profile=minimal
|
|
||||||
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --dry-run --profile=full
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Or manually:
|
This bootstrap script clones the repo to `~/.vim`, then runs the full installer.
|
||||||
|
It works correctly even when piped from curl — interactive prompts use `/dev/tty`.
|
||||||
|
|
||||||
|
For non-interactive or CI environments:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --yes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Traditional (git clone)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
|
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
|
||||||
cd ~/.vim && ./install.sh --profile=engineer
|
cd ~/.vim && ./install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Supports macOS (brew), Debian/Ubuntu (apt), Arch (pacman), Fedora (dnf).
|
### What the installer does
|
||||||
Set `CHOPSTICKS_DEST=/absolute/path` before running `get.sh` to install
|
|
||||||
somewhere other than `~/.vim`.
|
|
||||||
|
|
||||||
First launch installs plugins automatically (30-60s). Restart vim when done.
|
1. **Preflight** — checks network, detects OS and package manager, verifies or installs `curl`, `git`, and `vim`
|
||||||
Use `./install.sh --dry-run --profile=full` to inspect the resolved profile and
|
2. **sudo** — authenticates once upfront; gracefully skips system packages when unavailable
|
||||||
config path without changing files. Use `./install.sh --configure-only
|
3. **macOS** — offers to install Homebrew if `brew` is not found
|
||||||
--profile=minimal` to switch profiles without reinstalling plugins or tools.
|
4. **Node.js** — offers to install via nvm if not found (falls back to vim-lsp if declined)
|
||||||
|
5. **Python** — offers to install Python 3 if missing; bootstraps pip3 if only python3 is present
|
||||||
|
6. **Symlinks** — backs up any existing `~/.vimrc` with a timestamp, then symlinks `~/.vimrc → ~/.vim/.vimrc`
|
||||||
|
7. **Plugins** — installs vim-plug and runs `:PlugInstall` (with a progress notice during the black-screen period)
|
||||||
|
8. **System tools** — ripgrep, fzf, ctags, shellcheck, hadolint, marksman (verified downloads)
|
||||||
|
9. **Language tools** — npm formatters, pip formatters/linters, Go tools
|
||||||
|
10. **CoC extensions** — all language servers in one step
|
||||||
|
11. **tmux** — optionally appends vim-tmux-navigator bindings to `~/.tmux.conf`
|
||||||
|
|
||||||
## Profiles
|
**Supported platforms:** macOS (Homebrew), Debian/Ubuntu (apt), Arch Linux (pacman), Fedora (dnf).
|
||||||
|
|
||||||
Default profile: `engineer`. Interactive installs ask for this profile before
|
### Manual
|
||||||
plugins are installed; `--profile=minimal`, `--profile=engineer`, or
|
|
||||||
`--profile=full` selects it without prompting. `--yes` keeps the existing local
|
```bash
|
||||||
profile or uses `engineer`.
|
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
|
||||||
|
ln -sf ~/.vim/.vimrc ~/.vimrc
|
||||||
|
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
|
||||||
|
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
|
||||||
|
vim +PlugInstall +qall </dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## LSP: Tiered Backend
|
||||||
|
|
||||||
|
Code intelligence is provided by one of two backends, chosen automatically at startup:
|
||||||
|
|
||||||
|
| Condition | Backend | Capabilities |
|
||||||
|
|-----------|---------|-------------|
|
||||||
|
| Vim 8.0.1453+ **and** Node.js 14.14+ | **CoC** | Full LSP, snippets, extension ecosystem |
|
||||||
|
| Vim 8.0+ (no Node.js) | **vim-lsp** | LSP via language server binaries, asyncomplete |
|
||||||
|
| Any Vim | **ALE** | Async linting + auto-fix (always active, both backends) |
|
||||||
|
|
||||||
|
Both CoC and vim-lsp expose the same key mappings so switching backends is transparent.
|
||||||
|
|
||||||
|
### With Node.js (CoC)
|
||||||
|
|
||||||
|
Install language server extensions from inside Vim — or let `install.sh` do it automatically:
|
||||||
|
|
||||||
```vim
|
```vim
|
||||||
" Put this in ${XDG_CONFIG_HOME:-~/.config}/chopsticks.vim.
|
:CocInstall coc-pyright " Python
|
||||||
let g:chopsticks_profile = 'minimal' " core navigation/editing/git/markdown
|
:CocInstall coc-tsserver " JavaScript / TypeScript
|
||||||
let g:chopsticks_profile = 'engineer' " default: LSP, ALE, syntax extras
|
:CocInstall coc-go " Go
|
||||||
let g:chopsticks_profile = 'full' " engineer + heavier Markdown feedback
|
:CocInstall coc-rust-analyzer " Rust
|
||||||
|
:CocInstall coc-json coc-yaml " JSON, YAML
|
||||||
|
:CocInstall coc-html coc-css " HTML, CSS/SCSS
|
||||||
|
:CocInstall coc-sh " Shell
|
||||||
|
:CocInstall coc-sql " SQL
|
||||||
```
|
```
|
||||||
|
|
||||||
`minimal` avoids LSP, ALE, completion plugins, extra language syntax plugins,
|
**Markdown LSP** uses `marksman` as an external binary (not a CoC extension):
|
||||||
Startify, UndoTree, and browser Markdown preview. `full` keeps those and opts
|
|
||||||
into Markdown lint, format, spell, conceal, Marksman, and LSP virtual text.
|
|
||||||
|
|
||||||
Project updates leave `~/.config/chopsticks.vim` alone, so put local choices
|
```bash
|
||||||
there instead of editing the managed `.vimrc`. The `,?` cheat sheet follows the
|
brew install marksman # macOS
|
||||||
active profile and only shows keys for enabled features.
|
sudo pacman -S marksman # Arch
|
||||||
|
# or: ./install.sh handles it automatically
|
||||||
## Keys
|
|
||||||
|
|
||||||
Leader: `,`
|
|
||||||
|
|
||||||
```
|
|
||||||
Ctrl+p fuzzy find file gd go to definition
|
|
||||||
,rg ripgrep project K hover docs
|
|
||||||
,e toggle file sidebar ,cr run current file
|
|
||||||
,gs git status ,f format
|
|
||||||
,w save ,q quit
|
|
||||||
jk exit insert mode ,? cheat sheet
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
### Without Node.js (vim-lsp)
|
||||||
<summary><strong>All keybindings</strong></summary>
|
|
||||||
|
|
||||||
### Files
|
Open a source file, then run:
|
||||||
|
|
||||||
`Ctrl+p` find | `,b` buffers | `,rg` grep | `,rG` grep word | `,fh` recent | `,fl` lines | `,e` browser | `,E` browser (file dir) | `,,` last file
|
```vim
|
||||||
|
:LspInstallServer " detects filetype and installs the correct server
|
||||||
|
:LspStatus " check server status
|
||||||
|
```
|
||||||
|
|
||||||
### Code
|
Supported: Python, Go, Rust, TypeScript/JavaScript, Shell, HTML, CSS/SCSS, JSON, YAML, Markdown, SQL.
|
||||||
|
|
||||||
`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
|
---
|
||||||
|
|
||||||
### Edit
|
## Key Mappings
|
||||||
|
|
||||||
`,S`+2ch jump | `gc` comment | `cs"'` surround | `Alt+j/k` move line | `,u` undo tree | `,y` clipboard | `,*` replace word | `,F` re-indent | `,W` strip whitespace | `[<Space>` `]<Space>` blank lines
|
**Leader key:** `,` (comma)
|
||||||
|
|
||||||
|
Press `,` and wait 500 ms to see an interactive guide to all bindings (vim-which-key).
|
||||||
|
Press `,?` to open the built-in cheat sheet at any time.
|
||||||
|
|
||||||
|
### Survival
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `jk` | Exit insert mode → Normal (ergonomic Escape) |
|
||||||
|
| `Esc` | Exit insert / visual mode (standard) |
|
||||||
|
| `Ctrl+s` | Save file (normal and insert mode) |
|
||||||
|
| `,w` | Save file |
|
||||||
|
| `,x` | Save and quit |
|
||||||
|
| `,q` | Quit |
|
||||||
|
| `,?` | Open cheat sheet |
|
||||||
|
|
||||||
|
> **`Ctrl+s` note:** some terminals freeze on `Ctrl+s` (XON/XOFF). Add `stty -ixon`
|
||||||
|
> to your `~/.bashrc` / `~/.zshrc` to disable this permanently.
|
||||||
|
|
||||||
|
### Files and Buffers
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `Ctrl+p` | Fuzzy file search — git-aware (FZF) |
|
||||||
|
| `Ctrl+n` | Toggle file tree (NERDTree) |
|
||||||
|
| `,n` | Reveal current file in NERDTree |
|
||||||
|
| `,b` | Search open buffers (FZF) |
|
||||||
|
| `,rg` | Project-wide search (ripgrep + FZF) |
|
||||||
|
| `,rG` | Ripgrep for word under cursor (literal match) |
|
||||||
|
| `,rt` | Search tags (FZF) |
|
||||||
|
| `,gF` | Search git-tracked files (FZF) |
|
||||||
|
| `,l` | Next buffer |
|
||||||
|
| `,h` | Previous buffer |
|
||||||
|
| `,bd` | Close current buffer (preserves window layout) |
|
||||||
|
| `,,` | Switch to last file |
|
||||||
|
|
||||||
|
### Windows, Tabs, and tmux
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `Ctrl+h/j/k/l` | Navigate between Vim splits **and** tmux panes |
|
||||||
|
| `,=` | Increase window height |
|
||||||
|
| `,-` | Decrease window height |
|
||||||
|
| `,+` | Increase window width |
|
||||||
|
| `,_` | Decrease window width |
|
||||||
|
| `,tn` | New tab |
|
||||||
|
| `,tc` | Close tab |
|
||||||
|
| `,tl` | Toggle to last tab |
|
||||||
|
| `,tv` | Open terminal (vertical split) |
|
||||||
|
| `,th` | Open terminal (horizontal split) |
|
||||||
|
| `Esc Esc` | Exit terminal mode |
|
||||||
|
|
||||||
|
### Code Intelligence (CoC / vim-lsp)
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `gd` | Go to definition |
|
||||||
|
| `gy` | Go to type definition |
|
||||||
|
| `gi` | Go to implementation |
|
||||||
|
| `gr` | Show all references |
|
||||||
|
| `K` | Hover documentation |
|
||||||
|
| `[g` | Previous diagnostic |
|
||||||
|
| `]g` | Next diagnostic |
|
||||||
|
| `,rn` | Rename symbol |
|
||||||
|
| `,f` | Format selection |
|
||||||
|
| `,F` | Format whole file |
|
||||||
|
| `,ca` | Code action (cursor position) |
|
||||||
|
| `,o` | File outline (symbols) |
|
||||||
|
| `,ws` | Workspace symbols |
|
||||||
|
| `,cD` | Diagnostics list |
|
||||||
|
| `,qf` | Quick-fix current line (CoC) |
|
||||||
|
| `Tab` | Next completion item |
|
||||||
|
| `Shift+Tab` | Previous completion item |
|
||||||
|
| `Enter` | Confirm completion |
|
||||||
|
|
||||||
|
Text objects (CoC): `if`/`af` (function inner/around), `ic`/`ac` (class inner/around).
|
||||||
|
|
||||||
|
### Linting (ALE — always active)
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `[e` | Previous error / warning |
|
||||||
|
| `]e` | Next error / warning |
|
||||||
|
| `,aD` | Show error detail |
|
||||||
|
| `,ad` | Full diagnostics list |
|
||||||
|
|
||||||
|
Signs in the gutter: `X` = error, `!` = warning.
|
||||||
|
|
||||||
|
### Git (vim-fugitive)
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `,gs` | Git status (stage with `s`, commit with `cc`) |
|
||||||
|
| `,gc` | Git commit |
|
||||||
|
| `,gp` | Git push |
|
||||||
|
| `,gl` | Git pull |
|
||||||
|
| `,gd` | Git diff |
|
||||||
|
| `,gb` | Git blame |
|
||||||
|
|
||||||
|
### Search and Replace
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `n` / `N` | Next / previous match (cursor centered) |
|
||||||
|
| `//` | Search for visually selected text |
|
||||||
|
| `,*` | Search and replace word under cursor (file-wide) |
|
||||||
|
| `,rG` | Ripgrep word under cursor across project |
|
||||||
|
| `,<CR>` | Clear search highlight |
|
||||||
|
|
||||||
|
### Clipboard
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `,y` | Yank to system clipboard |
|
||||||
|
| `,Y` | Yank line to system clipboard |
|
||||||
|
| `,p` | Paste from system clipboard (after cursor) |
|
||||||
|
| `,P` | Paste from system clipboard (before cursor) |
|
||||||
|
|
||||||
|
### Editing and Navigation
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `s` + 2 chars | EasyMotion — jump anywhere on screen |
|
||||||
|
| `Space` | Toggle code fold |
|
||||||
|
| `Y` | Yank to end of line (consistent with `D`, `C`) |
|
||||||
|
| `Ctrl+d/u` | Half-page scroll (cursor stays centered) |
|
||||||
|
| `>` / `<` | Indent / dedent (keeps visual selection) |
|
||||||
|
| `Alt+j/k` | Move current line down / up |
|
||||||
|
| `0` | Jump to first non-blank character |
|
||||||
|
| `[q` / `]q` | Previous / next quickfix entry (vim-unimpaired) |
|
||||||
|
| `,u` | Toggle undo tree (visual branch history) |
|
||||||
|
| `,tt` | Toggle tagbar (code structure) |
|
||||||
|
| `F2` | Toggle paste mode |
|
||||||
|
| `F3` | Toggle absolute line numbers |
|
||||||
|
| `F4` | Toggle relative line numbers |
|
||||||
|
|
||||||
|
### Config and Utilities
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `,ev` | Edit `~/.vimrc` |
|
||||||
|
| `,sv` | Reload `~/.vimrc` |
|
||||||
|
| `,wa` | Save all open buffers |
|
||||||
|
| `,wd` | Change working directory to current file's location |
|
||||||
|
| `,cp` | Copy absolute file path to clipboard |
|
||||||
|
| `,cf` | Copy filename to clipboard |
|
||||||
|
| `,qo` / `,qc` | Open / close quickfix list |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### Startup Dashboard
|
||||||
|
|
||||||
|
Running `vim` (no arguments) opens a full-screen Startify dashboard showing recent
|
||||||
|
files, sessions, and bookmarks. Running `vim .` opens NERDTree on the left with
|
||||||
|
the dashboard on the right.
|
||||||
|
|
||||||
|
### Keybinding Guide
|
||||||
|
|
||||||
|
Press `,` and pause for 500 ms. A popup (vim-which-key) lists all leader bindings
|
||||||
|
organized into groups. No need to memorize everything upfront.
|
||||||
|
|
||||||
|
### Built-in Cheat Sheet
|
||||||
|
|
||||||
|
Press `,?` to open an inline reference covering modes, survival commands, search,
|
||||||
|
code intelligence, git, and clipboard — without leaving Vim.
|
||||||
|
|
||||||
|
### Session Management
|
||||||
|
|
||||||
|
```vim
|
||||||
|
:Obsess " start tracking the current session
|
||||||
|
:Obsess! " stop tracking
|
||||||
|
```
|
||||||
|
|
||||||
|
Sessions are stored in `~/.vim/sessions/` and automatically restored by vim-prosession
|
||||||
|
the next time you open Vim in the same directory.
|
||||||
|
|
||||||
|
### Project-Local Config
|
||||||
|
|
||||||
|
Drop a `.vimrc` in any project root to override settings for that project:
|
||||||
|
|
||||||
|
```vim
|
||||||
|
" project/.vimrc
|
||||||
|
set shiftwidth=2
|
||||||
|
let g:ale_python_black_options = '--line-length=100'
|
||||||
|
```
|
||||||
|
|
||||||
|
Loaded automatically via `set exrc`. Restricted to safe options via `set secure`.
|
||||||
|
|
||||||
|
### tmux Integration
|
||||||
|
|
||||||
|
`Ctrl+h/j/k/l` navigates seamlessly between Vim splits and tmux panes — no prefix
|
||||||
|
key, no mode switch.
|
||||||
|
|
||||||
|
**Vim side:** handled by vim-tmux-navigator (installed automatically).
|
||||||
|
|
||||||
|
**tmux side:** add to `~/.tmux.conf` (or let `install.sh` append it):
|
||||||
|
|
||||||
|
```tmux
|
||||||
|
is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\S+\/)?g?(view|n?vim?x?)(diff)?$'"
|
||||||
|
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L'
|
||||||
|
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D'
|
||||||
|
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U'
|
||||||
|
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R'
|
||||||
|
```
|
||||||
|
|
||||||
|
Then reload: `tmux source-file ~/.tmux.conf`
|
||||||
|
|
||||||
|
> **Note:** the `C-l` binding replaces the terminal's screen-clear shortcut inside
|
||||||
|
> tmux. To restore it, add `bind C-l send-keys 'C-l'` — then use `prefix + C-l`.
|
||||||
|
|
||||||
|
### Large File Handling
|
||||||
|
|
||||||
|
Files over 10 MB automatically disable syntax highlighting, undo history, and
|
||||||
|
linting to prevent Vim from stalling.
|
||||||
|
|
||||||
|
### TTY / Console Support
|
||||||
|
|
||||||
|
Detected automatically when `$TERM` is `linux` or `screen`. In TTY mode:
|
||||||
|
|
||||||
|
- True color and cursorline disabled
|
||||||
|
- Powerline separators replaced with plain ASCII
|
||||||
|
- FZF preview windows disabled
|
||||||
|
- IndentLine guides disabled
|
||||||
|
- Syntax column limit reduced to 120 characters
|
||||||
|
- Simpler built-in status line used instead of airline
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Language Support
|
||||||
|
|
||||||
|
| Language | Indent | Formatter | Linter | LSP |
|
||||||
|
|----------|--------|-----------|--------|-----|
|
||||||
|
| Python | 4 sp | black, isort | flake8, pylint | coc-pyright |
|
||||||
|
| JavaScript | 2 sp | prettier | eslint | coc-tsserver |
|
||||||
|
| TypeScript | 2 sp | prettier | eslint, tsserver | coc-tsserver |
|
||||||
|
| Go | tab | gofmt, goimports | staticcheck | coc-go |
|
||||||
|
| Rust | 4 sp | rustfmt | cargo | coc-rust-analyzer |
|
||||||
|
| Shell | 2 sp | — | shellcheck | coc-sh |
|
||||||
|
| YAML | 2 sp | prettier | yamllint | coc-yaml |
|
||||||
|
| HTML | 2 sp | prettier | — | coc-html |
|
||||||
|
| CSS / SCSS | 2 sp | prettier | stylelint | coc-css |
|
||||||
|
| Less | 2 sp | prettier | — | — |
|
||||||
|
| JSON | 2 sp | prettier | — | coc-json |
|
||||||
|
| Markdown | 2 sp | prettier | markdownlint | marksman |
|
||||||
|
| SQL | 4 sp | sqlfluff | sqlfluff | — |
|
||||||
|
| Dockerfile | 2 sp | — | hadolint | — |
|
||||||
|
|
||||||
|
`install.sh` installs all formatters and linters automatically.
|
||||||
|
ALE runs them asynchronously; format-on-save is active for all supported languages.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Plugins
|
||||||
|
|
||||||
|
### Navigation
|
||||||
|
- **NERDTree** — file tree explorer
|
||||||
|
- **fzf + fzf.vim** — fuzzy finder for files, buffers, tags, and ripgrep
|
||||||
|
|
||||||
### Git
|
### Git
|
||||||
|
- **vim-fugitive** — full Git integration inside Vim
|
||||||
|
- **vim-gitgutter** — diff signs in the sign column
|
||||||
|
|
||||||
`,gs` status | `,gd` diff | `,gb` blame | `,gc` commit | `,gp` push | `,gl` pull | `,gL` log graph | `,gC` FZF commits | `,gB` buffer commits | `]x` `[x` conflict
|
### LSP and Completion
|
||||||
|
- **coc.nvim** — full LSP + completion via Node.js (recommended)
|
||||||
|
- **vim-lsp** — pure VimScript LSP client (Node.js-free fallback)
|
||||||
|
- **vim-lsp-settings** — auto-configures language servers for vim-lsp
|
||||||
|
- **asyncomplete.vim** — async completion engine (vim-lsp mode)
|
||||||
|
|
||||||
### Windows
|
### Linting
|
||||||
|
- **ALE** — asynchronous lint engine, always active regardless of LSP backend
|
||||||
|
|
||||||
`Ctrl+hjkl` navigate (+ tmux) | `,z` maximize | `,h` `,l` buffers | `,bd` close buffer | `,=` `,−` resize | `,tv` `,th` terminal | `Esc Esc` exit terminal
|
### UI
|
||||||
|
- **vim-airline** — status line and tabline
|
||||||
|
- **vim-startify** — startup dashboard with session management
|
||||||
|
- **vim-which-key** — keybinding hint popup on leader pause
|
||||||
|
- **indentLine** — indent guide lines (non-TTY only)
|
||||||
|
- **undotree** — visual undo branch history
|
||||||
|
- **tagbar** — code structure sidebar via ctags
|
||||||
|
|
||||||
### Markdown
|
### Editing
|
||||||
|
- **vim-surround** — change surrounding quotes, brackets, and tags
|
||||||
|
- **vim-commentary** — `gc` to toggle comments
|
||||||
|
- **auto-pairs** — auto-close brackets and quotes
|
||||||
|
- **vim-easymotion** — jump anywhere on screen with 2 keystrokes (`s`)
|
||||||
|
- **vim-unimpaired** — bracket shortcut pairs (`[q`/`]q`, etc.)
|
||||||
|
- **targets.vim** — additional text objects
|
||||||
|
- **vim-snippets** — snippet library (used with CoC)
|
||||||
|
- **vim-tmux-navigator** — seamless `Ctrl+h/j/k/l` across Vim and tmux
|
||||||
|
|
||||||
`,mp` preview in browser | `,mt` table of contents
|
### Language Packs
|
||||||
|
- **vim-polyglot** — syntax for 100+ languages
|
||||||
|
- **vim-go** — Go syntax and tooling (LSP handled by coc-go)
|
||||||
|
|
||||||
### Toggle
|
### Session
|
||||||
|
- **vim-obsession** — continuous session saving
|
||||||
|
- **vim-prosession** — project-level session management
|
||||||
|
|
||||||
`F2` paste | `F3` line numbers | `F4` relative numbers | `F6` invisible chars | `,ss` spell check | `,af` format on save
|
### Color Schemes
|
||||||
|
- **gruvbox** (default), **dracula**, **solarized**, **onedark**
|
||||||
|
|
||||||
### Utilities
|
---
|
||||||
|
|
||||||
`,cp` copy full path | `,cf` copy filename | `,ev` edit vimrc | `,sv` reload vimrc | `,wa` save all | `:ChopsticksStatus` diagnostics
|
## Customization
|
||||||
|
|
||||||
</details>
|
### Change the color scheme
|
||||||
|
|
||||||
## LSP
|
In `~/.vimrc`, find and update the `colorscheme` line:
|
||||||
|
|
||||||
```vim
|
```vim
|
||||||
:LspInstallServer " auto-detects filetype
|
colorscheme dracula " options: gruvbox, solarized, onedark
|
||||||
:LspStatus " check what's running
|
|
||||||
:ChopsticksStatus " see all tools + LSP + linters at a glance
|
|
||||||
```
|
```
|
||||||
|
|
||||||
pylsp, gopls, rust-analyzer, clangd, sqls — no Node.js. JS/TS servers need Node.
|
True color is enabled automatically when `$COLORTERM=truecolor`. Falls back to
|
||||||
Markdown LSP (`marksman`) is opt-in so prose buffers stay quiet by default.
|
256-color, then 16-color in TTY.
|
||||||
|
|
||||||
ALE and vim-lsp coexist cleanly (`ale_disable_lsp=1`). ALE handles linting + formatting. vim-lsp handles everything else.
|
### Per-project overrides
|
||||||
|
|
||||||
## Markdown
|
Create `.vimrc` in your project root. Anything placed here overrides the global
|
||||||
|
config for that directory:
|
||||||
Markdown opens in writing mode: wrapped text, no spell noise, no concealed
|
|
||||||
syntax, no sign column, no real-time markdownlint, and no Marksman diagnostics.
|
|
||||||
The explicit commands still work:
|
|
||||||
|
|
||||||
```vim
|
```vim
|
||||||
,mp " preview in browser
|
" my-project/.vimrc
|
||||||
,mt " table of contents
|
set shiftwidth=2
|
||||||
|
let g:ale_python_black_options = '--line-length=120'
|
||||||
```
|
```
|
||||||
|
|
||||||
Opt into heavier Markdown tooling from your own vimrc before loading
|
### Modify keybindings
|
||||||
chopsticks:
|
|
||||||
|
|
||||||
```vim
|
Edit `~/.vimrc` directly (`,ev` opens it from inside Vim). Reload with `,sv`.
|
||||||
let g:chopsticks_markdown_lint = 1
|
|
||||||
let g:chopsticks_markdown_format_on_save = 1
|
|
||||||
let g:chopsticks_markdown_lsp = 1
|
|
||||||
let g:chopsticks_markdown_spell = 1
|
|
||||||
let g:chopsticks_markdown_conceal = 1
|
|
||||||
let g:previm_enable_realtime = 1
|
|
||||||
```
|
|
||||||
|
|
||||||
For Markdown LSP, install or select `marksman` first.
|
---
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
~/.vim/
|
|
||||||
├── .vimrc thin loader
|
|
||||||
├── modules/
|
|
||||||
│ ├── env.vim TTY detection, truecolor, skip built-in plugins
|
|
||||||
│ ├── plugins.vim vim-plug + 24–25 plugins
|
|
||||||
│ ├── core.vim settings, keymaps, performance
|
|
||||||
│ ├── ui.vim solarized, statusline, startify
|
|
||||||
│ ├── editing.vim easymotion, yank highlight, blank lines
|
|
||||||
│ ├── navigation.vim fzf, netrw sidebar, windows, terminal
|
|
||||||
│ ├── lsp.vim vim-lsp, asyncomplete
|
|
||||||
│ ├── lint.vim ale, format-on-save
|
|
||||||
│ ├── git.vim fugitive, gitgutter, conflict nav
|
|
||||||
│ ├── languages.vim vim-go, markdown, filetype settings
|
|
||||||
│ └── tools.vim run file, quickfix, cheat sheet, diagnostics
|
|
||||||
```
|
|
||||||
|
|
||||||
Each module is self-contained. Comment out one line in `.vimrc` to disable it. Add your own with `call s:load('mine')`.
|
|
||||||
|
|
||||||
## Performance
|
|
||||||
|
|
||||||
| Metric | Value |
|
|
||||||
| ------------------------ | ------------------------------------------- |
|
|
||||||
| Lazy-loaded | 7 plugins (on command or filetype) |
|
|
||||||
| Built-in plugins skipped | 12 (gzip, tar, zip, vimball, logiPat, etc.) |
|
|
||||||
| Large file threshold | 10MB (auto-disables syntax + undo) |
|
|
||||||
| TTY large file | 500KB (syntax disabled) |
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
| Problem | Fix |
|
**Plugins not loading**
|
||||||
| ------------------- | --------------------------------------------- |
|
|
||||||
| Plugins not loading | `:PlugInstall` then `:PlugUpdate` |
|
|
||||||
| LSP not starting | `:LspInstallServer` for current filetype |
|
|
||||||
| Colors wrong | `export COLORTERM=truecolor` in shell rc |
|
|
||||||
| `Ctrl+s` freezes | `stty -ixon` in shell rc |
|
|
||||||
| Everything slow | Large file? Auto-disabled >10MB |
|
|
||||||
| What's installed? | `:ChopsticksStatus` shows tools, LSP, linters |
|
|
||||||
|
|
||||||
More in the [wiki](https://github.com/m1ngsama/chopsticks/wiki).
|
```vim
|
||||||
|
:PlugInstall " install any missing plugins
|
||||||
|
:PlugUpdate " update all plugins
|
||||||
|
```
|
||||||
|
|
||||||
|
**CoC not working**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node --version # must be 14.14+
|
||||||
|
```
|
||||||
|
|
||||||
|
Inside Vim: `:CocInfo` for diagnostics, `:CocInstall <extension>` to add a language server.
|
||||||
|
|
||||||
|
**vim-lsp server not starting**
|
||||||
|
|
||||||
|
```vim
|
||||||
|
:LspInstallServer " install the correct server for the current filetype
|
||||||
|
:LspStatus " check server status
|
||||||
|
```
|
||||||
|
|
||||||
|
**Markdown LSP not starting**
|
||||||
|
|
||||||
|
`marksman` must be installed as a standalone binary (not a CoC extension):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install marksman # macOS
|
||||||
|
sudo pacman -S marksman # Arch
|
||||||
|
# or: ./install.sh handles it automatically
|
||||||
|
```
|
||||||
|
|
||||||
|
**Colors look wrong**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export TERM=xterm-256color # add to ~/.bashrc or ~/.zshrc
|
||||||
|
```
|
||||||
|
|
||||||
|
For true color: `export COLORTERM=truecolor`.
|
||||||
|
|
||||||
|
**ALE linters not found**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
which flake8 black prettier eslint # verify tools are on PATH
|
||||||
|
```
|
||||||
|
|
||||||
|
If tools were installed with `pip install --user` or `npm install -g`, make sure
|
||||||
|
the respective bin directories are on `$PATH`.
|
||||||
|
|
||||||
|
**`Ctrl+s` freezes the terminal**
|
||||||
|
|
||||||
|
Add `stty -ixon` to your `~/.bashrc`, `~/.zshrc`, or `~/.config/fish/config.fish`.
|
||||||
|
This disables XON/XOFF flow control permanently.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
See [CONTRIBUTING.md](CONTRIBUTING.md). The two rules that matter: no Node.js dependencies, and don't regress startup time.
|
Bug reports and pull requests are welcome. Please follow these guidelines:
|
||||||
|
|
||||||
|
### Reporting a bug
|
||||||
|
|
||||||
|
1. Search [existing issues](https://github.com/m1ngsama/chopsticks/issues) before opening a new one.
|
||||||
|
2. Include your Vim version (`vim --version`), OS, and a minimal reproduction.
|
||||||
|
3. If the bug is plugin-specific, check whether it reproduces with a minimal config
|
||||||
|
(`vim -u NONE`) or only with chopsticks loaded.
|
||||||
|
|
||||||
|
### Proposing a change
|
||||||
|
|
||||||
|
1. Open an issue first to discuss the change, especially for non-trivial additions.
|
||||||
|
2. Keep the scope focused — one feature or fix per PR.
|
||||||
|
3. Follow existing conventions: augroups for autocmds, TTY guards for visual features,
|
||||||
|
conditional plugin loading where appropriate.
|
||||||
|
4. Update `CHANGELOG.md` with a summary of the change.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
Chopsticks is an opinionated configuration. Changes should align with the design
|
||||||
|
principles above — in particular, KISS (no icon fonts, minimal dependencies) and
|
||||||
|
TTY-compatibility. Neovim-only features and Lua configs are out of scope.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
Inspired by [amix/vimrc](https://github.com/amix/vimrc).
|
||||||
|
Built with [vim-plug](https://github.com/junegunn/vim-plug),
|
||||||
|
[coc.nvim](https://github.com/neoclide/coc.nvim),
|
||||||
|
[vim-lsp](https://github.com/prabirshrestha/vim-lsp),
|
||||||
|
and the broader Vim plugin community.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
See [CHANGELOG.md](CHANGELOG.md).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[MIT](LICENSE)
|
[MIT](LICENSE) © m1ng
|
||||||
|
|
|
||||||
13
coc-settings.json
Normal file
13
coc-settings.json
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"languageserver": {
|
||||||
|
"marksman": {
|
||||||
|
"command": "marksman",
|
||||||
|
"args": ["server"],
|
||||||
|
"filetypes": ["markdown"],
|
||||||
|
"rootPatterns": [".git", ".marksman.toml"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"coc.preferences.formatOnSaveFiletypes": [
|
||||||
|
"markdown"
|
||||||
|
]
|
||||||
|
}
|
||||||
90
get.sh
Executable file → Normal file
90
get.sh
Executable file → Normal file
|
|
@ -4,77 +4,22 @@
|
||||||
# Usage:
|
# Usage:
|
||||||
# curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
|
# curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash
|
||||||
# curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --yes
|
# curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash -s -- --yes
|
||||||
# CHOPSTICKS_DEST=/absolute/path bash get.sh --dry-run
|
|
||||||
|
|
||||||
set -eo pipefail
|
set -eo pipefail
|
||||||
|
|
||||||
REPO="https://github.com/m1ngsama/chopsticks.git"
|
REPO="https://github.com/m1ngsama/chopsticks.git"
|
||||||
DEST="${CHOPSTICKS_DEST:-$HOME/.vim}"
|
DEST="$HOME/.vim"
|
||||||
DRY_RUN=0
|
|
||||||
INSTALLER_ARGS=()
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
cat <<'EOF'
|
|
||||||
Usage: get.sh [OPTIONS] [INSTALLER_OPTIONS]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
--dry-run Show what would happen without cloning, pulling, or installing
|
|
||||||
--help, -h Show this help and exit
|
|
||||||
|
|
||||||
Environment:
|
|
||||||
CHOPSTICKS_DEST Absolute install path (default: ~/.vim)
|
|
||||||
|
|
||||||
All other options are passed to install.sh after clone/update.
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
for arg in "$@"; do
|
|
||||||
case "$arg" in
|
|
||||||
--dry-run) DRY_RUN=1 ;;
|
|
||||||
--help|-h) usage; exit 0 ;;
|
|
||||||
*) INSTALLER_ARGS+=("$arg") ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then
|
|
||||||
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; BOLD='\033[1m'; NC='\033[0m'
|
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; BOLD='\033[1m'; NC='\033[0m'
|
||||||
else
|
|
||||||
GREEN=''; YELLOW=''; RED=''; BOLD=''; NC=''
|
|
||||||
fi
|
|
||||||
ok() { echo -e "${GREEN}[OK]${NC} $1"; }
|
ok() { echo -e "${GREEN}[OK]${NC} $1"; }
|
||||||
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
||||||
die() { echo -e "${RED}[FATAL]${NC} $1" >&2; exit 1; }
|
die() { echo -e "${RED}[FATAL]${NC} $1" >&2; exit 1; }
|
||||||
step() { echo -e "\n${BOLD}==> $1${NC}"; }
|
step() { echo -e "\n${BOLD}==> $1${NC}"; }
|
||||||
info() { echo " $1"; }
|
|
||||||
|
|
||||||
case "$DEST" in
|
|
||||||
/*) ;;
|
|
||||||
*) die "CHOPSTICKS_DEST must be an absolute path: $DEST" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
repo_origin() {
|
|
||||||
git -C "$DEST" config --get remote.origin.url 2>/dev/null || true
|
|
||||||
}
|
|
||||||
|
|
||||||
is_chopsticks_repo() {
|
|
||||||
local origin="$1"
|
|
||||||
origin="${origin%/}"
|
|
||||||
origin="${origin%.git}"
|
|
||||||
case "$origin" in
|
|
||||||
https://github.com/m1ngsama/chopsticks|\
|
|
||||||
git@github.com:m1ngsama/chopsticks|\
|
|
||||||
ssh://git@github.com/m1ngsama/chopsticks)
|
|
||||||
return 0 ;;
|
|
||||||
*)
|
|
||||||
return 1 ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
echo -e "${BOLD}chopsticks — One-command installer${NC}"
|
echo -e "${BOLD}chopsticks — One-command installer${NC}"
|
||||||
echo "----------------------------------"
|
echo "----------------------------------"
|
||||||
echo " Repo: $REPO"
|
echo " Repo: $REPO"
|
||||||
echo " Dest: $DEST"
|
echo " Dest: $DEST"
|
||||||
[[ $DRY_RUN -eq 1 ]] && echo " Mode: dry-run"
|
|
||||||
|
|
||||||
# ── git ───────────────────────────────────────────────────────────────────────
|
# ── git ───────────────────────────────────────────────────────────────────────
|
||||||
step "Checking for git"
|
step "Checking for git"
|
||||||
|
|
@ -94,39 +39,18 @@ ok "git $(git --version | awk '{print $3}')"
|
||||||
step "Setting up $DEST"
|
step "Setting up $DEST"
|
||||||
|
|
||||||
if [[ -d "$DEST/.git" ]]; then
|
if [[ -d "$DEST/.git" ]]; then
|
||||||
ORIGIN="$(repo_origin)"
|
|
||||||
if ! is_chopsticks_repo "$ORIGIN"; then
|
|
||||||
die "$DEST is a git repo, but it does not look like chopsticks.
|
|
||||||
origin: ${ORIGIN:-none}
|
|
||||||
Back it up first: mv \"$DEST\" \"$DEST.bak\"
|
|
||||||
Then re-run: curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash"
|
|
||||||
fi
|
|
||||||
[[ -f "$DEST/install.sh" && -f "$DEST/.vimrc" ]] || \
|
|
||||||
die "$DEST looks incomplete. Expected install.sh and .vimrc.
|
|
||||||
Back it up first: mv \"$DEST\" \"$DEST.bak\"
|
|
||||||
Then re-run: curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash"
|
|
||||||
if [[ $DRY_RUN -eq 1 ]]; then
|
|
||||||
info "Would update existing chopsticks repo at $DEST"
|
|
||||||
info "Would run: bash install.sh ${INSTALLER_ARGS[*]:-(no installer options)}"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
warn "$DEST already exists — pulling latest changes"
|
warn "$DEST already exists — pulling latest changes"
|
||||||
git -C "$DEST" pull --ff-only origin main 2>/dev/null || \
|
git -C "$DEST" pull --ff-only origin main 2>/dev/null || \
|
||||||
warn "Could not pull latest — using existing version (run: git -C ~/.vim pull)"
|
warn "Could not pull latest — using existing version (run: git -C ~/.vim pull)"
|
||||||
ok "Repository updated ($(git -C "$DEST" describe --tags 2>/dev/null || git -C "$DEST" rev-parse --short HEAD))"
|
ok "Repository updated"
|
||||||
elif [[ -d "$DEST" ]]; then
|
elif [[ -d "$DEST" ]]; then
|
||||||
die "$DEST exists but is not a chopsticks git repo.
|
die "$HOME/.vim exists but is not a chopsticks git repo.
|
||||||
Back it up first: mv \"$DEST\" \"$DEST.bak\"
|
Back it up first: mv ~/.vim ~/.vim.bak
|
||||||
Then re-run: curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash"
|
Then re-run: curl -fsSL https://raw.githubusercontent.com/m1ngsama/chopsticks/main/get.sh | bash"
|
||||||
else
|
else
|
||||||
if [[ $DRY_RUN -eq 1 ]]; then
|
|
||||||
info "Would clone $REPO to $DEST"
|
|
||||||
info "Would run: bash install.sh ${INSTALLER_ARGS[*]:-(no installer options)}"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
git clone --depth=1 "$REPO" "$DEST" || \
|
git clone --depth=1 "$REPO" "$DEST" || \
|
||||||
die "Clone failed — check your network connection"
|
die "Clone failed — check your network connection"
|
||||||
ok "Cloned to $DEST ($(git -C "$DEST" describe --tags 2>/dev/null || git -C "$DEST" rev-parse --short HEAD))"
|
ok "Cloned to $DEST"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Run installer ─────────────────────────────────────────────────────────────
|
# ── Run installer ─────────────────────────────────────────────────────────────
|
||||||
|
|
@ -139,7 +63,7 @@ cd "$DEST"
|
||||||
# Use a test-open to check /dev/tty is actually accessible (it may exist but be
|
# Use a test-open to check /dev/tty is actually accessible (it may exist but be
|
||||||
# unusable in non-interactive SSH sessions or container environments).
|
# unusable in non-interactive SSH sessions or container environments).
|
||||||
if { true </dev/tty; } 2>/dev/null; then
|
if { true </dev/tty; } 2>/dev/null; then
|
||||||
exec bash install.sh "${INSTALLER_ARGS[@]}" </dev/tty
|
exec bash install.sh "$@" </dev/tty
|
||||||
else
|
else
|
||||||
exec bash install.sh "${INSTALLER_ARGS[@]}"
|
exec bash install.sh "$@"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
973
install.sh
973
install.sh
File diff suppressed because it is too large
Load diff
212
modules/core.vim
212
modules/core.vim
|
|
@ -1,212 +0,0 @@
|
||||||
" core.vim — general settings, basic keymaps, performance, indentation
|
|
||||||
" filetype/syntax already enabled by plug#end() in plugins.vim
|
|
||||||
|
|
||||||
set number
|
|
||||||
set relativenumber
|
|
||||||
|
|
||||||
if !g:is_tty
|
|
||||||
set cursorline
|
|
||||||
endif
|
|
||||||
|
|
||||||
set nobackup
|
|
||||||
set scrolloff=10
|
|
||||||
set nowrap
|
|
||||||
set incsearch
|
|
||||||
set ignorecase
|
|
||||||
set smartcase
|
|
||||||
set showcmd
|
|
||||||
set showmode
|
|
||||||
set hlsearch
|
|
||||||
set history=1000
|
|
||||||
set wildmenu
|
|
||||||
set wildmode=list:longest
|
|
||||||
set wildignorecase
|
|
||||||
set wildignore=*.docx,*.jpg,*.png,*.gif,*.pdf,*.pyc,*.exe,*.flv,*.img,*.xlsx
|
|
||||||
set wildignore+=*/node_modules/*,*/.git/*,*/__pycache__/*,*/dist/*,*/build/*
|
|
||||||
set mouse=a
|
|
||||||
set encoding=utf-8
|
|
||||||
set foldmethod=indent
|
|
||||||
set foldlevel=99
|
|
||||||
set splitbelow
|
|
||||||
set splitright
|
|
||||||
set backspace=indent,eol,start
|
|
||||||
set nrformats-=octal
|
|
||||||
set autoread
|
|
||||||
set cmdheight=1
|
|
||||||
set hidden
|
|
||||||
set whichwrap+=<,>,h,l
|
|
||||||
set magic
|
|
||||||
set showmatch
|
|
||||||
set mat=2
|
|
||||||
set noerrorbells
|
|
||||||
set novisualbell
|
|
||||||
set t_vb=
|
|
||||||
set ttimeout
|
|
||||||
set ttimeoutlen=10
|
|
||||||
|
|
||||||
if $COLORTERM ==# 'gnome-terminal'
|
|
||||||
set t_Co=256
|
|
||||||
endif
|
|
||||||
|
|
||||||
if has("gui_running")
|
|
||||||
set guioptions-=T
|
|
||||||
set guioptions-=e
|
|
||||||
set t_Co=256
|
|
||||||
set guitablabel=%M\ %t
|
|
||||||
endif
|
|
||||||
|
|
||||||
set display+=lastline
|
|
||||||
set ffs=unix,dos,mac
|
|
||||||
set writebackup
|
|
||||||
|
|
||||||
if has('unix')
|
|
||||||
let s:swap_dir = expand(get(g:, 'chopsticks_swap_dir', '~/.vim/.swap'))
|
|
||||||
let &directory = s:swap_dir . '//,/tmp//'
|
|
||||||
silent! call mkdir(s:swap_dir, 'p', 0700)
|
|
||||||
endif
|
|
||||||
set swapfile
|
|
||||||
|
|
||||||
if has('persistent_undo')
|
|
||||||
set undofile
|
|
||||||
let &undodir = expand('~/.vim/.undo')
|
|
||||||
silent! call mkdir(&undodir, 'p', 0700)
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── Text, Tab and Indent ────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
if g:is_tty
|
|
||||||
set listchars=tab:>-,trail:.,extends:>,precedes:<,nbsp:_
|
|
||||||
else
|
|
||||||
set listchars=tab:→\ ,trail:·,extends:▸,precedes:◂,nbsp:·
|
|
||||||
endif
|
|
||||||
|
|
||||||
set expandtab
|
|
||||||
set smarttab
|
|
||||||
set shiftwidth=4
|
|
||||||
set tabstop=4
|
|
||||||
set lbr
|
|
||||||
set tw=0
|
|
||||||
set autoindent
|
|
||||||
set smartindent
|
|
||||||
|
|
||||||
" ── Leader ──────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
let mapleader = ","
|
|
||||||
|
|
||||||
" ── Basic Keymaps ───────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
nnoremap <leader>w :w<cr>
|
|
||||||
nnoremap <leader>q :q<cr>
|
|
||||||
nnoremap <leader>x :x<cr>
|
|
||||||
|
|
||||||
nnoremap <silent> <leader><cr> :noh<cr>
|
|
||||||
|
|
||||||
nnoremap <leader>bd :Bclose<cr>
|
|
||||||
nnoremap <leader>ba :bufdo bd<cr>
|
|
||||||
nnoremap <leader>l :bnext<cr>
|
|
||||||
nnoremap <leader>h :bprevious<cr>
|
|
||||||
|
|
||||||
nnoremap <leader>cd :lcd %:p:h<cr>:pwd<cr>
|
|
||||||
|
|
||||||
nnoremap 0 ^
|
|
||||||
vnoremap 0 ^
|
|
||||||
nnoremap gV `[v`]
|
|
||||||
|
|
||||||
cnoremap <C-p> <Up>
|
|
||||||
cnoremap <C-n> <Down>
|
|
||||||
|
|
||||||
nnoremap <M-j> :m .+1<CR>==
|
|
||||||
nnoremap <M-k> :m .-2<CR>==
|
|
||||||
vnoremap <M-j> :m '>+1<CR>gv=gv
|
|
||||||
vnoremap <M-k> :m '<-2<CR>gv=gv
|
|
||||||
|
|
||||||
nnoremap <silent> <leader>ss :setlocal spell!<CR>:echo 'Spell: ' . (&spell ? 'ON' : 'OFF')<CR>
|
|
||||||
|
|
||||||
nnoremap <silent> <F2> :set paste!<CR>:echo 'Paste: ' . (&paste ? 'ON' : 'OFF')<CR>
|
|
||||||
nnoremap <silent> <F3> :set invnumber<CR>:echo 'Line numbers: ' . (&number ? '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 <space> za
|
|
||||||
|
|
||||||
nnoremap Y y$
|
|
||||||
nnoremap Q <nop>
|
|
||||||
|
|
||||||
inoremap jk <Esc>
|
|
||||||
|
|
||||||
vnoremap < <gv
|
|
||||||
vnoremap > >gv
|
|
||||||
|
|
||||||
nnoremap n nzzzv
|
|
||||||
nnoremap N Nzzzv
|
|
||||||
|
|
||||||
vnoremap // y/\V<C-r>=escape(@",'/\')<CR><CR>
|
|
||||||
|
|
||||||
nnoremap <silent> <C-s> :w<CR>
|
|
||||||
inoremap <silent> <C-s> <C-o>:w<CR>
|
|
||||||
|
|
||||||
nnoremap <C-d> <C-d>zz
|
|
||||||
vnoremap <C-d> <C-d>zz
|
|
||||||
nnoremap <C-u> <C-u>zz
|
|
||||||
vnoremap <C-u> <C-u>zz
|
|
||||||
|
|
||||||
if has('clipboard')
|
|
||||||
nnoremap <leader>y "+y
|
|
||||||
vnoremap <leader>y "+y
|
|
||||||
nnoremap <leader>Y "+Y
|
|
||||||
nnoremap <leader>p "+p
|
|
||||||
vnoremap <leader>p "+p
|
|
||||||
nnoremap <leader>P "+P
|
|
||||||
vnoremap <leader>P "+P
|
|
||||||
endif
|
|
||||||
|
|
||||||
nnoremap <leader>qo :copen<CR>
|
|
||||||
nnoremap <leader>qc :cclose<CR>
|
|
||||||
|
|
||||||
augroup ChopstickResize
|
|
||||||
autocmd!
|
|
||||||
autocmd VimResized * wincmd =
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
" ── Performance ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
set synmaxcol=200
|
|
||||||
set lazyredraw
|
|
||||||
set complete-=i
|
|
||||||
|
|
||||||
if executable('rg')
|
|
||||||
set grepprg=rg\ --vimgrep\ --smart-case
|
|
||||||
set grepformat=%f:%l:%c:%m
|
|
||||||
endif
|
|
||||||
set updatetime=300
|
|
||||||
set shortmess+=cI
|
|
||||||
|
|
||||||
if g:is_tty
|
|
||||||
set signcolumn=auto
|
|
||||||
set synmaxcol=120
|
|
||||||
endif
|
|
||||||
" non-TTY signcolumn is set in ui.vim (=yes, fixed-width to prevent jitter)
|
|
||||||
|
|
||||||
" ── Project-Local Config ────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
set exrc
|
|
||||||
set secure
|
|
||||||
set sessionoptions=blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal
|
|
||||||
|
|
||||||
if has("patch-8.1.0360")
|
|
||||||
set diffopt=filler,internal,context:3,algorithm:histogram,indent-heuristic
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── Format Options ──────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
augroup ChopstickFormatOptions
|
|
||||||
autocmd!
|
|
||||||
autocmd FileType * setlocal formatoptions-=c formatoptions-=r formatoptions-=o formatoptions+=j
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
augroup ChopstickPaste
|
|
||||||
autocmd!
|
|
||||||
autocmd InsertLeave * set nopaste
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
set timeoutlen=500
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
" editing.vim — EasyMotion, yank highlight, search auto-clear, undotree
|
|
||||||
|
|
||||||
" ── EasyMotion ──────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
let g:EasyMotion_do_mapping = 0
|
|
||||||
let g:EasyMotion_smartcase = 1
|
|
||||||
|
|
||||||
if exists('g:plugs["vim-easymotion"]')
|
|
||||||
nmap <Leader>S <Plug>(easymotion-overwin-f2)
|
|
||||||
nmap <Leader>j <Plug>(easymotion-j)
|
|
||||||
nmap <Leader>k <Plug>(easymotion-k)
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── UndoTree ────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
if exists('g:plugs["undotree"]')
|
|
||||||
nnoremap <F5> :UndotreeToggle<CR>
|
|
||||||
nnoremap <leader>u :UndotreeToggle<CR>
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── Yank Highlight ──────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
if exists('##TextYankPost') && has('timers')
|
|
||||||
function! s:YankHighlight() abort
|
|
||||||
if v:event.operator !=# 'y' | return | endif
|
|
||||||
let l:m = matchadd('IncSearch',
|
|
||||||
\ printf('\%%>%dl\%%<%dl', line("'[") - 1, line("']") + 1))
|
|
||||||
call timer_start(150, {-> execute('silent! call matchdelete(' . l:m . ')')})
|
|
||||||
endfunction
|
|
||||||
augroup ChopstickYankHL
|
|
||||||
autocmd!
|
|
||||||
autocmd TextYankPost * call s:YankHighlight()
|
|
||||||
augroup END
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── Blank Line Insertion (replaces vim-unimpaired) ──────────────────────────
|
|
||||||
|
|
||||||
nnoremap <silent> [<Space> :<C-u>put! =repeat(nr2char(10), v:count1)<CR>'[
|
|
||||||
nnoremap <silent> ]<Space> :<C-u>put =repeat(nr2char(10), v:count1)<CR>
|
|
||||||
|
|
||||||
" ── Auto-Clear Search Highlight ─────────────────────────────────────────────
|
|
||||||
|
|
||||||
augroup ChopstickSearchHL
|
|
||||||
autocmd!
|
|
||||||
autocmd CursorHold * if get(v:, 'hlsearch', 0) | let v:hlsearch = 0 | endif
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
" ── Overlength Highlight (only chars past textwidth, not the whole column) ─
|
|
||||||
|
|
||||||
function! s:OverLengthApply() abort
|
|
||||||
if exists('w:overlength_match')
|
|
||||||
silent! call matchdelete(w:overlength_match)
|
|
||||||
unlet w:overlength_match
|
|
||||||
endif
|
|
||||||
if &textwidth <= 0 || &buftype !=# '' | return | endif
|
|
||||||
let w:overlength_match = matchadd('OverLength', '\%>' . &textwidth . 'v.\+', -1)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:OverLengthDefineHL() abort
|
|
||||||
hi default OverLength ctermbg=52 ctermfg=NONE guibg=#3a1f1f guifg=NONE
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
augroup ChopstickOverLength
|
|
||||||
autocmd!
|
|
||||||
autocmd ColorScheme * call s:OverLengthDefineHL()
|
|
||||||
autocmd OptionSet textwidth call s:OverLengthApply()
|
|
||||||
autocmd BufWinEnter,WinEnter,FileType * call s:OverLengthApply()
|
|
||||||
augroup END
|
|
||||||
call s:OverLengthDefineHL()
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
" env.vim — environment detection (must load first)
|
|
||||||
|
|
||||||
set nocompatible
|
|
||||||
|
|
||||||
let g:is_tty = empty($TERM) || $TERM ==# 'dumb' || $TERM =~# 'linux'
|
|
||||||
\ || $TERM =~# 'screen' || &term =~# 'builtin'
|
|
||||||
let g:has_true_color = ($COLORTERM ==# 'truecolor' || $COLORTERM ==# '24bit')
|
|
||||||
|
|
||||||
let g:chopsticks_profile = get(g:, 'chopsticks_profile', 'engineer')
|
|
||||||
if index(['minimal', 'engineer', 'full'], g:chopsticks_profile) < 0
|
|
||||||
let g:chopsticks_profile = 'engineer'
|
|
||||||
endif
|
|
||||||
|
|
||||||
let s:profile_full = g:chopsticks_profile ==# 'full'
|
|
||||||
let s:profile_minimal = g:chopsticks_profile ==# 'minimal'
|
|
||||||
|
|
||||||
let g:chopsticks_enable_lsp = get(g:, 'chopsticks_enable_lsp',
|
|
||||||
\ !s:profile_minimal)
|
|
||||||
let g:chopsticks_enable_lint = get(g:, 'chopsticks_enable_lint',
|
|
||||||
\ !s:profile_minimal)
|
|
||||||
let g:chopsticks_enable_extra_languages = get(g:,
|
|
||||||
\ 'chopsticks_enable_extra_languages', !s:profile_minimal)
|
|
||||||
let g:chopsticks_enable_ui_extras = get(g:, 'chopsticks_enable_ui_extras',
|
|
||||||
\ !s:profile_minimal)
|
|
||||||
let g:chopsticks_enable_markdown_preview = get(g:,
|
|
||||||
\ 'chopsticks_enable_markdown_preview', !s:profile_minimal)
|
|
||||||
|
|
||||||
let g:chopsticks_markdown_lint = get(g:, 'chopsticks_markdown_lint',
|
|
||||||
\ s:profile_full)
|
|
||||||
let g:chopsticks_markdown_format_on_save = get(g:,
|
|
||||||
\ 'chopsticks_markdown_format_on_save', s:profile_full)
|
|
||||||
let g:chopsticks_markdown_lsp = get(g:, 'chopsticks_markdown_lsp',
|
|
||||||
\ s:profile_full)
|
|
||||||
let g:chopsticks_markdown_spell = get(g:, 'chopsticks_markdown_spell',
|
|
||||||
\ s:profile_full)
|
|
||||||
let g:chopsticks_markdown_conceal = get(g:, 'chopsticks_markdown_conceal',
|
|
||||||
\ s:profile_full)
|
|
||||||
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
|
|
||||||
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_tarPlugin = 1
|
|
||||||
let g:loaded_vimballPlugin = 1
|
|
||||||
let g:loaded_zipPlugin = 1
|
|
||||||
let g:loaded_tutor_mode_plugin = 1
|
|
||||||
let g:loaded_spellfile_plugin = 1
|
|
||||||
let g:loaded_openPlugin = 1
|
|
||||||
let g:loaded_manpager_plugin = 1
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
" git.vim — Fugitive mappings, GitGutter config, conflict navigation
|
|
||||||
|
|
||||||
" ── GitGutter ───────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
let g:gitgutter_map_keys = 0
|
|
||||||
let g:gitgutter_sign_added = '+'
|
|
||||||
let g:gitgutter_sign_modified = '~'
|
|
||||||
let g:gitgutter_sign_removed = '-'
|
|
||||||
let g:gitgutter_sign_removed_first_line = '^'
|
|
||||||
let g:gitgutter_sign_modified_removed = '~'
|
|
||||||
|
|
||||||
" ── Fugitive ────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
if exists('g:plugs["vim-fugitive"]')
|
|
||||||
nnoremap <leader>gs :Git status<CR>
|
|
||||||
nnoremap <leader>gc :Git commit<CR>
|
|
||||||
nnoremap <leader>gp :Git push<CR>
|
|
||||||
nnoremap <leader>gl :Git pull<CR>
|
|
||||||
nnoremap <leader>gd :Gdiffsplit<CR>
|
|
||||||
nnoremap <leader>gb :Git blame<CR>
|
|
||||||
nnoremap <leader>gL :Git log --oneline --graph -20<CR>
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── Conflict Navigation ────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
nnoremap <silent> ]x /^\(<<<<<<<\\|=======\\|>>>>>>>\)<CR>
|
|
||||||
nnoremap <silent> [x ?^\(<<<<<<<\\|=======\\|>>>>>>>\)<CR>
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
" languages.vim — vim-go, vim-markdown, per-filetype autocmds
|
|
||||||
|
|
||||||
" ── vim-markdown ───────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
let g:vim_markdown_conceal = get(g:, 'vim_markdown_conceal',
|
|
||||||
\ g:chopsticks_markdown_conceal)
|
|
||||||
let g:vim_markdown_conceal_code_blocks = 0
|
|
||||||
let g:vim_markdown_folding_disabled = get(g:, 'vim_markdown_folding_disabled', 1)
|
|
||||||
let g:vim_markdown_folding_level = 2
|
|
||||||
let g:vim_markdown_frontmatter = 1
|
|
||||||
let g:vim_markdown_toml_frontmatter = 1
|
|
||||||
let g:vim_markdown_json_frontmatter = 1
|
|
||||||
let g:vim_markdown_follow_anchor = 1
|
|
||||||
let g:vim_markdown_new_list_item_indent = 2
|
|
||||||
let g:vim_markdown_strikethrough = 1
|
|
||||||
|
|
||||||
if exists('g:plugs["vim-markdown"]')
|
|
||||||
nnoremap <leader>mt :Toc<CR>
|
|
||||||
endif
|
|
||||||
|
|
||||||
if has('macunix')
|
|
||||||
let g:previm_open_cmd = '/usr/bin/open'
|
|
||||||
elseif executable('xdg-open')
|
|
||||||
let g:previm_open_cmd = 'xdg-open'
|
|
||||||
endif
|
|
||||||
let g:previm_enable_realtime = get(g:, 'previm_enable_realtime', 0)
|
|
||||||
if exists('g:plugs["previm"]')
|
|
||||||
nnoremap <leader>mp :PrevimOpen<CR>
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── vim-go (syntax only — vim-lsp handles intelligence) ─────────────────────
|
|
||||||
|
|
||||||
let g:go_gopls_enabled = 0
|
|
||||||
let g:go_code_completion_enabled = 0
|
|
||||||
let g:go_fmt_autosave = 0
|
|
||||||
let g:go_imports_autosave = 0
|
|
||||||
let g:go_highlight_types = 1
|
|
||||||
let g:go_highlight_fields = 1
|
|
||||||
let g:go_highlight_functions = 1
|
|
||||||
let g:go_highlight_function_calls = 1
|
|
||||||
|
|
||||||
" ── Filetype Detection ──────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function! s:MarkdownDefaults() abort
|
|
||||||
setlocal wrap linebreak textwidth=0 colorcolumn=0 signcolumn=no
|
|
||||||
let &l:conceallevel = get(g:, 'chopsticks_markdown_conceal', 0) ? 2 : 0
|
|
||||||
|
|
||||||
if get(g:, 'chopsticks_markdown_spell', 0)
|
|
||||||
setlocal spell
|
|
||||||
else
|
|
||||||
setlocal nospell
|
|
||||||
endif
|
|
||||||
|
|
||||||
if !get(g:, 'chopsticks_markdown_lint', 0)
|
|
||||||
\ && !get(g:, 'chopsticks_markdown_format_on_save', 0)
|
|
||||||
let b:ale_enabled = 0
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
augroup ChopstickFiletype
|
|
||||||
autocmd!
|
|
||||||
|
|
||||||
autocmd BufReadPost *
|
|
||||||
\ if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif
|
|
||||||
|
|
||||||
autocmd FileType python
|
|
||||||
\ setlocal expandtab shiftwidth=4 tabstop=4 textwidth=88
|
|
||||||
autocmd FileType javascript,typescript
|
|
||||||
\ setlocal expandtab shiftwidth=2 tabstop=2 textwidth=100
|
|
||||||
autocmd FileType go
|
|
||||||
\ setlocal noexpandtab shiftwidth=4 tabstop=4 textwidth=120
|
|
||||||
autocmd FileType rust
|
|
||||||
\ setlocal expandtab shiftwidth=4 tabstop=4 textwidth=100
|
|
||||||
autocmd FileType c,cpp
|
|
||||||
\ setlocal expandtab shiftwidth=4 tabstop=4 textwidth=80
|
|
||||||
autocmd FileType html,css
|
|
||||||
\ setlocal expandtab shiftwidth=2 tabstop=2
|
|
||||||
autocmd FileType yaml
|
|
||||||
\ setlocal expandtab shiftwidth=2 tabstop=2
|
|
||||||
autocmd FileType markdown call s:MarkdownDefaults()
|
|
||||||
autocmd FileType sh
|
|
||||||
\ setlocal expandtab shiftwidth=2 tabstop=2 textwidth=80
|
|
||||||
autocmd FileType make
|
|
||||||
\ setlocal noexpandtab shiftwidth=8 tabstop=8
|
|
||||||
autocmd FileType json
|
|
||||||
\ setlocal expandtab shiftwidth=2 tabstop=2
|
|
||||||
autocmd FileType dockerfile
|
|
||||||
\ setlocal expandtab shiftwidth=2 tabstop=2
|
|
||||||
augroup END
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
" lint.vim — ALE async linting and format-on-save
|
|
||||||
|
|
||||||
if !g:chopsticks_enable_lint
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
let g:ale_disable_lsp = 1
|
|
||||||
|
|
||||||
let s:ale_linters = {
|
|
||||||
\ 'python': ['flake8', 'pylint'],
|
|
||||||
\ 'javascript': ['eslint'],
|
|
||||||
\ 'typescript': ['eslint'],
|
|
||||||
\ 'go': ['staticcheck'],
|
|
||||||
\ 'rust': ['cargo'],
|
|
||||||
\ 'c': ['cc'],
|
|
||||||
\ 'sh': ['shellcheck'],
|
|
||||||
\ 'yaml': ['yamllint'],
|
|
||||||
\ 'dockerfile': ['hadolint'],
|
|
||||||
\ 'css': ['stylelint'],
|
|
||||||
\ 'scss': ['stylelint'],
|
|
||||||
\ 'sql': ['sqlfluff'],
|
|
||||||
\}
|
|
||||||
|
|
||||||
if g:chopsticks_markdown_lint
|
|
||||||
let s:ale_linters.markdown = ['markdownlint']
|
|
||||||
endif
|
|
||||||
|
|
||||||
let g:ale_linters = s:ale_linters
|
|
||||||
|
|
||||||
let s:ale_fixers = {
|
|
||||||
\ '*': ['remove_trailing_lines', 'trim_whitespace'],
|
|
||||||
\ 'python': ['black', 'isort'],
|
|
||||||
\ 'javascript': ['prettier', 'eslint'],
|
|
||||||
\ 'typescript': ['prettier', 'eslint'],
|
|
||||||
\ 'go': ['goimports'],
|
|
||||||
\ 'rust': ['rustfmt'],
|
|
||||||
\ 'c': ['clang-format'],
|
|
||||||
\ 'json': ['prettier'],
|
|
||||||
\ 'yaml': ['prettier'],
|
|
||||||
\ 'html': ['prettier'],
|
|
||||||
\ 'css': ['prettier'],
|
|
||||||
\ 'scss': ['prettier'],
|
|
||||||
\ 'less': ['prettier'],
|
|
||||||
\ 'sql': ['sqlfluff'],
|
|
||||||
\}
|
|
||||||
|
|
||||||
if g:chopsticks_markdown_format_on_save
|
|
||||||
let s:ale_fixers.markdown = ['prettier']
|
|
||||||
endif
|
|
||||||
|
|
||||||
let g:ale_fixers = s:ale_fixers
|
|
||||||
|
|
||||||
let g:ale_fix_on_save = get(g:, 'ale_fix_on_save', 1)
|
|
||||||
let g:ale_python_isort_options = '--profile black'
|
|
||||||
let g:ale_sign_error = 'X'
|
|
||||||
let g:ale_sign_warning = '!'
|
|
||||||
let g:ale_lint_on_text_changed = 'normal'
|
|
||||||
let g:ale_lint_on_insert_leave = 1
|
|
||||||
let g:ale_lint_on_enter = 1
|
|
||||||
let g:ale_lint_delay = 200
|
|
||||||
let g:ale_echo_delay = 100
|
|
||||||
let g:ale_virtualtext_cursor = get(g:, 'ale_virtualtext_cursor', 'disabled')
|
|
||||||
|
|
||||||
if exists('g:plugs["ale"]')
|
|
||||||
nnoremap <silent> [e :ALEPrevious<cr>
|
|
||||||
nnoremap <silent> ]e :ALENext<cr>
|
|
||||||
nnoremap <silent> <leader>aD :ALEDetail<cr>
|
|
||||||
nnoremap <silent> <leader>af :let g:ale_fix_on_save = !g:ale_fix_on_save
|
|
||||||
\ <bar> echo 'Format on save: ' . (g:ale_fix_on_save ? 'ON' : 'OFF')<cr>
|
|
||||||
endif
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
" lsp.vim — vim-lsp settings, asyncomplete, LSP buffer keymaps
|
|
||||||
|
|
||||||
if !g:chopsticks_enable_lsp
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
let g:lsp_settings_lazyload = 1
|
|
||||||
|
|
||||||
let g:lsp_settings_filetype_python = ['pylsp']
|
|
||||||
let g:lsp_settings_filetype_go = ['gopls']
|
|
||||||
let g:lsp_settings_filetype_rust = ['rust-analyzer']
|
|
||||||
let g:lsp_settings_filetype_typescript = ['typescript-language-server']
|
|
||||||
let g:lsp_settings_filetype_javascript = ['typescript-language-server']
|
|
||||||
let g:lsp_settings_filetype_c = ['clangd']
|
|
||||||
let g:lsp_settings_filetype_sh = ['bash-language-server']
|
|
||||||
let g:lsp_settings_filetype_html = ['vscode-html-language-server']
|
|
||||||
let g:lsp_settings_filetype_css = ['vscode-css-language-server']
|
|
||||||
let g:lsp_settings_filetype_scss = ['vscode-css-language-server']
|
|
||||||
let g:lsp_settings_filetype_json = ['vscode-json-language-server']
|
|
||||||
let g:lsp_settings_filetype_yaml = ['yaml-language-server']
|
|
||||||
let g:lsp_settings_filetype_sql = ['sqls']
|
|
||||||
|
|
||||||
if g:chopsticks_markdown_lsp
|
|
||||||
let g:lsp_settings_filetype_markdown = ['marksman']
|
|
||||||
endif
|
|
||||||
|
|
||||||
let g:lsp_diagnostics_virtual_text_enabled = g:chopsticks_lsp_virtual_text
|
|
||||||
let g:lsp_diagnostics_virtual_text_delay = 200
|
|
||||||
let g:lsp_diagnostics_highlights_enabled = !g:is_tty
|
|
||||||
let g:lsp_document_highlight_enabled = !g:is_tty
|
|
||||||
let g:lsp_document_highlight_delay = 200
|
|
||||||
let g:lsp_signs_enabled = 1
|
|
||||||
let g:lsp_diagnostics_echo_cursor = 1
|
|
||||||
let g:lsp_diagnostics_echo_delay = 100
|
|
||||||
let g:lsp_completion_documentation_enabled = 1
|
|
||||||
|
|
||||||
let g:lsp_signs_error = {'text': 'X'}
|
|
||||||
let g:lsp_signs_warning = {'text': '!'}
|
|
||||||
let g:lsp_signs_information = {'text': 'i'}
|
|
||||||
let g:lsp_signs_hint = {'text': '>'}
|
|
||||||
|
|
||||||
" ── Completion ──────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
if has('patch-8.1.1517')
|
|
||||||
set completeopt=menuone,noinsert,noselect,popup
|
|
||||||
else
|
|
||||||
set completeopt=menuone,noinsert,noselect
|
|
||||||
endif
|
|
||||||
set pumheight=15
|
|
||||||
let g:asyncomplete_auto_popup = 1
|
|
||||||
let g:asyncomplete_auto_completeopt = 0
|
|
||||||
let g:asyncomplete_popup_delay = 50
|
|
||||||
|
|
||||||
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
|
|
||||||
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
|
|
||||||
inoremap <expr> <CR> pumvisible() ? asyncomplete#close_popup() : "\<CR>"
|
|
||||||
|
|
||||||
" ── Buffer Keymaps ──────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function! s:on_lsp_buffer_enabled() abort
|
|
||||||
setlocal omnifunc=lsp#complete
|
|
||||||
if !g:is_tty && &filetype !=# 'markdown'
|
|
||||||
setlocal signcolumn=yes
|
|
||||||
endif
|
|
||||||
|
|
||||||
nmap <buffer> gd <plug>(lsp-definition)
|
|
||||||
nmap <buffer> gy <plug>(lsp-type-definition)
|
|
||||||
nmap <buffer> gi <plug>(lsp-implementation)
|
|
||||||
nmap <buffer> gr <plug>(lsp-references)
|
|
||||||
nmap <buffer> [g <plug>(lsp-previous-diagnostic)
|
|
||||||
nmap <buffer> ]g <plug>(lsp-next-diagnostic)
|
|
||||||
|
|
||||||
nmap <buffer> K <plug>(lsp-hover)
|
|
||||||
|
|
||||||
nmap <buffer> <leader>rn <plug>(lsp-rename)
|
|
||||||
nmap <buffer> <leader>ca <plug>(lsp-code-action)
|
|
||||||
nmap <buffer> <leader>f <plug>(lsp-document-format)
|
|
||||||
xmap <buffer> <leader>f <plug>(lsp-document-range-format)
|
|
||||||
|
|
||||||
nmap <buffer> <leader>o <plug>(lsp-document-symbol-search)
|
|
||||||
nmap <buffer> <leader>ws <plug>(lsp-workspace-symbol-search)
|
|
||||||
nmap <buffer> <leader>cD <plug>(lsp-document-diagnostics)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
augroup lsp_install
|
|
||||||
autocmd!
|
|
||||||
autocmd User lsp_buffer_enabled call s:on_lsp_buffer_enabled()
|
|
||||||
augroup END
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
" navigation.vim — FZF, netrw, buffer/window management, terminal
|
|
||||||
|
|
||||||
" ── netrw (built-in file browser) ───────────────────────────────────────────
|
|
||||||
|
|
||||||
let g:netrw_liststyle = 3
|
|
||||||
let g:netrw_banner = 0
|
|
||||||
let g:netrw_browse_split = 4
|
|
||||||
let g:netrw_winsize = 25
|
|
||||||
let g:netrw_altv = 1
|
|
||||||
let g:netrw_list_hide = '\(^\|\s\s\)\zs\.\S\+'
|
|
||||||
let g:netrw_list_hide .= ',\.pyc$,node_modules,\.git,__pycache__,\.DS_Store'
|
|
||||||
|
|
||||||
function! s:ToggleSidebar(...) abort
|
|
||||||
let l:dir = a:0 ? a:1 : getcwd()
|
|
||||||
if getbufvar(winbufnr(1), '&filetype') ==# 'netrw' && getwinvar(1, '&winfixwidth')
|
|
||||||
let l:cur = winnr()
|
|
||||||
1wincmd w
|
|
||||||
close
|
|
||||||
if l:cur > 1
|
|
||||||
execute (l:cur - 1) . 'wincmd w'
|
|
||||||
endif
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
execute 'topleft vertical 30new'
|
|
||||||
execute 'Explore ' . fnameescape(l:dir)
|
|
||||||
setlocal winfixwidth
|
|
||||||
setlocal bufhidden=wipe
|
|
||||||
wincmd p
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
nnoremap <silent> <leader>e :call <SID>ToggleSidebar()<CR>
|
|
||||||
nnoremap <silent> <leader>E :call <SID>ToggleSidebar(expand('%:p:h'))<CR>
|
|
||||||
|
|
||||||
augroup ChopstickNetrw
|
|
||||||
autocmd!
|
|
||||||
autocmd FileType netrw setlocal bufhidden=wipe
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
" ── FZF ─────────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function! s:SmartFiles() abort
|
|
||||||
if isdirectory('.git') || finddir('.git', '.;') !=# ''
|
|
||||||
GFiles
|
|
||||||
else
|
|
||||||
Files
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
if exists('g:plugs["fzf.vim"]')
|
|
||||||
nnoremap <C-p> :call <SID>SmartFiles()<CR>
|
|
||||||
nnoremap <leader>b :Buffers<CR>
|
|
||||||
nnoremap <leader>rg :Rg<CR>
|
|
||||||
nnoremap <leader>rG :RgWord<CR>
|
|
||||||
nnoremap <leader>rt :Tags<CR>
|
|
||||||
nnoremap <leader>gF :GFiles<CR>
|
|
||||||
nnoremap <leader>fh :History<CR>
|
|
||||||
nnoremap <leader>fc :Commands<CR>
|
|
||||||
nnoremap <leader>fm :Marks<CR>
|
|
||||||
nnoremap <leader>fl :BLines<CR>
|
|
||||||
nnoremap <leader>fL :Lines<CR>
|
|
||||||
nnoremap <leader>f/ :History/<CR>
|
|
||||||
nnoremap <leader>f: :History:<CR>
|
|
||||||
nnoremap <leader>gC :Commits<CR>
|
|
||||||
nnoremap <leader>gB :BCommits<CR>
|
|
||||||
endif
|
|
||||||
|
|
||||||
let g:fzf_layout = { 'down': '40%' }
|
|
||||||
|
|
||||||
if g:is_tty
|
|
||||||
let g:fzf_preview_window = []
|
|
||||||
else
|
|
||||||
let g:fzf_preview_window = ['right:50%', 'ctrl-/']
|
|
||||||
endif
|
|
||||||
|
|
||||||
function! s:Preview() abort
|
|
||||||
return g:is_tty ? {} : fzf#vim#with_preview()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
command! -bang -nargs=* Rg
|
|
||||||
\ call fzf#vim#grep(
|
|
||||||
\ 'rg --column --line-number --no-heading --color=always --smart-case -- '
|
|
||||||
\ .shellescape(<q-args>), 1, s:Preview(), <bang>0)
|
|
||||||
command! -bang -nargs=* RgWord
|
|
||||||
\ call fzf#vim#grep(
|
|
||||||
\ 'rg --column --line-number --no-heading --color=always --smart-case -F -- '
|
|
||||||
\ .shellescape(expand('<cword>')), 1, 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 ──────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function! s:ToggleMaximize() abort
|
|
||||||
if exists('t:maximize_session')
|
|
||||||
execute t:maximize_session
|
|
||||||
unlet t:maximize_session
|
|
||||||
echo 'Window: restored'
|
|
||||||
else
|
|
||||||
let t:maximize_session = winrestcmd()
|
|
||||||
resize | vertical resize
|
|
||||||
echo 'Window: MAXIMIZED'
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
nnoremap <silent> <leader>z :call <SID>ToggleMaximize()<CR>
|
|
||||||
|
|
||||||
" ── Terminal ────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
if has('terminal')
|
|
||||||
nnoremap <leader>tv :terminal<CR>
|
|
||||||
nnoremap <leader>th :terminal ++rows=10<CR>
|
|
||||||
tnoremap <Esc><Esc> <C-\><C-n>
|
|
||||||
tnoremap <C-h> <C-\><C-n><C-w>h
|
|
||||||
tnoremap <C-j> <C-\><C-n><C-w>j
|
|
||||||
tnoremap <C-k> <C-\><C-n><C-w>k
|
|
||||||
tnoremap <C-l> <C-\><C-n><C-w>l
|
|
||||||
endif
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
" plugins.vim — vim-plug declarations
|
|
||||||
|
|
||||||
let data_dir = has('nvim') ? stdpath('data') . '/site' : '~/.vim'
|
|
||||||
if empty(glob(data_dir . '/autoload/plug.vim'))
|
|
||||||
silent execute '!curl -fLo '.data_dir.'/autoload/plug.vim --create-dirs '
|
|
||||||
\ . 'https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
|
|
||||||
augroup PlugBootstrap
|
|
||||||
autocmd!
|
|
||||||
autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
|
|
||||||
augroup END
|
|
||||||
endif
|
|
||||||
|
|
||||||
call plug#begin('~/.vim/plugged')
|
|
||||||
|
|
||||||
" ── Navigation & Search ──────────────────────────────────────────────────────
|
|
||||||
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
|
|
||||||
Plug 'junegunn/fzf.vim'
|
|
||||||
|
|
||||||
" ── Git ──────────────────────────────────────────────────────────────────────
|
|
||||||
Plug 'tpope/vim-fugitive'
|
|
||||||
Plug 'airblade/vim-gitgutter'
|
|
||||||
|
|
||||||
" ── Editing ──────────────────────────────────────────────────────────────────
|
|
||||||
Plug 'tpope/vim-surround'
|
|
||||||
Plug 'tpope/vim-commentary'
|
|
||||||
Plug 'tpope/vim-repeat'
|
|
||||||
Plug 'tpope/vim-sleuth'
|
|
||||||
Plug 'wellle/targets.vim'
|
|
||||||
Plug 'jiangmiao/auto-pairs'
|
|
||||||
Plug 'easymotion/vim-easymotion', { 'on': '<Plug>(easymotion' }
|
|
||||||
|
|
||||||
if g:chopsticks_enable_lint
|
|
||||||
" ── Linting & Formatting ────────────────────────────────────────────────
|
|
||||||
Plug 'dense-analysis/ale'
|
|
||||||
endif
|
|
||||||
|
|
||||||
if g:chopsticks_enable_lsp
|
|
||||||
" ── LSP + Completion ─────────────────────────────────────────────────────
|
|
||||||
Plug 'prabirshrestha/vim-lsp'
|
|
||||||
Plug 'mattn/vim-lsp-settings'
|
|
||||||
Plug 'prabirshrestha/asyncomplete.vim'
|
|
||||||
Plug 'prabirshrestha/asyncomplete-lsp.vim'
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── Language Syntax ──────────────────────────────────────────────────────────
|
|
||||||
Plug 'preservim/vim-markdown', { 'for': 'markdown' }
|
|
||||||
if g:chopsticks_enable_markdown_preview
|
|
||||||
Plug 'previm/previm', { 'on': 'PrevimOpen' }
|
|
||||||
endif
|
|
||||||
if g:chopsticks_enable_extra_languages
|
|
||||||
Plug 'pangloss/vim-javascript', { 'for': ['javascript', 'javascript.jsx'] }
|
|
||||||
Plug 'HerringtonDarkholme/yats.vim', { 'for': ['typescript', 'typescript.tsx'] }
|
|
||||||
Plug 'fatih/vim-go', { 'for': 'go' }
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── UI ───────────────────────────────────────────────────────────────────────
|
|
||||||
if g:chopsticks_enable_ui_extras
|
|
||||||
Plug 'mbbill/undotree', { 'on': 'UndotreeToggle' }
|
|
||||||
Plug 'mhinz/vim-startify'
|
|
||||||
endif
|
|
||||||
Plug 'lifepillar/vim-solarized8'
|
|
||||||
if !empty($TMUX)
|
|
||||||
Plug 'christoomey/vim-tmux-navigator'
|
|
||||||
endif
|
|
||||||
|
|
||||||
call plug#end()
|
|
||||||
|
|
@ -1,387 +0,0 @@
|
||||||
" tools.vim — run file, sudo save, quickfix, helpers
|
|
||||||
|
|
||||||
" ── Buffer Close ───────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
command! Bclose call <SID>BufcloseCloseIt()
|
|
||||||
function! <SID>BufcloseCloseIt()
|
|
||||||
let l:currentBufNum = bufnr("%")
|
|
||||||
let l:alternateBufNum = bufnr("#")
|
|
||||||
if buflisted(l:alternateBufNum)
|
|
||||||
buffer #
|
|
||||||
else
|
|
||||||
bnext
|
|
||||||
endif
|
|
||||||
if bufnr("%") == l:currentBufNum
|
|
||||||
new
|
|
||||||
endif
|
|
||||||
if buflisted(l:currentBufNum)
|
|
||||||
execute("bdelete! " . l:currentBufNum)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" ── Utilities ──────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
nnoremap <leader>F gg=G``
|
|
||||||
vnoremap <leader>F =
|
|
||||||
nnoremap <leader>wa :wa<CR>
|
|
||||||
|
|
||||||
nnoremap <silent> <Leader>= :exe "resize " . (winheight(0) * 3/2)<CR>
|
|
||||||
nnoremap <silent> <Leader>- :exe "resize " . (winheight(0) * 2/3)<CR>
|
|
||||||
|
|
||||||
nnoremap <leader><leader> <c-^>
|
|
||||||
|
|
||||||
nnoremap <leader>W :%s/\s\+$//<CR>:let @/=''<CR>
|
|
||||||
vnoremap <leader>W :s/\s\+$//<CR>:let @/=''<CR>gv
|
|
||||||
|
|
||||||
nnoremap <leader>ev :edit $MYVIMRC<CR>
|
|
||||||
nnoremap <leader>sv :unlet! g:chopsticks_loaded<CR>:execute 'source ' . fnameescape($MYVIMRC)<CR>:echo "vimrc reloaded"<CR>
|
|
||||||
|
|
||||||
nnoremap <leader>* :%s/\<<C-r><C-w>\>//g<Left><Left>
|
|
||||||
vnoremap <leader>* :s///g<Left><Left><Left>
|
|
||||||
|
|
||||||
if has('clipboard')
|
|
||||||
nnoremap <leader>cp :let @+ = expand("%:p")<CR>:echo "Copied: " . expand("%:p")<CR>
|
|
||||||
nnoremap <leader>cf :let @+ = expand("%:t")<CR>:echo "Copied: " . expand("%:t")<CR>
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── Auto-Create Directories ─────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function! s:MkNonExDir(file, buf)
|
|
||||||
if empty(getbufvar(a:buf, '&buftype')) && a:file !~# '\v^\w+\:\/'
|
|
||||||
let dir = fnamemodify(a:file, ':h')
|
|
||||||
if !isdirectory(dir)
|
|
||||||
call mkdir(dir, 'p')
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
augroup BWCCreateDir
|
|
||||||
autocmd!
|
|
||||||
autocmd BufWritePre *
|
|
||||||
\ if !empty(expand('<afile>')) |
|
|
||||||
\ call s:MkNonExDir(expand('<afile>'), +expand('<abuf>')) |
|
|
||||||
\ endif
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
" ── Large File Handling ──────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
let g:LargeFile = get(g:, 'LargeFile', 1024 * 1024 * 10)
|
|
||||||
let s:tty_large = g:is_tty ? 512000 : g:LargeFile
|
|
||||||
|
|
||||||
function! s:ApplyLargeFileSettings() abort
|
|
||||||
if get(b:, 'chopsticks_large_file', 0)
|
|
||||||
setlocal bufhidden=unload undolevels=-1 noswapfile
|
|
||||||
let b:ale_enabled = 0
|
|
||||||
if &l:syntax !=# ''
|
|
||||||
setlocal syntax=
|
|
||||||
endif
|
|
||||||
elseif get(b:, 'chopsticks_tty_large_file', 0)
|
|
||||||
if &l:syntax !=# ''
|
|
||||||
setlocal syntax=
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:MarkLargeFile(file) abort
|
|
||||||
if empty(a:file)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
let l:fsize = getfsize(a:file)
|
|
||||||
if l:fsize > g:LargeFile || l:fsize == -2
|
|
||||||
let b:chopsticks_large_file = 1
|
|
||||||
elseif g:is_tty && l:fsize > s:tty_large
|
|
||||||
let b:chopsticks_tty_large_file = 1
|
|
||||||
endif
|
|
||||||
call s:ApplyLargeFileSettings()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
augroup ChopstickLargeFile
|
|
||||||
autocmd!
|
|
||||||
autocmd BufReadPre * call s:MarkLargeFile(expand('<afile>'))
|
|
||||||
autocmd BufReadPost,FileType,Syntax * call s:ApplyLargeFileSettings()
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
" ── Run Current File (,cr) ──────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function! s:RunFile() abort
|
|
||||||
write
|
|
||||||
let l:ft = &filetype
|
|
||||||
let l:file = shellescape(expand('%:p'))
|
|
||||||
if l:ft ==# 'python' | execute '!python3 ' . l:file
|
|
||||||
elseif l:ft ==# 'javascript' | execute '!node ' . l:file
|
|
||||||
elseif l:ft ==# 'typescript' | execute '!npx ts-node ' . l:file
|
|
||||||
elseif l:ft ==# 'go' | execute '!go run ' . l:file
|
|
||||||
elseif l:ft ==# 'rust' | execute '!cargo run'
|
|
||||||
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 ==# 'lua' | execute '!lua ' . l:file
|
|
||||||
elseif l:ft ==# 'ruby' | execute '!ruby ' . l:file
|
|
||||||
elseif l:ft ==# 'perl' | execute '!perl ' . l:file
|
|
||||||
else | echo 'No runner for filetype: ' . l:ft
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
nnoremap <leader>cr :call <SID>RunFile()<CR>
|
|
||||||
|
|
||||||
" ── Sudo Save ───────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
cnoremap w!! w !sudo tee > /dev/null %
|
|
||||||
|
|
||||||
" ── QuickFix ────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
augroup ChopstickQF
|
|
||||||
autocmd!
|
|
||||||
autocmd QuickFixCmdPost [^l]* cwindow
|
|
||||||
autocmd QuickFixCmdPost l* lwindow
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
nnoremap <silent> ]q :cnext<CR>
|
|
||||||
nnoremap <silent> [q :cprev<CR>
|
|
||||||
|
|
||||||
" ── Status Diagnostic (:ChopsticksStatus) ───────────────────────────────────
|
|
||||||
|
|
||||||
function! s:Check(name, cmd) abort
|
|
||||||
return executable(a:cmd) ? ' OK ' . a:name : ' -- ' . a:name . ' (missing: ' . a:cmd . ')'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:Off(name, reason) abort
|
|
||||||
return ' off ' . a:name . ' (' . a:reason . ')'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:LspCheck(ft, server) abort
|
|
||||||
if !get(g:, 'chopsticks_enable_lsp', 1)
|
|
||||||
return s:Off(a:ft, 'LSP disabled by profile')
|
|
||||||
endif
|
|
||||||
if !exists('*lsp#get_server_names')
|
|
||||||
return ' -- ' . a:ft . ' (vim-lsp not loaded)'
|
|
||||||
endif
|
|
||||||
let l:dir = expand('~/.local/share/vim-lsp-settings/servers/' . a:server)
|
|
||||||
if isdirectory(l:dir)
|
|
||||||
return ' OK ' . a:ft . ' (' . a:server . ')'
|
|
||||||
endif
|
|
||||||
return ' -- ' . a:ft . ' (:LspInstallServer in a ' . a:ft . ' file)'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:ChopsticksStatus() abort
|
|
||||||
let l:lines = []
|
|
||||||
call add(l:lines, 'chopsticks status')
|
|
||||||
call add(l:lines, repeat('─', 50))
|
|
||||||
call add(l:lines, '')
|
|
||||||
|
|
||||||
call add(l:lines, '── system tools ──')
|
|
||||||
call add(l:lines, s:Check('fzf', 'fzf'))
|
|
||||||
call add(l:lines, s:Check('ripgrep', 'rg'))
|
|
||||||
call add(l:lines, s:Check('git', 'git'))
|
|
||||||
call add(l:lines, s:Check('curl', 'curl'))
|
|
||||||
call add(l:lines, s:Check('node', 'node'))
|
|
||||||
call add(l:lines, s:Check('python3', 'python3'))
|
|
||||||
call add(l:lines, s:Check('go', 'go'))
|
|
||||||
call add(l:lines, '')
|
|
||||||
|
|
||||||
call add(l:lines, '── lsp servers ── (:LspInstallServer to install)')
|
|
||||||
call add(l:lines, s:LspCheck('python', 'pylsp'))
|
|
||||||
call add(l:lines, s:LspCheck('go', 'gopls'))
|
|
||||||
call add(l:lines, s:LspCheck('rust', 'rust-analyzer'))
|
|
||||||
call add(l:lines, s:LspCheck('typescript', 'typescript-language-server'))
|
|
||||||
call add(l:lines, s:LspCheck('c/c++', 'clangd'))
|
|
||||||
call add(l:lines, s:LspCheck('bash', 'bash-language-server'))
|
|
||||||
call add(l:lines, s:LspCheck('html', 'vscode-html-language-server'))
|
|
||||||
call add(l:lines, s:LspCheck('json', 'vscode-json-language-server'))
|
|
||||||
call add(l:lines, s:LspCheck('yaml', 'yaml-language-server'))
|
|
||||||
call add(l:lines, s:LspCheck('markdown', 'marksman'))
|
|
||||||
call add(l:lines, s:LspCheck('sql', 'sqls'))
|
|
||||||
call add(l:lines, '')
|
|
||||||
|
|
||||||
call add(l:lines, '── linters ──')
|
|
||||||
if get(g:, 'chopsticks_enable_lint', 1)
|
|
||||||
call add(l:lines, s:Check('flake8 (python)', 'flake8'))
|
|
||||||
call add(l:lines, s:Check('pylint (python)', 'pylint'))
|
|
||||||
call add(l:lines, s:Check('eslint (js/ts)', 'eslint'))
|
|
||||||
call add(l:lines, s:Check('staticcheck (go)', 'staticcheck'))
|
|
||||||
call add(l:lines, s:Check('shellcheck (sh)', 'shellcheck'))
|
|
||||||
call add(l:lines, s:Check('yamllint (yaml)', 'yamllint'))
|
|
||||||
call add(l:lines, s:Check('hadolint (docker)', 'hadolint'))
|
|
||||||
if get(g:, 'chopsticks_markdown_lint', 0)
|
|
||||||
call add(l:lines, s:Check('markdownlint (md)', 'markdownlint'))
|
|
||||||
else
|
|
||||||
call add(l:lines, s:Off('markdownlint (md)', 'disabled by default'))
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
call add(l:lines, s:Off('ALE linters', 'lint disabled by profile'))
|
|
||||||
endif
|
|
||||||
call add(l:lines, '')
|
|
||||||
|
|
||||||
call add(l:lines, '── formatters ── (format-on-save is ' . (get(g:, 'ale_fix_on_save', 0) ? 'ON' : 'OFF') . ')')
|
|
||||||
if get(g:, 'chopsticks_enable_lint', 1)
|
|
||||||
call add(l:lines, s:Check('black (python)', 'black'))
|
|
||||||
call add(l:lines, s:Check('isort (python)', 'isort'))
|
|
||||||
call add(l:lines, s:Check('prettier (js/ts/json)', 'prettier'))
|
|
||||||
if get(g:, 'chopsticks_markdown_format_on_save', 0)
|
|
||||||
call add(l:lines, s:Check('prettier (md)', 'prettier'))
|
|
||||||
else
|
|
||||||
call add(l:lines, s:Off('prettier (md)', 'disabled by default'))
|
|
||||||
endif
|
|
||||||
call add(l:lines, s:Check('goimports (go)', 'goimports'))
|
|
||||||
call add(l:lines, s:Check('rustfmt (rust)', 'rustfmt'))
|
|
||||||
call add(l:lines, s:Check('clang-format (c)', 'clang-format'))
|
|
||||||
else
|
|
||||||
call add(l:lines, s:Off('ALE formatters', 'lint disabled by profile'))
|
|
||||||
endif
|
|
||||||
call add(l:lines, '')
|
|
||||||
|
|
||||||
let l:ok = len(filter(copy(l:lines), 'v:val =~# " OK "'))
|
|
||||||
let l:miss = len(filter(copy(l:lines), 'v:val =~# " -- "'))
|
|
||||||
call add(l:lines, repeat('─', 50))
|
|
||||||
call add(l:lines, ' ' . l:ok . ' ready, ' . l:miss . ' missing')
|
|
||||||
call add(l:lines, '')
|
|
||||||
call add(l:lines, ' Install missing tools with ./install.sh')
|
|
||||||
if get(g:, 'chopsticks_enable_lsp', 1)
|
|
||||||
call add(l:lines, ' Install LSP servers with :LspInstallServer')
|
|
||||||
endif
|
|
||||||
|
|
||||||
let l:name = '__ChopsticksStatus__'
|
|
||||||
if bufwinnr(l:name) > 0
|
|
||||||
execute bufwinnr(l:name) . 'wincmd w | bd'
|
|
||||||
endif
|
|
||||||
execute 'botright new ' . l:name
|
|
||||||
resize 45
|
|
||||||
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile
|
|
||||||
setlocal nowrap nonumber norelativenumber signcolumn=no
|
|
||||||
call setline(1, l:lines)
|
|
||||||
setlocal nomodifiable readonly
|
|
||||||
nnoremap <buffer> <silent> q :bd<CR>
|
|
||||||
endfunction
|
|
||||||
command! ChopsticksStatus call s:ChopsticksStatus()
|
|
||||||
|
|
||||||
" ── Cheat Sheet (,?) ────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function! s:CheatSheet() abort
|
|
||||||
let l:name = '__ChopsticksCheatSheet__'
|
|
||||||
if bufwinnr(l:name) > 0
|
|
||||||
execute bufwinnr(l:name) . 'wincmd w | bd'
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
let l:has_lsp = get(g:, 'chopsticks_enable_lsp', 1)
|
|
||||||
let l:has_lint = get(g:, 'chopsticks_enable_lint', 1)
|
|
||||||
let l:has_undotree = exists('g:plugs["undotree"]')
|
|
||||||
let l:has_previm = exists('g:plugs["previm"]')
|
|
||||||
|
|
||||||
let l:lines = [
|
|
||||||
\ ' chopsticks ,? close',
|
|
||||||
\ ' ─────────────────────────────',
|
|
||||||
\ '',
|
|
||||||
\ ' ── files ──────────────────',
|
|
||||||
\ ' Ctrl+p find file',
|
|
||||||
\ ' ,b buffers',
|
|
||||||
\ ' ,rg grep project',
|
|
||||||
\ ' ,rG grep word',
|
|
||||||
\ ' ,e sidebar (cwd)',
|
|
||||||
\ ' ,E sidebar (file dir)',
|
|
||||||
\ ' ,, last file',
|
|
||||||
\ ' ,fh recent files',
|
|
||||||
\ ' ,fl lines in buffer',
|
|
||||||
\ ' ,fc commands',
|
|
||||||
\ ' ,fm marks',
|
|
||||||
\ '',
|
|
||||||
\ ' ── code ──────────────────',
|
|
||||||
\ ]
|
|
||||||
|
|
||||||
if l:has_lsp
|
|
||||||
call extend(l:lines, [
|
|
||||||
\ ' gd definition',
|
|
||||||
\ ' gy type definition',
|
|
||||||
\ ' gi implementation',
|
|
||||||
\ ' gr references',
|
|
||||||
\ ' K hover docs',
|
|
||||||
\ ' ,rn rename',
|
|
||||||
\ ' ,ca code action',
|
|
||||||
\ ' ,f format',
|
|
||||||
\ ' ,o outline',
|
|
||||||
\ ' [g ]g LSP diagnostics',
|
|
||||||
\ ' :LspInstallServer setup LSP',
|
|
||||||
\ ])
|
|
||||||
endif
|
|
||||||
|
|
||||||
call add(l:lines, ' ,cr run file')
|
|
||||||
if l:has_previm
|
|
||||||
call add(l:lines, ' ,mp markdown preview')
|
|
||||||
endif
|
|
||||||
call add(l:lines, ' ,mt table of contents')
|
|
||||||
|
|
||||||
if l:has_lint
|
|
||||||
call extend(l:lines, [
|
|
||||||
\ ' [e ]e ALE errors',
|
|
||||||
\ ' ,af format on save',
|
|
||||||
\ ])
|
|
||||||
endif
|
|
||||||
|
|
||||||
call extend(l:lines, [
|
|
||||||
\ '',
|
|
||||||
\ ' ── edit ──────────────────',
|
|
||||||
\ ' gc comment',
|
|
||||||
\ ' ,S+2ch easymotion jump',
|
|
||||||
\ ' cs"'' surround',
|
|
||||||
\ ])
|
|
||||||
|
|
||||||
if l:has_undotree
|
|
||||||
call add(l:lines, ' ,u undo tree')
|
|
||||||
endif
|
|
||||||
|
|
||||||
call extend(l:lines, [
|
|
||||||
\ ' ,y ,p clipboard y/p (v)',
|
|
||||||
\ ' Alt+j/k move line (v)',
|
|
||||||
\ ' ,* replace word (v)',
|
|
||||||
\ ' ,F re-indent (v)',
|
|
||||||
\ ' ,W strip trailing (v)',
|
|
||||||
\ '',
|
|
||||||
\ ' ── git ───────────────────',
|
|
||||||
\ ' ,gs status',
|
|
||||||
\ ' ,gd diff',
|
|
||||||
\ ' ,gb blame',
|
|
||||||
\ ' ,gc commit',
|
|
||||||
\ ' ,gp push',
|
|
||||||
\ ' ,gl pull',
|
|
||||||
\ ' ,gL log graph',
|
|
||||||
\ ' ,gC FZF commits',
|
|
||||||
\ ' [x ]x conflict markers',
|
|
||||||
\ '',
|
|
||||||
\ ' ── windows ───────────────',
|
|
||||||
\ ' Ctrl+hjkl navigate splits',
|
|
||||||
\ ' ,h ,l prev / next buf',
|
|
||||||
\ ' ,bd close buffer',
|
|
||||||
\ ' ,z maximize toggle',
|
|
||||||
\ ' ,= ,- resize height',
|
|
||||||
\ ' ,tv ,th terminal v / h',
|
|
||||||
\ ' ]q [q next / prev qf',
|
|
||||||
\ ' ,qo ,qc open / close qf',
|
|
||||||
\ '',
|
|
||||||
\ ' ── toggle ────────────────',
|
|
||||||
\ ' F2 paste mode',
|
|
||||||
\ ' F3 line numbers',
|
|
||||||
\ ' F4 relative numbers',
|
|
||||||
\ ' F6 invisible chars',
|
|
||||||
\ ' ,ss spell check',
|
|
||||||
\ '',
|
|
||||||
\ ' ── survival ──────────────',
|
|
||||||
\ ' ,w save',
|
|
||||||
\ ' ,q quit',
|
|
||||||
\ ' ,x save + quit',
|
|
||||||
\ ' Ctrl+s save (any mode)',
|
|
||||||
\ ' jk exit insert',
|
|
||||||
\ ' :w!! sudo save',
|
|
||||||
\ ' ,ev edit vimrc',
|
|
||||||
\ ' ,sv reload vimrc',
|
|
||||||
\ ' :ChopsticksStatus health',
|
|
||||||
\ ])
|
|
||||||
|
|
||||||
execute 'vertical botright new ' . l:name
|
|
||||||
vertical resize 42
|
|
||||||
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile
|
|
||||||
setlocal nowrap nonumber norelativenumber signcolumn=no
|
|
||||||
setlocal winfixwidth
|
|
||||||
call setline(1, l:lines)
|
|
||||||
setlocal nomodifiable readonly
|
|
||||||
nnoremap <buffer> <silent> q :bd<CR>
|
|
||||||
nnoremap <buffer> <silent> <leader>? :bd<CR>
|
|
||||||
endfunction
|
|
||||||
nnoremap <silent> <leader>? :call <SID>CheatSheet()<CR>
|
|
||||||
226
modules/ui.vim
226
modules/ui.vim
|
|
@ -1,226 +0,0 @@
|
||||||
" ui.vim — colorscheme, statusline, startify
|
|
||||||
|
|
||||||
" ── Colorscheme (Solarized Dark — matches tmux palette) ────────────────────
|
|
||||||
|
|
||||||
if g:has_true_color && has('termguicolors') && !g:is_tty
|
|
||||||
let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
|
|
||||||
let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
|
|
||||||
set termguicolors
|
|
||||||
endif
|
|
||||||
|
|
||||||
set background=dark
|
|
||||||
|
|
||||||
function! s:WarnSolarized8Missing(...) abort
|
|
||||||
echohl WarningMsg
|
|
||||||
echom 'chopsticks: solarized8 not installed — run :PlugInstall'
|
|
||||||
echohl None
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
if !g:is_tty
|
|
||||||
try
|
|
||||||
colorscheme solarized8
|
|
||||||
catch /^Vim\%((\a\+)\)\=:E185/
|
|
||||||
colorscheme default
|
|
||||||
if has('timers')
|
|
||||||
call timer_start(500, function('s:WarnSolarized8Missing'))
|
|
||||||
else
|
|
||||||
augroup ChopstickColorschemeWarn
|
|
||||||
autocmd!
|
|
||||||
autocmd VimEnter * call s:WarnSolarized8Missing()
|
|
||||||
augroup END
|
|
||||||
endif
|
|
||||||
endtry
|
|
||||||
else
|
|
||||||
colorscheme default
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── Window separators, fillchars, cursorline visibility ────────────────────
|
|
||||||
|
|
||||||
if !g:is_tty
|
|
||||||
set fillchars+=vert:│,eob:\
|
|
||||||
endif
|
|
||||||
|
|
||||||
function! s:UIPolish() abort
|
|
||||||
hi VertSplit ctermbg=234 ctermfg=240 guibg=#002b36 guifg=#586e75 cterm=NONE gui=NONE
|
|
||||||
hi CursorLine ctermbg=235 guibg=#0c4452 cterm=NONE gui=NONE
|
|
||||||
hi CursorLineNr ctermbg=235 ctermfg=136 guibg=#0c4452 guifg=#b58900 cterm=bold gui=bold
|
|
||||||
hi SignColumn ctermbg=234 guibg=#002b36
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
augroup ChopstickUIPolish
|
|
||||||
autocmd!
|
|
||||||
autocmd ColorScheme * call s:UIPolish()
|
|
||||||
augroup END
|
|
||||||
if !g:is_tty | call s:UIPolish() | endif
|
|
||||||
|
|
||||||
if has("gui_running")
|
|
||||||
if has("gui_gtk2") || has("gui_gtk3")
|
|
||||||
set guifont=Hack\ 12,Source\ Code\ Pro\ 12,Monospace\ 12
|
|
||||||
elseif has("gui_win32")
|
|
||||||
set guifont=Consolas:h11:cANSI
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── Startify ────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
if exists('g:plugs["vim-startify"]')
|
|
||||||
let g:startify_lists = [
|
|
||||||
\ { 'type': 'sessions', 'header': [' Sessions'] },
|
|
||||||
\ { 'type': 'files', 'header': [' Recent Files'] },
|
|
||||||
\ { 'type': 'dir', 'header': [' Current Dir'] },
|
|
||||||
\ ]
|
|
||||||
|
|
||||||
let g:startify_bookmarks = [{'v': '~/.vimrc'}]
|
|
||||||
let g:startify_session_persistence = 1
|
|
||||||
let g:startify_session_autoload = 1
|
|
||||||
let g:startify_change_to_vcs_root = 1
|
|
||||||
let g:startify_fortune_use_unicode = 0
|
|
||||||
let g:startify_enable_special = 0
|
|
||||||
let g:startify_files_number = 8
|
|
||||||
let g:startify_padding_left = 4
|
|
||||||
|
|
||||||
function! s:SetupDirView() abort
|
|
||||||
if argc() != 1 || !isdirectory(argv()[0]) || exists('s:std_in')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let l:dir = fnameescape(argv()[0])
|
|
||||||
execute 'cd ' . l:dir
|
|
||||||
vertical rightbelow vnew
|
|
||||||
if exists(':Startify') == 2
|
|
||||||
Startify
|
|
||||||
else
|
|
||||||
enew
|
|
||||||
endif
|
|
||||||
wincmd h
|
|
||||||
vertical resize 30
|
|
||||||
setlocal winfixwidth
|
|
||||||
wincmd l
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
if !g:is_tty
|
|
||||||
augroup ChopstickStartup
|
|
||||||
autocmd!
|
|
||||||
autocmd StdinReadPre * let s:std_in = 1
|
|
||||||
autocmd VimEnter * nested call <SID>SetupDirView()
|
|
||||||
augroup END
|
|
||||||
endif
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── Status Line (native — Solarized palette, seamless with tmux bar) ───────
|
|
||||||
|
|
||||||
set laststatus=2
|
|
||||||
set noshowmode
|
|
||||||
|
|
||||||
function! s:SLDefineColors() abort
|
|
||||||
hi SLNormal ctermbg=136 ctermfg=234 cterm=bold guibg=#b58900 guifg=#002b36 gui=bold
|
|
||||||
hi SLInsert ctermbg=33 ctermfg=234 cterm=bold guibg=#268bd2 guifg=#002b36 gui=bold
|
|
||||||
hi SLVisual ctermbg=125 ctermfg=234 cterm=bold guibg=#d33682 guifg=#002b36 gui=bold
|
|
||||||
hi SLReplace ctermbg=160 ctermfg=234 cterm=bold guibg=#dc322f guifg=#002b36 gui=bold
|
|
||||||
hi SLCommand ctermbg=37 ctermfg=234 cterm=bold guibg=#2aa198 guifg=#002b36 gui=bold
|
|
||||||
hi SLBody ctermbg=235 ctermfg=245 cterm=none guibg=#073642 guifg=#93a1a1
|
|
||||||
hi SLFlag ctermbg=235 ctermfg=136 cterm=none guibg=#073642 guifg=#b58900
|
|
||||||
hi SLRight ctermbg=235 ctermfg=240 cterm=none guibg=#073642 guifg=#586e75
|
|
||||||
hi SLGit ctermbg=235 ctermfg=37 cterm=none guibg=#073642 guifg=#2aa198
|
|
||||||
hi SLFtype ctermbg=235 ctermfg=244 cterm=none guibg=#073642 guifg=#839496
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
augroup SLColors
|
|
||||||
autocmd!
|
|
||||||
autocmd ColorScheme * call s:SLDefineColors()
|
|
||||||
augroup END
|
|
||||||
call s:SLDefineColors()
|
|
||||||
|
|
||||||
function! SLMode() abort
|
|
||||||
let l:m = mode()
|
|
||||||
if l:m ==# 'n' | return [' N ', 'SLNormal' ]
|
|
||||||
elseif l:m ==# 'i' | return [' I ', 'SLInsert' ]
|
|
||||||
elseif l:m =~# '[vV]' || l:m ==# "\<C-v>" | return [' V ', 'SLVisual' ]
|
|
||||||
elseif l:m ==# 'R' | return [' R ', 'SLReplace']
|
|
||||||
elseif l:m ==# 'c' | return [' C ', 'SLCommand']
|
|
||||||
elseif l:m ==# 't' | return [' T ', 'SLInsert' ]
|
|
||||||
else | return [' ' . l:m . ' ', 'SLNormal']
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! SLGit() abort
|
|
||||||
if !exists('*FugitiveHead') | return '' | endif
|
|
||||||
let l:b = FugitiveHead()
|
|
||||||
return empty(l:b) ? '' : ' ' . l:b . ' '
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! SLAle() abort
|
|
||||||
if !exists('*ale#statusline#Count') | return '' | endif
|
|
||||||
let l:c = ale#statusline#Count(bufnr(''))
|
|
||||||
let l:e = l:c.error + l:c.style_error
|
|
||||||
let l:w = l:c.warning + l:c.style_warning
|
|
||||||
if l:e == 0 && l:w == 0 | return '' | endif
|
|
||||||
return printf(' E:%d W:%d ', l:e, l:w)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! SLFlags() abort
|
|
||||||
let l:f = ''
|
|
||||||
if &paste | let l:f .= ' PASTE' | endif
|
|
||||||
if &spell | let l:f .= ' SPELL' | endif
|
|
||||||
return empty(l:f) ? '' : l:f . ' '
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! SLBuild() abort
|
|
||||||
let [l:label, l:hl] = SLMode()
|
|
||||||
let l:s = '%#' . l:hl . '#' . l:label
|
|
||||||
let l:s .= '%#SLBody# %f '
|
|
||||||
let l:s .= '%#SLFlag#%m%r'
|
|
||||||
let l:s .= '%#SLFlag#' . SLFlags()
|
|
||||||
let l:s .= '%#SLBody#%='
|
|
||||||
let l:s .= '%#SLFlag#' . SLAle()
|
|
||||||
let l:s .= '%#SLGit#' . SLGit()
|
|
||||||
let l:s .= '%#SLFtype# %y '
|
|
||||||
let l:s .= '%#SLRight# %l:%c %P '
|
|
||||||
return l:s
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
set statusline=%!SLBuild()
|
|
||||||
|
|
||||||
if g:is_tty
|
|
||||||
set statusline=%f\ %h%w%m%r\ %=%(%l,%c%V\ %=\ %P%)
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── Tabline (native — shows listed buffers when >1, else hidden) ───────────
|
|
||||||
|
|
||||||
function! s:TLDefineColors() abort
|
|
||||||
hi TabLine ctermbg=234 ctermfg=244 cterm=none guibg=#002b36 guifg=#839496 gui=none
|
|
||||||
hi TabLineSel ctermbg=235 ctermfg=136 cterm=bold guibg=#073642 guifg=#b58900 gui=bold
|
|
||||||
hi TabLineFill ctermbg=234 ctermfg=240 cterm=none guibg=#002b36 guifg=#586e75 gui=none
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
augroup TLColors
|
|
||||||
autocmd!
|
|
||||||
autocmd ColorScheme * call s:TLDefineColors()
|
|
||||||
augroup END
|
|
||||||
call s:TLDefineColors()
|
|
||||||
|
|
||||||
function! TLBuild() abort
|
|
||||||
let l:s = ''
|
|
||||||
let l:cur = bufnr('%')
|
|
||||||
for l:b in range(1, bufnr('$'))
|
|
||||||
if !buflisted(l:b) || getbufvar(l:b, '&buftype') !=# '' | continue | endif
|
|
||||||
let l:hl = (l:b == l:cur) ? '%#TabLineSel#' : '%#TabLine#'
|
|
||||||
let l:name = bufname(l:b)
|
|
||||||
let l:name = empty(l:name) ? '[No Name]' : fnamemodify(l:name, ':t')
|
|
||||||
let l:mod = getbufvar(l:b, '&modified') ? ' +' : ''
|
|
||||||
let l:s .= l:hl . ' ' . l:b . ' ' . l:name . l:mod . ' '
|
|
||||||
endfor
|
|
||||||
let l:s .= '%#TabLineFill#%='
|
|
||||||
return l:s
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
if !g:is_tty
|
|
||||||
set showtabline=1
|
|
||||||
set tabline=%!TLBuild()
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ── SignColumn: always reserve a column so width never jitters ─────────────
|
|
||||||
|
|
||||||
if !g:is_tty
|
|
||||||
set signcolumn=yes
|
|
||||||
endif
|
|
||||||
251
scripts/test.sh
251
scripts/test.sh
|
|
@ -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
|
|
||||||
Loading…
Reference in a new issue