Compare commits

...

3 commits

Author SHA1 Message Date
5604eddbdb fix: remaining usability and design improvements
.vimrc:
- Remove path+=** (hangs on large repos with node_modules)
- Add plugin guards for FZF, Git, ALE, Markdown, EasyMotion, UndoTree
  mappings (prevent E492 when plugins not loaded)
- Replace SmartFiles system() subprocess with isdirectory/finddir
  (no more synchronous fork on every Ctrl+p)
- Remove duplicate SLDefineColors VimEnter call (ColorScheme alone suffices)
- Convert all remaining nmap/map to nnoremap/noremap (eliminate recursive
  mapping risk and visual/operator-pending mode contamination)
- Expand cheat sheet with spell checking, utilities, window resize,
  F-key toggles, EasyMotion line motions, buffer management

get.sh:
- Support NO_COLOR and non-TTY output
- Show version tag or commit hash after clone/pull

QUICKSTART.md:
- Warn about first-launch plugin install (30-60s wait)
- Note that some language servers need Node.js
2026-04-15 10:15:07 +08:00
233ceabf53 fix: usability and design improvements across .vimrc, install.sh, README
.vimrc:
- Remove global eventignore+=FileType corruption in large file handler
- Add t_8f/t_8b for tmux true color support
- Fix vnoremap J/K shadowing built-in J (join); use Alt+j/k in visual mode
- Replace map with nnoremap for buffer/tab/spell/misc mappings (prevents
  visual/operator-pending mode contamination)
- Change BufEnter to FileType for formatoptions (fires less frequently)
- Remove duplicate whitespace trim (ALE already handles it via fix_on_save)
- Guard <leader>so to only source vim files
- Guard <leader>cp/<leader>cf with has('clipboard')
- Add completeopt=popup for floating completion docs (Vim 8.1.1517+)
- Change Startify header from "MINGSAMA" to "chopsticks"
- Make Startify bookmarks conditional (only show shell rc files that exist)
- EasyMotion <Leader>j/k: map → nmap (prevent visual mode leak)
- Move-line: nnoremap instead of nmap for normal mode variant

install.sh:
- Add --help flag
- Support NO_COLOR and non-TTY output (no ANSI codes when redirected)
- Include $BASH_COMMAND in ERR trap for better debugging
- Use mktemp for secure temp files instead of predictable /tmp paths
- Warn user when pip falls back to --break-system-packages

README:
- Add missing mappings: jk, F2-F6, gV, //, ,ev, ,sv, ,cp, ,cf, ,*, ,F, ,W, ,ms, ,ss
- Note that some language servers require Node.js even though vim-lsp doesn't
- Clarify Alt+j/k works in both normal and visual mode
2026-04-15 10:08:10 +08:00
0ba2e84e0c fix: correct 13 bugs across .vimrc, install.sh, and docs
.vimrc:
- Fix syntax=OFF no-op in large file handler (syntax= is correct)
- Fix <leader>rG broken -F flag (new RgWord command with -F before --)
- Fix :Gdiff → :Gdiffsplit (fugitive v3+ compat)
- Fix go_def_mode/go_info_mode conflicting with go_gopls_enabled=0
- Fix <leader>m prefix collision with mt/mp (renamed to <leader>ms)
- Wrap PlugInstall autocmd in augroup (prevent doubling on re-source)

install.sh:
- Guard against empty version string in hadolint/marksman downloads
- Add HAS_SUDO check in _do_binary_apt before sudo mv
- Add PlugClean warning when existing plugins directory is non-empty
- Fix pkg_install brew-first priority (macOS-only now, Linux fallback)
- Fix menu double-draw flicker on first render
- Fix Fedora deselected tools not tracked in SKIPPED array

docs:
- Remove nonexistent nvm install step from README
- Fix TOC description (side window, not quickfix) in README/QUICKSTART
- Fix TTY detection description (add dumb, empty, builtin)
- Add missing ,cd and ,wa mappings to README
- Remove dead CoC formatOnSaveFiletypes from coc-settings.json
2026-04-15 09:57:26 +08:00
6 changed files with 284 additions and 146 deletions

236
.vimrc
View file

@ -44,7 +44,7 @@ set wildmode=list:longest
set wildignorecase set wildignorecase
set wildignore=*.docx,*.jpg,*.png,*.gif,*.pdf,*.pyc,*.exe,*.flv,*.img,*.xlsx set wildignore=*.docx,*.jpg,*.png,*.gif,*.pdf,*.pyc,*.exe,*.flv,*.img,*.xlsx
set wildignore+=*/node_modules/*,*/.git/*,*/__pycache__/*,*/dist/*,*/build/* set wildignore+=*/node_modules/*,*/.git/*,*/__pycache__/*,*/dist/*,*/build/*
set path+=** " path+=** removed: hangs on large repos (node_modules); use Ctrl+p (FZF) instead
set mouse=a set mouse=a
set encoding=utf-8 set encoding=utf-8
set foldmethod=indent set foldmethod=indent
@ -96,7 +96,10 @@ let data_dir = has('nvim') ? stdpath('data') . '/site' : '~/.vim'
if empty(glob(data_dir . '/autoload/plug.vim')) if empty(glob(data_dir . '/autoload/plug.vim'))
silent execute '!curl -fLo '.data_dir.'/autoload/plug.vim --create-dirs ' silent execute '!curl -fLo '.data_dir.'/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'
autocmd VimEnter * PlugInstall --sync | source $MYVIMRC augroup PlugBootstrap
autocmd!
autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
augroup END
endif endif
call plug#begin('~/.vim/plugged') call plug#begin('~/.vim/plugged')
@ -157,6 +160,9 @@ call plug#end()
" ============================================================================ " ============================================================================
if g:has_true_color && has('termguicolors') && !g:is_tty if g:has_true_color && has('termguicolors') && !g:is_tty
" Required for true color inside tmux
let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
set termguicolors set termguicolors
endif endif
@ -208,42 +214,42 @@ set smartindent
let mapleader = "," let mapleader = ","
" Saving / quitting " Saving / quitting
nmap <leader>w :w!<cr> nnoremap <leader>w :w!<cr>
nmap <leader>q :q<cr> nnoremap <leader>q :q<cr>
nmap <leader>x :x<cr> nnoremap <leader>x :x<cr>
" Clear search highlight " Clear search highlight
map <silent> <leader><cr> :noh<cr> nnoremap <silent> <leader><cr> :noh<cr>
" Buffer navigation " Buffer navigation
map <leader>bd :Bclose<cr> nnoremap <leader>bd :Bclose<cr>
map <leader>ba :bufdo bd<cr> nnoremap <leader>ba :bufdo bd<cr>
map <leader>l :bnext<cr> nnoremap <leader>l :bnext<cr>
map <leader>h :bprevious<cr> nnoremap <leader>h :bprevious<cr>
" Tab management " Tab management
map <leader>tn :tabnew<cr> nnoremap <leader>tn :tabnew<cr>
map <leader>to :tabonly<cr> nnoremap <leader>to :tabonly<cr>
map <leader>tc :tabclose<cr> nnoremap <leader>tc :tabclose<cr>
map <leader>tm :tabmove nnoremap <leader>tm :tabmove
map <leader>t<leader> :tabnext<cr> nnoremap <leader>t<leader> :tabnext<cr>
let g:lasttab = 1 let g:lasttab = 1
nmap <Leader>tl :exe "tabn ".g:lasttab<CR> nnoremap <Leader>tl :exe "tabn ".g:lasttab<CR>
augroup ChopstickTabHistory augroup ChopstickTabHistory
autocmd! autocmd!
autocmd TabLeave * let g:lasttab = tabpagenr() autocmd TabLeave * let g:lasttab = tabpagenr()
augroup END augroup END
map <leader>te :tabedit <C-r>=expand("%:p:h")<cr>/ nnoremap <leader>te :tabedit <C-r>=expand("%:p:h")<cr>/
map <leader>cd :lcd %:p:h<cr>:pwd<cr> nnoremap <leader>cd :lcd %:p:h<cr>:pwd<cr>
" File browser (netrw — built-in, no plugins) " File browser (netrw — built-in, no plugins)
nnoremap <leader>e :Explore<CR> nnoremap <leader>e :Explore<CR>
nnoremap <leader>E :Vexplore<CR> nnoremap <leader>E :Vexplore<CR>
" Remap 0 to first non-blank " Remap 0 to first non-blank (all modes intentional)
map 0 ^ noremap 0 ^
" Reselect last paste " Reselect last paste
nnoremap gV `[v`] nnoremap gV `[v`]
@ -252,18 +258,18 @@ nnoremap gV `[v`]
cnoremap <C-p> <Up> cnoremap <C-p> <Up>
cnoremap <C-n> <Down> cnoremap <C-n> <Down>
" Move lines " Move lines (Alt+j / Alt+k in both normal and visual mode)
nmap <M-j> mz:m+<cr>`z nnoremap <M-j> :m .+1<CR>==
nmap <M-k> mz:m-2<cr>`z nnoremap <M-k> :m .-2<CR>==
vnoremap J :m '>+1<CR>gv=gv vnoremap <M-j> :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv vnoremap <M-k> :m '<-2<CR>gv=gv
" Spell checking " Spell checking
map <leader>ss :setlocal spell!<cr> nnoremap <leader>ss :setlocal spell!<cr>
map <leader>sn ]s nnoremap <leader>sn ]s
map <leader>sp [s nnoremap <leader>sp [s
map <leader>sa zg nnoremap <leader>sa zg
map <leader>s? z= nnoremap <leader>s? z=
" Toggle modes " Toggle modes
set pastetoggle=<F2> set pastetoggle=<F2>
@ -348,19 +354,21 @@ let g:netrw_list_hide .= ',\.pyc$,node_modules,\.git,__pycache__,\.DS_Store'
" Ctrl+p: git-aware file search (GFiles inside repo, Files outside) " Ctrl+p: git-aware file search (GFiles inside repo, Files outside)
function! s:SmartFiles() abort function! s:SmartFiles() abort
if !empty(system('git rev-parse --show-toplevel 2>/dev/null')) if isdirectory('.git') || finddir('.git', '.;') !=# ''
GFiles GFiles
else else
Files Files
endif endif
endfunction endfunction
map <C-p> :call <SID>SmartFiles()<CR> if exists('g:plugs["fzf.vim"]')
map <leader>b :Buffers<CR> nnoremap <C-p> :call <SID>SmartFiles()<CR>
map <leader>rg :Rg<CR> nnoremap <leader>b :Buffers<CR>
map <leader>rG :Rg -F <C-r><C-w><CR> nnoremap <leader>rg :Rg<CR>
map <leader>rt :Tags<CR> nnoremap <leader>rG :RgWord<CR>
map <leader>gF :GFiles<CR> nnoremap <leader>rt :Tags<CR>
nnoremap <leader>gF :GFiles<CR>
endif
let g:fzf_layout = { 'down': '40%' } let g:fzf_layout = { 'down': '40%' }
@ -384,6 +392,19 @@ else
command! -bang GFiles call fzf#vim#gitfiles('', fzf#vim#with_preview(), <bang>0) command! -bang GFiles call fzf#vim#gitfiles('', fzf#vim#with_preview(), <bang>0)
endif endif
" RgWord: fixed-string search for word under cursor (flags before --)
if g:is_tty
command! -bang -nargs=* RgWord
\ call fzf#vim#grep(
\ 'rg --column --line-number --no-heading --color=always --smart-case -F -- '
\ .shellescape(expand('<cword>')), 1, <bang>0)
else
command! -bang -nargs=* RgWord
\ call fzf#vim#grep(
\ 'rg --column --line-number --no-heading --color=always --smart-case -F -- '
\ .shellescape(expand('<cword>')), 1, fzf#vim#with_preview(), <bang>0)
endif
" ============================================================================ " ============================================================================
" => GitGutter " => GitGutter
" ============================================================================ " ============================================================================
@ -439,9 +460,11 @@ let g:ale_lint_on_text_changed = 'normal'
let g:ale_lint_on_insert_leave = 1 let g:ale_lint_on_insert_leave = 1
let g:ale_lint_on_enter = 1 let g:ale_lint_on_enter = 1
nmap <silent> [e :ALEPrevious<cr> if exists('g:plugs["ale"]')
nmap <silent> ]e :ALENext<cr> nnoremap <silent> [e :ALEPrevious<cr>
nmap <silent> <leader>aD :ALEDetail<cr> nnoremap <silent> ]e :ALENext<cr>
nnoremap <silent> <leader>aD :ALEDetail<cr>
endif
" ============================================================================ " ============================================================================
" => vim-go " => vim-go
@ -450,8 +473,8 @@ nmap <silent> <leader>aD :ALEDetail<cr>
" vim-lsp (gopls) handles all Go intelligence; disable vim-go's own LSP layer " vim-lsp (gopls) handles all Go intelligence; disable vim-go's own LSP layer
let g:go_gopls_enabled = 0 let g:go_gopls_enabled = 0
let g:go_code_completion_enabled = 0 let g:go_code_completion_enabled = 0
let g:go_def_mode = 'gopls' let g:go_def_mode = 'godef'
let g:go_info_mode = 'gopls' let g:go_info_mode = 'godef'
let g:go_fmt_autosave = 0 " ALE handles format-on-save let g:go_fmt_autosave = 0 " ALE handles format-on-save
let g:go_imports_autosave = 0 let g:go_imports_autosave = 0
let g:go_highlight_types = 1 let g:go_highlight_types = 1
@ -490,7 +513,11 @@ let g:lsp_signs_warning = {'text': '!'}
let g:lsp_signs_information = {'text': 'i'} let g:lsp_signs_information = {'text': 'i'}
let g:lsp_signs_hint = {'text': '>'} let g:lsp_signs_hint = {'text': '>'}
set completeopt=menuone,noinsert,noselect if has('patch-8.1.1517')
set completeopt=menuone,noinsert,noselect,popup
else
set completeopt=menuone,noinsert,noselect
endif
set pumheight=15 set pumheight=15
let g:asyncomplete_auto_popup = 1 let g:asyncomplete_auto_popup = 1
let g:asyncomplete_auto_completeopt = 1 let g:asyncomplete_auto_completeopt = 1
@ -550,15 +577,19 @@ let g:vim_markdown_follow_anchor = 1
let g:vim_markdown_new_list_item_indent = 2 let g:vim_markdown_new_list_item_indent = 2
let g:vim_markdown_strikethrough = 1 let g:vim_markdown_strikethrough = 1
" Table of contents in quickfix " Table of contents (side window)
nnoremap <leader>mt :Toc<CR> if exists('g:plugs["vim-markdown"]')
nnoremap <leader>mt :Toc<CR>
endif
" ============================================================================ " ============================================================================
" => previm (Markdown browser preview) " => previm (Markdown browser preview)
" ============================================================================ " ============================================================================
" <leader>mp open live-reloading preview in browser " <leader>mp open live-reloading preview in browser
nnoremap <leader>mp :PrevimOpen<CR> if exists('g:plugs["previm"]')
nnoremap <leader>mp :PrevimOpen<CR>
endif
let g:previm_enable_realtime = 1 let g:previm_enable_realtime = 1
" ============================================================================ " ============================================================================
@ -568,19 +599,22 @@ let g:previm_enable_realtime = 1
let g:EasyMotion_do_mapping = 0 let g:EasyMotion_do_mapping = 0
let g:EasyMotion_smartcase = 1 let g:EasyMotion_smartcase = 1
" s + two chars: jump anywhere on screen if exists('g:plugs["vim-easymotion"]')
nmap s <Plug>(easymotion-overwin-f2) " s + two chars: jump anywhere on screen
nmap s <Plug>(easymotion-overwin-f2)
" J/K: line motions " Line motions
map <Leader>j <Plug>(easymotion-j) nmap <Leader>j <Plug>(easymotion-j)
map <Leader>k <Plug>(easymotion-k) nmap <Leader>k <Plug>(easymotion-k)
endif
" ============================================================================ " ============================================================================
" => UndoTree " => UndoTree
" ============================================================================ " ============================================================================
nnoremap <F5> :UndotreeToggle<CR> if exists('g:plugs["undotree"]')
nnoremap <leader>u :UndotreeToggle<CR> nnoremap <F5> :UndotreeToggle<CR>
nnoremap <leader>u :UndotreeToggle<CR>
endif
" ============================================================================ " ============================================================================
" => IndentLine (non-TTY only) " => IndentLine (non-TTY only)
@ -604,12 +638,12 @@ endif
if exists('g:plugs["vim-startify"]') if exists('g:plugs["vim-startify"]')
let g:startify_custom_header = [ let g:startify_custom_header = [
\ ' ███╗ ███╗ ██╗███╗ ██╗ ██████╗ ███████╗ █████╗ ███╗ ███╗ █████╗ ', \ ' ██████╗██╗ ██╗ ██████╗ ██████╗ ███████╗████████╗██╗ ██████╗██╗ ██╗███████╗',
\ ' ████╗ ████║███║████╗ ██║██╔════╝ ██╔════╝██╔══██╗████╗ ████║██╔══██╗ ', \ ' ██╔════╝██║ ██║██╔═══██╗██╔══██╗██╔════╝╚══██╔══╝██║██╔════╝██║ ██╔╝██╔════╝',
\ ' ██╔████╔██║╚██║██╔██╗ ██║██║ ███╗███████╗███████║██╔████╔██║███████║ ', \ ' ██║ ███████║██║ ██║██████╔╝███████╗ ██║ ██║██║ █████╔╝ ███████╗',
\ ' ██║╚██╔╝██║ ██║██║╚██╗██║██║ ██║╚════██║██╔══██║██║╚██╔╝██║██╔══██║ ', \ ' ██║ ██╔══██║██║ ██║██╔═══╝ ╚════██║ ██║ ██║██║ ██╔═██╗ ╚════██║',
\ ' ██║ ╚═╝ ██║ ██║██║ ╚████║╚██████╔╝███████║██║ ██║██║ ╚═╝ ██║██║ ██║ ', \ ' ╚██████╗██║ ██║╚██████╔╝██║ ███████║ ██║ ██║╚██████╗██║ ██╗███████║',
\ ' ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝', \ ' ╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝',
\ '', \ '',
\ ] \ ]
@ -620,11 +654,16 @@ if exists('g:plugs["vim-startify"]')
\ { 'type': 'bookmarks', 'header': [' Bookmarks'] }, \ { 'type': 'bookmarks', 'header': [' Bookmarks'] },
\ ] \ ]
let g:startify_bookmarks = [ let g:startify_bookmarks = [{'v': '~/.vimrc'}]
\ {'v': '~/.vimrc'}, if filereadable(expand('~/.zshrc'))
\ {'z': '~/.zshrc'}, call add(g:startify_bookmarks, {'z': '~/.zshrc'})
\ {'b': '~/.bashrc'}, endif
\ ] if filereadable(expand('~/.bashrc'))
call add(g:startify_bookmarks, {'b': '~/.bashrc'})
endif
if filereadable(expand('~/.config/fish/config.fish'))
call add(g:startify_bookmarks, {'f': '~/.config/fish/config.fish'})
endif
let g:startify_session_persistence = 1 let g:startify_session_persistence = 1
let g:startify_session_autoload = 1 let g:startify_session_autoload = 1
@ -685,7 +724,6 @@ endfunction
augroup SLColors augroup SLColors
autocmd! autocmd!
autocmd ColorScheme * call s:SLDefineColors() autocmd ColorScheme * call s:SLDefineColors()
autocmd VimEnter * call s:SLDefineColors()
augroup END augroup END
" Current mode → [label, highlight-group] " Current mode → [label, highlight-group]
@ -781,7 +819,7 @@ endfunc
" Suppress comment continuation on Enter / o / O " Suppress comment continuation on Enter / o / O
augroup ChopstickFormatOptions augroup ChopstickFormatOptions
autocmd! autocmd!
autocmd BufEnter * setlocal formatoptions-=c formatoptions-=r formatoptions-=o autocmd FileType * setlocal formatoptions-=c formatoptions-=r formatoptions-=o
augroup END augroup END
" Auto-disable paste mode on leaving insert " Auto-disable paste mode on leaving insert
@ -790,13 +828,6 @@ augroup ChopstickPaste
autocmd InsertLeave * set nopaste autocmd InsertLeave * set nopaste
augroup END augroup END
" Strip trailing whitespace on save (real files only)
augroup ChopstickCleanup
autocmd!
autocmd BufWritePre *
\ if empty(&buftype) && !empty(expand('<afile>')) | call CleanExtraSpaces() | endif
augroup END
augroup ChopstickFiletype augroup ChopstickFiletype
autocmd! autocmd!
@ -891,7 +922,7 @@ nnoremap <leader><leader> <c-^>
nnoremap <leader>W :%s/\s\+$//<CR>:let @/=''<CR> nnoremap <leader>W :%s/\s\+$//<CR>:let @/=''<CR>
" Source helpers " Source helpers
nnoremap <leader>so :source %<CR> nnoremap <leader>so :if &filetype ==# 'vim' <Bar> source % <Bar> echo "Sourced " . expand('%') <Bar> else <Bar> echo "Not a vim file" <Bar> endif<CR>
nnoremap <leader>ev :edit $MYVIMRC<CR> nnoremap <leader>ev :edit $MYVIMRC<CR>
nnoremap <leader>sv :source $MYVIMRC<CR>:echo "vimrc reloaded"<CR> nnoremap <leader>sv :source $MYVIMRC<CR>:echo "vimrc reloaded"<CR>
@ -899,11 +930,13 @@ nnoremap <leader>sv :source $MYVIMRC<CR>:echo "vimrc reloaded"<CR>
nnoremap <leader>* :%s/\<<C-r><C-w>\>//g<Left><Left> nnoremap <leader>* :%s/\<<C-r><C-w>\>//g<Left><Left>
" Copy path / filename to clipboard " Copy path / filename to clipboard
nnoremap <leader>cp :let @+ = expand("%:p")<CR>:echo "Copied: " . expand("%:p")<CR> if has('clipboard')
nnoremap <leader>cf :let @+ = expand("%:t")<CR>:echo "Copied: " . expand("%:t")<CR> nnoremap <leader>cp :let @+ = expand("%:p")<CR>:echo "Copied: " . expand("%:p")<CR>
nnoremap <leader>cf :let @+ = expand("%:t")<CR>:echo "Copied: " . expand("%:t")<CR>
endif
" Scratch markdown buffer " Scratch markdown buffer
map <leader>m :e ~/buffer.md<cr> nnoremap <leader>ms :e ~/buffer.md<cr>
" Auto-create parent directories on save " Auto-create parent directories on save
function! s:MkNonExDir(file, buf) function! s:MkNonExDir(file, buf)
@ -926,12 +959,14 @@ augroup END
" => Git Shortcuts " => Git Shortcuts
" ============================================================================ " ============================================================================
nnoremap <leader>gs :Git status<CR> if exists('g:plugs["vim-fugitive"]')
nnoremap <leader>gc :Git commit<CR> nnoremap <leader>gs :Git status<CR>
nnoremap <leader>gp :Git push<CR> nnoremap <leader>gc :Git commit<CR>
nnoremap <leader>gl :Git pull<CR> nnoremap <leader>gp :Git push<CR>
nnoremap <leader>gd :Gdiff<CR> nnoremap <leader>gl :Git pull<CR>
nnoremap <leader>gb :Git blame<CR> nnoremap <leader>gd :Gdiffsplit<CR>
nnoremap <leader>gb :Git blame<CR>
endif
" ============================================================================ " ============================================================================
" => Terminal Integration " => Terminal Integration
@ -965,9 +1000,8 @@ augroup END
function! LargeFileSettings() function! LargeFileSettings()
setlocal bufhidden=unload setlocal bufhidden=unload
setlocal undolevels=-1 setlocal undolevels=-1
setlocal eventignore+=FileType
setlocal noswapfile setlocal noswapfile
setlocal syntax=OFF setlocal syntax=
let b:ale_enabled = 0 let b:ale_enabled = 0
echo "Large file (>10 MB): syntax, undo, and linting disabled." echo "Large file (>10 MB): syntax, undo, and linting disabled."
endfunction endfunction
@ -977,7 +1011,7 @@ if g:is_tty
autocmd! autocmd!
autocmd BufReadPre * autocmd BufReadPre *
\ if !empty(expand('<afile>')) && getfsize(expand('<afile>')) > 512000 | \ if !empty(expand('<afile>')) && getfsize(expand('<afile>')) > 512000 |
\ setlocal syntax=OFF | \ setlocal syntax= |
\ endif \ endif
augroup END augroup END
@ -1051,9 +1085,20 @@ function! s:CheatSheet() abort
\ 'EDITING', \ 'EDITING',
\ ' gc Toggle comment (visual mode too)', \ ' gc Toggle comment (visual mode too)',
\ ' s + 2 chars EasyMotion — jump anywhere on screen', \ ' s + 2 chars EasyMotion — jump anywhere on screen',
\ ' ,u Undo tree (visual branch history)', \ ' ,j / ,k EasyMotion — line motions',
\ ' ,u / F5 Undo tree (visual branch history)',
\ ' ,y / ,Y Yank / yank line to system clipboard', \ ' ,y / ,Y Yank / yank line to system clipboard',
\ ' ,p / ,P Paste from system clipboard (after / before)', \ ' ,p / ,P Paste from system clipboard',
\ ' Alt+j / Alt+k Move line down / up (also visual mode)',
\ ' ,F Re-indent entire file',
\ ' ,W Strip trailing whitespace',
\ ' ,* Search and replace word under cursor',
\ '',
\ 'SPELLING',
\ ' ,ss Toggle spell checking',
\ ' ,sn / ,sp Next / prev misspelling',
\ ' ,sa Add word to dictionary',
\ ' ,s? Suggest corrections',
\ '', \ '',
\ 'GIT', \ 'GIT',
\ ' ,gs Status ,gd Diff ,gb Blame', \ ' ,gs Status ,gd Diff ,gb Blame',
@ -1062,8 +1107,19 @@ function! s:CheatSheet() abort
\ 'WINDOWS & PANES', \ 'WINDOWS & PANES',
\ ' Ctrl+h/j/k/l Navigate Vim splits and tmux panes', \ ' Ctrl+h/j/k/l Navigate Vim splits and tmux panes',
\ ' ,h / ,l Prev / next buffer', \ ' ,h / ,l Prev / next buffer',
\ ' ,bd Close buffer (keep layout)',
\ ' ,tn / ,tc New tab / close tab | ,tl Last tab',
\ ' ,tv / ,th Open terminal (vertical / horizontal)', \ ' ,tv / ,th Open terminal (vertical / horizontal)',
\ ' Esc Esc Exit terminal mode', \ ' Esc Esc Exit terminal mode',
\ ' ,= / ,- Resize height (grow / shrink)',
\ ' ,+ / ,_ Resize width (grow / shrink)',
\ '',
\ 'UTILITIES',
\ ' ,ev / ,sv Edit / reload ~/.vimrc',
\ ' ,cp / ,cf Copy file path / filename to clipboard',
\ ' ,ms Open scratch markdown buffer',
\ ' ,cd Change CWD to current file directory',
\ ' F2 Paste F3 Line# F4 Relative# F6 Invisible',
\ '', \ '',
\ 'SESSION', \ 'SESSION',
\ ' :Obsess Start tracking session', \ ' :Obsess Start tracking session',
@ -1081,7 +1137,7 @@ nnoremap <silent> <leader>? :call <SID>CheatSheet()<CR>
" ============================================================================ " ============================================================================
" Show syntax highlight stack for word under cursor " Show syntax highlight stack for word under cursor
nmap <leader>sh :call <SID>SynStack()<CR> nnoremap <leader>sh :call <SID>SynStack()<CR>
function! <SID>SynStack() function! <SID>SynStack()
if !exists("*synstack") | return | endif if !exists("*synstack") | return | endif
echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")') echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')

View file

@ -56,6 +56,10 @@ vim . # startup dashboard, current directory listed
vim myfile # edit a specific file vim myfile # edit a specific file
``` ```
> **First launch:** Vim will automatically install plugins on the first open
> (takes 3060 seconds depending on network). This is normal — wait for it
> to finish, then restart Vim.
--- ---
## Step 3: Set Up LSP ## Step 3: Set Up LSP
@ -67,7 +71,9 @@ Open a source file, then run:
``` ```
This auto-detects the filetype and installs the correct language server. This auto-detects the filetype and installs the correct language server.
No Node.js required — vim-lsp runs on pure VimScript. vim-lsp itself runs on pure VimScript — no Node.js required. However,
some language servers (JS/TS, HTML, CSS, JSON, YAML) are npm packages
that need Node.js to run. Python, Go, and Rust servers don't need it.
Check status: Check status:
```vim ```vim
@ -142,7 +148,7 @@ K Show documentation
| Key | Action | | Key | Action |
|-----|--------| |-----|--------|
| `,mp` | Open live preview in browser | | `,mp` | Open live preview in browser |
| `,mt` | Table of contents | | `,mt` | Table of contents (side window) |
| `zr` / `zm` | Unfold / fold all headings | | `zr` / `zm` | Unfold / fold all headings |
Formatting in the buffer is live: `**bold**` renders as bold, Formatting in the buffer is live: `**bold**` renders as bold,

View file

@ -86,11 +86,10 @@ cd ~/.vim && ./install.sh
3. Backs up existing `~/.vimrc`, then symlinks `~/.vimrc → ~/.vim/.vimrc` 3. Backs up existing `~/.vimrc`, then symlinks `~/.vimrc → ~/.vim/.vimrc`
4. Installs vim-plug and runs `:PlugInstall` 4. Installs vim-plug and runs `:PlugInstall`
5. Offers to install system tools (ripgrep, fzf, ctags, shellcheck, hadolint, marksman) 5. Offers to install system tools (ripgrep, fzf, ctags, shellcheck, hadolint, marksman)
6. Offers to install Node.js via nvm (for npm formatters — optional) 6. Offers to install npm formatters (prettier, eslint, etc.) — requires Node.js
7. Offers to install npm formatters (prettier, eslint, etc.) 7. Offers to install Python formatters/linters (black, isort, flake8, etc.)
8. Offers to install Python formatters/linters (black, isort, flake8, etc.) 8. Offers to install Go tools (gopls, goimports, staticcheck)
9. Offers to install Go tools (gopls, goimports, staticcheck) 9. Offers to append vim-tmux-navigator bindings to `~/.tmux.conf`
10. Offers to append vim-tmux-navigator bindings to `~/.tmux.conf`
**Supported platforms:** macOS (Homebrew), Debian/Ubuntu (apt), Arch (pacman), Fedora (dnf). **Supported platforms:** macOS (Homebrew), Debian/Ubuntu (apt), Arch (pacman), Fedora (dnf).
@ -125,6 +124,10 @@ Supported languages and their servers:
| Markdown | marksman | | Markdown | marksman |
| SQL | sqls | | SQL | sqls |
**Note:** While vim-lsp itself needs no Node.js, some language servers (TypeScript,
HTML, CSS, JSON, YAML) are npm packages that require Node.js to run. Python (pylsp),
Go (gopls), and Rust (rust-analyzer) language servers do not need Node.js.
**Markdown LSP** requires `marksman` as a standalone binary: **Markdown LSP** requires `marksman` as a standalone binary:
```bash ```bash
@ -150,10 +153,12 @@ Press `,?` at any time to open the built-in cheat sheet.
| `,E` | Open netrw in vertical split | | `,E` | Open netrw in vertical split |
| `,b` | Search open buffers (FZF) | | `,b` | Search open buffers (FZF) |
| `,rg` | Project-wide search (ripgrep + FZF) | | `,rg` | Project-wide search (ripgrep + FZF) |
| `,rG` | Ripgrep for word under cursor | | `,rG` | Ripgrep word under cursor (fixed-string) |
| `,,` | Switch to last file | | `,,` | Switch to last file |
| `,l` / `,h` | Next / previous buffer | | `,l` / `,h` | Next / previous buffer |
| `,bd` | Close current buffer (preserves window layout) | | `,bd` | Close current buffer (preserves window layout) |
| `,wa` | Save all open buffers |
| `,cd` | Change working directory to current file's directory |
### Code Intelligence (vim-lsp) ### Code Intelligence (vim-lsp)
@ -179,7 +184,7 @@ Press `,?` at any time to open the built-in cheat sheet.
| Key | Action | | Key | Action |
|-----|--------| |-----|--------|
| `,mp` | Open live preview in browser (previm) | | `,mp` | Open live preview in browser (previm) |
| `,mt` | Table of contents | | `,mt` | Table of contents (side window) |
| `zr` / `zm` | Unfold / fold all headings | | `zr` / `zm` | Unfold / fold all headings |
### Git (vim-fugitive) ### Git (vim-fugitive)
@ -202,8 +207,14 @@ Press `,?` at any time to open the built-in cheat sheet.
| `Space` | Toggle code fold | | `Space` | Toggle code fold |
| `Y` | Yank to end of line | | `Y` | Yank to end of line |
| `Ctrl+d` / `Ctrl+u` | Half-page scroll, cursor centred | | `Ctrl+d` / `Ctrl+u` | Half-page scroll, cursor centred |
| `Alt+j` / `Alt+k` | Move line down / up | | `Alt+j` / `Alt+k` | Move line down / up (normal and visual) |
| `,u` | Undo tree (visual branch history) | | `,u` | Undo tree (visual branch history) |
| `F2` | Toggle paste mode |
| `F3` / `F4` | Toggle line numbers / relative numbers |
| `F5` | Toggle undo tree |
| `F6` | Toggle invisible characters |
| `gV` | Reselect last paste |
| `//` | Search visual selection |
### Survival ### Survival
@ -211,7 +222,8 @@ Press `,?` at any time to open the built-in cheat sheet.
|-----|--------| |-----|--------|
| `jk` | Exit insert mode | | `jk` | Exit insert mode |
| `Esc` | Exit insert / visual mode | | `Esc` | Exit insert / visual mode |
| `Ctrl+s` | Save | | `jk` | Exit insert mode |
| `Ctrl+s` | Save (any mode) |
| `,w` | Save | | `,w` | Save |
| `,x` | Save and quit | | `,x` | Save and quit |
| `,q` | Quit | | `,q` | Quit |
@ -226,6 +238,13 @@ Press `,?` at any time to open the built-in cheat sheet.
| `Esc Esc` | Exit terminal mode | | `Esc Esc` | Exit terminal mode |
| `,tn` / `,tc` | New tab / close tab | | `,tn` / `,tc` | New tab / close tab |
| `,tl` | Toggle to last tab | | `,tl` | Toggle to last tab |
| `,ev` / `,sv` | Edit / reload `~/.vimrc` |
| `,cp` / `,cf` | Copy file path / filename to clipboard |
| `,*` | Search and replace word under cursor |
| `,F` | Re-indent entire file |
| `,W` | Strip trailing whitespace |
| `,ms` | Open scratch markdown buffer |
| `,ss` | Toggle spell checking |
--- ---
@ -253,7 +272,7 @@ No Node.js required. Uses `open` (macOS) or `xdg-open` (Linux).
### Table of contents ### Table of contents
```vim ```vim
,mt " open TOC in a quickfix window — press Enter to jump to heading ,mt " open TOC in a side window — press Enter to jump to heading
``` ```
--- ---
@ -307,7 +326,7 @@ bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R'
### TTY / SSH Support ### TTY / SSH Support
Detected automatically when `$TERM` is `linux` or `screen`. In TTY mode: Detected automatically when `$TERM` is unset, `dumb`, `linux`, `screen`, or contains `builtin`. In TTY mode:
- True colour and cursorline disabled - True colour and cursorline disabled
- FZF preview windows disabled - FZF preview windows disabled

View file

@ -6,8 +6,5 @@
"filetypes": ["markdown"], "filetypes": ["markdown"],
"rootPatterns": [".git", ".marksman.toml"] "rootPatterns": [".git", ".marksman.toml"]
} }
}, }
"coc.preferences.formatOnSaveFiletypes": [
"markdown"
]
} }

10
get.sh
View file

@ -10,7 +10,11 @@ set -eo pipefail
REPO="https://github.com/m1ngsama/chopsticks.git" REPO="https://github.com/m1ngsama/chopsticks.git"
DEST="$HOME/.vim" DEST="$HOME/.vim"
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; BOLD='\033[1m'; NC='\033[0m' if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; BOLD='\033[1m'; NC='\033[0m'
else
GREEN=''; YELLOW=''; RED=''; BOLD=''; NC=''
fi
ok() { echo -e "${GREEN}[OK]${NC} $1"; } ok() { echo -e "${GREEN}[OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; } warn() { echo -e "${YELLOW}[!]${NC} $1"; }
die() { echo -e "${RED}[FATAL]${NC} $1" >&2; exit 1; } die() { echo -e "${RED}[FATAL]${NC} $1" >&2; exit 1; }
@ -42,7 +46,7 @@ if [[ -d "$DEST/.git" ]]; then
warn "$DEST already exists — pulling latest changes" warn "$DEST already exists — pulling latest changes"
git -C "$DEST" pull --ff-only origin main 2>/dev/null || \ git -C "$DEST" pull --ff-only origin main 2>/dev/null || \
warn "Could not pull latest — using existing version (run: git -C ~/.vim pull)" warn "Could not pull latest — using existing version (run: git -C ~/.vim pull)"
ok "Repository updated" ok "Repository updated ($(git -C "$DEST" describe --tags 2>/dev/null || git -C "$DEST" rev-parse --short HEAD))"
elif [[ -d "$DEST" ]]; then elif [[ -d "$DEST" ]]; then
die "$HOME/.vim exists but is not a chopsticks git repo. die "$HOME/.vim exists but is not a chopsticks git repo.
Back it up first: mv ~/.vim ~/.vim.bak Back it up first: mv ~/.vim ~/.vim.bak
@ -50,7 +54,7 @@ elif [[ -d "$DEST" ]]; then
else else
git clone --depth=1 "$REPO" "$DEST" || \ git clone --depth=1 "$REPO" "$DEST" || \
die "Clone failed — check your network connection" die "Clone failed — check your network connection"
ok "Cloned to $DEST" ok "Cloned to $DEST ($(git -C "$DEST" describe --tags 2>/dev/null || git -C "$DEST" rev-parse --short HEAD))"
fi fi
# ── Run installer ───────────────────────────────────────────────────────────── # ── Run installer ─────────────────────────────────────────────────────────────

View file

@ -1,23 +1,41 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# install.sh - chopsticks vim configuration installer # install.sh - chopsticks vim configuration installer
# Usage: cd /path/to/chopsticks && ./install.sh [--yes] # Usage: cd /path/to/chopsticks && ./install.sh [--yes] [--help]
# #
# --yes non-interactive: install all optional components automatically # --yes non-interactive: install all optional components automatically
# --help show this help and exit
set -eo pipefail set -eo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
AUTO_YES=0 AUTO_YES=0
[[ "${1:-}" == "--yes" ]] && AUTO_YES=1 for arg in "$@"; do
case "$arg" in
--yes) AUTO_YES=1 ;;
--help|-h)
echo "Usage: ./install.sh [OPTIONS]"
echo ""
echo "Options:"
echo " --yes Non-interactive mode: select all defaults automatically"
echo " --help Show this help and exit"
echo ""
echo "Supported platforms: macOS (brew), Debian/Ubuntu (apt), Arch (pacman), Fedora (dnf)"
exit 0 ;;
esac
done
# ── Colours ─────────────────────────────────────────────────────────────────── # ── Colours (respect NO_COLOR and non-TTY) ───────────────────────────────────
GREEN='\033[0;32m' if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then
YELLOW='\033[1;33m' GREEN='\033[0;32m'
RED='\033[0;31m' YELLOW='\033[1;33m'
BOLD='\033[1m' RED='\033[0;31m'
CYAN='\033[0;36m' BOLD='\033[1m'
DIM='\033[2m' CYAN='\033[0;36m'
NC='\033[0m' DIM='\033[2m'
NC='\033[0m'
else
GREEN='' YELLOW='' RED='' BOLD='' CYAN='' DIM='' NC=''
fi
ok() { echo -e "${GREEN}[OK]${NC} $1"; } ok() { echo -e "${GREEN}[OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; } warn() { echo -e "${YELLOW}[!]${NC} $1"; }
@ -50,13 +68,14 @@ ask() {
# ── Error trap ──────────────────────────────────────────────────────────────── # ── Error trap ────────────────────────────────────────────────────────────────
on_error() { on_error() {
echo -e "\n${RED}[FATAL]${NC} Unexpected error at line ${BASH_LINENO[0]}." >&2 echo -e "\n${RED}[FATAL]${NC} Command '${BASH_COMMAND}' failed at line ${BASH_LINENO[0]}." >&2
echo " To get a full debug log:" >&2 echo " To get a full debug log:" >&2
echo " ./install.sh 2>&1 | tee /tmp/chopsticks-install.log" >&2 echo " ./install.sh 2>&1 | tee /tmp/chopsticks-install.log" >&2
echo " Report issues: https://github.com/m1ngsama/chopsticks/issues" >&2 echo " Report issues: https://github.com/m1ngsama/chopsticks/issues" >&2
} }
trap on_error ERR trap on_error ERR
trap 'rm -f /tmp/chopsticks-hadolint /tmp/chopsticks-marksman 2>/dev/null' EXIT _TMPDIR=$(mktemp -d "${TMPDIR:-/tmp}/chopsticks-XXXXXX")
trap 'rm -rf "$_TMPDIR" 2>/dev/null' EXIT
# ── Safe download helper ────────────────────────────────────────────────────── # ── Safe download helper ──────────────────────────────────────────────────────
safe_download() { safe_download() {
@ -72,10 +91,11 @@ safe_download() {
# ── Cross-platform package install helper ───────────────────────────────────── # ── Cross-platform package install helper ─────────────────────────────────────
pkg_install() { pkg_install() {
local brew_pkg="${1:-}" apt_pkg="${2:-}" pac_pkg="${3:-}" dnf_pkg="${4:-}" local brew_pkg="${1:-}" apt_pkg="${2:-}" pac_pkg="${3:-}" dnf_pkg="${4:-}"
if [[ $HAS_BREW -eq 1 && -n "$brew_pkg" ]]; then brew install "$brew_pkg" >/dev/null 2>&1 if [[ $OS == "macos" && $HAS_BREW -eq 1 && -n "$brew_pkg" ]]; then brew install "$brew_pkg" >/dev/null 2>&1
elif [[ $HAS_APT -eq 1 && -n "$apt_pkg" && $HAS_SUDO -eq 1 ]]; then sudo apt-get install -y "$apt_pkg" >/dev/null 2>&1 elif [[ $HAS_APT -eq 1 && -n "$apt_pkg" && $HAS_SUDO -eq 1 ]]; then sudo apt-get install -y "$apt_pkg" >/dev/null 2>&1
elif [[ $HAS_PACMAN -eq 1 && -n "$pac_pkg" && $HAS_SUDO -eq 1 ]]; then sudo pacman -S --noconfirm "$pac_pkg" >/dev/null 2>&1 elif [[ $HAS_PACMAN -eq 1 && -n "$pac_pkg" && $HAS_SUDO -eq 1 ]]; then sudo pacman -S --noconfirm "$pac_pkg" >/dev/null 2>&1
elif [[ $HAS_DNF -eq 1 && -n "$dnf_pkg" && $HAS_SUDO -eq 1 ]]; then sudo dnf install -y "$dnf_pkg" >/dev/null 2>&1 elif [[ $HAS_DNF -eq 1 && -n "$dnf_pkg" && $HAS_SUDO -eq 1 ]]; then sudo dnf install -y "$dnf_pkg" >/dev/null 2>&1
elif [[ $HAS_BREW -eq 1 && -n "$brew_pkg" ]]; then brew install "$brew_pkg" >/dev/null 2>&1
else return 1 else return 1
fi fi
} }
@ -164,11 +184,14 @@ _menu_checkbox() {
local _key _esc _i local _key _esc _i
tput civis 2>/dev/null # hide cursor tput civis 2>/dev/null # hide cursor
_menu_draw local _first=1
while true; do while true; do
tput cuu "$_lines" 2>/dev/null # move back to top of menu if [[ $_first -eq 0 ]]; then
tput cuu "$_lines" 2>/dev/null # move back to top of menu
fi
_menu_draw _menu_draw
_first=0
IFS= read -r -s -n1 _key </dev/tty IFS= read -r -s -n1 _key </dev/tty
if [[ $_key == $'\x1b' ]]; then if [[ $_key == $'\x1b' ]]; then
@ -412,6 +435,9 @@ _vim_run() {
vim --not-a-term "$@" 2>/dev/null vim --not-a-term "$@" 2>/dev/null
fi fi
} }
if [[ -d "$HOME/.vim/plugged" ]] && [[ -n "$(ls -A "$HOME/.vim/plugged" 2>/dev/null)" ]]; then
warn "PlugClean: removing plugins not listed in .vimrc from ~/.vim/plugged"
fi
_vim_run +'PlugClean!' +qall || true # remove plugins no longer in vimrc; ignore exit code (none expected) _vim_run +'PlugClean!' +qall || true # remove plugins no longer in vimrc; ignore exit code (none expected)
_vim_run +'PlugInstall --sync' +qall || true # fzf post-install hook may exit non-zero; harmless _vim_run +'PlugInstall --sync' +qall || true # fzf post-install hook may exit non-zero; harmless
@ -558,6 +584,10 @@ _do_binary_apt() {
if command -v "$check" >/dev/null 2>&1; then if command -v "$check" >/dev/null 2>&1; then
ok "$name (already installed)"; return ok "$name (already installed)"; return
fi fi
if [[ $HAS_SUDO -ne 1 ]]; then
fail "$name — sudo not available, cannot install to /usr/local/bin"
FAILED+=("$name"); return
fi
if safe_download "$url" "$tmp"; then if safe_download "$url" "$tmp"; then
chmod +x "$tmp" && sudo mv "$tmp" /usr/local/bin/"$check" chmod +x "$tmp" && sudo mv "$tmp" /usr/local/bin/"$check"
ok "$name"; INSTALLED+=("$name") ok "$name"; INSTALLED+=("$name")
@ -583,20 +613,38 @@ elif [[ $HAS_APT -eq 1 ]]; then
_do_sys "shellcheck" shellcheck "$_I_SHELLCHECK" "" shellcheck "" "" _do_sys "shellcheck" shellcheck "$_I_SHELLCHECK" "" shellcheck "" ""
# hadolint: no apt package — binary from GitHub releases # hadolint: no apt package — binary from GitHub releases
HARCH=$(arch_github) if [[ $_I_HADOLINT -ge 0 ]] && _selected "$_I_HADOLINT"; then
HVER=$(curl -fsSL https://api.github.com/repos/hadolint/hadolint/releases/latest \ HARCH=$(arch_github)
| grep '"tag_name"' | cut -d'"' -f4 2>/dev/null) || HVER="" HVER=$(curl -fsSL https://api.github.com/repos/hadolint/hadolint/releases/latest \
_do_binary_apt "hadolint" hadolint "$_I_HADOLINT" \ | grep '"tag_name"' | cut -d'"' -f4 2>/dev/null) || HVER=""
"https://github.com/hadolint/hadolint/releases/download/${HVER}/hadolint-Linux-${HARCH}" \ if [[ -z "$HVER" ]]; then
/tmp/chopsticks-hadolint fail "hadolint — could not determine latest release version"
FAILED+=("hadolint")
else
_do_binary_apt "hadolint" hadolint "$_I_HADOLINT" \
"https://github.com/hadolint/hadolint/releases/download/${HVER}/hadolint-Linux-${HARCH}" \
"$_TMPDIR/hadolint"
fi
else
skip "hadolint"; SKIPPED+=("hadolint")
fi
# marksman: no apt package — binary from GitHub releases # marksman: no apt package — binary from GitHub releases
MARCH=$(arch_linux_x64) if [[ $_I_MARKSMAN -ge 0 ]] && _selected "$_I_MARKSMAN"; then
MVER=$(curl -fsSL https://api.github.com/repos/artempyanykh/marksman/releases/latest \ MARCH=$(arch_linux_x64)
| grep '"tag_name"' | cut -d'"' -f4 2>/dev/null) || MVER="" MVER=$(curl -fsSL https://api.github.com/repos/artempyanykh/marksman/releases/latest \
_do_binary_apt "marksman" marksman "$_I_MARKSMAN" \ | grep '"tag_name"' | cut -d'"' -f4 2>/dev/null) || MVER=""
"https://github.com/artempyanykh/marksman/releases/download/${MVER}/marksman-linux-${MARCH}" \ if [[ -z "$MVER" ]]; then
/tmp/chopsticks-marksman fail "marksman — could not determine latest release version"
FAILED+=("marksman")
else
_do_binary_apt "marksman" marksman "$_I_MARKSMAN" \
"https://github.com/artempyanykh/marksman/releases/download/${MVER}/marksman-linux-${MARCH}" \
"$_TMPDIR/marksman"
fi
else
skip "marksman"; SKIPPED+=("marksman")
fi
elif [[ $HAS_PACMAN -eq 1 ]]; then elif [[ $HAS_PACMAN -eq 1 ]]; then
_do_sys "ripgrep" rg "$_I_RIPGREP" "" "" ripgrep "" _do_sys "ripgrep" rg "$_I_RIPGREP" "" "" ripgrep ""
@ -610,16 +658,22 @@ elif [[ $HAS_DNF -eq 1 ]]; then
_do_sys "ripgrep" rg "$_I_RIPGREP" "" "" "" ripgrep _do_sys "ripgrep" rg "$_I_RIPGREP" "" "" "" ripgrep
_do_sys "fzf" fzf "$_I_FZF" "" "" "" fzf _do_sys "fzf" fzf "$_I_FZF" "" "" "" fzf
_do_sys "shellcheck" shellcheck "$_I_SHELLCHECK" "" "" "" ShellCheck _do_sys "shellcheck" shellcheck "$_I_SHELLCHECK" "" "" "" ShellCheck
if [[ $_I_CTAGS -ge 0 ]] && _selected "$_I_CTAGS"; then if [[ $_I_CTAGS -ge 0 ]]; then
skip "universal-ctags — Fedora: install manually: sudo dnf install ctags" if _selected "$_I_CTAGS"; then
skip "universal-ctags — Fedora: install manually: sudo dnf install ctags"
fi
SKIPPED+=("universal-ctags") SKIPPED+=("universal-ctags")
fi fi
if [[ $_I_HADOLINT -ge 0 ]] && _selected "$_I_HADOLINT"; then if [[ $_I_HADOLINT -ge 0 ]]; then
skip "hadolint — Fedora: install manually: https://github.com/hadolint/hadolint/releases" if _selected "$_I_HADOLINT"; then
skip "hadolint — Fedora: install manually: https://github.com/hadolint/hadolint/releases"
fi
SKIPPED+=("hadolint") SKIPPED+=("hadolint")
fi fi
if [[ $_I_MARKSMAN -ge 0 ]] && _selected "$_I_MARKSMAN"; then if [[ $_I_MARKSMAN -ge 0 ]]; then
skip "marksman — Fedora: install manually: https://github.com/artempyanykh/marksman/releases" if _selected "$_I_MARKSMAN"; then
skip "marksman — Fedora: install manually: https://github.com/artempyanykh/marksman/releases"
fi
SKIPPED+=("marksman") SKIPPED+=("marksman")
fi fi
else else
@ -679,8 +733,10 @@ else
if command -v "$check" >/dev/null 2>&1; then if command -v "$check" >/dev/null 2>&1; then
ok "$pkg (already installed)"; return ok "$pkg (already installed)"; return
fi fi
if pip3 install --quiet "$pkg" 2>/dev/null || \ if pip3 install --quiet "$pkg" 2>/dev/null; then
pip3 install --quiet --break-system-packages "$pkg" 2>/dev/null; then ok "$pkg"; INSTALLED+=("$pkg")
elif pip3 install --quiet --break-system-packages "$pkg" 2>/dev/null; then
warn "$pkg installed with --break-system-packages (consider using a virtualenv)"
ok "$pkg"; INSTALLED+=("$pkg") ok "$pkg"; INSTALLED+=("$pkg")
else else
fail "$pkg"; FAILED+=("$pkg") fail "$pkg"; FAILED+=("$pkg")