Compare commits

...

4 commits

Author SHA1 Message Date
9442aa0499 ux: dashboard-style startup — fullscreen Startify, m1ngsama header
- Remove NERDTree auto-open on bare `vim` — Startify now renders
  fullscreen like neovim's snacks dashboard (use Ctrl+n for tree)
- `vim .` keeps NERDTree left + Startify right (directory workflow)
- Replace minimal text header with centered m1ngsama ASCII block art
  (mirrors neovim config aesthetic)
- Center art and info subheader dynamically based on window width
- Add startify_padding_left = 4 for list item breathing room
- Reorder lists: Sessions → Recent Files → Current Dir → Bookmarks
2026-03-29 19:54:44 +08:00
3236155b84 docs: comprehensive v1.0.0 documentation update
- README: full rewrite — updated language table (staticcheck, yamllint,
  hadolint, marksman via coc-settings.json), install.sh platform coverage,
  removed coc-marksman references, added CHANGELOG link
- QUICKSTART: rewrite to reflect automated install.sh, updated language
  workflows (staticcheck for Go, marksman for Markdown)
- CHANGELOG: new file documenting v1.0.0, v0.9.0, and v0.1.0 releases
- .gitignore: add *.swp, *.swo, .DS_Store, Session.vim
2026-03-29 18:05:51 +08:00
3daf725ad8
audit: wrap loose autocmds in augroups, fix install.sh robustness (#13)
.vimrc:
- Wrap all loose autocmds in named augroups with autocmd! (prevents
  doubling on :source $MYVIMRC): ChopstickTabHistory, ChopstickResize,
  ChopstickStdin, CocHighlight, ChopstickCleanup, ChopstickFiletype,
  ChopstickTTYLargeFile, ChopstickWhichKey, ChopstickStartify

install.sh:
- Add Arch Linux (pacman) branch for system tools
- Add hadolint to system tools (brew/apt binary download/pacman)
- Add staticcheck to Go tools
- Add yamllint to pip tools
- Remove sqlfmt from npm (SQL unified to sqlfluff via pip)
- Remove coc-marksman (package does not exist on npm)
- Add coc-settings.json symlink step with backup
- Add pip3 bootstrap when python3 present but pip3 absent
- Fix PlugInstall and CocInstall to use </dev/null (TTY-safe)

coc-settings.json:
- New file: configures marksman as Markdown LSP server for CoC
  (replaces the broken coc-marksman npm package approach)
2026-03-29 16:36:43 +08:00
db16c2f8fc
fix: vim-go startup hang, E495 errors, and afile guard safety (#12)
vim-go / install hang:
- Remove { 'do': ':GoUpdateBinaries' } from vim-go Plug declaration.
  This hook downloads gopls, dlv, gotest and ~10 other binaries during
  PlugInstall, causing multi-minute hangs that look like vim is frozen.
  Run :GoUpdateBinaries manually if Go debugging tools are needed.

vim-go / CoC conflict:
- Add g:go_gopls_enabled = 0 — disables vim-go's own gopls client.
  Without this, vim-go registers a BufWinEnter * autocmd that calls
  go#lsp#DidOpen(expand('<afile>:p')), which fires on NERDTree/Startify
  buffers (no file name), triggers E495, and makes vim wait for Enter.
- g:go_fmt_autosave = 0, g:go_imports_autosave = 0 — CoC/ALE handle
  format-on-save; vim-go's auto-save would double-format.
- g:go_code_completion_enabled = 0 — CoC handles completion.
- Keep vim-go syntax highlights (go_highlight_*) which CoC doesn't provide.

<afile> guard (E495 hardening):
- BWCCreateDir (BufWritePre): wrap in !empty(expand('<afile>')) guard.
- LargeFile (BufReadPre): same guard — special buffers have no file name.
- CleanExtraSpaces (BufWritePre): guard with empty(&buftype) in addition,
  so it only runs for normal file buffers, not terminals or help windows.
- TTY BufReadPre size check: same guard.
2026-03-29 12:22:21 +08:00
7 changed files with 647 additions and 372 deletions

5
.gitignore vendored
View file

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

192
.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', { 'do': ':GoUpdateBinaries' } " Go support Plug 'fatih/vim-go' " Go support (run :GoUpdateBinaries manually if needed)
" ===== Color Schemes ===== " ===== Color Schemes =====
Plug 'morhetz/gruvbox' " Gruvbox theme Plug 'morhetz/gruvbox' " Gruvbox theme
@ -235,6 +235,14 @@ 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
@ -343,7 +351,10 @@ 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>
au TabLeave * let g:lasttab = tabpagenr() augroup ChopstickTabHistory
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>/
@ -411,7 +422,10 @@ 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
autocmd VimResized * wincmd = augroup ChopstickResize
autocmd!
autocmd VimResized * wincmd =
augroup END
" ============================================================================ " ============================================================================
" => Plugin Settings " => Plugin Settings
@ -437,7 +451,10 @@ 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
autocmd StdinReadPre * let s:std_in=1 augroup ChopstickStdin
autocmd!
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
@ -451,12 +468,8 @@ 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 renders first; open NERDTree alongside it " vim (no args) → Startify fullscreen dashboard, no auto NERDTree
autocmd User Startified " Use Ctrl+n to open NERDTree when needed
\ if argc() == 0 && !exists('s:std_in') |
\ NERDTree |
\ wincmd p |
\ endif
augroup END augroup END
endif endif
@ -538,7 +551,7 @@ let g:ale_linters = {
\ 'python': ['flake8', 'pylint'], \ 'python': ['flake8', 'pylint'],
\ 'javascript': ['eslint'], \ 'javascript': ['eslint'],
\ 'typescript': ['eslint', 'tsserver'], \ 'typescript': ['eslint', 'tsserver'],
\ 'go': ['gopls', 'golint'], \ 'go': ['gopls', 'staticcheck'],
\ 'rust': ['cargo'], \ 'rust': ['cargo'],
\ 'sh': ['shellcheck'], \ 'sh': ['shellcheck'],
\ 'yaml': ['yamllint'], \ 'yaml': ['yamllint'],
@ -563,7 +576,7 @@ let g:ale_fixers = {
\ 'scss': ['prettier'], \ 'scss': ['prettier'],
\ 'less': ['prettier'], \ 'less': ['prettier'],
\ 'markdown': ['prettier'], \ 'markdown': ['prettier'],
\ 'sql': ['sqlfmt'], \ 'sql': ['sqlfluff'],
\} \}
" 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)
@ -574,6 +587,21 @@ 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>
@ -641,7 +669,10 @@ if g:use_coc
endfunction endfunction
" Highlight symbol and its references on cursor hold " Highlight symbol and its references on cursor hold
autocmd CursorHold * silent call CocActionAsync('highlight') augroup CocHighlight
autocmd!
autocmd CursorHold * silent call CocActionAsync('highlight')
augroup END
" Symbol renaming " Symbol renaming
nmap <leader>rn <Plug>(coc-rename) nmap <leader>rn <Plug>(coc-rename)
@ -818,54 +849,58 @@ fun! CleanExtraSpaces()
call setreg('/', old_query) call setreg('/', old_query)
endfun endfun
if has("autocmd") augroup ChopstickCleanup
" Run for all files; ALE trim_whitespace is idempotent so no conflict autocmd!
autocmd BufWritePre * call CleanExtraSpaces() " Run for real files only; skip special buffers (NERDTree, Startify, terminal, etc.)
endif autocmd BufWritePre * if empty(&buftype) && !empty(expand('<afile>')) | call CleanExtraSpaces() | endif
augroup END
" ============================================================================ " ============================================================================
" => Auto Commands " => Auto Commands
" ============================================================================ " ============================================================================
" Return to last edit position when opening files augroup ChopstickFiletype
autocmd BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif autocmd!
" Return to last edit position when opening files
autocmd BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif
" Set specific file types " Set specific file types
autocmd BufNewFile,BufRead *.json setlocal filetype=json autocmd BufNewFile,BufRead *.json setlocal filetype=json
autocmd BufNewFile,BufRead *.md setlocal filetype=markdown autocmd BufNewFile,BufRead *.md setlocal filetype=markdown
autocmd BufNewFile,BufRead *.jsx setlocal filetype=javascript.jsx autocmd BufNewFile,BufRead *.jsx setlocal filetype=javascript.jsx
autocmd BufNewFile,BufRead *.tsx setlocal filetype=typescript.tsx autocmd BufNewFile,BufRead *.tsx setlocal filetype=typescript.tsx
" Python specific settings " Python specific settings
autocmd FileType python setlocal expandtab shiftwidth=4 tabstop=4 colorcolumn=88 autocmd FileType python setlocal expandtab shiftwidth=4 tabstop=4 colorcolumn=88
" JavaScript specific settings " JavaScript specific settings
autocmd FileType javascript,typescript setlocal expandtab shiftwidth=2 tabstop=2 autocmd FileType javascript,typescript setlocal expandtab shiftwidth=2 tabstop=2
" Go specific settings " Go specific settings
autocmd FileType go setlocal noexpandtab shiftwidth=4 tabstop=4 autocmd FileType go setlocal noexpandtab shiftwidth=4 tabstop=4
" HTML/CSS specific settings " HTML/CSS specific settings
autocmd FileType html,css setlocal expandtab shiftwidth=2 tabstop=2 autocmd FileType html,css setlocal expandtab shiftwidth=2 tabstop=2
" YAML specific settings " YAML specific settings
autocmd FileType yaml setlocal expandtab shiftwidth=2 tabstop=2 autocmd FileType yaml setlocal expandtab shiftwidth=2 tabstop=2
" Markdown specific settings " Markdown specific settings
autocmd FileType markdown setlocal wrap linebreak spell tw=0 autocmd FileType markdown setlocal wrap linebreak spell tw=0
" Shell script settings " Shell script settings
autocmd FileType sh setlocal expandtab shiftwidth=2 tabstop=2 autocmd FileType sh setlocal expandtab shiftwidth=2 tabstop=2
" Makefile settings (must use tabs) " Makefile settings (must use tabs)
autocmd FileType make setlocal noexpandtab shiftwidth=8 tabstop=8 autocmd FileType make setlocal noexpandtab shiftwidth=8 tabstop=8
" JSON specific settings " JSON specific settings
autocmd FileType json setlocal expandtab shiftwidth=2 tabstop=2 autocmd FileType json setlocal expandtab shiftwidth=2 tabstop=2
" 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
@ -981,7 +1016,8 @@ function! s:MkNonExDir(file, buf)
endfunction endfunction
augroup BWCCreateDir augroup BWCCreateDir
autocmd! autocmd!
autocmd BufWritePre * :call s:MkNonExDir(expand('<afile>'), +expand('<abuf>')) " Guard: <afile> is empty for special buffers (NERDTree, Startify, etc.)
autocmd BufWritePre * if !empty(expand('<afile>')) | call s:MkNonExDir(expand('<afile>'), +expand('<abuf>')) | endif
augroup END augroup END
" ============================================================================ " ============================================================================
@ -1036,7 +1072,8 @@ endif
let g:LargeFile = 1024 * 1024 * 10 let g:LargeFile = 1024 * 1024 * 10
augroup LargeFile augroup LargeFile
autocmd! autocmd!
autocmd BufReadPre * let f=getfsize(expand("<afile>")) | if f > g:LargeFile || f == -2 | call LargeFileSettings() | endif " Guard: <afile> is empty for special buffers
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()
@ -1055,7 +1092,10 @@ 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
autocmd BufReadPre * if getfsize(expand("<afile>")) > 512000 | setlocal syntax=OFF | endif augroup ChopstickTTYLargeFile
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%)
@ -1085,7 +1125,10 @@ 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)
autocmd VimEnter * call which_key#register(',', 'g:which_key_map') augroup ChopstickWhichKey
autocmd!
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>
@ -1200,8 +1243,24 @@ endif
" ============================================================================ " ============================================================================
if exists('g:plugs["vim-startify"]') if exists('g:plugs["vim-startify"]')
" Dynamic header: config name, vim version, current dir, git branch, key tips " Centered dashboard header — matches neovim startup aesthetic
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 = ''
@ -1212,20 +1271,21 @@ if exists('g:plugs["vim-startify"]')
let l:git = ' [' . substitute(l:branch, '\n\+$', '', '') . ']' let l:git = ' [' . substitute(l:branch, '\n\+$', '', '') . ']'
endif endif
endif endif
return [ let l:info = l:ver . ' ' . l:cwd . l:git
\ ' chopsticks | ' . l:ver . ' | ' . l:cwd . l:git, let l:info_pad = max([0, (winwidth(0) - len(l:info)) / 2])
\ ' , = leader | , + pause = key hints | Ctrl-p = files | ,rg = search', call add(l:lines, '')
\ '', 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: restores full project state; dir + recent files below " Sessions first, then recent files — mirrors dashboard plugin ordering
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'] },
\ ] \ ]
" Quick-access bookmarks for common config files " Quick-access bookmarks for common config files
@ -1242,11 +1302,17 @@ 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
" Limit recent files shown " Show more recent files
let g:startify_files_number = 10 let g:startify_files_number = 8
" 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)
autocmd User Startified setlocal buftype= augroup ChopstickStartify
autocmd!
autocmd User Startified setlocal buftype=
augroup END
endif endif
" ============================================================================ " ============================================================================

85
CHANGELOG.md Normal file
View file

@ -0,0 +1,85 @@
# 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,6 +2,8 @@
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
@ -9,8 +11,15 @@ git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
cd ~/.vim && ./install.sh cd ~/.vim && ./install.sh
``` ```
The script handles everything: symlinks, vim-plug, plugin download. The script handles everything: symlinks, vim-plug, plugins, and all tools.
No root access required. It detects your OS (macOS/Debian/Arch/Fedora) and installs what it can automatically.
**Non-interactive (CI / server):**
```bash
./install.sh --yes
```
---
## Step 2: Open Vim ## Step 2: Open Vim
@ -18,15 +27,23 @@ No root access required.
vim vim
``` ```
The startup screen shows recent files and sessions. Press `q` to dismiss The startup screen (vim-startify) shows recent files and sessions.
or just start typing a filename to open. Press `Ctrl+p` to find a file, or just type a path.
## Step 3: Install LSP (pick one path) To open a project:
```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 # confirm >= 14.14 node --version # must be >= 14.14
``` ```
Inside Vim, install language servers for your stack: Inside Vim, install language servers for your stack:
@ -35,80 +52,75 @@ 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
``` ```
### Path B: Without Node.js (vim-lsp) Or let `install.sh` do it — it asks during setup.
Open a file of your language, then run: ### Path B: Without Node.js (vim-lsp — no dependencies)
Open a source file, then run:
```vim ```vim
:LspInstallServer :LspInstallServer
``` ```
This auto-detects and installs the correct language server binary. This auto-detects and installs the correct language server for the current filetype.
---
## 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
### The 10 keys that matter most ### 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
``` ```
,w Save ,gs git status (stage with 's', commit with 'cc')
,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 |
|-------|---------------------------------|
| `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 (works in 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 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
@ -118,37 +130,45 @@ fuzzy-search files by name. Use `,rg` to search file contents.
--- ---
## Common Workflows ## Language Workflows
### Python project ### Python
```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 on save. Lint errors show in the sign column as Auto-formats with `black` + `isort` on save. Lint errors show as `X`/`!` in the sign column.
`X` (error) and `!` (warning). Jump between them with `[g` / `]g`.
### JavaScript / TypeScript project ### JavaScript / TypeScript
```bash ```bash
npm install -g prettier eslint typescript npm install -g prettier eslint typescript
vim src/index.ts
``` ```
Auto-formats with prettier on save. Use `:CocInstall coc-tsserver` for Auto-formats with `prettier` on save.
full IntelliSense (requires Node.js).
### Go project ### Go
```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
vim main.go go install golang.org/x/tools/cmd/goimports@latest
go install honnef.co/go/tools/cmd/staticcheck@latest
``` ```
gofmt runs on save automatically. `gd` jumps to definitions even across `gofmt` + `goimports` run on save automatically.
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)
```
--- ---
@ -160,16 +180,26 @@ Edit config live:
,sv " reloads config without restarting ,sv " reloads config without restarting
``` ```
Per-project overrides: create `.vimrc` in your project root. 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 ## Quick Reference Card
``` ```
FILES FILES
Ctrl+n File tree toggle Ctrl+n File tree toggle
Ctrl+p Fuzzy find file Ctrl+p Fuzzy find file (git-aware)
,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
@ -185,8 +215,8 @@ CODE
,F Format whole file ,F Format whole file
GIT GIT
,gs Status | ,gd Diff | ,gb Blame ,gs Status | ,gd Diff | ,gb Blame
,gc Commit | ,gp Push | ,gl Pull ,gc Commit | ,gp Push | ,gl Pull
WINDOWS WINDOWS
Ctrl+h/j/k/l Move between panes Ctrl+h/j/k/l Move between panes
@ -198,8 +228,7 @@ WINDOWS
SEARCH SEARCH
/text Search forward /text Search forward
?text Search backward ?text Search backward
,<CR> Clear search highlight ,* Replace word under cursor (project-wide)
,* Replace word under cursor (project)
``` ```
--- ---

408
README.md
View file

@ -1,9 +1,10 @@
# chopsticks - Vim Configuration # chopsticks Vim Configuration
A native Vim configuration optimized for engineering workflows. Designed for A native Vim configuration optimized for full-stack engineering workflows.
Vim 8.0+ with automatic fallbacks for minimal environments (TTY, no Node.js). Vim 8.0+ · Tiered LSP · TTY-aware · Zero icon fonts · 14 languages.
## Quick Install [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![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
@ -16,30 +17,31 @@ 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 environments - **TTY-aware** — Automatic detection and optimization for console/SSH 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 :Files/:GFiles | | fzf | any | Optional — enables `Ctrl+p` fuzzy search |
| ctags | any | Optional, enables :TagbarToggle | | ctags | any | Optional — enables `F8` tag browser |
--- ---
## Installation ## Installation
### Automatic ### Automatic (recommended)
```bash ```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
@ -47,22 +49,30 @@ cd ~/.vim
./install.sh ./install.sh
``` ```
The script: The installer:
1. Checks for a working Vim installation 1. Checks Vim version and detects OS / package managers
2. Backs up your existing `~/.vimrc` if present 2. Backs up any existing `~/.vimrc` (timestamped)
3. Creates a symlink: `~/.vimrc -> ~/.vim/.vimrc` 3. Creates symlinks: `~/.vimrc -> ~/.vim/.vimrc` and `~/.vim/coc-settings.json`
4. Installs vim-plug 4. Installs vim-plug and runs `:PlugInstall`
5. Runs `:PlugInstall` to download all plugins 5. Optionally installs system tools, language tools, and CoC extensions
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 vim +PlugInstall +qall </dev/null
``` ```
--- ---
@ -71,13 +81,13 @@ vim +PlugInstall +qall
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)
@ -90,12 +100,16 @@ 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-marksman " Markdown :CocInstall coc-sh " Shell
: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:
@ -104,8 +118,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, Supported languages: Python, Go, Rust, TypeScript, JavaScript, Shell, HTML,
HTML, CSS/SCSS, JSON, YAML, Markdown, SQL — via `vim-lsp-settings`. CSS/SCSS, JSON, YAML, Markdown, SQL — via `vim-lsp-settings`.
--- ---
@ -117,148 +131,144 @@ 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) | | `Ctrl+p` | Fuzzy file search (FZF — git-aware) |
| `,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) |
| `,gF` | Search git-tracked files (FZF) | | `,gF` | Search git-tracked files (FZF) |
| `,l` | Next buffer | | `,l` | Next buffer |
| `,h` | Previous buffer | | `,h` | Previous buffer |
| `,bd` | Close current buffer | | `,bd` | Close current buffer |
| `,,` | Switch to last file | | `,,` | Switch to last file |
### 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 |
| `<Leader>+` | Increase window width | | `<Leader>+` | Increase window width |
| `<Leader>_` | Decrease window width | | `<Leader>_` | Decrease window width |
| `,tn` | New tab | | `,tn` | New tab |
| `,tc` | Close tab | | `,tc` | Close tab |
| `,tl` | Toggle to last tab | | `,tl` | Toggle to last tab |
### 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 |
| `gr` | Show references | | `gr` | Show references |
| `K` | Hover documentation | | `K` | Hover documentation |
| `[g` | Previous diagnostic | | `[g` | Previous diagnostic |
| `]g` | Next diagnostic | | `]g` | Next diagnostic |
| `,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) | | `,o` | File outline |
| `,cl` | Run code lens (CoC) | | `,ws` | Workspace symbols |
| `,o` | File outline | | `,cD` | Diagnostics list |
| `,ws` | Workspace symbols | | `,cr` | Resume last CoC list |
| `,cD` | Diagnostics list | | `,qf` | Quick-fix current line (CoC) |
| `,cr` | Resume last CoC list | | `,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 |
Text objects (CoC only): `if`/`af` (function), `ic`/`ac` (class) 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 |
Signs: `X` = error, `!` = warning 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 |
| `,gl` | Git pull | | `,gl` | Git pull |
| `,gd` | Git diff | | `,gd` | Git diff |
| `,gb` | Git blame | | `,gb` | Git blame |
| `,gF` | Search git-tracked files (FZF) | | `,gF` | Search git-tracked files (FZF) |
### Engineering Utilities ### Engineering Utilities
| Key | Action | | Key | Action |
|----------|-------------------------------------| |-----|--------|
| `,ev` | Edit `~/.vimrc` | | `,ev` | Edit `~/.vimrc` |
| `,sv` | Reload `~/.vimrc` | | `,sv` | Reload `~/.vimrc` |
| `,F` | Format entire file (= indent) | | `,F` | Format entire file |
| `,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 |
| `,cp` | Copy file path to clipboard | | `,cp` | Copy file path to clipboard |
| `,cf` | Copy filename to clipboard | | `,cf` | Copy filename to clipboard |
| `,y` | Yank to system clipboard | | `,y` | Yank to system clipboard |
| `,Y` | Yank line to system clipboard | | `,Y` | Yank line to system clipboard |
| `,*` | Search+replace word under cursor | | `,*` | Search+replace word under cursor |
| `,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, 10r) | | `,th` | Open terminal (horizontal, 10 rows) |
| `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`) |
| `n` / `N` | Search next/prev (cursor centered) | | `n` / `N` | Search next/prev (cursor centered) |
| `Ctrl+d/u` | Half-page scroll (cursor centered) | | `Ctrl+d/u` | Half-page scroll (cursor centered) |
| `>` | Indent (keeps visual selection) | | `>` | Indent (keeps visual selection) |
| `<` | Dedent (keeps visual selection) | | `<` | Dedent (keeps visual selection) |
| `[q` / `]q`| Previous/next quickfix (vim-unimpaired) | | `[q` / `]q` | Previous/next quickfix (vim-unimpaired) |
| `[e` / `]e`| Previous/next ALE error/warning | | `[e` / `]e` | Previous/next ALE error/warning |
| `F2` | Toggle paste mode | | `F2` | Toggle paste mode |
| `F3` | Toggle line numbers | | `F3` | Toggle line numbers |
| `F4` | Toggle relative line numbers | | `F4` | Toggle relative line numbers |
| `F5` | Toggle undo history (UndoTree) | | `F5` | Toggle undo history (UndoTree) |
| `F8` | Toggle code tag browser (Tagbar) | | `F8` | Toggle code tag browser (Tagbar) |
| `0` | Jump to first non-blank character | | `0` | Jump to first non-blank character |
| `Alt+j/k` | Move line up/down | | `Alt+j/k` | Move line up/down |
--- ---
## Features ## Features
### vim-startify: Startup Screen ### Startup Screen (vim-startify)
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-which-key: Keybinding Guide **`vim .` layout** — NERDTree on the left, Startify on the right.
### 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
@ -266,8 +276,8 @@ Markdown, help).
:Obsess! " Stop tracking :Obsess! " Stop tracking
``` ```
Sessions are stored in `~/.vim/sessions/` and automatically resumed by Sessions stored in `~/.vim/sessions/` and automatically resumed by vim-prosession
vim-prosession on the next Vim launch in the same directory. on the next Vim launch in the same directory.
### Project-Local Config ### Project-Local Config
@ -283,91 +293,88 @@ Loaded automatically. Security-restricted via `set secure`.
### Large File Handling ### Large File Handling
Files over 10MB automatically disable syntax highlighting and undo history Files over 10 MB automatically disable syntax highlighting and undo history
to prevent Vim from freezing. to prevent Vim from freezing.
### TTY / Console Support ### TTY / Console Support
Detected automatically when `$TERM` is `linux` or `screen`, or when running Detected automatically when `$TERM` is `linux` or `screen`. In TTY mode:
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 used - Simpler status line
--- ---
## Language Support ## Language Support
| Language | Indent | Formatter | Linter | | Language | Indent | Formatter | Linter | LSP (CoC) |
|----------------|--------|------------------|--------------------------| |----------|--------|-----------|--------|-----------|
| Python | 4sp | black + isort | flake8, pylint | | Python | 4sp | black + isort | flake8, pylint | coc-pyright |
| JavaScript | 2sp | prettier | eslint | | JavaScript | 2sp | prettier | eslint | coc-tsserver |
| TypeScript | 2sp | prettier | eslint, tsserver | | TypeScript | 2sp | prettier | eslint, tsserver | coc-tsserver |
| Go | tab | gofmt, goimports | gopls, golint | | Go | tab | gofmt, goimports | staticcheck | coc-go |
| Rust | 4sp | rustfmt | cargo | | Rust | 4sp | rustfmt | cargo | coc-rust-analyzer |
| Shell | 2sp | - | shellcheck | | Shell | 2sp | — | shellcheck | coc-sh |
| YAML | 2sp | prettier | yamllint | | YAML | 2sp | prettier | yamllint | coc-yaml |
| HTML | 2sp | prettier | - | | HTML | 2sp | prettier | — | coc-html |
| CSS / SCSS | 2sp | prettier | stylelint | | CSS / SCSS | 2sp | prettier | stylelint | coc-css |
| Less | 2sp | prettier | - | | Less | 2sp | prettier | — | — |
| JSON | 2sp | prettier | - | | JSON | 2sp | prettier | — | coc-json |
| Markdown | 2sp | prettier | markdownlint | | Markdown | 2sp | prettier | markdownlint | marksman (coc-settings.json) |
| SQL | 4sp | sqlfmt | sqlfluff | | SQL | 4sp | sqlfluff | sqlfluff | — |
| Dockerfile | 2sp | - | hadolint | | Dockerfile | 2sp | — | hadolint | — |
Install linters separately — `install.sh` lists the exact commands. `install.sh` installs all linters and formatters automatically.
ALE runs them asynchronously on save (`ale_fix_on_save = 1` when using CoC). ALE runs them asynchronously; format-on-save active when using CoC.
--- ---
## Plugin List ## Plugin List
### Navigation ### Navigation
- **NERDTree** - File tree explorer - **NERDTree** — File tree explorer
- **fzf + fzf.vim** - Fuzzy finder - **fzf + fzf.vim** — Fuzzy finder (file, buffer, tag, ripgrep)
- **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 - **vim-startify** — Startup screen with sessions
- **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 - **vim-go** — Go development tools (formatting + highlighting; LSP handled by coc-go)
### 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**
@ -400,6 +407,14 @@ 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
@ -408,8 +423,7 @@ node --version # must be >= 14.14
**Colors look wrong:** **Colors look wrong:**
```bash ```bash
# Add to ~/.bashrc or ~/.zshrc export TERM=xterm-256color # add to ~/.bashrc or ~/.zshrc
export TERM=xterm-256color
``` ```
**ALE not finding linters:** **ALE not finding linters:**
@ -421,12 +435,18 @@ 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 [MIT](LICENSE) © m1ng

13
coc-settings.json Normal file
View file

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

View file

@ -93,13 +93,28 @@ HAS_BREW=0; command -v brew >/dev/null 2>&1 && HAS_BREW=1
HAS_APT=0; command -v apt >/dev/null 2>&1 && HAS_APT=1 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_PIP=0; command -v pip3 >/dev/null 2>&1 && HAS_PIP=1 && ok "Python/pip3 detected" HAS_PYTHON=0; command -v python3 >/dev/null 2>&1 && HAS_PYTHON=1
HAS_GO=0; command -v go >/dev/null 2>&1 && HAS_GO=1 && ok "Go $(go version | awk '{print $3}') 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_NODE -eq 0 ]] && warn "Node.js not found — JS/TS/Markdown npm tools will be skipped" # Bootstrap pip3 when python3 exists but pip3 is absent (common on Ubuntu minimal images)
[[ $HAS_PIP -eq 0 ]] && warn "pip3 not found — Python tools will be skipped" if [[ $HAS_PYTHON -eq 1 && $HAS_PIP -eq 0 ]]; then
[[ $HAS_GO -eq 0 ]] && warn "Go not found — Go tools will be skipped" 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_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"
# ============================================================================ # ============================================================================
# Symlink # Symlink
@ -116,6 +131,17 @@ 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
# ============================================================================ # ============================================================================
@ -132,7 +158,8 @@ else
fi fi
step "Installing Vim plugins" step "Installing Vim plugins"
vim +PlugInstall +qall # </dev/null prevents Vim from reading stdin in non-interactive/piped environments
vim +PlugInstall +qall </dev/null
ok "Plugins installed" ok "Plugins installed"
# ============================================================================ # ============================================================================
@ -141,7 +168,7 @@ ok "Plugins installed"
step "System tools" step "System tools"
if ask "Install system tools (ripgrep, fzf, ctags, shellcheck, marksman)?"; then if ask "Install system tools (ripgrep, fzf, ctags, shellcheck, hadolint, 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
@ -163,17 +190,36 @@ if ask "Install system tools (ripgrep, fzf, ctags, shellcheck, marksman)?"; then
if [[ $OS == macos ]]; then if [[ $OS == macos ]]; then
command -v brew >/dev/null 2>&1 || { warn "brew not found — skipping system tools"; } command -v brew >/dev/null 2>&1 || { warn "brew not found — skipping system tools"; }
install_sys "ripgrep" rg "brew install ripgrep" install_sys "ripgrep" rg "brew install ripgrep"
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 "marksman" marksman "brew install marksman" install_sys "hadolint" hadolint "brew install hadolint"
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
install_sys "ripgrep" rg "sudo apt-get install -y ripgrep" install_sys "ripgrep" rg "sudo apt-get install -y ripgrep"
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)
@ -192,21 +238,30 @@ if ask "Install system tools (ripgrep, fzf, ctags, shellcheck, marksman)?"; then
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" "marksman") SKIPPED+=("ripgrep" "fzf" "ctags" "shellcheck" "hadolint" "marksman")
fi fi
else else
skip "system tools" skip "system tools"
SKIPPED+=("ripgrep" "fzf" "ctags" "shellcheck" "marksman") SKIPPED+=("ripgrep" "fzf" "ctags" "shellcheck" "hadolint" "marksman")
fi fi
# ============================================================================ # ============================================================================
@ -237,7 +292,6 @@ 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")
@ -254,7 +308,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, sqlfluff)?"; then if ask "Install Python tools (black, isort, flake8, pylint, yamllint, 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
@ -274,24 +328,25 @@ 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" "sqlfluff") SKIPPED+=("black" "isort" "flake8" "pylint" "yamllint" "sqlfluff")
fi fi
else else
skip "Python tools (pip3 not installed)" skip "Python tools (pip3 not installed)"
SKIPPED+=("black" "isort" "flake8" "pylint" "sqlfluff") SKIPPED+=("black" "isort" "flake8" "pylint" "yamllint" "sqlfluff")
fi fi
# ============================================================================ # ============================================================================
# Go tools (gopls, goimports) # Go tools (gopls, goimports, staticcheck)
# ============================================================================ # ============================================================================
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)?"; then if ask "Install Go tools (gopls, goimports, staticcheck)?"; 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"
@ -310,8 +365,9 @@ if [[ $HAS_GO -eq 1 ]]; then
FAILED+=("$name") FAILED+=("$name")
fi fi
} }
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
@ -319,11 +375,11 @@ if [[ $HAS_GO -eq 1 ]]; then
fi fi
else else
skip "Go tools" skip "Go tools"
SKIPPED+=("gopls" "goimports") SKIPPED+=("gopls" "goimports" "staticcheck")
fi fi
else else
skip "Go tools (go not installed)" skip "Go tools (go not installed)"
SKIPPED+=("gopls" "goimports") SKIPPED+=("gopls" "goimports" "staticcheck")
fi fi
# ============================================================================ # ============================================================================
@ -334,7 +390,8 @@ 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
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 # 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-sql' +qall </dev/null
ok "CoC language servers installed" ok "CoC language servers installed"
else else
skip "CoC language servers" skip "CoC language servers"