mirror of
https://oauth2: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@github.com/m1ngsama/chopsticks.git
synced 2026-05-10 19:10:59 +08:00
Compare commits
No commits in common. "5604eddbdbdb2c7fb76bfb68fd805386d0792916" and "0b3f631e98f4563c0dc43fb166c0e9cc7235822f" have entirely different histories.
5604eddbdb
...
0b3f631e98
6 changed files with 146 additions and 284 deletions
234
.vimrc
234
.vimrc
|
|
@ -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/*
|
||||||
" path+=** removed: hangs on large repos (node_modules); use Ctrl+p (FZF) instead
|
set path+=**
|
||||||
set mouse=a
|
set mouse=a
|
||||||
set encoding=utf-8
|
set encoding=utf-8
|
||||||
set foldmethod=indent
|
set foldmethod=indent
|
||||||
|
|
@ -96,10 +96,7 @@ 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'
|
||||||
augroup PlugBootstrap
|
|
||||||
autocmd!
|
|
||||||
autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
|
autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
|
||||||
augroup END
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call plug#begin('~/.vim/plugged')
|
call plug#begin('~/.vim/plugged')
|
||||||
|
|
@ -160,9 +157,6 @@ 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
|
||||||
|
|
||||||
|
|
@ -214,42 +208,42 @@ set smartindent
|
||||||
let mapleader = ","
|
let mapleader = ","
|
||||||
|
|
||||||
" Saving / quitting
|
" Saving / quitting
|
||||||
nnoremap <leader>w :w!<cr>
|
nmap <leader>w :w!<cr>
|
||||||
nnoremap <leader>q :q<cr>
|
nmap <leader>q :q<cr>
|
||||||
nnoremap <leader>x :x<cr>
|
nmap <leader>x :x<cr>
|
||||||
|
|
||||||
" Clear search highlight
|
" Clear search highlight
|
||||||
nnoremap <silent> <leader><cr> :noh<cr>
|
map <silent> <leader><cr> :noh<cr>
|
||||||
|
|
||||||
" Buffer navigation
|
" Buffer navigation
|
||||||
nnoremap <leader>bd :Bclose<cr>
|
map <leader>bd :Bclose<cr>
|
||||||
nnoremap <leader>ba :bufdo bd<cr>
|
map <leader>ba :bufdo bd<cr>
|
||||||
nnoremap <leader>l :bnext<cr>
|
map <leader>l :bnext<cr>
|
||||||
nnoremap <leader>h :bprevious<cr>
|
map <leader>h :bprevious<cr>
|
||||||
|
|
||||||
" Tab management
|
" Tab management
|
||||||
nnoremap <leader>tn :tabnew<cr>
|
map <leader>tn :tabnew<cr>
|
||||||
nnoremap <leader>to :tabonly<cr>
|
map <leader>to :tabonly<cr>
|
||||||
nnoremap <leader>tc :tabclose<cr>
|
map <leader>tc :tabclose<cr>
|
||||||
nnoremap <leader>tm :tabmove
|
map <leader>tm :tabmove
|
||||||
nnoremap <leader>t<leader> :tabnext<cr>
|
map <leader>t<leader> :tabnext<cr>
|
||||||
|
|
||||||
let g:lasttab = 1
|
let g:lasttab = 1
|
||||||
nnoremap <Leader>tl :exe "tabn ".g:lasttab<CR>
|
nmap <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
|
||||||
|
|
||||||
nnoremap <leader>te :tabedit <C-r>=expand("%:p:h")<cr>/
|
map <leader>te :tabedit <C-r>=expand("%:p:h")<cr>/
|
||||||
nnoremap <leader>cd :lcd %:p:h<cr>:pwd<cr>
|
map <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 (all modes intentional)
|
" Remap 0 to first non-blank
|
||||||
noremap 0 ^
|
map 0 ^
|
||||||
|
|
||||||
" Reselect last paste
|
" Reselect last paste
|
||||||
nnoremap gV `[v`]
|
nnoremap gV `[v`]
|
||||||
|
|
@ -258,18 +252,18 @@ nnoremap gV `[v`]
|
||||||
cnoremap <C-p> <Up>
|
cnoremap <C-p> <Up>
|
||||||
cnoremap <C-n> <Down>
|
cnoremap <C-n> <Down>
|
||||||
|
|
||||||
" Move lines (Alt+j / Alt+k in both normal and visual mode)
|
" Move lines
|
||||||
nnoremap <M-j> :m .+1<CR>==
|
nmap <M-j> mz:m+<cr>`z
|
||||||
nnoremap <M-k> :m .-2<CR>==
|
nmap <M-k> mz:m-2<cr>`z
|
||||||
vnoremap <M-j> :m '>+1<CR>gv=gv
|
vnoremap J :m '>+1<CR>gv=gv
|
||||||
vnoremap <M-k> :m '<-2<CR>gv=gv
|
vnoremap K :m '<-2<CR>gv=gv
|
||||||
|
|
||||||
" Spell checking
|
" Spell checking
|
||||||
nnoremap <leader>ss :setlocal spell!<cr>
|
map <leader>ss :setlocal spell!<cr>
|
||||||
nnoremap <leader>sn ]s
|
map <leader>sn ]s
|
||||||
nnoremap <leader>sp [s
|
map <leader>sp [s
|
||||||
nnoremap <leader>sa zg
|
map <leader>sa zg
|
||||||
nnoremap <leader>s? z=
|
map <leader>s? z=
|
||||||
|
|
||||||
" Toggle modes
|
" Toggle modes
|
||||||
set pastetoggle=<F2>
|
set pastetoggle=<F2>
|
||||||
|
|
@ -354,21 +348,19 @@ 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 isdirectory('.git') || finddir('.git', '.;') !=# ''
|
if !empty(system('git rev-parse --show-toplevel 2>/dev/null'))
|
||||||
GFiles
|
GFiles
|
||||||
else
|
else
|
||||||
Files
|
Files
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
if exists('g:plugs["fzf.vim"]')
|
map <C-p> :call <SID>SmartFiles()<CR>
|
||||||
nnoremap <C-p> :call <SID>SmartFiles()<CR>
|
map <leader>b :Buffers<CR>
|
||||||
nnoremap <leader>b :Buffers<CR>
|
map <leader>rg :Rg<CR>
|
||||||
nnoremap <leader>rg :Rg<CR>
|
map <leader>rG :Rg -F <C-r><C-w><CR>
|
||||||
nnoremap <leader>rG :RgWord<CR>
|
map <leader>rt :Tags<CR>
|
||||||
nnoremap <leader>rt :Tags<CR>
|
map <leader>gF :GFiles<CR>
|
||||||
nnoremap <leader>gF :GFiles<CR>
|
|
||||||
endif
|
|
||||||
|
|
||||||
let g:fzf_layout = { 'down': '40%' }
|
let g:fzf_layout = { 'down': '40%' }
|
||||||
|
|
||||||
|
|
@ -392,19 +384,6 @@ 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
|
||||||
" ============================================================================
|
" ============================================================================
|
||||||
|
|
@ -460,11 +439,9 @@ 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
|
||||||
|
|
||||||
if exists('g:plugs["ale"]')
|
nmap <silent> [e :ALEPrevious<cr>
|
||||||
nnoremap <silent> [e :ALEPrevious<cr>
|
nmap <silent> ]e :ALENext<cr>
|
||||||
nnoremap <silent> ]e :ALENext<cr>
|
nmap <silent> <leader>aD :ALEDetail<cr>
|
||||||
nnoremap <silent> <leader>aD :ALEDetail<cr>
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ============================================================================
|
" ============================================================================
|
||||||
" => vim-go
|
" => vim-go
|
||||||
|
|
@ -473,8 +450,8 @@ endif
|
||||||
" 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 = 'godef'
|
let g:go_def_mode = 'gopls'
|
||||||
let g:go_info_mode = 'godef'
|
let g:go_info_mode = 'gopls'
|
||||||
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
|
||||||
|
|
@ -513,11 +490,7 @@ 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': '>'}
|
||||||
|
|
||||||
if has('patch-8.1.1517')
|
set completeopt=menuone,noinsert,noselect
|
||||||
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
|
||||||
|
|
@ -577,19 +550,15 @@ 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 (side window)
|
" Table of contents in quickfix
|
||||||
if exists('g:plugs["vim-markdown"]')
|
nnoremap <leader>mt :Toc<CR>
|
||||||
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
|
||||||
if exists('g:plugs["previm"]')
|
nnoremap <leader>mp :PrevimOpen<CR>
|
||||||
nnoremap <leader>mp :PrevimOpen<CR>
|
|
||||||
endif
|
|
||||||
let g:previm_enable_realtime = 1
|
let g:previm_enable_realtime = 1
|
||||||
|
|
||||||
" ============================================================================
|
" ============================================================================
|
||||||
|
|
@ -599,22 +568,19 @@ 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
|
||||||
|
|
||||||
if exists('g:plugs["vim-easymotion"]')
|
" s + two chars: jump anywhere on screen
|
||||||
" s + two chars: jump anywhere on screen
|
nmap s <Plug>(easymotion-overwin-f2)
|
||||||
nmap s <Plug>(easymotion-overwin-f2)
|
|
||||||
" Line motions
|
" J/K: line motions
|
||||||
nmap <Leader>j <Plug>(easymotion-j)
|
map <Leader>j <Plug>(easymotion-j)
|
||||||
nmap <Leader>k <Plug>(easymotion-k)
|
map <Leader>k <Plug>(easymotion-k)
|
||||||
endif
|
|
||||||
|
|
||||||
" ============================================================================
|
" ============================================================================
|
||||||
" => UndoTree
|
" => UndoTree
|
||||||
" ============================================================================
|
" ============================================================================
|
||||||
|
|
||||||
if exists('g:plugs["undotree"]')
|
nnoremap <F5> :UndotreeToggle<CR>
|
||||||
nnoremap <F5> :UndotreeToggle<CR>
|
nnoremap <leader>u :UndotreeToggle<CR>
|
||||||
nnoremap <leader>u :UndotreeToggle<CR>
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ============================================================================
|
" ============================================================================
|
||||||
" => IndentLine (non-TTY only)
|
" => IndentLine (non-TTY only)
|
||||||
|
|
@ -638,12 +604,12 @@ endif
|
||||||
|
|
||||||
if exists('g:plugs["vim-startify"]')
|
if exists('g:plugs["vim-startify"]')
|
||||||
let g:startify_custom_header = [
|
let g:startify_custom_header = [
|
||||||
\ ' ██████╗██╗ ██╗ ██████╗ ██████╗ ███████╗████████╗██╗ ██████╗██╗ ██╗███████╗',
|
\ ' ███╗ ███╗ ██╗███╗ ██╗ ██████╗ ███████╗ █████╗ ███╗ ███╗ █████╗ ',
|
||||||
\ ' ██╔════╝██║ ██║██╔═══██╗██╔══██╗██╔════╝╚══██╔══╝██║██╔════╝██║ ██╔╝██╔════╝',
|
\ ' ████╗ ████║███║████╗ ██║██╔════╝ ██╔════╝██╔══██╗████╗ ████║██╔══██╗ ',
|
||||||
\ ' ██║ ███████║██║ ██║██████╔╝███████╗ ██║ ██║██║ █████╔╝ ███████╗',
|
\ ' ██╔████╔██║╚██║██╔██╗ ██║██║ ███╗███████╗███████║██╔████╔██║███████║ ',
|
||||||
\ ' ██║ ██╔══██║██║ ██║██╔═══╝ ╚════██║ ██║ ██║██║ ██╔═██╗ ╚════██║',
|
\ ' ██║╚██╔╝██║ ██║██║╚██╗██║██║ ██║╚════██║██╔══██║██║╚██╔╝██║██╔══██║ ',
|
||||||
\ ' ╚██████╗██║ ██║╚██████╔╝██║ ███████║ ██║ ██║╚██████╗██║ ██╗███████║',
|
\ ' ██║ ╚═╝ ██║ ██║██║ ╚████║╚██████╔╝███████║██║ ██║██║ ╚═╝ ██║██║ ██║ ',
|
||||||
\ ' ╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝',
|
\ ' ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝',
|
||||||
\ '',
|
\ '',
|
||||||
\ ]
|
\ ]
|
||||||
|
|
||||||
|
|
@ -654,16 +620,11 @@ if exists('g:plugs["vim-startify"]')
|
||||||
\ { 'type': 'bookmarks', 'header': [' Bookmarks'] },
|
\ { 'type': 'bookmarks', 'header': [' Bookmarks'] },
|
||||||
\ ]
|
\ ]
|
||||||
|
|
||||||
let g:startify_bookmarks = [{'v': '~/.vimrc'}]
|
let g:startify_bookmarks = [
|
||||||
if filereadable(expand('~/.zshrc'))
|
\ {'v': '~/.vimrc'},
|
||||||
call add(g:startify_bookmarks, {'z': '~/.zshrc'})
|
\ {'z': '~/.zshrc'},
|
||||||
endif
|
\ {'b': '~/.bashrc'},
|
||||||
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
|
||||||
|
|
@ -724,6 +685,7 @@ 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]
|
||||||
|
|
@ -819,7 +781,7 @@ endfunc
|
||||||
" Suppress comment continuation on Enter / o / O
|
" Suppress comment continuation on Enter / o / O
|
||||||
augroup ChopstickFormatOptions
|
augroup ChopstickFormatOptions
|
||||||
autocmd!
|
autocmd!
|
||||||
autocmd FileType * setlocal formatoptions-=c formatoptions-=r formatoptions-=o
|
autocmd BufEnter * 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
|
||||||
|
|
@ -828,6 +790,13 @@ 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!
|
||||||
|
|
||||||
|
|
@ -922,7 +891,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 :if &filetype ==# 'vim' <Bar> source % <Bar> echo "Sourced " . expand('%') <Bar> else <Bar> echo "Not a vim file" <Bar> endif<CR>
|
nnoremap <leader>so :source %<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>
|
||||||
|
|
||||||
|
|
@ -930,13 +899,11 @@ 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
|
||||||
if has('clipboard')
|
nnoremap <leader>cp :let @+ = expand("%:p")<CR>:echo "Copied: " . expand("%:p")<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>
|
||||||
nnoremap <leader>cf :let @+ = expand("%:t")<CR>:echo "Copied: " . expand("%:t")<CR>
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Scratch markdown buffer
|
" Scratch markdown buffer
|
||||||
nnoremap <leader>ms :e ~/buffer.md<cr>
|
map <leader>m :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)
|
||||||
|
|
@ -959,14 +926,12 @@ augroup END
|
||||||
" => Git Shortcuts
|
" => Git Shortcuts
|
||||||
" ============================================================================
|
" ============================================================================
|
||||||
|
|
||||||
if exists('g:plugs["vim-fugitive"]')
|
nnoremap <leader>gs :Git status<CR>
|
||||||
nnoremap <leader>gs :Git status<CR>
|
nnoremap <leader>gc :Git commit<CR>
|
||||||
nnoremap <leader>gc :Git commit<CR>
|
nnoremap <leader>gp :Git push<CR>
|
||||||
nnoremap <leader>gp :Git push<CR>
|
nnoremap <leader>gl :Git pull<CR>
|
||||||
nnoremap <leader>gl :Git pull<CR>
|
nnoremap <leader>gd :Gdiff<CR>
|
||||||
nnoremap <leader>gd :Gdiffsplit<CR>
|
nnoremap <leader>gb :Git blame<CR>
|
||||||
nnoremap <leader>gb :Git blame<CR>
|
|
||||||
endif
|
|
||||||
|
|
||||||
" ============================================================================
|
" ============================================================================
|
||||||
" => Terminal Integration
|
" => Terminal Integration
|
||||||
|
|
@ -1000,8 +965,9 @@ 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=
|
setlocal syntax=OFF
|
||||||
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
|
||||||
|
|
@ -1011,7 +977,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= |
|
\ setlocal syntax=OFF |
|
||||||
\ endif
|
\ endif
|
||||||
augroup END
|
augroup END
|
||||||
|
|
||||||
|
|
@ -1085,20 +1051,9 @@ 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',
|
||||||
\ ' ,j / ,k EasyMotion — line motions',
|
\ ' ,u Undo tree (visual branch history)',
|
||||||
\ ' ,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',
|
\ ' ,p / ,P Paste from system clipboard (after / before)',
|
||||||
\ ' 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',
|
||||||
|
|
@ -1107,19 +1062,8 @@ 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',
|
||||||
|
|
@ -1137,7 +1081,7 @@ nnoremap <silent> <leader>? :call <SID>CheatSheet()<CR>
|
||||||
" ============================================================================
|
" ============================================================================
|
||||||
|
|
||||||
" Show syntax highlight stack for word under cursor
|
" Show syntax highlight stack for word under cursor
|
||||||
nnoremap <leader>sh :call <SID>SynStack()<CR>
|
nmap <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")')
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,6 @@ 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 30–60 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
|
||||||
|
|
@ -71,9 +67,7 @@ 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.
|
||||||
vim-lsp itself runs on pure VimScript — no Node.js required. However,
|
No Node.js required — vim-lsp runs on pure VimScript.
|
||||||
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
|
||||||
|
|
@ -148,7 +142,7 @@ K Show documentation
|
||||||
| Key | Action |
|
| Key | Action |
|
||||||
|-----|--------|
|
|-----|--------|
|
||||||
| `,mp` | Open live preview in browser |
|
| `,mp` | Open live preview in browser |
|
||||||
| `,mt` | Table of contents (side window) |
|
| `,mt` | Table of contents |
|
||||||
| `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,
|
||||||
|
|
|
||||||
41
README.md
41
README.md
|
|
@ -86,10 +86,11 @@ 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 npm formatters (prettier, eslint, etc.) — requires Node.js
|
6. Offers to install Node.js via nvm (for npm formatters — optional)
|
||||||
7. Offers to install Python formatters/linters (black, isort, flake8, etc.)
|
7. Offers to install npm formatters (prettier, eslint, etc.)
|
||||||
8. Offers to install Go tools (gopls, goimports, staticcheck)
|
8. Offers to install Python formatters/linters (black, isort, flake8, etc.)
|
||||||
9. Offers to append vim-tmux-navigator bindings to `~/.tmux.conf`
|
9. Offers to install Go tools (gopls, goimports, staticcheck)
|
||||||
|
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).
|
||||||
|
|
||||||
|
|
@ -124,10 +125,6 @@ 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
|
||||||
|
|
@ -153,12 +150,10 @@ 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 word under cursor (fixed-string) |
|
| `,rG` | Ripgrep for word under cursor |
|
||||||
| `,,` | 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)
|
||||||
|
|
||||||
|
|
@ -184,7 +179,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 (side window) |
|
| `,mt` | Table of contents |
|
||||||
| `zr` / `zm` | Unfold / fold all headings |
|
| `zr` / `zm` | Unfold / fold all headings |
|
||||||
|
|
||||||
### Git (vim-fugitive)
|
### Git (vim-fugitive)
|
||||||
|
|
@ -207,14 +202,8 @@ 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 (normal and visual) |
|
| `Alt+j` / `Alt+k` | Move line down / up |
|
||||||
| `,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
|
||||||
|
|
||||||
|
|
@ -222,8 +211,7 @@ 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 |
|
||||||
| `jk` | Exit insert mode |
|
| `Ctrl+s` | Save |
|
||||||
| `Ctrl+s` | Save (any mode) |
|
|
||||||
| `,w` | Save |
|
| `,w` | Save |
|
||||||
| `,x` | Save and quit |
|
| `,x` | Save and quit |
|
||||||
| `,q` | Quit |
|
| `,q` | Quit |
|
||||||
|
|
@ -238,13 +226,6 @@ 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 |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -272,7 +253,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 side window — press Enter to jump to heading
|
,mt " open TOC in a quickfix window — press Enter to jump to heading
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -326,7 +307,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 unset, `dumb`, `linux`, `screen`, or contains `builtin`. In TTY mode:
|
Detected automatically when `$TERM` is `linux` or `screen`. In TTY mode:
|
||||||
|
|
||||||
- True colour and cursorline disabled
|
- True colour and cursorline disabled
|
||||||
- FZF preview windows disabled
|
- FZF preview windows disabled
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,8 @@
|
||||||
"filetypes": ["markdown"],
|
"filetypes": ["markdown"],
|
||||||
"rootPatterns": [".git", ".marksman.toml"]
|
"rootPatterns": [".git", ".marksman.toml"]
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"coc.preferences.formatOnSaveFiletypes": [
|
||||||
|
"markdown"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
get.sh
10
get.sh
|
|
@ -10,11 +10,7 @@ set -eo pipefail
|
||||||
REPO="https://github.com/m1ngsama/chopsticks.git"
|
REPO="https://github.com/m1ngsama/chopsticks.git"
|
||||||
DEST="$HOME/.vim"
|
DEST="$HOME/.vim"
|
||||||
|
|
||||||
if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then
|
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; BOLD='\033[1m'; NC='\033[0m'
|
||||||
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; BOLD='\033[1m'; NC='\033[0m'
|
|
||||||
else
|
|
||||||
GREEN=''; YELLOW=''; RED=''; BOLD=''; NC=''
|
|
||||||
fi
|
|
||||||
ok() { echo -e "${GREEN}[OK]${NC} $1"; }
|
ok() { echo -e "${GREEN}[OK]${NC} $1"; }
|
||||||
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
||||||
die() { echo -e "${RED}[FATAL]${NC} $1" >&2; exit 1; }
|
die() { echo -e "${RED}[FATAL]${NC} $1" >&2; exit 1; }
|
||||||
|
|
@ -46,7 +42,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 ($(git -C "$DEST" describe --tags 2>/dev/null || git -C "$DEST" rev-parse --short HEAD))"
|
ok "Repository updated"
|
||||||
elif [[ -d "$DEST" ]]; then
|
elif [[ -d "$DEST" ]]; then
|
||||||
die "$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
|
||||||
|
|
@ -54,7 +50,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 ($(git -C "$DEST" describe --tags 2>/dev/null || git -C "$DEST" rev-parse --short HEAD))"
|
ok "Cloned to $DEST"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Run installer ─────────────────────────────────────────────────────────────
|
# ── Run installer ─────────────────────────────────────────────────────────────
|
||||||
|
|
|
||||||
98
install.sh
98
install.sh
|
|
@ -1,41 +1,23 @@
|
||||||
#!/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] [--help]
|
# Usage: cd /path/to/chopsticks && ./install.sh [--yes]
|
||||||
#
|
#
|
||||||
# --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
|
||||||
for arg in "$@"; do
|
[[ "${1:-}" == "--yes" ]] && AUTO_YES=1
|
||||||
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 (respect NO_COLOR and non-TTY) ───────────────────────────────────
|
# ── Colours ───────────────────────────────────────────────────────────────────
|
||||||
if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then
|
GREEN='\033[0;32m'
|
||||||
GREEN='\033[0;32m'
|
YELLOW='\033[1;33m'
|
||||||
YELLOW='\033[1;33m'
|
RED='\033[0;31m'
|
||||||
RED='\033[0;31m'
|
BOLD='\033[1m'
|
||||||
BOLD='\033[1m'
|
CYAN='\033[0;36m'
|
||||||
CYAN='\033[0;36m'
|
DIM='\033[2m'
|
||||||
DIM='\033[2m'
|
NC='\033[0m'
|
||||||
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"; }
|
||||||
|
|
@ -68,14 +50,13 @@ ask() {
|
||||||
|
|
||||||
# ── Error trap ────────────────────────────────────────────────────────────────
|
# ── Error trap ────────────────────────────────────────────────────────────────
|
||||||
on_error() {
|
on_error() {
|
||||||
echo -e "\n${RED}[FATAL]${NC} Command '${BASH_COMMAND}' failed at line ${BASH_LINENO[0]}." >&2
|
echo -e "\n${RED}[FATAL]${NC} Unexpected error 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
|
||||||
_TMPDIR=$(mktemp -d "${TMPDIR:-/tmp}/chopsticks-XXXXXX")
|
trap 'rm -f /tmp/chopsticks-hadolint /tmp/chopsticks-marksman 2>/dev/null' EXIT
|
||||||
trap 'rm -rf "$_TMPDIR" 2>/dev/null' EXIT
|
|
||||||
|
|
||||||
# ── Safe download helper ──────────────────────────────────────────────────────
|
# ── Safe download helper ──────────────────────────────────────────────────────
|
||||||
safe_download() {
|
safe_download() {
|
||||||
|
|
@ -91,11 +72,10 @@ 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 [[ $OS == "macos" && $HAS_BREW -eq 1 && -n "$brew_pkg" ]]; then brew install "$brew_pkg" >/dev/null 2>&1
|
if [[ $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
|
||||||
}
|
}
|
||||||
|
|
@ -184,14 +164,11 @@ _menu_checkbox() {
|
||||||
local _key _esc _i
|
local _key _esc _i
|
||||||
|
|
||||||
tput civis 2>/dev/null # hide cursor
|
tput civis 2>/dev/null # hide cursor
|
||||||
local _first=1
|
_menu_draw
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
if [[ $_first -eq 0 ]]; then
|
|
||||||
tput cuu "$_lines" 2>/dev/null # move back to top of menu
|
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
|
||||||
|
|
@ -435,9 +412,6 @@ _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
|
||||||
|
|
||||||
|
|
@ -584,10 +558,6 @@ _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")
|
||||||
|
|
@ -613,38 +583,20 @@ 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
|
||||||
if [[ $_I_HADOLINT -ge 0 ]] && _selected "$_I_HADOLINT"; then
|
|
||||||
HARCH=$(arch_github)
|
HARCH=$(arch_github)
|
||||||
HVER=$(curl -fsSL https://api.github.com/repos/hadolint/hadolint/releases/latest \
|
HVER=$(curl -fsSL https://api.github.com/repos/hadolint/hadolint/releases/latest \
|
||||||
| grep '"tag_name"' | cut -d'"' -f4 2>/dev/null) || HVER=""
|
| grep '"tag_name"' | cut -d'"' -f4 2>/dev/null) || HVER=""
|
||||||
if [[ -z "$HVER" ]]; then
|
|
||||||
fail "hadolint — could not determine latest release version"
|
|
||||||
FAILED+=("hadolint")
|
|
||||||
else
|
|
||||||
_do_binary_apt "hadolint" hadolint "$_I_HADOLINT" \
|
_do_binary_apt "hadolint" hadolint "$_I_HADOLINT" \
|
||||||
"https://github.com/hadolint/hadolint/releases/download/${HVER}/hadolint-Linux-${HARCH}" \
|
"https://github.com/hadolint/hadolint/releases/download/${HVER}/hadolint-Linux-${HARCH}" \
|
||||||
"$_TMPDIR/hadolint"
|
/tmp/chopsticks-hadolint
|
||||||
fi
|
|
||||||
else
|
|
||||||
skip "hadolint"; SKIPPED+=("hadolint")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# marksman: no apt package — binary from GitHub releases
|
# marksman: no apt package — binary from GitHub releases
|
||||||
if [[ $_I_MARKSMAN -ge 0 ]] && _selected "$_I_MARKSMAN"; then
|
|
||||||
MARCH=$(arch_linux_x64)
|
MARCH=$(arch_linux_x64)
|
||||||
MVER=$(curl -fsSL https://api.github.com/repos/artempyanykh/marksman/releases/latest \
|
MVER=$(curl -fsSL https://api.github.com/repos/artempyanykh/marksman/releases/latest \
|
||||||
| grep '"tag_name"' | cut -d'"' -f4 2>/dev/null) || MVER=""
|
| grep '"tag_name"' | cut -d'"' -f4 2>/dev/null) || MVER=""
|
||||||
if [[ -z "$MVER" ]]; then
|
|
||||||
fail "marksman — could not determine latest release version"
|
|
||||||
FAILED+=("marksman")
|
|
||||||
else
|
|
||||||
_do_binary_apt "marksman" marksman "$_I_MARKSMAN" \
|
_do_binary_apt "marksman" marksman "$_I_MARKSMAN" \
|
||||||
"https://github.com/artempyanykh/marksman/releases/download/${MVER}/marksman-linux-${MARCH}" \
|
"https://github.com/artempyanykh/marksman/releases/download/${MVER}/marksman-linux-${MARCH}" \
|
||||||
"$_TMPDIR/marksman"
|
/tmp/chopsticks-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 ""
|
||||||
|
|
@ -658,22 +610,16 @@ 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 ]]; then
|
if [[ $_I_CTAGS -ge 0 ]] && _selected "$_I_CTAGS"; then
|
||||||
if _selected "$_I_CTAGS"; then
|
|
||||||
skip "universal-ctags — Fedora: install manually: sudo dnf install ctags"
|
skip "universal-ctags — Fedora: install manually: sudo dnf install ctags"
|
||||||
fi
|
|
||||||
SKIPPED+=("universal-ctags")
|
SKIPPED+=("universal-ctags")
|
||||||
fi
|
fi
|
||||||
if [[ $_I_HADOLINT -ge 0 ]]; then
|
if [[ $_I_HADOLINT -ge 0 ]] && _selected "$_I_HADOLINT"; then
|
||||||
if _selected "$_I_HADOLINT"; then
|
|
||||||
skip "hadolint — Fedora: install manually: https://github.com/hadolint/hadolint/releases"
|
skip "hadolint — Fedora: install manually: https://github.com/hadolint/hadolint/releases"
|
||||||
fi
|
|
||||||
SKIPPED+=("hadolint")
|
SKIPPED+=("hadolint")
|
||||||
fi
|
fi
|
||||||
if [[ $_I_MARKSMAN -ge 0 ]]; then
|
if [[ $_I_MARKSMAN -ge 0 ]] && _selected "$_I_MARKSMAN"; then
|
||||||
if _selected "$_I_MARKSMAN"; then
|
|
||||||
skip "marksman — Fedora: install manually: https://github.com/artempyanykh/marksman/releases"
|
skip "marksman — Fedora: install manually: https://github.com/artempyanykh/marksman/releases"
|
||||||
fi
|
|
||||||
SKIPPED+=("marksman")
|
SKIPPED+=("marksman")
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
|
@ -733,10 +679,8 @@ 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; then
|
if pip3 install --quiet "$pkg" 2>/dev/null || \
|
||||||
ok "$pkg"; INSTALLED+=("$pkg")
|
pip3 install --quiet --break-system-packages "$pkg" 2>/dev/null; then
|
||||||
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")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue