LSP 分层后端、UI 增强、UX 修复与完整文档

合并 PR #5:tiered LSP backend (CoC/vim-lsp), vim-which-key, vim-startify, indentLine, 修复按键冲突,UX 改进。
This commit is contained in:
m1ngsama 2026-02-21 12:30:06 +08:00 committed by GitHub
parent b2ccc50b4d
commit 323bf4a6b3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 952 additions and 749 deletions

459
.vimrc
View file

@ -37,15 +37,6 @@ if !g:is_tty
set cursorline set cursorline
endif endif
" Set shift width to 4 spaces
set shiftwidth=4
" Set tab width to 4 columns
set tabstop=4
" Use space characters instead of tabs
set expandtab
" Do not save backup files " Do not save backup files
set nobackup set nobackup
@ -70,9 +61,6 @@ set showcmd
" Show the mode you are on the last line " Show the mode you are on the last line
set showmode set showmode
" Show matching words during a search
set showmatch
" Use highlighting when doing a search " Use highlighting when doing a search
set hlsearch set hlsearch
@ -124,10 +112,8 @@ set lazyredraw
" For regular expressions turn magic on " For regular expressions turn magic on
set magic set magic
" Show matching brackets when text indicator is over them " Show matching brackets and how many tenths of a second to blink
set showmatch set showmatch
" How many tenths of a second to blink when matching brackets
set mat=2 set mat=2
" No annoying sound on errors " No annoying sound on errors
@ -152,11 +138,16 @@ endif
" Use Unix as the standard file type " Use Unix as the standard file type
set ffs=unix,dos,mac set ffs=unix,dos,mac
" Turn backup off, since most stuff is in SVN, git etc. anyway
set nobackup
set nowb set nowb
set noswapfile set noswapfile
" Persistent undo across sessions
if has('persistent_undo')
set undofile
let &undodir = expand('~/.vim/.undo')
silent! call mkdir(&undodir, 'p', 0700)
endif
" ============================================================================ " ============================================================================
" => Vim-Plug Plugin Manager " => Vim-Plug Plugin Manager
" ============================================================================ " ============================================================================
@ -175,7 +166,6 @@ call plug#begin('~/.vim/plugged')
Plug 'preservim/nerdtree' " File explorer Plug 'preservim/nerdtree' " File explorer
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim' " Fuzzy finder Plug 'junegunn/fzf.vim' " Fuzzy finder
Plug 'ctrlpvim/ctrlp.vim' " Fuzzy file finder
" ===== Git Integration ===== " ===== Git Integration =====
Plug 'tpope/vim-fugitive' " Git wrapper Plug 'tpope/vim-fugitive' " Git wrapper
@ -207,9 +197,9 @@ Plug 'mbbill/undotree' " Undo history visualizer
Plug 'preservim/tagbar' " Tag browser Plug 'preservim/tagbar' " Tag browser
Plug 'easymotion/vim-easymotion' " Easy motion Plug 'easymotion/vim-easymotion' " Easy motion
" ===== Code Intelligence ===== " ===== Code Intelligence (CoC: requires Vim 8.0.1453+ and Node.js) =====
if has('vim9') || has('nvim') if (has('nvim') || has('patch-8.0.1453')) && executable('node')
Plug 'neoclide/coc.nvim', {'branch': 'release'} " LSP & Completion Plug 'neoclide/coc.nvim', {'branch': 'release'} " Full LSP + completion via Node.js
endif endif
" ===== Session Management ===== " ===== Session Management =====
@ -221,8 +211,36 @@ Plug 'tpope/vim-unimpaired' " Handy bracket mappings
Plug 'wellle/targets.vim' " Additional text objects Plug 'wellle/targets.vim' " Additional text objects
Plug 'honza/vim-snippets' " Snippet collection Plug 'honza/vim-snippets' " Snippet collection
" ===== Native LSP (vim-lsp: works without Node.js, Vim 8.0+ only) =====
" Used as fallback when CoC/Node.js is unavailable
if !((has('nvim') || has('patch-8.0.1453')) && executable('node'))
Plug 'prabirshrestha/vim-lsp' " Pure VimScript LSP client
Plug 'mattn/vim-lsp-settings' " Auto-configure language servers
Plug 'prabirshrestha/asyncomplete.vim' " Async completion framework
Plug 'prabirshrestha/asyncomplete-lsp.vim' " LSP completion source for asyncomplete
endif
" ===== Enhanced UI Experience =====
Plug 'mhinz/vim-startify' " Startup screen with recent files
Plug 'liuchengxu/vim-which-key' " Show keybindings on leader pause
if !g:is_tty
Plug 'Yggdroot/indentLine' " Indent guide lines
endif
call plug#end() call plug#end()
" ============================================================================
" => LSP Backend Detection & Completion Settings
" ============================================================================
" Detect which LSP backend is active
" Priority: CoC (full-featured, needs Node.js) > vim-lsp (lightweight fallback)
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"]')
" Limit popup menu height (applies to all completion)
set pumheight=15
" ============================================================================ " ============================================================================
" => Colors and Fonts " => Colors and Fonts
" ============================================================================ " ============================================================================
@ -278,9 +296,8 @@ set tabstop=4
set lbr set lbr
set tw=500 set tw=500
set ai "Auto indent set autoindent
set si "Smart indent set smartindent
set wrap "Wrap lines
" ============================================================================ " ============================================================================
" => Key Mappings " => Key Mappings
@ -335,7 +352,7 @@ au TabLeave * let g:lasttab = tabpagenr()
map <leader>te :tabedit <C-r>=expand("%:p:h")<cr>/ map <leader>te :tabedit <C-r>=expand("%:p:h")<cr>/
" Switch CWD to the directory of the open buffer " Switch CWD to the directory of the open buffer
map <leader>cd :cd %:p:h<cr>:pwd<cr> map <leader>wd :cd %:p:h<cr>:pwd<cr>
" Remap VIM 0 to first non-blank character " Remap VIM 0 to first non-blank character
map 0 ^ map 0 ^
@ -355,9 +372,6 @@ map <leader>sp [s
map <leader>sa zg map <leader>sa zg
map <leader>s? z= map <leader>s? z=
" Remove trailing whitespace
nnoremap <leader>w :let _s=@/<Bar>:%s/\s\+$//e<Bar>:let @/=_s<Bar><CR>
" Toggle paste mode " Toggle paste mode
set pastetoggle=<F2> set pastetoggle=<F2>
@ -370,6 +384,38 @@ nnoremap <F4> :set invrelativenumber<CR>
" Enable folding with the spacebar " Enable folding with the spacebar
nnoremap <space> za nnoremap <space> za
" Y yanks to end of line (consistent with D, C)
nnoremap Y y$
" Disable accidental Ex mode
nnoremap Q <nop>
" Keep visual selection after indent
vnoremap < <gv
vnoremap > >gv
" Center cursor when jumping through search results
nnoremap n nzzzv
nnoremap N Nzzzv
" Center cursor after half-page scroll
nnoremap <C-d> <C-d>zz
nnoremap <C-u> <C-u>zz
" System clipboard yank (conditional: requires clipboard provider)
if has('clipboard')
nnoremap <leader>y "+y
vnoremap <leader>y "+y
nnoremap <leader>Y "+Y
endif
" Quickfix list shortcuts ([q/]q from vim-unimpaired handles navigation)
nnoremap <leader>qo :copen<CR>
nnoremap <leader>qc :cclose<CR>
" Auto-equalize splits when terminal window is resized
autocmd VimResized * wincmd =
" ============================================================================ " ============================================================================
" => Plugin Settings " => Plugin Settings
" ============================================================================ " ============================================================================
@ -379,7 +425,10 @@ map <C-n> :NERDTreeToggle<CR>
map <leader>n :NERDTreeFind<CR> map <leader>n :NERDTreeFind<CR>
" Close vim if the only window left open is a NERDTree " Close vim if the only window left open is a NERDTree
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif augroup NERDTreeAutoClose
autocmd!
autocmd BufEnter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif
augroup END
" Show hidden files " Show hidden files
let NERDTreeShowHidden=1 let NERDTreeShowHidden=1
@ -401,7 +450,8 @@ endif
map <C-p> :Files<CR> map <C-p> :Files<CR>
map <leader>b :Buffers<CR> map <leader>b :Buffers<CR>
map <leader>rg :Rg<CR> map <leader>rg :Rg<CR>
map <leader>t :Tags<CR> map <leader>rt :Tags<CR>
map <leader>gF :GFiles<CR>
" FZF customization for better project search " FZF customization for better project search
let g:fzf_layout = { 'down': '40%' } let g:fzf_layout = { 'down': '40%' }
@ -431,13 +481,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
" --- CtrlP ---
let g:ctrlp_working_path_mode = 'ra'
let g:ctrlp_show_hidden = 1
let g:ctrlp_custom_ignore = {
\ 'dir': '\v[\/]\.(git|hg|svn)$',
\ 'file': '\v\.(exe|so|dll|pyc)$',
\ }
" --- Airline --- " --- Airline ---
" Disable powerline fonts in TTY for compatibility " Disable powerline fonts in TTY for compatibility
@ -494,17 +537,18 @@ let g:ale_fixers = {
\ 'markdown': ['prettier'], \ 'markdown': ['prettier'],
\} \}
let g:ale_fix_on_save = 1 " Don't fix on save if LSP is handling formatting (avoids double-format)
let g:ale_fix_on_save = !g:use_vimlsp
let g:ale_sign_error = 'X' let g:ale_sign_error = 'X'
let g:ale_sign_warning = '!' let g:ale_sign_warning = '!'
let g:ale_lint_on_text_changed = 'never' 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
" Navigate between errors " Navigate between errors: [e/]e (unimpaired style), <leader>aD for detail
nmap <silent> <leader>aj :ALENext<cr> nmap <silent> [e :ALENext<cr>
nmap <silent> <leader>ak :ALEPrevious<cr> nmap <silent> ]e :ALEPrevious<cr>
nmap <silent> <leader>ad :ALEDetail<cr> nmap <silent> <leader>aD :ALEDetail<cr>
" --- Tagbar --- " --- Tagbar ---
nmap <F8> :TagbarToggle<CR> nmap <F8> :TagbarToggle<CR>
@ -525,16 +569,16 @@ let g:EasyMotion_smartcase = 1
map <Leader>j <Plug>(easymotion-j) map <Leader>j <Plug>(easymotion-j)
map <Leader>k <Plug>(easymotion-k) map <Leader>k <Plug>(easymotion-k)
" --- CoC (Conquer of Completion) --- " --- CoC (Conquer of Completion) - Full LSP via Node.js ---
if exists('g:plugs["coc.nvim"]') if g:use_coc
" Use tab for trigger completion with characters ahead and navigate " Tab for trigger completion / navigate popup
inoremap <silent><expr> <TAB> inoremap <silent><expr> <TAB>
\ coc#pum#visible() ? coc#pum#next(1) : \ coc#pum#visible() ? coc#pum#next(1) :
\ CheckBackspace() ? "\<Tab>" : \ CheckBackspace() ? "\<Tab>" :
\ coc#refresh() \ coc#refresh()
inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>" inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"
" Make <CR> to accept selected completion item " CR to confirm selected completion item
inoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm() inoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm()
\: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>" \: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
@ -543,12 +587,13 @@ if exists('g:plugs["coc.nvim"]')
return !col || getline('.')[col - 1] =~# '\s' return !col || getline('.')[col - 1] =~# '\s'
endfunction endfunction
" Use <c-space> to trigger completion " <C-Space> to trigger completion manually
inoremap <silent><expr> <c-space> coc#refresh() inoremap <silent><expr> <c-space> coc#refresh()
" Use `[g` and `]g` to navigate diagnostics " Diagnostic navigation
nmap <silent> [g <Plug>(coc-diagnostic-prev) nmap <silent> [g <Plug>(coc-diagnostic-prev)
nmap <silent> ]g <Plug>(coc-diagnostic-next) nmap <silent> ]g <Plug>(coc-diagnostic-next)
nmap <silent> <leader>ad :CocDiagnostics<CR>
" GoTo code navigation " GoTo code navigation
nmap <silent> gd <Plug>(coc-definition) nmap <silent> gd <Plug>(coc-definition)
@ -556,9 +601,8 @@ if exists('g:plugs["coc.nvim"]')
nmap <silent> gi <Plug>(coc-implementation) nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references) nmap <silent> gr <Plug>(coc-references)
" Use K to show documentation in preview window " Hover documentation
nnoremap <silent> K :call ShowDocumentation()<CR> nnoremap <silent> K :call ShowDocumentation()<CR>
function! ShowDocumentation() function! ShowDocumentation()
if CocAction('hasProvider', 'hover') if CocAction('hasProvider', 'hover')
call CocActionAsync('doHover') call CocActionAsync('doHover')
@ -567,15 +611,133 @@ if exists('g:plugs["coc.nvim"]')
endif endif
endfunction endfunction
" Highlight the symbol and its references when holding the cursor " Highlight symbol and its references on cursor hold
autocmd CursorHold * silent call CocActionAsync('highlight') autocmd CursorHold * silent call CocActionAsync('highlight')
" Symbol renaming " Symbol renaming
nmap <leader>rn <Plug>(coc-rename) nmap <leader>rn <Plug>(coc-rename)
" Formatting selected code " Format selected code
xmap <leader>f <Plug>(coc-format-selected) xmap <leader>f <Plug>(coc-format-selected)
nmap <leader>f <Plug>(coc-format-selected) nmap <leader>f <Plug>(coc-format-selected)
" Code actions (cursor, file, selected range)
nmap <leader>ca <Plug>(coc-codeaction-cursor)
nmap <leader>cA <Plug>(coc-codeaction-source)
xmap <leader>ca <Plug>(coc-codeaction-selected)
" Apply auto-fix for current line
nmap <leader>qf <Plug>(coc-fix-current)
" Run code lens action on current line
nmap <leader>cl <Plug>(coc-codelens-action)
" Workspace symbols and outline
nnoremap <silent> <leader>ws :CocList -I symbols<CR>
nnoremap <silent> <leader>o :CocList outline<CR>
" Search recently used commands
nnoremap <silent> <leader>cc :CocList commands<CR>
" Resume latest CoC list
nnoremap <silent> <leader>cr :CocListResume<CR>
" Show all diagnostics
nnoremap <silent> <leader>cD :CocList diagnostics<CR>
" Text object for function/class (requires language server support)
xmap if <Plug>(coc-funcobj-i)
omap if <Plug>(coc-funcobj-i)
xmap af <Plug>(coc-funcobj-a)
omap af <Plug>(coc-funcobj-a)
xmap ic <Plug>(coc-classobj-i)
omap ic <Plug>(coc-classobj-i)
xmap ac <Plug>(coc-classobj-a)
omap ac <Plug>(coc-classobj-a)
" Scroll float windows
if has('nvim-0.4.0') || has('patch-8.2.0750')
nnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
nnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
inoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(1)\<cr>" : "\<Right>"
inoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(0)\<cr>" : "\<Left>"
endif
" Status line integration
set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}
endif
" --- vim-lsp (Native VimScript LSP - fallback when Node.js unavailable) ---
if g:use_vimlsp
" Auto-configure language servers via vim-lsp-settings
let g:lsp_settings_filetype_python = ['pylsp', 'pyright-langserver']
let g:lsp_settings_filetype_go = ['gopls']
let g:lsp_settings_filetype_rust = ['rust-analyzer']
let g:lsp_settings_filetype_typescript = ['typescript-language-server']
let g:lsp_settings_filetype_javascript = ['typescript-language-server']
let g:lsp_settings_filetype_sh = ['bash-language-server']
" Performance: disable virtual text diagnostics in TTY
let g:lsp_diagnostics_virtual_text_enabled = !g:is_tty
let g:lsp_diagnostics_highlights_enabled = !g:is_tty
let g:lsp_document_highlight_enabled = !g:is_tty
let g:lsp_signs_enabled = 1
let g:lsp_diagnostics_echo_cursor = 1
let g:lsp_completion_documentation_enabled = 1
" Diagnostic signs (ASCII, KISS)
let g:lsp_signs_error = {'text': 'X'}
let g:lsp_signs_warning = {'text': '!'}
let g:lsp_signs_information = {'text': 'i'}
let g:lsp_signs_hint = {'text': '>'}
" asyncomplete manages completeopt for vim-lsp mode
set completeopt=menuone,noinsert,noselect
let g:asyncomplete_auto_popup = 1
let g:asyncomplete_auto_completeopt = 1
let g:asyncomplete_popup_delay = 200
" Tab to navigate completion popup (mirrors CoC behavior)
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <expr> <CR> pumvisible() ? asyncomplete#close_popup() : "\<CR>"
" Key mappings (mirror CoC's gd/gy/gi/gr/K/<leader>rn layout)
function! s:on_lsp_buffer_enabled() abort
setlocal omnifunc=lsp#complete
setlocal signcolumn=yes
" Navigation
nmap <buffer> gd <plug>(lsp-definition)
nmap <buffer> gy <plug>(lsp-type-definition)
nmap <buffer> gi <plug>(lsp-implementation)
nmap <buffer> gr <plug>(lsp-references)
nmap <buffer> [g <plug>(lsp-previous-diagnostic)
nmap <buffer> ]g <plug>(lsp-next-diagnostic)
" Hover documentation
nmap <buffer> K <plug>(lsp-hover)
" Refactoring
nmap <buffer> <leader>rn <plug>(lsp-rename)
nmap <buffer> <leader>ca <plug>(lsp-code-action)
nmap <buffer> <leader>f <plug>(lsp-document-format)
" Workspace
nmap <buffer> <leader>ws <plug>(lsp-workspace-symbol-search)
nmap <buffer> <leader>o <plug>(lsp-document-symbol-search)
nmap <buffer> <leader>cD <plug>(lsp-document-diagnostics)
" Enable auto-format on save for filetypes with reliable LSP formatters
if index(['python', 'go', 'rust', 'typescript', 'javascript', 'sh'], &filetype) >= 0
autocmd BufWritePre <buffer> LspDocumentFormatSync
endif
endfunction
augroup lsp_install
autocmd!
autocmd User lsp_buffer_enabled call s:on_lsp_buffer_enabled()
augroup END
endif endif
" ============================================================================ " ============================================================================
@ -682,9 +844,6 @@ set laststatus=2
" => Misc " => Misc
" ============================================================================ " ============================================================================
" Quickly open a buffer for scribble
map <leader>q :e ~/buffer<cr>
" Quickly open a markdown buffer for scribble " Quickly open a markdown buffer for scribble
map <leader>m :e ~/buffer.md<cr> map <leader>m :e ~/buffer.md<cr>
@ -743,9 +902,6 @@ set secure
" Quick format entire file " Quick format entire file
nnoremap <leader>F gg=G`` nnoremap <leader>F gg=G``
" Toggle between source and header files (for C/C++)
nnoremap <leader>a :A<CR>
" Quick save all buffers " Quick save all buffers
nnoremap <leader>wa :wa<CR> nnoremap <leader>wa :wa<CR>
@ -796,7 +952,7 @@ augroup END
" ============================================================================ " ============================================================================
" Show syntax highlighting groups for word under cursor " Show syntax highlighting groups for word under cursor
nmap <leader>sp :call <SID>SynStack()<CR> nmap <leader>sh :call <SID>SynStack()<CR>
function! <SID>SynStack() function! <SID>SynStack()
if !exists("*synstack") if !exists("*synstack")
return return
@ -850,8 +1006,8 @@ function! LargeFileSettings()
setlocal undolevels=-1 setlocal undolevels=-1
setlocal eventignore+=FileType setlocal eventignore+=FileType
setlocal noswapfile setlocal noswapfile
setlocal buftype=nowrite setlocal syntax=OFF
echo "Large file detected. Some features disabled for performance." echo "Large file (>10MB): syntax and undo disabled for performance."
endfunction endfunction
" ============================================================================ " ============================================================================
@ -866,15 +1022,7 @@ if g:is_tty
" 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%)
" Disable some visual effects " Reduce syntax highlighting complexity in TTY (global is 200, lower here)
set novisualbell
set noerrorbells
" Faster redraw
set lazyredraw
set ttyfast
" Reduce syntax highlighting complexity
set synmaxcol=120 set synmaxcol=120
endif endif
@ -887,6 +1035,177 @@ if g:is_tty && !exists("g:tty_message_shown")
let g:tty_message_shown = 1 let g:tty_message_shown = 1
endif endif
" ============================================================================
" => Which-Key: Keybinding Hints
" ============================================================================
" Show available bindings after <leader> with a 500ms pause
set timeoutlen=500
if exists('g:plugs["vim-which-key"]')
" Register after plugins are loaded (autoload functions available at VimEnter)
autocmd VimEnter * call which_key#register(',', 'g:which_key_map')
nnoremap <silent> <leader> :<C-u>WhichKey ','<CR>
vnoremap <silent> <leader> :<C-u>WhichKeyVisual ','<CR>
" Top-level single-key bindings (w and q also have sub-groups below)
let g:which_key_map = {}
let g:which_key_map['x'] = 'save-and-quit'
let g:which_key_map['F'] = 'format-file'
let g:which_key_map['W'] = 'strip-trailing-whitespace'
let g:which_key_map['m'] = 'scratch-markdown'
let g:which_key_map['n'] = 'nerdtree-find'
let g:which_key_map['o'] = 'outline'
let g:which_key_map['b'] = 'buffers'
let g:which_key_map['h'] = 'prev-buffer'
let g:which_key_map['l'] = 'next-buffer'
let g:which_key_map['*'] = 'search-replace-word'
let g:which_key_map[','] = 'last-file'
let g:which_key_map['y'] = 'clipboard-yank'
let g:which_key_map['Y'] = 'clipboard-yank-line'
" [a]LE lint group ([e/]e navigate; <leader>aD for detail)
let g:which_key_map['a'] = {
\ 'name': '+ale-lint',
\ 'D': 'ale-detail',
\ }
" [c]ode / [c]opy group
let g:which_key_map['c'] = {
\ 'name': '+code/copy',
\ 'a': 'code-action-cursor',
\ 'A': 'code-action-source',
\ 'c': 'coc-commands',
\ 'D': 'diagnostics-list',
\ 'l': 'code-lens',
\ 'r': 'coc-list-resume',
\ 'p': 'copy-filepath',
\ 'f': 'copy-filename',
\ }
" [e]dit group
let g:which_key_map['e'] = {
\ 'name': '+edit',
\ 'v': 'edit-vimrc',
\ }
" [g]it group
let g:which_key_map['g'] = {
\ 'name': '+git',
\ 's': 'status',
\ 'c': 'commit',
\ 'p': 'push',
\ 'l': 'pull',
\ 'd': 'diff',
\ 'b': 'blame',
\ 'F': 'git-files-fzf',
\ }
" [q]uickfix group (also: <leader>q = fast quit)
let g:which_key_map['q'] = {
\ 'name': '+quickfix',
\ 'f': 'lsp-fix-current',
\ 'o': 'open-quickfix',
\ 'c': 'close-quickfix',
\ }
" [r]efactor / [r]ipgrep / [r]eplace group
let g:which_key_map['r'] = {
\ 'name': '+search/refactor',
\ 'n': 'rename',
\ 'g': 'ripgrep',
\ 't': 'tags-search',
\ }
" [s]pell / [s]ource group
let g:which_key_map['s'] = {
\ 'name': '+spell/source',
\ 's': 'toggle-spell',
\ 'n': 'next-spell',
\ 'p': 'prev-spell',
\ 'a': 'add-word',
\ '?': 'suggest',
\ 'v': 'source-vimrc',
\ 'o': 'source-file',
\ 'h': 'syntax-highlight-stack',
\ }
" [t]ab / [t]erminal group
let g:which_key_map['t'] = {
\ 'name': '+tab/terminal',
\ 'n': 'new-tab',
\ 'o': 'tab-only',
\ 'c': 'close-tab',
\ 'm': 'move-tab',
\ 'l': 'last-tab',
\ 'e': 'edit-in-tab',
\ 'v': 'terminal-vertical',
\ 'h': 'terminal-horizontal',
\ }
" [w]orkspace / [w]indow / save group (also: <leader>w = fast save)
let g:which_key_map['w'] = {
\ 'name': '+save/window',
\ 'a': 'save-all',
\ 's': 'workspace-symbols',
\ 'd': 'change-dir',
\ }
endif
" ============================================================================
" => Startify: Startup Screen
" ============================================================================
if exists('g:plugs["vim-startify"]')
" Simple ASCII header, no icons (KISS)
let g:startify_custom_header = [
\ ' VIM - Vi IMproved',
\ ' Type :help if you are in trouble',
\ '',
\ ]
" Sections shown on start screen
let g:startify_lists = [
\ { 'type': 'files', 'header': [' Recent Files'] },
\ { 'type': 'dir', 'header': [' Directory: '. getcwd()] },
\ { 'type': 'sessions', 'header': [' Sessions'] },
\ { 'type': 'bookmarks', 'header': [' Bookmarks'] },
\ ]
" Session integration
let g:startify_session_persistence = 1 " Auto-save session on quit
let g:startify_session_autoload = 1 " Auto-load Session.vim if present
let g:startify_change_to_vcs_root = 1 " cd to git root on open
let g:startify_fortune_use_unicode = 0 " No unicode in fortune (KISS)
let g:startify_enable_special = 0 " No <empty> / <quit> entries
" Limit recent files shown
let g:startify_files_number = 10
" Don't open NERDTree when startify is active
autocmd User Startified setlocal buftype=
endif
" ============================================================================
" => IndentLine: Indent Guide Lines (non-TTY only)
" ============================================================================
if !g:is_tty && exists('g:plugs["indentLine"]')
" Use simple ASCII bar as indent guide
let g:indentLine_char = '|'
let g:indentLine_first_char = '|'
let g:indentLine_showFirstIndentLevel = 1
" Disable in certain filetypes where it causes issues
let g:indentLine_fileTypeExclude = ['text', 'help', 'startify', 'nerdtree', 'markdown']
let g:indentLine_bufTypeExclude = ['help', 'terminal', 'nofile']
" Conceal level settings (prevent hiding quotes in JSON/markdown)
let g:indentLine_setConceal = 2
let g:indentLine_concealcursor = ''
endif
" ============================================================================ " ============================================================================
" End of Configuration " End of Configuration
" ============================================================================ " ============================================================================

View file

@ -1,274 +1,207 @@
# Quick Start Guide # Quick Start
Get up and running with this Vim configuration in 5 minutes! Five minutes from zero to a working Vim engineering environment.
## Installation ## Step 1: Install
### One-Line Install
```bash ```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim && cd ~/.vim && ./install.sh
```
**IMPORTANT:** Always run the install script from the `~/.vim` directory (where you cloned the repository). The script validates this to ensure correct symlink creation.
That's it! The script will:
- Verify it's being run from the correct directory
- Backup your existing .vimrc
- Create and validate symlink to the new configuration
- Install vim-plug
- Install all plugins automatically
### Manual Install
```bash
# 1. Clone the repository
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
cd ~/.vim && ./install.sh
# 2. Create symlink
ln -sf ~/.vim/.vimrc ~/.vimrc
# 3. Install vim-plug
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
# 4. Open Vim and install plugins
vim +PlugInstall +qall
``` ```
## Essential Key Mappings The script handles everything: symlinks, vim-plug, plugin download.
No root access required.
### File Operations ## Step 2: Open Vim
| Key | Action |
|-----|--------|
| `,w` | Quick save |
| `,q` | Quick quit |
| `,x` | Save and quit |
### Navigation ```bash
| Key | Action | vim
|-----|--------| ```
| `Ctrl+n` | Toggle file explorer (NERDTree) |
| `Ctrl+p` | Fuzzy file search (FZF) |
| `Ctrl+h/j/k/l` | Navigate between windows |
| `,b` | Search open buffers |
### Code Intelligence The startup screen shows recent files and sessions. Press `q` to dismiss
| Key | Action | or just start typing a filename to open.
|-----|--------|
| `gd` | Go to definition |
| `gr` | Find references |
| `K` | Show documentation |
| `Tab` | Autocomplete (when popup is visible) |
### Editing ## Step 3: Install LSP (pick one path)
| Key | Action |
|-----|--------| ### Path A: With Node.js (full CoC)
| `gc` | Comment/uncomment (in visual mode) |
| `Space` | Toggle fold | ```bash
| `,,+Enter` | Clear search highlight | node --version # confirm >= 14.14
```
Inside Vim, install language servers for your stack:
```vim
:CocInstall coc-pyright coc-tsserver coc-go coc-rust-analyzer
```
### Path B: Without Node.js (vim-lsp)
Open a file of your language, then run:
```vim
:LspInstallServer
```
This auto-detects and installs the correct language server binary.
---
## Daily Use
### The 10 keys that matter most
```
,w Save
,q Quit
Ctrl+n File tree
Ctrl+p Fuzzy find file
gd Go to definition
K Show docs
[g ]g Prev/next diagnostic
,rn Rename symbol
,gs Git status
, (pause 500ms) Show all shortcuts
```
### Open a project
```bash
cd ~/my-project && vim
```
NERDTree auto-opens when you launch Vim on a directory. Use `Ctrl+p` to
fuzzy-search files by name. Use `,rg` to search file contents.
### Navigate code
| Key | Action |
|-------|---------------------------------|
| `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
,gb blame current file
,gc commit
,gp push
,gl pull
```
---
## Common Workflows ## Common Workflows
### Opening a Project ### Python project
```bash ```bash
# Navigate to your project directory pip install black flake8 pylint isort
cd ~/my-project vim my_script.py
# Open Vim
vim
# Press Ctrl+n to open file explorer
# Press Ctrl+p to fuzzy search files
``` ```
### Editing Code Auto-formats with black on save. Lint errors show in the sign column as
`X` (error) and `!` (warning). Jump between them with `[g` / `]g`.
1. Open a file with `Ctrl+p` or through NERDTree ### JavaScript / TypeScript project
2. Use `gd` to jump to definitions
3. Use `K` to view documentation
4. Use `Tab` for autocomplete while typing
5. Save with `,w`
### Working with Git
| Command | Action |
|---------|--------|
| `:Git status` | View git status |
| `:Git diff` | View changes |
| `:Git commit` | Commit changes |
| `:Git push` | Push to remote |
| `,gb` | Open git blame window |
### Search and Replace
```vim
" Search in current file
/searchterm
" Search across project (with FZF)
,rg
" Replace in file
:%s/old/new/g
" Replace with confirmation
:%s/old/new/gc
```
## Language-Specific Features
### Python
- Auto-formatting with Black (on save)
- Linting with flake8/pylint
- 4-space indentation
- 88-character line limit
**Setup:**
```bash ```bash
pip install black flake8 pylint npm install -g prettier eslint typescript
vim -c "CocInstall coc-pyright" -c "q" vim src/index.ts
``` ```
### JavaScript/TypeScript Auto-formats with prettier on save. Use `:CocInstall coc-tsserver` for
full IntelliSense (requires Node.js).
- Prettier formatting (on save) ### Go project
- ESLint integration
- 2-space indentation
**Setup:**
```bash
npm install -g prettier eslint
vim -c "CocInstall coc-tsserver coc-prettier coc-eslint" -c "q"
```
### Go
- Auto-formatting with gofmt
- Auto-imports with goimports
- Tab indentation
**Setup:**
```bash ```bash
go install golang.org/x/tools/gopls@latest go install golang.org/x/tools/gopls@latest
vim -c "CocInstall coc-go" -c "q" vim main.go
``` ```
## Troubleshooting gofmt runs on save automatically. `gd` jumps to definitions even across
package boundaries when gopls is running.
### Plugins not working? ---
## Customize
Edit config live:
```vim ```vim
:PlugInstall ,ev " opens ~/.vimrc in Vim
:PlugUpdate ,sv " reloads config without restarting
``` ```
### Autocomplete not working? Per-project overrides: create `.vimrc` in your project root.
Make sure Node.js is installed: ---
```bash
node --version # Should be >= 14.14
```
Then install CoC language servers: ## Quick Reference
```vim
:CocInstall coc-json coc-tsserver coc-pyright
```
### FZF not finding files?
Install FZF and ripgrep:
```bash
# Ubuntu/Debian
sudo apt install fzf ripgrep
# macOS
brew install fzf ripgrep
```
### Colors look weird?
Add to your `~/.bashrc` or `~/.zshrc`:
```bash
export TERM=xterm-256color
```
## Customization
The `.vimrc` file is well-organized into sections:
1. **General Settings** (lines 1-150) - Basic Vim behavior
2. **Plugin Management** (lines 151-230) - Plugin list
3. **Key Mappings** (lines 300-400) - Custom shortcuts
4. **Plugin Settings** (lines 400-600) - Plugin configurations
To customize:
1. Open `~/.vim/.vimrc`
2. Find the section you want to modify
3. Make your changes
4. Reload with `:source ~/.vimrc` or restart Vim
### Common Customizations
**Change colorscheme:**
```vim
" In .vimrc, find the colorscheme line and change to:
colorscheme dracula
" or: solarized, onedark, gruvbox
```
**Change leader key:**
```vim
" Default is comma (,), change to space:
let mapleader = " "
```
**Disable relative line numbers:**
```vim
set norelativenumber
```
## Next Steps
1. Read the full [README.md](README.md) for complete documentation
2. Check out `:help` in Vim for built-in documentation
3. Customize the configuration to your needs
4. Share your improvements!
## Quick Reference Card
Print this for your desk:
``` ```
┌─────────────────────────────────────────────┐ FILES
│ Vim Quick Reference │ Ctrl+n File tree toggle
├─────────────────────────────────────────────┤ Ctrl+p Fuzzy find file
│ FILES │ ,b Search open buffers
│ Ctrl+n File explorer │ ,rg Search file contents (ripgrep)
│ Ctrl+p Fuzzy find files │ ,w Save | ,q Quit | ,x Save+quit
│ ,w Save │ ,wa Save all buffers
│ ,q Quit │
├─────────────────────────────────────────────┤ CODE
│ NAVIGATION │ gd Go to definition
│ gd Go to definition │ K Show documentation
│ gr Find references │ [g / ]g Prev/next diagnostic
│ K Show docs │ ,rn Rename symbol
│ Ctrl+o Jump back │ ,ca Code action
│ Ctrl+i Jump forward │ ,f Format selection
├─────────────────────────────────────────────┤ ,F Format whole file
│ EDITING │
│ gc Comment (visual mode) │ GIT
│ Tab Autocomplete │ ,gs Status | ,gd Diff | ,gb Blame
│ Space Toggle fold │ ,gc Commit | ,gp Push | ,gl Pull
├─────────────────────────────────────────────┤
│ SEARCH │ WINDOWS
│ /text Search forward │ Ctrl+h/j/k/l Move between panes
│ ?text Search backward │ ,tv Open terminal (vertical)
│ ,rg Project-wide search │ ,th Open terminal (horizontal)
│ ,,Enter Clear highlight │ Esc Exit terminal mode
└─────────────────────────────────────────────┘ F5 Undo tree | F8 Tag browser
SEARCH
/text Search forward
?text Search backward
,<CR> Clear search highlight
,* Replace word under cursor (project)
``` ```
Happy Vimming! ---
See [README.md](README.md) for the complete reference.

647
README.md
View file

@ -1,54 +1,45 @@
# The Ultimate Vim Configuration # chopsticks - Vim Configuration
A comprehensive, modern Vim configuration optimized for engineering workflows. This configuration transforms vanilla Vim into a powerful, feature-rich development environment with enterprise-grade tooling. A native Vim configuration optimized for engineering workflows. Designed for
Vim 8.0+ with automatic fallbacks for minimal environments (TTY, no Node.js).
**NEW: Quick installation script and enhanced engineering features!** ## Quick Install
## Quick Start
```bash ```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim && cd ~/.vim && ./install.sh git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
cd ~/.vim && ./install.sh
``` ```
**Note:** The installation script must be run from the cloned `~/.vim` directory. See [QUICKSTART.md](QUICKSTART.md) for detailed getting started guide. See [QUICKSTART.md](QUICKSTART.md) for the 5-minute guide.
## Features ---
### Core Enhancements ## Design Principles
- **Smart Line Numbers**: Hybrid line numbers (absolute + relative) for efficient navigation
- **Modern UI**: Gruvbox color scheme with airline status bar
- **Plugin Management**: vim-plug for easy plugin installation and updates
- **Auto-completion**: CoC (Conquer of Completion) for intelligent code completion
- **Syntax Checking**: ALE (Asynchronous Lint Engine) for real-time linting
### File Navigation - **KISS**: No icon fonts, no unicode glyphs, plain ASCII throughout
- **NERDTree**: Visual file explorer (`Ctrl+n`) - **Tiered LSP**: CoC (full) with vim-lsp fallback - works with or without Node.js
- **FZF**: Blazing fast fuzzy finder (`Ctrl+p`) - **TTY-aware**: Automatic detection and optimization for console environments
- **CtrlP**: Alternative fuzzy file finder - **Engineering-first**: Git workflow, session management, project-local config
- **Easy Motion**: Jump to any location with minimal keystrokes
### Git Integration ---
- **Fugitive**: Complete Git wrapper for Vim
- **GitGutter**: Show git diff in the sign column
### Code Editing ## Requirements
- **Auto-pairs**: Automatic bracket/quote pairing
- **Surround**: Easily change surrounding quotes, brackets, tags
- **Commentary**: Quick code commenting (`gc`)
- **Multi-language Support**: vim-polyglot for 100+ languages
### Productivity Tools | Requirement | Minimum | Notes |
- **UndoTree**: Visualize and navigate undo history (`F5`) |----------------|-------------|--------------------------------|
- **Tagbar**: Code structure browser (`F8`) | Vim | 8.0+ | vim9script not required |
- **Smart Window Management**: Easy navigation with `Ctrl+hjkl` | git | any | For cloning and fugitive |
- **Session Management**: Auto-save sessions with vim-obsession | curl | any | For vim-plug auto-install |
- **Project-Specific Settings**: Per-project .vimrc support | Node.js | 14.14+ | Optional, enables CoC LSP |
- **Large File Optimization**: Automatic performance tuning for files >10MB | ripgrep (rg) | any | Optional, enables :Rg search |
- **TTY/Basic Terminal Support**: Automatic optimization for console environments | fzf | any | Optional, enables :Files/:GFiles |
| ctags | any | Optional, enables :TagbarToggle |
---
## Installation ## Installation
### Automatic Installation (Recommended) ### Automatic
```bash ```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
@ -56,417 +47,379 @@ cd ~/.vim
./install.sh ./install.sh
``` ```
**IMPORTANT:** You must run the install script from the `~/.vim` directory (the cloned repository directory). Do not copy the script to another location and run it from there. The script:
1. Checks for a working Vim installation
2. Backs up your existing `~/.vimrc` if present
3. Creates a symlink: `~/.vimrc -> ~/.vim/.vimrc`
4. Installs vim-plug
5. Runs `:PlugInstall` to download all plugins
6. Optionally installs CoC language servers (if Node.js is available)
The installation script will: ### Manual
- Verify it's being run from the correct directory
- Backup your existing configuration
- Create necessary symlinks
- Validate symlink creation
- Install vim-plug automatically
- Install all plugins
- Offer to install CoC language servers
### Manual Installation
```bash ```bash
# 1. Clone this repository
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
cd ~/.vim ln -sf ~/.vim/.vimrc ~/.vimrc
# 2. Create symlink to .vimrc
ln -s ~/.vim/.vimrc ~/.vimrc
# 3. Install vim-plug
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
# 4. Open Vim and install plugins
vim +PlugInstall +qall vim +PlugInstall +qall
``` ```
### 4. (Optional) Install recommended dependencies ---
For the best experience, install these optional dependencies: ## LSP: Tiered Backend System
```bash Code intelligence is provided by one of two backends, selected automatically:
# FZF (fuzzy finder)
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install
# ripgrep (better grep) | Condition | Backend | Features |
# On Ubuntu/Debian |----------------------------------|----------------|-----------------------------------------------|
sudo apt install ripgrep | 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|
| Any Vim | **ALE** | Linting and auto-fix (always active) |
# On macOS Both backends expose identical key mappings (`gd`, `K`, `[g`, `]g`, `<leader>rn`, `<leader>ca`).
brew install ripgrep
# Node.js (for CoC) ### CoC setup (with Node.js)
# Required for code completion
curl -sL install-node.now.sh/lts | bash
# Universal Ctags (for Tagbar) Install language server extensions from inside Vim:
# On Ubuntu/Debian
sudo apt install universal-ctags
# On macOS
brew install universal-ctags
```
### 5. Install CoC language servers
For intelligent code completion, install language servers:
```vim ```vim
" Python :CocInstall coc-pyright " Python
:CocInstall coc-pyright :CocInstall coc-tsserver " JavaScript / TypeScript
:CocInstall coc-go " Go
" JavaScript/TypeScript :CocInstall coc-rust-analyzer " Rust
:CocInstall coc-tsserver :CocInstall coc-json coc-yaml " JSON, YAML
:CocInstall coc-html coc-css " HTML, CSS
" Go
:CocInstall coc-go
" JSON
:CocInstall coc-json
" HTML/CSS
:CocInstall coc-html coc-css
" See more: https://github.com/neoclide/coc.nvim/wiki/Using-coc-extensions
``` ```
### vim-lsp setup (without Node.js)
Install language server binaries for your languages, then run:
```vim
:LspInstallServer " auto-installs servers for the current filetype
```
Supported: `pylsp`, `gopls`, `rust-analyzer`, `typescript-language-server`,
`bash-language-server`, and all others covered by `vim-lsp-settings`.
---
## Key Mappings ## Key Mappings
### General Leader key: `,` (comma)
| Key | Action | Press `,` and wait 500ms for an interactive guide to all bindings (vim-which-key).
|-----|--------|
| `,w` | Quick save |
| `,q` | Quick quit |
| `,x` | Save and quit |
| `,,` + Enter | Clear search highlight |
### Window Navigation ### Files and Buffers
| Key | Action | | Key | Action |
|-----|--------| |------------|-------------------------------------|
| `Ctrl+h` | Move to left window | | `Ctrl+n` | Toggle file tree (NERDTree) |
| `Ctrl+j` | Move to bottom window | | `,n` | Reveal current file in NERDTree |
| `Ctrl+k` | Move to top window | | `Ctrl+p` | Fuzzy file search (FZF) |
| `Ctrl+l` | Move to right window | | `,b` | Search open buffers (FZF) |
| `,rg` | Project-wide search (ripgrep+FZF) |
| `,rt` | Search tags (FZF) |
| `,gF` | Search git-tracked files (FZF) |
| `,l` | Next buffer |
| `,h` | Previous buffer |
| `,bd` | Close current buffer |
| `,,` | Switch to last file |
### Buffer Management ### Windows and Tabs
| Key | Action | | Key | Action |
|-----|--------| |--------------|---------------------------------|
| `,l` | Next buffer | | `Ctrl+h/j/k/l` | Navigate between windows |
| `,h` | Previous buffer | | `<Leader>=` | Increase window height |
| `,bd` | Close current buffer | | `<Leader>-` | Decrease window height |
| `,ba` | Close all buffers | | `<Leader>+` | Increase window width |
| `<Leader>_` | Decrease window width |
| `,tn` | New tab |
| `,tc` | Close tab |
| `,tl` | Toggle to last tab |
### Tab Management ### Code Intelligence (CoC / vim-lsp)
| Key | Action | | Key | Action |
|-----|--------| |-------------|---------------------------------|
| `,tn` | New tab | | `gd` | Go to definition |
| `,tc` | Close tab | | `gy` | Go to type definition |
| `,tl` | Toggle to last tab | | `gi` | Go to implementation |
| `gr` | Show references |
| `K` | Hover documentation |
| `[g` | Previous diagnostic |
| `]g` | Next diagnostic |
| `,rn` | Rename symbol |
| `,f` | Format selection |
| `,ca` | Code action (cursor) |
| `,qf` | Quick-fix current line (CoC) |
| `,cl` | Run code lens (CoC) |
| `,o` | File outline |
| `,ws` | Workspace symbols |
| `,cD` | Diagnostics list |
| `,cr` | Resume last CoC list |
| `Tab` | Next completion item |
| `Shift+Tab` | Previous completion item |
| `Enter` | Confirm completion |
### File Navigation Text objects (CoC only): `if`/`af` (function), `ic`/`ac` (class)
| Key | Action |
|-----|--------|
| `Ctrl+n` | Toggle NERDTree |
| `,n` | Find current file in NERDTree |
| `Ctrl+p` | FZF file search |
| `,b` | FZF buffer search |
| `,rg` | Ripgrep search |
### Code Navigation (CoC)
| Key | Action |
|-----|--------|
| `gd` | Go to definition |
| `gy` | Go to type definition |
| `gi` | Go to implementation |
| `gr` | Go to references |
| `K` | Show documentation |
| `[g` | Previous diagnostic |
| `]g` | Next diagnostic |
| `,rn` | Rename symbol |
### Linting (ALE) ### Linting (ALE)
| Key | Action | | Key | Action |
|-----|--------| |----------|-----------------------|
| `,aj` | Next error/warning | | `[e` | Next error/warning |
| `,ak` | Previous error/warning | | `]e` | Previous error/warning|
| `,ad` | Show error details | | `,aD` | Show error details |
### Git Workflow Signs: `X` = error, `!` = warning
| Key | Action | ### Git Workflow (fugitive)
|-----|--------|
| `,gs` | Git status | | Key | Action |
| `,gc` | Git commit | |--------|---------------------------------|
| `,gp` | Git push | | `,gs` | Git status |
| `,gl` | Git pull | | `,gc` | Git commit |
| `,gd` | Git diff | | `,gp` | Git push |
| `,gb` | Git blame | | `,gl` | Git pull |
| `,gd` | Git diff |
| `,gb` | Git blame |
| `,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 | | `,F` | Format entire file (= indent) |
| `,wa` | Save all buffers | | `,W` | Strip trailing whitespace |
| `,cp` | Copy file path | | `,wa` | Save all open buffers |
| `,cf` | Copy filename | | `,wd` | Change CWD to current buffer's dir |
| `,*` | Search & replace word under cursor | | `,cp` | Copy file path to clipboard |
| `,<leader>` | Switch to last file | | `,cf` | Copy filename to clipboard |
| `,y` | Yank to system clipboard |
| `,Y` | Yank line to system clipboard |
| `,*` | Search+replace word under cursor |
| `,qo` | Open quickfix list |
| `,qc` | Close quickfix list |
| `,tv` | Open terminal (vertical split) |
| `,th` | Open terminal (horizontal, 10r) |
| `Esc` | Exit terminal mode |
### Other Utilities ### Navigation and Editing
| Key | Action | | Key | Action |
|-----|--------| |------------|---------------------------------------------|
| `F2` | Toggle paste mode | | `s`+2ch | EasyMotion jump to any location |
| `F3` | Toggle line numbers | | `Space` | Toggle code fold |
| `F4` | Toggle relative numbers | | `Y` | Yank to end of line (like `D`, `C`) |
| `F5` | Toggle UndoTree | | `n` / `N` | Search next/prev (cursor centered) |
| `F8` | Toggle Tagbar | | `Ctrl+d/u` | Half-page scroll (cursor centered) |
| `Space` | Toggle fold | | `>` | Indent (keeps visual selection) |
| `s` + 2 chars | EasyMotion jump | | `<` | Dedent (keeps visual selection) |
| `[q` / `]q`| Previous/next quickfix (vim-unimpaired) |
| `[e` / `]e`| Previous/next ALE error/warning |
| `F2` | Toggle paste mode |
| `F3` | Toggle line numbers |
| `F4` | Toggle relative line numbers |
| `F5` | Toggle undo history (UndoTree) |
| `F8` | Toggle code tag browser (Tagbar) |
| `0` | Jump to first non-blank character |
| `Alt+j/k` | Move line up/down |
## Plugin List ---
### File Navigation & Search ## Features
- **NERDTree**: File system explorer
- **FZF**: Fuzzy file finder
- **CtrlP**: Alternative fuzzy finder
### Git ### vim-startify: Startup Screen
- **vim-fugitive**: Git integration
- **vim-gitgutter**: Git diff in sign column
### UI Opens when Vim is launched without a file argument. Shows:
- **vim-airline**: Enhanced status line - Recently opened files
- **gruvbox**: Color scheme - Sessions for the current directory
- Bookmarks
### Code Editing Session auto-saves on quit. Auto-loads `Session.vim` if found in the current
- **vim-surround**: Manage surroundings directory. Auto-changes to git root on file open.
- **vim-commentary**: Code commenting
- **auto-pairs**: Auto close brackets
- **ALE**: Asynchronous linting
### Language Support ### vim-which-key: Keybinding Guide
- **vim-polyglot**: Language pack for 100+ languages
- **vim-go**: Go development
### Productivity Press `,` and pause for 500ms. A popup lists all available leader bindings
- **UndoTree**: Undo history visualizer organized by group. Useful for onboarding and discovering shortcuts.
- **Tagbar**: Code structure browser
- **EasyMotion**: Fast cursor movement
- **CoC**: Code completion and LSP
- **vim-obsession**: Session management
- **vim-prosession**: Project sessions
- **vim-unimpaired**: Handy bracket mappings
- **targets.vim**: Additional text objects
## Color Schemes ### indentLine: Indent Guides
Available color schemes (change in .vimrc): Draws `|` characters at each indent level. Disabled automatically in TTY
environments and for filetypes where it causes display problems (JSON,
Markdown, help).
- **gruvbox** (default) - Warm, retro groove colors ### Session Management
- **dracula** - Dark theme with vivid colors
- **solarized** - Precision colors for machines and people
- **onedark** - Atom's iconic One Dark theme
To change:
```vim ```vim
colorscheme dracula :Obsess " Start tracking session
:Obsess! " Stop tracking
``` ```
## Engineering Features Sessions are stored in `~/.vim/sessions/` and automatically resumed by
vim-prosession on the next Vim launch in the same directory.
### Project-Specific Configuration ### Project-Local Config
Create a `.vimrc` file in your project root for project-specific settings: Place a `.vimrc` in any project root:
```vim ```vim
" .vimrc in project root " project/.vimrc
set shiftwidth=2 set shiftwidth=2
let g:ale_python_black_options = '--line-length=100' let g:ale_python_black_options = '--line-length=100'
``` ```
The configuration automatically loads project-specific settings while maintaining security. Loaded automatically. Security-restricted via `set secure`.
### Session Management
Sessions are automatically saved with vim-obsession:
```vim
" Start session tracking
:Obsess
" Stop session tracking
:Obsess!
" Sessions are saved to ~/.vim/sessions/
```
### Large File Handling ### Large File Handling
Files larger than 10MB automatically disable heavy features for better performance: Files over 10MB automatically disable syntax highlighting and undo history
- Syntax highlighting optimized to prevent Vim from freezing.
- Undo levels reduced
- Swap files disabled
### Terminal Integration ### TTY / Console Support
Open integrated terminal: Detected automatically when `$TERM` is `linux` or `screen`, or when running
- `,tv` - Vertical terminal split on a basic built-in terminal. In TTY mode:
- `,th` - Horizontal terminal split (10 rows)
Navigate out of terminal with `Esc` then normal window navigation. - True color and cursorline disabled
- Powerline separators replaced with plain ASCII
- FZF preview windows disabled
- NERDTree auto-open skipped
- Syntax column limit reduced to 120
- Simpler status line used
### TTY and Basic Terminal Support ---
The configuration automatically detects and optimizes for basic terminal environments (TTY, Linux console): ## Language Support
**Automatic Optimizations:** | Language | Indent | Formatter | Linter |
- Disables true color mode for compatibility |----------------|--------|---------------|---------------------|
- Uses simple ASCII separators instead of powerline fonts | Python | 4sp | black + isort | flake8, pylint |
- Falls back to default colorscheme | JavaScript | 2sp | prettier | eslint |
- Disables cursorline for better performance | TypeScript | 2sp | prettier | eslint, tsserver |
- Simplifies signcolumn behavior | Go | tab | gofmt, goimports | gopls, golint |
- Disables FZF preview windows | Rust | 4sp | rustfmt | cargo |
- Skips auto-opening NERDTree | Shell | 2sp | - | shellcheck |
- Uses simpler status line | YAML | 2sp | prettier | yamllint |
- Reduces syntax highlighting complexity | HTML/CSS | 2sp | prettier | - |
- Faster startup and redraw | Markdown | 2sp | prettier | - |
| JSON | 2sp | prettier | - |
| Dockerfile | 2sp | - | hadolint |
**Detected Terminals:** Install linters separately (e.g. `pip install black flake8`, `npm i -g prettier`).
- Linux console (TERM=linux) ALE runs them asynchronously and auto-fixes on save.
- Screen sessions (TERM=screen)
- Basic built-in terminals
The configuration provides a message on first run in TTY mode to inform about the optimizations. ---
## Customization ## Plugin List
The configuration is organized into sections: ### Navigation
- **NERDTree** - File tree explorer
- **fzf + fzf.vim** - Fuzzy finder
- **CtrlP** - Fallback fuzzy finder (no fzf dependency)
1. **General Settings**: Basic Vim behavior ### Git
2. **Plugin Management**: vim-plug configuration - **vim-fugitive** - Git commands inside Vim
3. **Colors & Fonts**: Visual appearance - **vim-gitgutter** - Diff signs in the sign column
4. **Key Mappings**: Custom keybindings
5. **Plugin Settings**: Individual plugin configurations
6. **Auto Commands**: File-type specific settings
7. **Helper Functions**: Utility functions
8. **Engineering Utilities**: Project workflow tools
9. **Git Workflow**: Git integration shortcuts
Feel free to modify any section to suit your needs! ### LSP and Completion
- **coc.nvim** - Full LSP + completion (requires Node.js 14.14+)
- **vim-lsp** - Pure VimScript LSP client (fallback, no Node.js)
- **vim-lsp-settings** - Auto-configure language servers for vim-lsp
- **asyncomplete.vim** - Async completion (used with vim-lsp)
### Quick Customization ### Linting
- **ALE** - Asynchronous Lint Engine (always active)
### UI
- **vim-airline** - Status and tabline
- **vim-startify** - Startup screen
- **vim-which-key** - Keybinding hint popup
- **indentLine** - Indent guide lines (non-TTY)
- **undotree** - Undo history visualizer
- **tagbar** - Code structure sidebar
### Editing
- **vim-surround** - Change surrounding quotes, brackets, tags
- **vim-commentary** - `gc` to toggle comments
- **auto-pairs** - Auto-close brackets and quotes
- **vim-easymotion** - Jump anywhere with 2 keystrokes
- **vim-unimpaired** - Bracket shortcut pairs
- **targets.vim** - Extra text objects
- **vim-snippets** - Snippet library (used with CoC/UltiSnips)
### Language Packs
- **vim-polyglot** - Syntax for 100+ languages
- **vim-go** - Go development tools
### Session
- **vim-obsession** - Continuous session saving
- **vim-prosession** - Project-level session management
### Color Schemes
- **gruvbox** (default), **dracula**, **solarized**, **onedark**
---
## Color Scheme
Change in `.vimrc` (find the `colorscheme` line):
Edit configuration:
```vim ```vim
,ev " Opens .vimrc in Vim colorscheme dracula " or: gruvbox, solarized, onedark
``` ```
Reload configuration: True color is enabled automatically when the terminal supports it
```vim (`$COLORTERM=truecolor`). Falls back to 256-color, then 16-color (TTY).
,sv " Sources .vimrc without restart
```
## Language-Specific Settings ---
### Python
- 4 spaces indentation
- 88 character line limit (Black formatter)
- Auto-formatting with Black + isort on save
- Linting with flake8 and pylint
### JavaScript/TypeScript
- 2 spaces indentation
- Prettier formatting on save
- ESLint integration
- TypeScript server support
### Go
- Tab indentation
- Auto-formatting with gofmt
- Auto-import with goimports
- gopls language server
### Rust
- Auto-formatting with rustfmt
- Cargo integration
### Shell Scripts
- 2 spaces indentation
- shellcheck linting
### Docker
- Dockerfile syntax highlighting
- hadolint linting
### YAML
- 2 spaces indentation
- yamllint integration
### HTML/CSS
- 2 spaces indentation
- Prettier formatting
### Markdown
- Line wrapping enabled
- Spell checking enabled
- Prettier formatting
## Troubleshooting ## Troubleshooting
### Plugins not working **Plugins not installed:**
```vim ```vim
:PlugInstall :PlugInstall
:PlugUpdate :PlugUpdate
``` ```
### CoC not working **CoC not working:**
Make sure Node.js is installed:
```bash ```bash
node --version # Should be >= 14.14 node --version # must be >= 14.14
``` ```
### Colors look wrong **vim-lsp server not starting:**
```vim
Enable true colors in your terminal emulator and add to your shell rc: :LspInstallServer " install server for current filetype
:LspStatus " check server status
```
**Colors look wrong:**
```bash ```bash
# Add to ~/.bashrc or ~/.zshrc
export TERM=xterm-256color export TERM=xterm-256color
``` ```
**ALE not finding linters:**
```bash
which flake8 black prettier eslint # confirm tools are on PATH
```
---
## References ## References
This configuration is inspired by: - [amix/vimrc](https://github.com/amix/vimrc)
- [vim-plug](https://github.com/junegunn/vim-plug)
- [amix/vimrc](https://github.com/amix/vimrc) - The ultimate vimrc - [coc.nvim](https://github.com/neoclide/coc.nvim)
- [vim-plug](https://github.com/junegunn/vim-plug) - Minimalist plugin manager - [vim-lsp](https://github.com/prabirshrestha/vim-lsp)
- [Top 50 Vim Configuration Options](https://www.shortcutfoo.com/blog/top-50-vim-configuration-options) - [vim-lsp-settings](https://github.com/mattn/vim-lsp-settings)
- [Modern Vim Development Setup 2025](https://swedishembedded.com/developers/vim-in-minutes)
## License ## License
MIT License - Feel free to use and modify! MIT
## Contributing
Suggestions and improvements are welcome! Feel free to open an issue or submit a pull request.

View file

@ -1,140 +1,138 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# install.sh - chopsticks vim configuration installer
# ============================================================================ # Usage: cd ~/.vim && ./install.sh
# Vim Configuration - Quick Installation Script
# ============================================================================
set -e set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BOLD='\033[1m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
RED='\033[0;31m' RED='\033[0;31m'
NC='\033[0m' # No Color BOLD='\033[1m'
NC='\033[0m'
# Function to print status messages ok() { echo -e "${GREEN}[OK]${NC} $1"; }
print_status() { warn() { echo -e "${YELLOW}[!]${NC} $1"; }
echo -e "${GREEN}==>${NC} ${BOLD}$1${NC}" die() { echo -e "${RED}[ERR]${NC} $1" >&2; exit 1; }
} step() { echo -e "\n${BOLD}==> $1${NC}"; }
print_warning() { echo -e "${BOLD}chopsticks - Vim Configuration Installer${NC}"
echo -e "${YELLOW}Warning:${NC} $1" echo "----------------------------------------"
}
print_error() { # --- Preflight checks ---
echo -e "${RED}Error:${NC} $1"
}
echo -e "${BOLD}========================================${NC}" step "Checking environment"
echo -e "${BOLD}Vim Configuration Installer${NC}"
echo -e "${BOLD}========================================${NC}\n"
# Verify .vimrc exists in script directory [ -f "$SCRIPT_DIR/.vimrc" ] || die ".vimrc not found in $SCRIPT_DIR. Run from the cloned repo: cd ~/.vim && ./install.sh"
if [ ! -f "$SCRIPT_DIR/.vimrc" ]; then
print_error "Cannot find .vimrc in $SCRIPT_DIR" command -v vim >/dev/null 2>&1 || die "vim not found. Install it first:
echo "Please run this script from the chopsticks directory:" Ubuntu/Debian: sudo apt install vim
echo " cd ~/.vim && ./install.sh" Fedora: sudo dnf install vim
exit 1 macOS: brew install vim"
VIM_VERSION=$(vim --version | head -n1)
ok "Found $VIM_VERSION"
# Check Vim version >= 8.0
vim --version | grep -q 'Vi IMproved 8\|Vi IMproved 9' || \
warn "Vim 8.0+ recommended for full LSP support. Some features may be missing."
# Detect Node.js for CoC
HAS_NODE=0
if command -v node >/dev/null 2>&1; then
NODE_VER=$(node --version)
ok "Node.js $NODE_VER detected - CoC LSP will be available"
HAS_NODE=1
else
warn "Node.js not found - will use vim-lsp (no Node.js required)"
echo " Install Node.js later to enable CoC: https://nodejs.org/en/download"
fi fi
# Check if vim is installed # --- Symlink ---
if ! command -v vim &> /dev/null; then
print_error "Vim is not installed. Please install Vim first."
echo " Ubuntu/Debian: sudo apt install vim"
echo " macOS: brew install vim"
echo " Fedora: sudo dnf install vim"
exit 1
fi
print_status "Vim version: $(vim --version | head -n1)" step "Setting up ~/.vimrc symlink"
# Backup existing .vimrc if it exists
if [ -f "$HOME/.vimrc" ] && [ ! -L "$HOME/.vimrc" ]; then if [ -f "$HOME/.vimrc" ] && [ ! -L "$HOME/.vimrc" ]; then
BACKUP_FILE="$HOME/.vimrc.backup.$(date +%Y%m%d_%H%M%S)" TS=$(date +%Y%m%d_%H%M%S)
print_warning "Backing up existing .vimrc to $BACKUP_FILE" warn "Backing up existing ~/.vimrc to ~/.vimrc.backup.$TS"
mv "$HOME/.vimrc" "$BACKUP_FILE" mv "$HOME/.vimrc" "$HOME/.vimrc.backup.$TS"
fi fi
# Create symlink to .vimrc
print_status "Creating symlink: $HOME/.vimrc -> $SCRIPT_DIR/.vimrc"
ln -sf "$SCRIPT_DIR/.vimrc" "$HOME/.vimrc" ln -sf "$SCRIPT_DIR/.vimrc" "$HOME/.vimrc"
# Verify symlink was created correctly if [ "$(readlink "$HOME/.vimrc")" = "$SCRIPT_DIR/.vimrc" ]; then
if [ -L "$HOME/.vimrc" ]; then ok "~/.vimrc -> $SCRIPT_DIR/.vimrc"
LINK_TARGET=$(readlink "$HOME/.vimrc")
if [ "$LINK_TARGET" = "$SCRIPT_DIR/.vimrc" ]; then
echo -e "${GREEN}[OK]${NC} Symlink created successfully"
else
print_warning "Symlink points to unexpected target: $LINK_TARGET"
fi
else else
print_error "Failed to create symlink" die "Symlink verification failed"
exit 1
fi fi
# Install vim-plug if not already installed # --- vim-plug ---
VIM_PLUG_PATH="$HOME/.vim/autoload/plug.vim"
if [ ! -f "$VIM_PLUG_PATH" ]; then step "Installing vim-plug"
print_status "Installing vim-plug..."
curl -fLo "$VIM_PLUG_PATH" --create-dirs \ VIM_PLUG="$HOME/.vim/autoload/plug.vim"
if [ ! -f "$VIM_PLUG" ]; then
curl -fLo "$VIM_PLUG" --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
echo -e "${GREEN}[OK]${NC} vim-plug installed successfully" ok "vim-plug installed"
else else
echo -e "${GREEN}[OK]${NC} vim-plug already installed" ok "vim-plug already present"
fi fi
# Install plugins # --- Plugins ---
print_status "Installing Vim plugins..."
step "Installing Vim plugins"
vim +PlugInstall +qall vim +PlugInstall +qall
ok "Plugins installed"
echo -e "\n${GREEN}[OK]${NC} ${BOLD}Installation complete!${NC}\n" # --- Optional: CoC language servers ---
# Print optional dependencies
echo -e "${BOLD}Optional Dependencies (Recommended):${NC}"
echo "" echo ""
echo -e "${BOLD}1. FZF (Fuzzy Finder):${NC}" if [ "$HAS_NODE" -eq 1 ]; then
echo " Ubuntu/Debian: sudo apt install fzf ripgrep" read -p "Install CoC language servers for common languages? [y/N] " -n 1 -r
echo " macOS: brew install fzf ripgrep" echo
echo "" if [[ $REPLY =~ ^[Yy]$ ]]; then
echo -e "${BOLD}2. Node.js (for CoC completion):${NC}" step "Installing CoC language servers"
echo " Ubuntu/Debian: curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - && sudo apt install -y nodejs"
echo " macOS: brew install node"
echo ""
echo -e "${BOLD}3. Universal Ctags (for code navigation):${NC}"
echo " Ubuntu/Debian: sudo apt install universal-ctags"
echo " macOS: brew install universal-ctags"
echo ""
echo -e "${BOLD}4. Language-specific tools:${NC}"
echo " Python: pip install black flake8 pylint"
echo " JavaScript: npm install -g prettier eslint"
echo " Go: go install golang.org/x/tools/gopls@latest"
echo ""
# Ask to install CoC language servers
read -p "Do you want to install CoC language servers now? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_status "Installing CoC language servers..."
# Check if node is installed
if ! command -v node &> /dev/null; then
print_error "Node.js is not installed. Please install Node.js first."
else
vim +'CocInstall -sync coc-json coc-tsserver coc-pyright coc-sh coc-html coc-css coc-yaml' +qall vim +'CocInstall -sync coc-json coc-tsserver coc-pyright coc-sh coc-html coc-css coc-yaml' +qall
echo -e "${GREEN}[OK]${NC} CoC language servers installed" ok "CoC language servers installed"
echo " Add more with :CocInstall coc-go coc-rust-analyzer etc."
fi fi
else
echo " To enable LSP without Node.js:"
echo " 1. Open a source file in Vim"
echo " 2. Run :LspInstallServer"
echo " 3. vim-lsp-settings will auto-install the right language server"
fi fi
# --- Done ---
echo "" echo ""
echo -e "${BOLD}========================================${NC}" echo -e "${BOLD}========================================${NC}"
echo -e "${GREEN}All done!${NC} Open Vim and start coding!" echo -e "${GREEN}Installation complete.${NC}"
echo -e "${BOLD}========================================${NC}" echo -e "${BOLD}========================================${NC}"
echo "" echo ""
echo -e "Quick tips:" echo "Optional tools (install for best experience):"
echo " - Press ${BOLD}Ctrl+n${NC} to toggle file explorer (NERDTree)" echo ""
echo " - Press ${BOLD}Ctrl+p${NC} to fuzzy search files (FZF)" echo " ripgrep (,rg project search)"
echo " - Press ${BOLD},w${NC} to quick save" echo " Ubuntu: sudo apt install ripgrep"
echo " - Press ${BOLD}K${NC} on a function to see documentation" echo " macOS: brew install ripgrep"
echo " - See README.md for complete key mappings" echo ""
echo " fzf (Ctrl+p file search)"
echo " Ubuntu: sudo apt install fzf"
echo " macOS: brew install fzf"
echo ""
echo " ctags (F8 tag browser)"
echo " Ubuntu: sudo apt install universal-ctags"
echo " macOS: brew install universal-ctags"
echo ""
echo " Language linters:"
echo " Python: pip install black flake8 pylint isort"
echo " JS/TS: npm install -g prettier eslint typescript"
echo " Go: go install golang.org/x/tools/gopls@latest"
echo " Shell: sudo apt install shellcheck"
echo ""
echo "Getting started:"
echo " See QUICKSTART.md for the 5-minute guide"
echo " Run 'vim' and press ',' then wait 500ms for keybinding hints"
echo "" echo ""