Compare commits

..

No commits in common. "9442aa0499d4864dc0bf236c609a79050e273823" and "d8eee9dc237185e4f674fe838abdb487e7248053" have entirely different histories.

7 changed files with 372 additions and 647 deletions

5
.gitignore vendored
View file

@ -1,6 +1 @@
*.json *.json
!coc-settings.json
*.swp
*.swo
.DS_Store
Session.vim

120
.vimrc
View file

@ -181,7 +181,7 @@ Plug 'dense-analysis/ale' " Async linting engine
" ===== Language Support ===== " ===== Language Support =====
Plug 'sheerun/vim-polyglot' " Language pack Plug 'sheerun/vim-polyglot' " Language pack
Plug 'fatih/vim-go' " Go support (run :GoUpdateBinaries manually if needed) Plug 'fatih/vim-go', { 'do': ':GoUpdateBinaries' } " Go support
" ===== Color Schemes ===== " ===== Color Schemes =====
Plug 'morhetz/gruvbox' " Gruvbox theme Plug 'morhetz/gruvbox' " Gruvbox theme
@ -235,14 +235,6 @@ call plug#end()
let g:use_coc = (has('nvim') || has('patch-8.0.1453')) && executable('node') && exists('g:plugs["coc.nvim"]') let g:use_coc = (has('nvim') || has('patch-8.0.1453')) && executable('node') && exists('g:plugs["coc.nvim"]')
let g:use_vimlsp = !g:use_coc && has('patch-8.0.0') && exists('g:plugs["vim-lsp"]') let g:use_vimlsp = !g:use_coc && has('patch-8.0.0') && exists('g:plugs["vim-lsp"]')
" Suppress coc.nvim's blocking startup warning on Vim < 9.0.0438
" (the guard above already prevents coc from loading, but the warning
" fires from the plugin file itself if coc.nvim is in runtimepath)
if !g:use_coc
let g:coc_start_at_startup = 0
let g:coc_disable_startup_warning = 1
endif
" Limit popup menu height (applies to all completion) " Limit popup menu height (applies to all completion)
set pumheight=15 set pumheight=15
@ -351,10 +343,7 @@ map <leader>t<leader> :tabnext<cr>
" Let 'tl' toggle between this and the last accessed tab " Let 'tl' toggle between this and the last accessed tab
let g:lasttab = 1 let g:lasttab = 1
nmap <Leader>tl :exe "tabn ".g:lasttab<CR> nmap <Leader>tl :exe "tabn ".g:lasttab<CR>
augroup ChopstickTabHistory au TabLeave * let g:lasttab = tabpagenr()
autocmd!
autocmd TabLeave * let g:lasttab = tabpagenr()
augroup END
" Opens a new tab with the current buffer's path " Opens a new tab with the current buffer's path
map <leader>te :tabedit <C-r>=expand("%:p:h")<cr>/ map <leader>te :tabedit <C-r>=expand("%:p:h")<cr>/
@ -422,10 +411,7 @@ nnoremap <leader>qo :copen<CR>
nnoremap <leader>qc :cclose<CR> nnoremap <leader>qc :cclose<CR>
" Auto-equalize splits when terminal window is resized " Auto-equalize splits when terminal window is resized
augroup ChopstickResize
autocmd!
autocmd VimResized * wincmd = autocmd VimResized * wincmd =
augroup END
" ============================================================================ " ============================================================================
" => Plugin Settings " => Plugin Settings
@ -451,10 +437,7 @@ let NERDTreeIgnore=['\.pyc$', '\~$', '\.swp$', '\.git$', '\.DS_Store', 'node_mod
let NERDTreeWinSize=35 let NERDTreeWinSize=35
" Track stdin reads so startup autocmds can skip pipe/heredoc input " Track stdin reads so startup autocmds can skip pipe/heredoc input
augroup ChopstickStdin
autocmd!
autocmd StdinReadPre * let s:std_in=1 autocmd StdinReadPre * let s:std_in=1
augroup END
" Startup layout (non-TTY only — keeps TTY startup instant) " Startup layout (non-TTY only — keeps TTY startup instant)
if !g:is_tty if !g:is_tty
@ -468,8 +451,12 @@ if !g:is_tty
\ wincmd p | \ wincmd p |
\ if exists(':Startify') == 2 | Startify | else | enew | endif | \ if exists(':Startify') == 2 | Startify | else | enew | endif |
\ endif \ endif
" vim (no args) → Startify fullscreen dashboard, no auto NERDTree " vim (no args) → Startify renders first; open NERDTree alongside it
" Use Ctrl+n to open NERDTree when needed autocmd User Startified
\ if argc() == 0 && !exists('s:std_in') |
\ NERDTree |
\ wincmd p |
\ endif
augroup END augroup END
endif endif
@ -551,7 +538,7 @@ let g:ale_linters = {
\ 'python': ['flake8', 'pylint'], \ 'python': ['flake8', 'pylint'],
\ 'javascript': ['eslint'], \ 'javascript': ['eslint'],
\ 'typescript': ['eslint', 'tsserver'], \ 'typescript': ['eslint', 'tsserver'],
\ 'go': ['gopls', 'staticcheck'], \ 'go': ['gopls', 'golint'],
\ 'rust': ['cargo'], \ 'rust': ['cargo'],
\ 'sh': ['shellcheck'], \ 'sh': ['shellcheck'],
\ 'yaml': ['yamllint'], \ 'yaml': ['yamllint'],
@ -576,7 +563,7 @@ let g:ale_fixers = {
\ 'scss': ['prettier'], \ 'scss': ['prettier'],
\ 'less': ['prettier'], \ 'less': ['prettier'],
\ 'markdown': ['prettier'], \ 'markdown': ['prettier'],
\ 'sql': ['sqlfluff'], \ 'sql': ['sqlfmt'],
\} \}
" Don't fix on save if LSP is handling formatting (avoids double-format) " Don't fix on save if LSP is handling formatting (avoids double-format)
@ -587,21 +574,6 @@ let g:ale_lint_on_text_changed = 'never'
let g:ale_lint_on_insert_leave = 0 let g:ale_lint_on_insert_leave = 0
let g:ale_lint_on_enter = 0 let g:ale_lint_on_enter = 0
" --- vim-go: disable built-in LSP/gopls — CoC (coc-go) handles all Go intelligence ---
" vim-go's gopls conflicts with coc-go and causes E495 errors on startup
" (BufWinEnter afile expand fails for non-file buffers like NERDTree/Startify)
let g:go_gopls_enabled = 0 " disable vim-go's own gopls — coc-go handles LSP
let g:go_code_completion_enabled = 0 " let CoC handle completion
" Use godef as fallback for jump-to-def when CoC unavailable; gopls+disabled = error
let g:go_def_mode = g:use_coc ? 'gopls' : 'godef'
let g:go_info_mode = g:use_coc ? 'gopls' : 'godef'
let g:go_fmt_autosave = 0 " CoC/ALE handle format-on-save
let g:go_imports_autosave = 0
let g:go_highlight_types = 1 " keep syntax features
let g:go_highlight_fields = 1
let g:go_highlight_functions = 1
let g:go_highlight_function_calls = 1
" Navigate between errors: [e/]e (unimpaired style), <leader>aD for detail " Navigate between errors: [e/]e (unimpaired style), <leader>aD for detail
nmap <silent> [e :ALENext<cr> nmap <silent> [e :ALENext<cr>
nmap <silent> ]e :ALEPrevious<cr> nmap <silent> ]e :ALEPrevious<cr>
@ -669,10 +641,7 @@ if g:use_coc
endfunction endfunction
" Highlight symbol and its references on cursor hold " Highlight symbol and its references on cursor hold
augroup CocHighlight
autocmd!
autocmd CursorHold * silent call CocActionAsync('highlight') autocmd CursorHold * silent call CocActionAsync('highlight')
augroup END
" Symbol renaming " Symbol renaming
nmap <leader>rn <Plug>(coc-rename) nmap <leader>rn <Plug>(coc-rename)
@ -849,18 +818,15 @@ fun! CleanExtraSpaces()
call setreg('/', old_query) call setreg('/', old_query)
endfun endfun
augroup ChopstickCleanup if has("autocmd")
autocmd! " Run for all files; ALE trim_whitespace is idempotent so no conflict
" Run for real files only; skip special buffers (NERDTree, Startify, terminal, etc.) autocmd BufWritePre * call CleanExtraSpaces()
autocmd BufWritePre * if empty(&buftype) && !empty(expand('<afile>')) | call CleanExtraSpaces() | endif endif
augroup END
" ============================================================================ " ============================================================================
" => Auto Commands " => Auto Commands
" ============================================================================ " ============================================================================
augroup ChopstickFiletype
autocmd!
" Return to last edit position when opening files " Return to last edit position when opening files
autocmd BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif autocmd BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif
@ -900,7 +866,6 @@ augroup ChopstickFiletype
" Docker specific settings " Docker specific settings
autocmd BufNewFile,BufRead Dockerfile* setlocal filetype=dockerfile autocmd BufNewFile,BufRead Dockerfile* setlocal filetype=dockerfile
autocmd FileType dockerfile setlocal expandtab shiftwidth=2 tabstop=2 autocmd FileType dockerfile setlocal expandtab shiftwidth=2 tabstop=2
augroup END
" ============================================================================ " ============================================================================
" => Status Line " => Status Line
@ -1016,8 +981,7 @@ function! s:MkNonExDir(file, buf)
endfunction endfunction
augroup BWCCreateDir augroup BWCCreateDir
autocmd! autocmd!
" Guard: <afile> is empty for special buffers (NERDTree, Startify, etc.) autocmd BufWritePre * :call s:MkNonExDir(expand('<afile>'), +expand('<abuf>'))
autocmd BufWritePre * if !empty(expand('<afile>')) | call s:MkNonExDir(expand('<afile>'), +expand('<abuf>')) | endif
augroup END augroup END
" ============================================================================ " ============================================================================
@ -1072,8 +1036,7 @@ endif
let g:LargeFile = 1024 * 1024 * 10 let g:LargeFile = 1024 * 1024 * 10
augroup LargeFile augroup LargeFile
autocmd! autocmd!
" Guard: <afile> is empty for special buffers autocmd BufReadPre * let f=getfsize(expand("<afile>")) | if f > g:LargeFile || f == -2 | call LargeFileSettings() | endif
autocmd BufReadPre * if !empty(expand('<afile>')) | let f=getfsize(expand('<afile>')) | if f > g:LargeFile || f == -2 | call LargeFileSettings() | endif | endif
augroup END augroup END
function! LargeFileSettings() function! LargeFileSettings()
@ -1092,10 +1055,7 @@ endfunction
" Additional optimizations for TTY/basic terminals " Additional optimizations for TTY/basic terminals
if g:is_tty if g:is_tty
" Disable syntax highlighting for very large files in TTY " Disable syntax highlighting for very large files in TTY
augroup ChopstickTTYLargeFile autocmd BufReadPre * if getfsize(expand("<afile>")) > 512000 | setlocal syntax=OFF | endif
autocmd!
autocmd BufReadPre * if !empty(expand('<afile>')) && getfsize(expand('<afile>')) > 512000 | setlocal syntax=OFF | endif
augroup END
" Simpler status line for TTY " Simpler status line for TTY
set statusline=%f\ %h%w%m%r\ %=%(%l,%c%V\ %=\ %P%) set statusline=%f\ %h%w%m%r\ %=%(%l,%c%V\ %=\ %P%)
@ -1125,10 +1085,7 @@ set timeoutlen=500
if exists('g:plugs["vim-which-key"]') if exists('g:plugs["vim-which-key"]')
" Register after plugins are loaded (autoload functions available at VimEnter) " Register after plugins are loaded (autoload functions available at VimEnter)
augroup ChopstickWhichKey
autocmd!
autocmd VimEnter * call which_key#register(',', 'g:which_key_map') autocmd VimEnter * call which_key#register(',', 'g:which_key_map')
augroup END
nnoremap <silent> <leader> :<C-u>WhichKey ','<CR> nnoremap <silent> <leader> :<C-u>WhichKey ','<CR>
vnoremap <silent> <leader> :<C-u>WhichKeyVisual ','<CR> vnoremap <silent> <leader> :<C-u>WhichKeyVisual ','<CR>
@ -1243,24 +1200,8 @@ endif
" ============================================================================ " ============================================================================
if exists('g:plugs["vim-startify"]') if exists('g:plugs["vim-startify"]')
" Centered dashboard header — matches neovim startup aesthetic " Dynamic header: config name, vim version, current dir, git branch, key tips
function! StartifyHeader() abort function! StartifyHeader() abort
let l:art = [
\ '███╗ ███╗ ██╗███╗ ██╗ ██████╗ ███████╗ █████╗ ███╗ ███╗ █████╗ ',
\ '████╗ ████║███║████╗ ██║██╔════╝ ██╔════╝██╔══██╗████╗ ████║██╔══██╗',
\ '██╔████╔██║╚██║██╔██╗ ██║██║ ███╗███████╗███████║██╔████╔██║███████║ ',
\ '██║╚██╔╝██║ ██║██║╚██╗██║██║ ██║╚════██║██╔══██║██║╚██╔╝██║██╔══██║',
\ '██║ ╚═╝ ██║ ██║██║ ╚████║╚██████╔╝███████║██║ ██║██║ ╚═╝ ██║██║ ██║',
\ '╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝',
\ ]
let l:art_w = 71
let l:pad = max([0, (winwidth(0) - l:art_w) / 2])
let l:indent = repeat(' ', l:pad)
let l:lines = []
for l:line in l:art
call add(l:lines, l:indent . l:line)
endfor
" Info subheader: vim version + cwd + git branch
let l:ver = 'Vim ' . (v:version / 100) . '.' . printf('%02d', v:version % 100) let l:ver = 'Vim ' . (v:version / 100) . '.' . printf('%02d', v:version % 100)
let l:cwd = fnamemodify(getcwd(), ':t') let l:cwd = fnamemodify(getcwd(), ':t')
let l:git = '' let l:git = ''
@ -1271,20 +1212,19 @@ if exists('g:plugs["vim-startify"]')
let l:git = ' [' . substitute(l:branch, '\n\+$', '', '') . ']' let l:git = ' [' . substitute(l:branch, '\n\+$', '', '') . ']'
endif endif
endif endif
let l:info = l:ver . ' ' . l:cwd . l:git return [
let l:info_pad = max([0, (winwidth(0) - len(l:info)) / 2]) \ ' chopsticks | ' . l:ver . ' | ' . l:cwd . l:git,
call add(l:lines, '') \ ' , = leader | , + pause = key hints | Ctrl-p = files | ,rg = search',
call add(l:lines, repeat(' ', l:info_pad) . l:info) \ '',
call add(l:lines, '') \ ]
return l:lines
endfunction endfunction
let g:startify_custom_header = 'StartifyHeader()' let g:startify_custom_header = 'StartifyHeader()'
" Sessions first, then recent files — mirrors dashboard plugin ordering " Sessions first: restores full project state; dir + recent files below
let g:startify_lists = [ let g:startify_lists = [
\ { 'type': 'sessions', 'header': [' Sessions'] }, \ { 'type': 'sessions', 'header': [' Sessions'] },
\ { 'type': 'dir', 'header': [' Directory: ' . getcwd()] },
\ { 'type': 'files', 'header': [' Recent Files'] }, \ { 'type': 'files', 'header': [' Recent Files'] },
\ { 'type': 'dir', 'header': [' Current Dir'] },
\ { 'type': 'bookmarks', 'header': [' Bookmarks'] }, \ { 'type': 'bookmarks', 'header': [' Bookmarks'] },
\ ] \ ]
@ -1302,17 +1242,11 @@ if exists('g:plugs["vim-startify"]')
let g:startify_fortune_use_unicode = 0 " ASCII only (KISS) let g:startify_fortune_use_unicode = 0 " ASCII only (KISS)
let g:startify_enable_special = 0 " Hide <empty> / <quit> clutter let g:startify_enable_special = 0 " Hide <empty> / <quit> clutter
" Show more recent files " Limit recent files shown
let g:startify_files_number = 8 let g:startify_files_number = 10
" Left padding for list items (gives visual breathing room)
let g:startify_padding_left = 4
" Required for NERDTree compatibility (prevents buftype conflicts) " Required for NERDTree compatibility (prevents buftype conflicts)
augroup ChopstickStartify
autocmd!
autocmd User Startified setlocal buftype= autocmd User Startified setlocal buftype=
augroup END
endif endif
" ============================================================================ " ============================================================================

View file

@ -1,85 +0,0 @@
# Changelog
All notable changes to chopsticks are documented here.
---
## [1.0.0] - 2026-03-29
First stable release. Full-stack engineering environment out of the box — automatic
installation, tiered LSP, TTY fallback, and coverage for 14 languages.
### Added
- **Arch Linux support** in `install.sh` — pacman branch for all system tools
- **`hadolint`** added to system tools installation (Dockerfile linting)
- **`staticcheck`** added to Go tools (replaces archived `golint`)
- **`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
- 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`
### Fixed
- **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`
---
## [0.9.0] - 2026-02-21
### Added
- **Full-stack language coverage** — LSP, lint, and format for: Python,
JavaScript, TypeScript, Go, Rust, Shell, YAML, HTML, CSS/SCSS, Less,
JSON, Markdown, SQL, Dockerfile
- **`install.sh` overhaul** — automated installation of system tools, npm tools,
pip tools, Go tools, and CoC language server extensions with platform detection
and interactive prompts; `--yes` flag for non-interactive mode
- **vim-startify** startup screen with dynamic header (version, cwd, git branch)
- **vim-which-key** keybinding popup on `,` + 500ms pause
- **Startup layout**`vim .` opens NERDTree left + Startify right; bare `vim`
opens Startify with NERDTree alongside
- **Session management** via vim-obsession + vim-prosession
- **Large file handling** — syntax and undo disabled for files > 10 MB
- **Project-local config**`.vimrc` in project root auto-loaded via `set exrc`
- **Persistent undo**`~/.vim/.undo/` with `undolevels=1000`
### 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`
### Fixed
- Multiple leader key conflicts resolved (`,ad`, `,cd`, `,cp`, `,sp`, `,t`)
- CtrlP removed (redundant with FZF)
- Duplicate `set` options cleaned up
- `<leader>A` dead mapping (no alternate-file plugin) removed
---
## [0.1.0] - 2024
Initial release — base Vim configuration with vim-plug, basic plugins, and
TTY/non-TTY detection.

View file

@ -2,8 +2,6 @@
Five minutes from zero to a working Vim engineering environment. Five minutes from zero to a working Vim engineering environment.
---
## Step 1: Install ## Step 1: Install
```bash ```bash
@ -11,15 +9,8 @@ git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
cd ~/.vim && ./install.sh cd ~/.vim && ./install.sh
``` ```
The script handles everything: symlinks, vim-plug, plugins, and all tools. The script handles everything: symlinks, vim-plug, plugin download.
It detects your OS (macOS/Debian/Arch/Fedora) and installs what it can automatically. No root access required.
**Non-interactive (CI / server):**
```bash
./install.sh --yes
```
---
## Step 2: Open Vim ## Step 2: Open Vim
@ -27,23 +18,15 @@ It detects your OS (macOS/Debian/Arch/Fedora) and installs what it can automatic
vim vim
``` ```
The startup screen (vim-startify) shows recent files and sessions. The startup screen shows recent files and sessions. Press `q` to dismiss
Press `Ctrl+p` to find a file, or just type a path. or just start typing a filename to open.
To open a project: ## Step 3: Install LSP (pick one path)
```bash
vim . # NERDTree on left, Startify on right
vim myfile # opens file directly
```
--- ### Path A: With Node.js (full CoC)
## Step 3: Set Up LSP (pick your path)
### Path A: With Node.js (CoC — full LSP)
```bash ```bash
node --version # must be >= 14.14 node --version # confirm >= 14.14
``` ```
Inside Vim, install language servers for your stack: Inside Vim, install language servers for your stack:
@ -52,43 +35,48 @@ Inside Vim, install language servers for your stack:
:CocInstall coc-pyright coc-tsserver coc-go coc-rust-analyzer :CocInstall coc-pyright coc-tsserver coc-go coc-rust-analyzer
``` ```
Or let `install.sh` do it — it asks during setup. ### Path B: Without Node.js (vim-lsp)
### Path B: Without Node.js (vim-lsp — no dependencies) Open a file of your language, then run:
Open a source file, then run:
```vim ```vim
:LspInstallServer :LspInstallServer
``` ```
This auto-detects and installs the correct language server for the current filetype. This auto-detects and installs the correct language server binary.
---
## The 10 Keys That Matter
```
, (pause 500ms) Show all shortcuts
Ctrl+p Fuzzy find file
Ctrl+n Toggle file tree
gd Go to definition
K Show documentation
[g / ]g Prev / next diagnostic
,rn Rename symbol
,rg Search project contents
,gs Git status
,w / ,q Save / Quit
```
--- ---
## Daily Use ## Daily Use
### Navigate Code ### The 10 keys that matter most
```
,w Save
,q Quit
Ctrl+n File tree
Ctrl+p Fuzzy find file
gd Go to definition
K Show docs
[g ]g Prev/next diagnostic
,rn Rename symbol
,gs Git status
, (pause 500ms) Show all shortcuts
```
### Open a project
```bash
cd ~/my-project && vim
```
NERDTree auto-opens when you launch Vim on a directory. Use `Ctrl+p` to
fuzzy-search files by name. Use `,rg` to search file contents.
### Navigate code
| Key | Action | | Key | Action |
|-----|--------| |-------|---------------------------------|
| `gd` | Go to definition | | `gd` | Go to definition |
| `gy` | Go to type definition | | `gy` | Go to type definition |
| `gi` | Go to implementation | | `gi` | Go to implementation |
@ -97,30 +85,30 @@ K Show documentation
| `Ctrl+o` | Jump back | | `Ctrl+o` | Jump back |
| `Ctrl+i` | Jump forward | | `Ctrl+i` | Jump forward |
### Edit Code ### Edit code
| Key | Action | | Key | Action |
|-----|--------| |---------|-------------------------------------|
| `Tab` | Select next completion item | | `Tab` | Select next completion item |
| `Enter` | Confirm completion | | `Enter` | Confirm completion |
| `gc` | Toggle comment (visual mode too) | | `gc` | Toggle comment (works in visual mode too) |
| `cs"'` | Change surrounding `"` to `'` | | `cs"'` | Change surrounding `"` to `'` |
| `ds(` | Delete surrounding `(` | | `ds(` | Delete surrounding `(` |
| `s`+2ch | EasyMotion: jump anywhere | | `s`+2ch | EasyMotion: jump anywhere |
### Manage Errors ### Manage errors
| Key | Action | | Key | Action |
|-----|--------| |--------|-------------------------------|
| `]g` | Jump to next diagnostic | | `]g` | Jump to next diagnostic |
| `[g` | Jump to previous diagnostic | | `[g` | Jump to previous diagnostic |
| `K` | Read the error message | | `K` | Read the error message |
| `,ca` | Apply code action / auto-fix | | `,ca` | Apply code action / auto-fix |
### Git Workflow ### Git workflow
``` ```
,gs git status (stage with 's', commit with 'cc') ,gs git status (stage files with 's', commit with 'cc')
,gd diff current file ,gd diff current file
,gb blame current file ,gb blame current file
,gc commit ,gc commit
@ -130,45 +118,37 @@ K Show documentation
--- ---
## Language Workflows ## Common Workflows
### Python ### Python project
```bash ```bash
# tools installed by install.sh; or manually:
pip install black flake8 pylint isort pip install black flake8 pylint isort
vim my_script.py
``` ```
Auto-formats with `black` + `isort` on save. Lint errors show as `X`/`!` in the sign column. Auto-formats with black on save. Lint errors show in the sign column as
`X` (error) and `!` (warning). Jump between them with `[g` / `]g`.
### JavaScript / TypeScript ### JavaScript / TypeScript project
```bash ```bash
npm install -g prettier eslint typescript npm install -g prettier eslint typescript
vim src/index.ts
``` ```
Auto-formats with `prettier` on save. Auto-formats with prettier on save. Use `:CocInstall coc-tsserver` for
full IntelliSense (requires Node.js).
### Go ### Go project
```bash ```bash
# tools installed by install.sh; or manually:
go install golang.org/x/tools/gopls@latest go install golang.org/x/tools/gopls@latest
go install golang.org/x/tools/cmd/goimports@latest vim main.go
go install honnef.co/go/tools/cmd/staticcheck@latest
``` ```
`gofmt` + `goimports` run on save automatically. gofmt runs on save automatically. `gd` jumps to definitions even across
package boundaries when gopls is running.
### Markdown
Install `marksman` for LSP support (completions, link checking):
```bash
brew install marksman # macOS
sudo pacman -S marksman # Arch
# or: ./install.sh (handles it automatically)
```
--- ---
@ -180,26 +160,16 @@ Edit config live:
,sv " reloads config without restarting ,sv " reloads config without restarting
``` ```
Per-project settings: create `.vimrc` in your project root. Per-project overrides: 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 ## Quick Reference
``` ```
FILES FILES
Ctrl+n File tree toggle Ctrl+n File tree toggle
Ctrl+p Fuzzy find file (git-aware) Ctrl+p Fuzzy find file
,b Search open buffers ,b Search open buffers
,rg Search file contents (ripgrep) ,rg Search file contents (ripgrep)
,w Save | ,q Quit | ,x Save+quit ,w Save | ,q Quit | ,x Save+quit
@ -228,7 +198,8 @@ WINDOWS
SEARCH SEARCH
/text Search forward /text Search forward
?text Search backward ?text Search backward
,* Replace word under cursor (project-wide) ,<CR> Clear search highlight
,* Replace word under cursor (project)
``` ```
--- ---

226
README.md
View file

@ -1,10 +1,9 @@
# chopsticks Vim Configuration # chopsticks - Vim Configuration
A native Vim configuration optimized for full-stack engineering workflows. A native Vim configuration optimized for engineering workflows. Designed for
Vim 8.0+ · Tiered LSP · TTY-aware · Zero icon fonts · 14 languages. Vim 8.0+ with automatic fallbacks for minimal environments (TTY, no Node.js).
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) ## Quick Install
[![Vim 8.0+](https://img.shields.io/badge/Vim-8.0%2B-brightgreen.svg)](https://www.vim.org/)
```bash ```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
@ -17,31 +16,30 @@ See [QUICKSTART.md](QUICKSTART.md) for the 5-minute guide.
## Design Principles ## Design Principles
- **KISS** — No icon fonts, no unicode glyphs, plain ASCII throughout - **KISS**: No icon fonts, no unicode glyphs, plain ASCII throughout
- **Tiered LSP** — CoC (full) with vim-lsp fallback; works with or without Node.js - **Tiered LSP**: CoC (full) with vim-lsp fallback - works with or without Node.js
- **TTY-aware** — Automatic detection and optimization for console/SSH environments - **TTY-aware**: Automatic detection and optimization for console environments
- **Engineering-first** — Git workflow, session management, project-local config - **Engineering-first**: Git workflow, session management, project-local config
- **Batteries included**`install.sh` handles all dependencies automatically
--- ---
## Requirements ## Requirements
| Requirement | Minimum | Notes | | Requirement | Minimum | Notes |
|-------------|---------|-------| |----------------|-------------|--------------------------------|
| Vim | 8.0+ | vim9script not required | | Vim | 8.0+ | vim9script not required |
| git | any | For cloning and fugitive | | git | any | For cloning and fugitive |
| curl | any | For vim-plug auto-install | | curl | any | For vim-plug auto-install |
| Node.js | 14.14+ | Optional — enables CoC LSP | | Node.js | 14.14+ | Optional, enables CoC LSP |
| ripgrep (rg) | any | Optional — enables `:Rg` search | | ripgrep (rg) | any | Optional, enables :Rg search |
| fzf | any | Optional — enables `Ctrl+p` fuzzy search | | fzf | any | Optional, enables :Files/:GFiles |
| ctags | any | Optional — enables `F8` tag browser | | ctags | any | Optional, enables :TagbarToggle |
--- ---
## Installation ## Installation
### Automatic (recommended) ### Automatic
```bash ```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
@ -49,30 +47,22 @@ cd ~/.vim
./install.sh ./install.sh
``` ```
The installer: The script:
1. Checks Vim version and detects OS / package managers 1. Checks for a working Vim installation
2. Backs up any existing `~/.vimrc` (timestamped) 2. Backs up your existing `~/.vimrc` if present
3. Creates symlinks: `~/.vimrc -> ~/.vim/.vimrc` and `~/.vim/coc-settings.json` 3. Creates a symlink: `~/.vimrc -> ~/.vim/.vimrc`
4. Installs vim-plug and runs `:PlugInstall` 4. Installs vim-plug
5. Optionally installs system tools, language tools, and CoC extensions 5. Runs `:PlugInstall` to download all plugins
6. Optionally installs CoC language servers (if Node.js is available)
Supported platforms: **macOS** (Homebrew), **Debian/Ubuntu** (apt), **Arch Linux** (pacman), **Fedora** (dnf).
Use `--yes` for non-interactive / CI environments:
```bash
./install.sh --yes
```
### Manual ### Manual
```bash ```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
ln -sf ~/.vim/.vimrc ~/.vimrc ln -sf ~/.vim/.vimrc ~/.vimrc
ln -sf ~/.vim/coc-settings.json ~/.vim/coc-settings.json
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
vim +PlugInstall +qall </dev/null vim +PlugInstall +qall
``` ```
--- ---
@ -82,12 +72,12 @@ vim +PlugInstall +qall </dev/null
Code intelligence is provided by one of two backends, selected automatically: Code intelligence is provided by one of two backends, selected automatically:
| Condition | Backend | Features | | Condition | Backend | Features |
|-----------|---------|----------| |----------------------------------|----------------|-----------------------------------------------|
| Vim 8.0.1453+ AND Node.js 14.14+ | **CoC** | Full LSP, snippets, extensions ecosystem | | Vim 8.0.1453+ AND Node.js 14.14+ | **CoC** | Full LSP, snippets, extensions ecosystem |
| Vim 8.0+ (no Node.js) | **vim-lsp** | LSP via language server binaries, asyncomplete| | Vim 8.0+ (no Node.js) | **vim-lsp** | LSP via language server binaries, asyncomplete|
| Any Vim | **ALE** | Linting and auto-fix (always active) | | Any Vim | **ALE** | Linting and auto-fix (always active) |
Both backends expose identical key mappings: `gd`, `K`, `[g`, `]g`, `<leader>rn`, `<leader>ca`. Both backends expose identical key mappings (`gd`, `K`, `[g`, `]g`, `<leader>rn`, `<leader>ca`).
### CoC setup (with Node.js) ### CoC setup (with Node.js)
@ -100,16 +90,12 @@ Install language server extensions from inside Vim:
:CocInstall coc-rust-analyzer " Rust :CocInstall coc-rust-analyzer " Rust
:CocInstall coc-json coc-yaml " JSON, YAML :CocInstall coc-json coc-yaml " JSON, YAML
:CocInstall coc-html coc-css " HTML, CSS :CocInstall coc-html coc-css " HTML, CSS
:CocInstall coc-sh " Shell :CocInstall coc-marksman " Markdown
:CocInstall coc-sql " SQL :CocInstall coc-sql " SQL
``` ```
`install.sh` installs all of the above automatically when prompted. `install.sh` installs all of the above automatically when prompted.
**Markdown LSP** — `marksman` is configured via `coc-settings.json` (not a CoC
extension — install `marksman` binary via `brew install marksman` or download from
[releases](https://github.com/artempyanykh/marksman/releases)).
### vim-lsp setup (without Node.js) ### vim-lsp setup (without Node.js)
Install language server binaries for your languages, then run: Install language server binaries for your languages, then run:
@ -118,8 +104,8 @@ Install language server binaries for your languages, then run:
:LspInstallServer " auto-installs the right server for the current filetype :LspInstallServer " auto-installs the right server for the current filetype
``` ```
Supported languages: Python, Go, Rust, TypeScript, JavaScript, Shell, HTML, Supported languages: Python, Go, Rust, TypeScript, JavaScript, Shell,
CSS/SCSS, JSON, YAML, Markdown, SQL — via `vim-lsp-settings`. HTML, CSS/SCSS, JSON, YAML, Markdown, SQL — via `vim-lsp-settings`.
--- ---
@ -132,10 +118,10 @@ Press `,` and wait 500ms for an interactive guide to all bindings (vim-which-key
### Files and Buffers ### Files and Buffers
| Key | Action | | Key | Action |
|-----|--------| |------------|-------------------------------------|
| `Ctrl+n` | Toggle file tree (NERDTree) | | `Ctrl+n` | Toggle file tree (NERDTree) |
| `,n` | Reveal current file in NERDTree | | `,n` | Reveal current file in NERDTree |
| `Ctrl+p` | Fuzzy file search (FZF — git-aware) | | `Ctrl+p` | Fuzzy file search (FZF) |
| `,b` | Search open buffers (FZF) | | `,b` | Search open buffers (FZF) |
| `,rg` | Project-wide search (ripgrep+FZF) | | `,rg` | Project-wide search (ripgrep+FZF) |
| `,rt` | Search tags (FZF) | | `,rt` | Search tags (FZF) |
@ -148,7 +134,7 @@ Press `,` and wait 500ms for an interactive guide to all bindings (vim-which-key
### Windows and Tabs ### Windows and Tabs
| Key | Action | | Key | Action |
|-----|--------| |--------------|---------------------------------|
| `Ctrl+h/j/k/l` | Navigate between windows | | `Ctrl+h/j/k/l` | Navigate between windows |
| `<Leader>=` | Increase window height | | `<Leader>=` | Increase window height |
| `<Leader>-` | Decrease window height | | `<Leader>-` | Decrease window height |
@ -161,7 +147,7 @@ Press `,` and wait 500ms for an interactive guide to all bindings (vim-which-key
### Code Intelligence (CoC / vim-lsp) ### Code Intelligence (CoC / vim-lsp)
| Key | Action | | Key | Action |
|-----|--------| |-------------|---------------------------------|
| `gd` | Go to definition | | `gd` | Go to definition |
| `gy` | Go to type definition | | `gy` | Go to type definition |
| `gi` | Go to implementation | | `gi` | Go to implementation |
@ -172,12 +158,12 @@ Press `,` and wait 500ms for an interactive guide to all bindings (vim-which-key
| `,rn` | Rename symbol | | `,rn` | Rename symbol |
| `,f` | Format selection | | `,f` | Format selection |
| `,ca` | Code action (cursor) | | `,ca` | Code action (cursor) |
| `,qf` | Quick-fix current line (CoC) |
| `,cl` | Run code lens (CoC) |
| `,o` | File outline | | `,o` | File outline |
| `,ws` | Workspace symbols | | `,ws` | Workspace symbols |
| `,cD` | Diagnostics list | | `,cD` | Diagnostics list |
| `,cr` | Resume last CoC list | | `,cr` | Resume last CoC list |
| `,qf` | Quick-fix current line (CoC) |
| `,cl` | Run code lens (CoC) |
| `Tab` | Next completion item | | `Tab` | Next completion item |
| `Shift+Tab` | Previous completion item | | `Shift+Tab` | Previous completion item |
| `Enter` | Confirm completion | | `Enter` | Confirm completion |
@ -187,7 +173,7 @@ Text objects (CoC only): `if`/`af` (function), `ic`/`ac` (class)
### Linting (ALE) ### Linting (ALE)
| Key | Action | | Key | Action |
|-----|--------| |----------|-----------------------|
| `[e` | Next error/warning | | `[e` | Next error/warning |
| `]e` | Previous error/warning| | `]e` | Previous error/warning|
| `,aD` | Show error details | | `,aD` | Show error details |
@ -197,7 +183,7 @@ Signs: `X` = error, `!` = warning
### Git Workflow (fugitive) ### Git Workflow (fugitive)
| Key | Action | | Key | Action |
|-----|--------| |--------|---------------------------------|
| `,gs` | Git status | | `,gs` | Git status |
| `,gc` | Git commit | | `,gc` | Git commit |
| `,gp` | Git push | | `,gp` | Git push |
@ -209,10 +195,10 @@ Signs: `X` = error, `!` = warning
### Engineering Utilities ### Engineering Utilities
| Key | Action | | Key | Action |
|-----|--------| |----------|-------------------------------------|
| `,ev` | Edit `~/.vimrc` | | `,ev` | Edit `~/.vimrc` |
| `,sv` | Reload `~/.vimrc` | | `,sv` | Reload `~/.vimrc` |
| `,F` | Format entire file | | `,F` | Format entire file (= indent) |
| `,W` | Strip trailing whitespace | | `,W` | Strip trailing whitespace |
| `,wa` | Save all open buffers | | `,wa` | Save all open buffers |
| `,wd` | Change CWD to current buffer's dir | | `,wd` | Change CWD to current buffer's dir |
@ -224,13 +210,13 @@ Signs: `X` = error, `!` = warning
| `,qo` | Open quickfix list | | `,qo` | Open quickfix list |
| `,qc` | Close quickfix list | | `,qc` | Close quickfix list |
| `,tv` | Open terminal (vertical split) | | `,tv` | Open terminal (vertical split) |
| `,th` | Open terminal (horizontal, 10 rows) | | `,th` | Open terminal (horizontal, 10r) |
| `Esc` | Exit terminal mode | | `Esc` | Exit terminal mode |
### Navigation and Editing ### Navigation and Editing
| Key | Action | | Key | Action |
|-----|--------| |------------|---------------------------------------------|
| `s`+2ch | EasyMotion jump to any location | | `s`+2ch | EasyMotion jump to any location |
| `Space` | Toggle code fold | | `Space` | Toggle code fold |
| `Y` | Yank to end of line (like `D`, `C`) | | `Y` | Yank to end of line (like `D`, `C`) |
@ -252,23 +238,27 @@ Signs: `X` = error, `!` = warning
## Features ## Features
### Startup Screen (vim-startify) ### vim-startify: Startup Screen
Opens when Vim is launched without a file argument. Shows: Opens when Vim is launched without a file argument. Shows:
- Session list for current directory
- Recently opened files - Recently opened files
- Sessions for the current directory
- Bookmarks - Bookmarks
Session auto-saves on quit. Auto-loads `Session.vim` if found in the current Session auto-saves on quit. Auto-loads `Session.vim` if found in the current
directory. Auto-changes to git root on file open. directory. Auto-changes to git root on file open.
**`vim .` layout** — NERDTree on the left, Startify on the right. ### vim-which-key: Keybinding Guide
### Keybinding Guide (vim-which-key)
Press `,` and pause for 500ms. A popup lists all available leader bindings Press `,` and pause for 500ms. A popup lists all available leader bindings
organized by group. Useful for onboarding and discovering shortcuts. organized by group. Useful for onboarding and discovering shortcuts.
### indentLine: Indent Guides
Draws `|` characters at each indent level. Disabled automatically in TTY
environments and for filetypes where it causes display problems (JSON,
Markdown, help).
### Session Management ### Session Management
```vim ```vim
@ -276,8 +266,8 @@ organized by group. Useful for onboarding and discovering shortcuts.
:Obsess! " Stop tracking :Obsess! " Stop tracking
``` ```
Sessions stored in `~/.vim/sessions/` and automatically resumed by vim-prosession Sessions are stored in `~/.vim/sessions/` and automatically resumed by
on the next Vim launch in the same directory. vim-prosession on the next Vim launch in the same directory.
### Project-Local Config ### Project-Local Config
@ -298,83 +288,86 @@ to prevent Vim from freezing.
### TTY / Console Support ### TTY / Console Support
Detected automatically when `$TERM` is `linux` or `screen`. In TTY mode: Detected automatically when `$TERM` is `linux` or `screen`, or when running
on a basic built-in terminal. In TTY mode:
- True color and cursorline disabled - True color and cursorline disabled
- Powerline separators replaced with plain ASCII - Powerline separators replaced with plain ASCII
- FZF preview windows disabled - FZF preview windows disabled
- NERDTree auto-open skipped - NERDTree auto-open skipped
- Syntax column limit reduced to 120 - Syntax column limit reduced to 120
- Simpler status line - Simpler status line used
--- ---
## Language Support ## Language Support
| Language | Indent | Formatter | Linter | LSP (CoC) | | Language | Indent | Formatter | Linter |
|----------|--------|-----------|--------|-----------| |----------------|--------|------------------|--------------------------|
| Python | 4sp | black + isort | flake8, pylint | coc-pyright | | Python | 4sp | black + isort | flake8, pylint |
| JavaScript | 2sp | prettier | eslint | coc-tsserver | | JavaScript | 2sp | prettier | eslint |
| TypeScript | 2sp | prettier | eslint, tsserver | coc-tsserver | | TypeScript | 2sp | prettier | eslint, tsserver |
| Go | tab | gofmt, goimports | staticcheck | coc-go | | Go | tab | gofmt, goimports | gopls, golint |
| Rust | 4sp | rustfmt | cargo | coc-rust-analyzer | | Rust | 4sp | rustfmt | cargo |
| Shell | 2sp | — | shellcheck | coc-sh | | Shell | 2sp | - | shellcheck |
| YAML | 2sp | prettier | yamllint | coc-yaml | | YAML | 2sp | prettier | yamllint |
| HTML | 2sp | prettier | — | coc-html | | HTML | 2sp | prettier | - |
| CSS / SCSS | 2sp | prettier | stylelint | coc-css | | CSS / SCSS | 2sp | prettier | stylelint |
| Less | 2sp | prettier | — | — | | Less | 2sp | prettier | - |
| JSON | 2sp | prettier | — | coc-json | | JSON | 2sp | prettier | - |
| Markdown | 2sp | prettier | markdownlint | marksman (coc-settings.json) | | Markdown | 2sp | prettier | markdownlint |
| SQL | 4sp | sqlfluff | sqlfluff | — | | SQL | 4sp | sqlfmt | sqlfluff |
| Dockerfile | 2sp | — | hadolint | — | | Dockerfile | 2sp | - | hadolint |
`install.sh` installs all linters and formatters automatically. Install linters separately — `install.sh` lists the exact commands.
ALE runs them asynchronously; format-on-save active when using CoC. ALE runs them asynchronously on save (`ale_fix_on_save = 1` when using CoC).
--- ---
## Plugin List ## Plugin List
### Navigation ### Navigation
- **NERDTree** — File tree explorer - **NERDTree** - File tree explorer
- **fzf + fzf.vim** — Fuzzy finder (file, buffer, tag, ripgrep) - **fzf + fzf.vim** - Fuzzy finder
- **CtrlP** - Fallback fuzzy finder (no fzf dependency)
### Git ### Git
- **vim-fugitive** Git commands inside Vim - **vim-fugitive** - Git commands inside Vim
- **vim-gitgutter** Diff signs in the sign column - **vim-gitgutter** - Diff signs in the sign column
### LSP and Completion ### LSP and Completion
- **coc.nvim** Full LSP + completion (requires Node.js 14.14+) - **coc.nvim** - Full LSP + completion (requires Node.js 14.14+)
- **vim-lsp** Pure VimScript LSP client (fallback, no Node.js) - **vim-lsp** - Pure VimScript LSP client (fallback, no Node.js)
- **vim-lsp-settings** Auto-configure language servers for vim-lsp - **vim-lsp-settings** - Auto-configure language servers for vim-lsp
- **asyncomplete.vim** Async completion (used with vim-lsp) - **asyncomplete.vim** - Async completion (used with vim-lsp)
### Linting ### Linting
- **ALE** Asynchronous Lint Engine (always active) - **ALE** - Asynchronous Lint Engine (always active)
### UI ### UI
- **vim-airline** Status and tabline - **vim-airline** - Status and tabline
- **vim-startify** — Startup screen with sessions - **vim-startify** - Startup screen
- **vim-which-key** Keybinding hint popup - **vim-which-key** - Keybinding hint popup
- **indentLine** Indent guide lines (non-TTY) - **indentLine** - Indent guide lines (non-TTY)
- **undotree** Undo history visualizer - **undotree** - Undo history visualizer
- **tagbar** Code structure sidebar - **tagbar** - Code structure sidebar
### Editing ### Editing
- **vim-surround** Change surrounding quotes, brackets, tags - **vim-surround** - Change surrounding quotes, brackets, tags
- **vim-commentary** `gc` to toggle comments - **vim-commentary** - `gc` to toggle comments
- **auto-pairs** Auto-close brackets and quotes - **auto-pairs** - Auto-close brackets and quotes
- **vim-easymotion** Jump anywhere with 2 keystrokes - **vim-easymotion** - Jump anywhere with 2 keystrokes
- **vim-unimpaired** Bracket shortcut pairs - **vim-unimpaired** - Bracket shortcut pairs
- **targets.vim** Extra text objects - **targets.vim** - Extra text objects
- **vim-snippets** Snippet library (used with CoC/UltiSnips) - **vim-snippets** - Snippet library (used with CoC/UltiSnips)
### Language Packs ### Language Packs
- **vim-polyglot** Syntax for 100+ languages - **vim-polyglot** - Syntax for 100+ languages
- **vim-go** — Go development tools (formatting + highlighting; LSP handled by coc-go) - **vim-go** - Go development tools
### Session ### Session
- **vim-obsession** Continuous session saving - **vim-obsession** - Continuous session saving
- **vim-prosession** Project-level session management - **vim-prosession** - Project-level session management
### Color Schemes ### Color Schemes
- **gruvbox** (default), **dracula**, **solarized**, **onedark** - **gruvbox** (default), **dracula**, **solarized**, **onedark**
@ -407,14 +400,6 @@ True color is enabled automatically when the terminal supports it
node --version # must be >= 14.14 node --version # must be >= 14.14
``` ```
**Markdown LSP not starting:**
```bash
marksman --version # must be installed separately
brew install marksman # macOS
sudo pacman -S marksman # Arch
# or: ./install.sh (installs automatically)
```
**vim-lsp server not starting:** **vim-lsp server not starting:**
```vim ```vim
:LspInstallServer " install server for current filetype :LspInstallServer " install server for current filetype
@ -423,7 +408,8 @@ sudo pacman -S marksman # Arch
**Colors look wrong:** **Colors look wrong:**
```bash ```bash
export TERM=xterm-256color # add to ~/.bashrc or ~/.zshrc # Add to ~/.bashrc or ~/.zshrc
export TERM=xterm-256color
``` ```
**ALE not finding linters:** **ALE not finding linters:**
@ -435,18 +421,12 @@ which flake8 black prettier eslint # confirm tools are on PATH
## References ## References
- [amix/vimrc](https://github.com/amix/vimrc)
- [vim-plug](https://github.com/junegunn/vim-plug) - [vim-plug](https://github.com/junegunn/vim-plug)
- [coc.nvim](https://github.com/neoclide/coc.nvim) - [coc.nvim](https://github.com/neoclide/coc.nvim)
- [vim-lsp](https://github.com/prabirshrestha/vim-lsp) - [vim-lsp](https://github.com/prabirshrestha/vim-lsp)
- [vim-lsp-settings](https://github.com/mattn/vim-lsp-settings) - [vim-lsp-settings](https://github.com/mattn/vim-lsp-settings)
- [amix/vimrc](https://github.com/amix/vimrc)
---
## Changelog
See [CHANGELOG.md](CHANGELOG.md).
## License ## License
[MIT](LICENSE) © m1ng MIT

View file

@ -1,13 +0,0 @@
{
"languageserver": {
"marksman": {
"command": "marksman",
"args": ["server"],
"filetypes": ["markdown"],
"rootPatterns": [".git", ".marksman.toml"]
}
},
"coc.preferences.formatOnSaveFiletypes": [
"markdown"
]
}

View file

@ -94,24 +94,9 @@ HAS_APT=0; command -v apt >/dev/null 2>&1 && HAS_APT=1
HAS_DNF=0; command -v dnf >/dev/null 2>&1 && HAS_DNF=1 HAS_DNF=0; command -v dnf >/dev/null 2>&1 && HAS_DNF=1
HAS_PACMAN=0; command -v pacman >/dev/null 2>&1 && HAS_PACMAN=1 HAS_PACMAN=0; command -v pacman >/dev/null 2>&1 && HAS_PACMAN=1
HAS_NODE=0; command -v node >/dev/null 2>&1 && HAS_NODE=1 && ok "Node.js $(node --version) detected" HAS_NODE=0; command -v node >/dev/null 2>&1 && HAS_NODE=1 && ok "Node.js $(node --version) detected"
HAS_PYTHON=0; command -v python3 >/dev/null 2>&1 && HAS_PYTHON=1 HAS_PIP=0; command -v pip3 >/dev/null 2>&1 && HAS_PIP=1 && ok "Python/pip3 detected"
HAS_PIP=0; command -v pip3 >/dev/null 2>&1 && HAS_PIP=1
HAS_GO=0; command -v go >/dev/null 2>&1 && HAS_GO=1 && ok "Go $(go version | awk '{print $3}') detected" HAS_GO=0; command -v go >/dev/null 2>&1 && HAS_GO=1 && ok "Go $(go version | awk '{print $3}') detected"
# Bootstrap pip3 when python3 exists but pip3 is absent (common on Ubuntu minimal images)
if [[ $HAS_PYTHON -eq 1 && $HAS_PIP -eq 0 ]]; then
warn "python3 found but pip3 missing — attempting bootstrap"
if python3 -m ensurepip --upgrade >/dev/null 2>&1 || \
(command -v apt-get >/dev/null 2>&1 && sudo apt-get install -y python3-pip >/dev/null 2>&1) || \
(command -v pacman >/dev/null 2>&1 && sudo pacman -S --noconfirm python-pip >/dev/null 2>&1) || \
(command -v dnf >/dev/null 2>&1 && sudo dnf install -y python3-pip >/dev/null 2>&1); then
command -v pip3 >/dev/null 2>&1 && HAS_PIP=1 && ok "pip3 bootstrapped"
else
warn "pip3 bootstrap failed — Python tools will be skipped"
fi
fi
[[ $HAS_PIP -eq 1 ]] && ok "Python/pip3 detected"
[[ $HAS_NODE -eq 0 ]] && warn "Node.js not found — JS/TS/Markdown npm tools will be skipped" [[ $HAS_NODE -eq 0 ]] && warn "Node.js not found — JS/TS/Markdown npm tools will be skipped"
[[ $HAS_PIP -eq 0 ]] && warn "pip3 not found — Python tools will be skipped" [[ $HAS_PIP -eq 0 ]] && warn "pip3 not found — Python tools will be skipped"
[[ $HAS_GO -eq 0 ]] && warn "Go not found — Go tools will be skipped" [[ $HAS_GO -eq 0 ]] && warn "Go not found — Go tools will be skipped"
@ -131,17 +116,6 @@ fi
ln -sf "$SCRIPT_DIR/.vimrc" "$HOME/.vimrc" ln -sf "$SCRIPT_DIR/.vimrc" "$HOME/.vimrc"
ok "~/.vimrc -> $SCRIPT_DIR/.vimrc" ok "~/.vimrc -> $SCRIPT_DIR/.vimrc"
# CoC settings (marksman markdown LSP + format-on-save config)
mkdir -p "$HOME/.vim"
COC_CFG="$HOME/.vim/coc-settings.json"
if [ -f "$COC_CFG" ] && [ ! -L "$COC_CFG" ]; then
TS=$(date +%Y%m%d_%H%M%S)
warn "Backing up existing coc-settings.json to ~/.vim/coc-settings.json.backup.$TS"
mv "$COC_CFG" "$COC_CFG.backup.$TS"
fi
ln -sf "$SCRIPT_DIR/coc-settings.json" "$COC_CFG"
ok "~/.vim/coc-settings.json -> $SCRIPT_DIR/coc-settings.json"
# ============================================================================ # ============================================================================
# vim-plug + plugins # vim-plug + plugins
# ============================================================================ # ============================================================================
@ -158,8 +132,7 @@ else
fi fi
step "Installing Vim plugins" step "Installing Vim plugins"
# </dev/null prevents Vim from reading stdin in non-interactive/piped environments vim +PlugInstall +qall
vim +PlugInstall +qall </dev/null
ok "Plugins installed" ok "Plugins installed"
# ============================================================================ # ============================================================================
@ -168,7 +141,7 @@ ok "Plugins installed"
step "System tools" step "System tools"
if ask "Install system tools (ripgrep, fzf, ctags, shellcheck, hadolint, marksman)?"; then if ask "Install system tools (ripgrep, fzf, ctags, shellcheck, marksman)?"; then
install_sys() { install_sys() {
local name="$1"; local check="$2"; shift 2 local name="$1"; local check="$2"; shift 2
if command -v "$check" >/dev/null 2>&1; then if command -v "$check" >/dev/null 2>&1; then
@ -194,7 +167,6 @@ if ask "Install system tools (ripgrep, fzf, ctags, shellcheck, hadolint, marksma
install_sys "fzf" fzf "brew install fzf" install_sys "fzf" fzf "brew install fzf"
install_sys "universal-ctags" ctags "brew install universal-ctags" install_sys "universal-ctags" ctags "brew install universal-ctags"
install_sys "shellcheck" shellcheck "brew install shellcheck" install_sys "shellcheck" shellcheck "brew install shellcheck"
install_sys "hadolint" hadolint "brew install hadolint"
install_sys "marksman" marksman "brew install marksman" install_sys "marksman" marksman "brew install marksman"
elif [[ $HAS_APT -eq 1 ]]; then elif [[ $HAS_APT -eq 1 ]]; then
sudo apt-get update -qq sudo apt-get update -qq
@ -202,24 +174,6 @@ if ask "Install system tools (ripgrep, fzf, ctags, shellcheck, hadolint, marksma
install_sys "fzf" fzf "sudo apt-get install -y fzf" install_sys "fzf" fzf "sudo apt-get install -y fzf"
install_sys "universal-ctags" ctags "sudo apt-get install -y universal-ctags" install_sys "universal-ctags" ctags "sudo apt-get install -y universal-ctags"
install_sys "shellcheck" shellcheck "sudo apt-get install -y shellcheck" install_sys "shellcheck" shellcheck "sudo apt-get install -y shellcheck"
# hadolint: no apt package, download binary
if ! command -v hadolint >/dev/null 2>&1; then
ARCH=$(uname -m)
[[ "$ARCH" == "x86_64" ]] && HARCH="x86_64" || HARCH="arm64"
HVER=$(curl -s https://api.github.com/repos/hadolint/hadolint/releases/latest \
| grep '"tag_name"' | cut -d'"' -f4)
if [[ -n "$HVER" ]]; then
curl -fsSL "https://github.com/hadolint/hadolint/releases/download/${HVER}/hadolint-Linux-${HARCH}" \
-o /tmp/hadolint && chmod +x /tmp/hadolint && sudo mv /tmp/hadolint /usr/local/bin/hadolint
ok "hadolint"
INSTALLED+=("hadolint")
else
warn "hadolint: could not detect latest release, install manually"
SKIPPED+=("hadolint")
fi
else
ok "hadolint (already installed)"
fi
# marksman: no apt package, download binary # marksman: no apt package, download binary
if ! command -v marksman >/dev/null 2>&1; then if ! command -v marksman >/dev/null 2>&1; then
ARCH=$(uname -m) ARCH=$(uname -m)
@ -238,30 +192,21 @@ if ask "Install system tools (ripgrep, fzf, ctags, shellcheck, hadolint, marksma
else else
ok "marksman (already installed)" ok "marksman (already installed)"
fi fi
elif [[ $HAS_PACMAN -eq 1 ]]; then
install_sys "ripgrep" rg "sudo pacman -S --noconfirm ripgrep"
install_sys "fzf" fzf "sudo pacman -S --noconfirm fzf"
install_sys "universal-ctags" ctags "sudo pacman -S --noconfirm ctags"
install_sys "shellcheck" shellcheck "sudo pacman -S --noconfirm shellcheck"
install_sys "hadolint" hadolint "sudo pacman -S --noconfirm hadolint"
install_sys "marksman" marksman "sudo pacman -S --noconfirm marksman"
elif [[ $HAS_DNF -eq 1 ]]; then elif [[ $HAS_DNF -eq 1 ]]; then
install_sys "ripgrep" rg "sudo dnf install -y ripgrep" install_sys "ripgrep" rg "sudo dnf install -y ripgrep"
install_sys "fzf" fzf "sudo dnf install -y fzf" install_sys "fzf" fzf "sudo dnf install -y fzf"
install_sys "shellcheck" shellcheck "sudo dnf install -y ShellCheck" install_sys "shellcheck" shellcheck "sudo dnf install -y ShellCheck"
skip "universal-ctags — install manually: sudo dnf install ctags" skip "universal-ctags — install manually: sudo dnf install ctags"
SKIPPED+=("ctags") SKIPPED+=("ctags")
skip "hadolint — install manually from https://github.com/hadolint/hadolint/releases"
SKIPPED+=("hadolint")
skip "marksman — install manually from https://github.com/artempyanykh/marksman/releases" skip "marksman — install manually from https://github.com/artempyanykh/marksman/releases"
SKIPPED+=("marksman") SKIPPED+=("marksman")
else else
warn "Unknown Linux distro — skipping system tools (install manually)" warn "Unknown Linux distro — skipping system tools (install manually)"
SKIPPED+=("ripgrep" "fzf" "ctags" "shellcheck" "hadolint" "marksman") SKIPPED+=("ripgrep" "fzf" "ctags" "shellcheck" "marksman")
fi fi
else else
skip "system tools" skip "system tools"
SKIPPED+=("ripgrep" "fzf" "ctags" "shellcheck" "hadolint" "marksman") SKIPPED+=("ripgrep" "fzf" "ctags" "shellcheck" "marksman")
fi fi
# ============================================================================ # ============================================================================
@ -292,6 +237,7 @@ if [[ $HAS_NODE -eq 1 ]]; then
npm_install stylelint-config-standard npm_install stylelint-config-standard
npm_install eslint npm_install eslint
npm_install typescript tsc npm_install typescript tsc
npm_install sqlfmt
else else
skip "npm tools" skip "npm tools"
SKIPPED+=("prettier" "markdownlint-cli" "stylelint" "eslint" "typescript") SKIPPED+=("prettier" "markdownlint-cli" "stylelint" "eslint" "typescript")
@ -308,7 +254,7 @@ fi
step "Python tools (formatters + linters)" step "Python tools (formatters + linters)"
if [[ $HAS_PIP -eq 1 ]]; then if [[ $HAS_PIP -eq 1 ]]; then
if ask "Install Python tools (black, isort, flake8, pylint, yamllint, sqlfluff)?"; then if ask "Install Python tools (black, isort, flake8, pylint, sqlfluff)?"; then
pip_install() { pip_install() {
local pkg="$1"; local check="${2:-$1}" local pkg="$1"; local check="${2:-$1}"
if command -v "$check" >/dev/null 2>&1; then if command -v "$check" >/dev/null 2>&1; then
@ -328,25 +274,24 @@ if [[ $HAS_PIP -eq 1 ]]; then
pip_install isort pip_install isort
pip_install flake8 pip_install flake8
pip_install pylint pip_install pylint
pip_install yamllint
pip_install sqlfluff pip_install sqlfluff
else else
skip "Python tools" skip "Python tools"
SKIPPED+=("black" "isort" "flake8" "pylint" "yamllint" "sqlfluff") SKIPPED+=("black" "isort" "flake8" "pylint" "sqlfluff")
fi fi
else else
skip "Python tools (pip3 not installed)" skip "Python tools (pip3 not installed)"
SKIPPED+=("black" "isort" "flake8" "pylint" "yamllint" "sqlfluff") SKIPPED+=("black" "isort" "flake8" "pylint" "sqlfluff")
fi fi
# ============================================================================ # ============================================================================
# Go tools (gopls, goimports, staticcheck) # Go tools (gopls, goimports)
# ============================================================================ # ============================================================================
step "Go tools" step "Go tools"
if [[ $HAS_GO -eq 1 ]]; then if [[ $HAS_GO -eq 1 ]]; then
if ask "Install Go tools (gopls, goimports, staticcheck)?"; then if ask "Install Go tools (gopls, goimports)?"; then
# Go installs binaries to $(go env GOPATH)/bin — add to PATH for this session # Go installs binaries to $(go env GOPATH)/bin — add to PATH for this session
GOBIN="$(go env GOPATH)/bin" GOBIN="$(go env GOPATH)/bin"
export PATH="$PATH:$GOBIN" export PATH="$PATH:$GOBIN"
@ -367,7 +312,6 @@ if [[ $HAS_GO -eq 1 ]]; then
} }
go_install gopls "golang.org/x/tools/gopls@latest" gopls go_install gopls "golang.org/x/tools/gopls@latest" gopls
go_install goimports "golang.org/x/tools/cmd/goimports@latest" goimports go_install goimports "golang.org/x/tools/cmd/goimports@latest" goimports
go_install staticcheck "honnef.co/go/tools/cmd/staticcheck@latest" staticcheck
# Remind user to add GOPATH/bin to their shell profile # Remind user to add GOPATH/bin to their shell profile
if ! echo "$PATH" | grep -q "$GOBIN"; then if ! echo "$PATH" | grep -q "$GOBIN"; then
@ -375,11 +319,11 @@ if [[ $HAS_GO -eq 1 ]]; then
fi fi
else else
skip "Go tools" skip "Go tools"
SKIPPED+=("gopls" "goimports" "staticcheck") SKIPPED+=("gopls" "goimports")
fi fi
else else
skip "Go tools (go not installed)" skip "Go tools (go not installed)"
SKIPPED+=("gopls" "goimports" "staticcheck") SKIPPED+=("gopls" "goimports")
fi fi
# ============================================================================ # ============================================================================
@ -390,8 +334,7 @@ step "CoC language server extensions"
if [[ $HAS_NODE -eq 1 ]]; then if [[ $HAS_NODE -eq 1 ]]; then
if ask "Install CoC language servers (LSP for all configured languages)?"; then if ask "Install CoC language servers (LSP for all configured languages)?"; then
# Note: coc-marksman doesn't exist on npm — markdown LSP is handled via coc-settings.json vim +'CocInstall -sync coc-json coc-tsserver coc-pyright coc-sh coc-html coc-css coc-yaml coc-go coc-rust-analyzer coc-marksman coc-sql' +qall
vim +'CocInstall -sync coc-json coc-tsserver coc-pyright coc-sh coc-html coc-css coc-yaml coc-go coc-rust-analyzer coc-sql' +qall </dev/null
ok "CoC language servers installed" ok "CoC language servers installed"
else else
skip "CoC language servers" skip "CoC language servers"