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
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
set nobackup
@ -70,9 +61,6 @@ set showcmd
" Show the mode you are on the last line
set showmode
" Show matching words during a search
set showmatch
" Use highlighting when doing a search
set hlsearch
@ -124,10 +112,8 @@ set lazyredraw
" For regular expressions turn magic on
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
" How many tenths of a second to blink when matching brackets
set mat=2
" No annoying sound on errors
@ -152,11 +138,16 @@ endif
" Use Unix as the standard file type
set ffs=unix,dos,mac
" Turn backup off, since most stuff is in SVN, git etc. anyway
set nobackup
set nowb
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
" ============================================================================
@ -175,7 +166,6 @@ call plug#begin('~/.vim/plugged')
Plug 'preservim/nerdtree' " File explorer
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim' " Fuzzy finder
Plug 'ctrlpvim/ctrlp.vim' " Fuzzy file finder
" ===== Git Integration =====
Plug 'tpope/vim-fugitive' " Git wrapper
@ -207,9 +197,9 @@ Plug 'mbbill/undotree' " Undo history visualizer
Plug 'preservim/tagbar' " Tag browser
Plug 'easymotion/vim-easymotion' " Easy motion
" ===== Code Intelligence =====
if has('vim9') || has('nvim')
Plug 'neoclide/coc.nvim', {'branch': 'release'} " LSP & Completion
" ===== Code Intelligence (CoC: requires Vim 8.0.1453+ and Node.js) =====
if (has('nvim') || has('patch-8.0.1453')) && executable('node')
Plug 'neoclide/coc.nvim', {'branch': 'release'} " Full LSP + completion via Node.js
endif
" ===== Session Management =====
@ -221,8 +211,36 @@ Plug 'tpope/vim-unimpaired' " Handy bracket mappings
Plug 'wellle/targets.vim' " Additional text objects
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()
" ============================================================================
" => 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
" ============================================================================
@ -278,9 +296,8 @@ set tabstop=4
set lbr
set tw=500
set ai "Auto indent
set si "Smart indent
set wrap "Wrap lines
set autoindent
set smartindent
" ============================================================================
" => Key Mappings
@ -335,7 +352,7 @@ au TabLeave * let g:lasttab = tabpagenr()
map <leader>te :tabedit <C-r>=expand("%:p:h")<cr>/
" 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
map 0 ^
@ -355,9 +372,6 @@ map <leader>sp [s
map <leader>sa zg
map <leader>s? z=
" Remove trailing whitespace
nnoremap <leader>w :let _s=@/<Bar>:%s/\s\+$//e<Bar>:let @/=_s<Bar><CR>
" Toggle paste mode
set pastetoggle=<F2>
@ -370,6 +384,38 @@ nnoremap <F4> :set invrelativenumber<CR>
" Enable folding with the spacebar
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
" ============================================================================
@ -379,7 +425,10 @@ map <C-n> :NERDTreeToggle<CR>
map <leader>n :NERDTreeFind<CR>
" 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
let NERDTreeShowHidden=1
@ -401,7 +450,8 @@ endif
map <C-p> :Files<CR>
map <leader>b :Buffers<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
let g:fzf_layout = { 'down': '40%' }
@ -431,13 +481,6 @@ else
command! -bang GFiles call fzf#vim#gitfiles('', fzf#vim#with_preview(), <bang>0)
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 ---
" Disable powerline fonts in TTY for compatibility
@ -494,17 +537,18 @@ let g:ale_fixers = {
\ '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_warning = '!'
let g:ale_lint_on_text_changed = 'never'
let g:ale_lint_on_insert_leave = 0
let g:ale_lint_on_enter = 0
" Navigate between errors
nmap <silent> <leader>aj :ALENext<cr>
nmap <silent> <leader>ak :ALEPrevious<cr>
nmap <silent> <leader>ad :ALEDetail<cr>
" Navigate between errors: [e/]e (unimpaired style), <leader>aD for detail
nmap <silent> [e :ALENext<cr>
nmap <silent> ]e :ALEPrevious<cr>
nmap <silent> <leader>aD :ALEDetail<cr>
" --- Tagbar ---
nmap <F8> :TagbarToggle<CR>
@ -525,16 +569,16 @@ let g:EasyMotion_smartcase = 1
map <Leader>j <Plug>(easymotion-j)
map <Leader>k <Plug>(easymotion-k)
" --- CoC (Conquer of Completion) ---
if exists('g:plugs["coc.nvim"]')
" Use tab for trigger completion with characters ahead and navigate
" --- CoC (Conquer of Completion) - Full LSP via Node.js ---
if g:use_coc
" Tab for trigger completion / navigate popup
inoremap <silent><expr> <TAB>
\ coc#pum#visible() ? coc#pum#next(1) :
\ CheckBackspace() ? "\<Tab>" :
\ coc#refresh()
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()
\: "\<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'
endfunction
" Use <c-space> to trigger completion
" <C-Space> to trigger completion manually
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-next)
nmap <silent> <leader>ad :CocDiagnostics<CR>
" GoTo code navigation
nmap <silent> gd <Plug>(coc-definition)
@ -556,9 +601,8 @@ if exists('g:plugs["coc.nvim"]')
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)
" Use K to show documentation in preview window
" Hover documentation
nnoremap <silent> K :call ShowDocumentation()<CR>
function! ShowDocumentation()
if CocAction('hasProvider', 'hover')
call CocActionAsync('doHover')
@ -567,15 +611,133 @@ if exists('g:plugs["coc.nvim"]')
endif
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')
" Symbol renaming
nmap <leader>rn <Plug>(coc-rename)
" Formatting selected code
" Format selected code
xmap <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
" ============================================================================
@ -682,9 +844,6 @@ set laststatus=2
" => Misc
" ============================================================================
" Quickly open a buffer for scribble
map <leader>q :e ~/buffer<cr>
" Quickly open a markdown buffer for scribble
map <leader>m :e ~/buffer.md<cr>
@ -743,9 +902,6 @@ set secure
" Quick format entire file
nnoremap <leader>F gg=G``
" Toggle between source and header files (for C/C++)
nnoremap <leader>a :A<CR>
" Quick save all buffers
nnoremap <leader>wa :wa<CR>
@ -796,7 +952,7 @@ augroup END
" ============================================================================
" 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()
if !exists("*synstack")
return
@ -850,8 +1006,8 @@ function! LargeFileSettings()
setlocal undolevels=-1
setlocal eventignore+=FileType
setlocal noswapfile
setlocal buftype=nowrite
echo "Large file detected. Some features disabled for performance."
setlocal syntax=OFF
echo "Large file (>10MB): syntax and undo disabled for performance."
endfunction
" ============================================================================
@ -866,15 +1022,7 @@ if g:is_tty
" Simpler status line for TTY
set statusline=%f\ %h%w%m%r\ %=%(%l,%c%V\ %=\ %P%)
" Disable some visual effects
set novisualbell
set noerrorbells
" Faster redraw
set lazyredraw
set ttyfast
" Reduce syntax highlighting complexity
" Reduce syntax highlighting complexity in TTY (global is 200, lower here)
set synmaxcol=120
endif
@ -887,6 +1035,177 @@ if g:is_tty && !exists("g:tty_message_shown")
let g:tty_message_shown = 1
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
" ============================================================================

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
### One-Line Install
## Step 1: Install
```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
# 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
cd ~/.vim && ./install.sh
```
## Essential Key Mappings
The script handles everything: symlinks, vim-plug, plugin download.
No root access required.
### File Operations
| Key | Action |
|-----|--------|
| `,w` | Quick save |
| `,q` | Quick quit |
| `,x` | Save and quit |
## Step 2: Open Vim
### Navigation
| Key | Action |
|-----|--------|
| `Ctrl+n` | Toggle file explorer (NERDTree) |
| `Ctrl+p` | Fuzzy file search (FZF) |
| `Ctrl+h/j/k/l` | Navigate between windows |
| `,b` | Search open buffers |
```bash
vim
```
The startup screen shows recent files and sessions. Press `q` to dismiss
or just start typing a filename to open.
## Step 3: Install LSP (pick one path)
### Path A: With Node.js (full CoC)
```bash
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
### Code Intelligence
| Key | Action |
|-----|--------|
|-------|---------------------------------|
| `gd` | Go to definition |
| `gr` | Find references |
| `K` | Show documentation |
| `Tab` | Autocomplete (when popup is visible) |
| `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
### Editing
| Key | Action |
|-----|--------|
| `gc` | Comment/uncomment (in visual mode) |
| `Space` | Toggle fold |
| `,,+Enter` | Clear search highlight |
|---------|-------------------------------------|
| `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
### Opening a Project
### Python project
```bash
# Navigate to your project directory
cd ~/my-project
# Open Vim
vim
# Press Ctrl+n to open file explorer
# Press Ctrl+p to fuzzy search files
pip install black flake8 pylint isort
vim my_script.py
```
### 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
2. Use `gd` to jump to definitions
3. Use `K` to view documentation
4. Use `Tab` for autocomplete while typing
5. Save with `,w`
### JavaScript / TypeScript project
### 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
pip install black flake8 pylint
vim -c "CocInstall coc-pyright" -c "q"
npm install -g prettier eslint typescript
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)
- ESLint integration
- 2-space indentation
### Go project
**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
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
:PlugInstall
:PlugUpdate
,ev " opens ~/.vimrc in Vim
,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:
```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:
## Quick Reference
```
┌─────────────────────────────────────────────┐
│ Vim Quick Reference │
├─────────────────────────────────────────────┤
│ FILES │
│ Ctrl+n File explorer │
│ Ctrl+p Fuzzy find files │
│ ,w Save │
│ ,q Quit │
├─────────────────────────────────────────────┤
│ NAVIGATION │
│ gd Go to definition │
│ gr Find references │
│ K Show docs │
│ Ctrl+o Jump back │
│ Ctrl+i Jump forward │
├─────────────────────────────────────────────┤
│ EDITING │
│ gc Comment (visual mode) │
│ Tab Autocomplete │
│ Space Toggle fold │
├─────────────────────────────────────────────┤
│ SEARCH │
│ /text Search forward │
│ ?text Search backward │
│ ,rg Project-wide search │
│ ,,Enter Clear highlight │
└─────────────────────────────────────────────┘
FILES
Ctrl+n File tree toggle
Ctrl+p Fuzzy find file
,b Search open buffers
,rg Search file contents (ripgrep)
,w Save | ,q Quit | ,x Save+quit
,wa Save all buffers
CODE
gd Go to definition
K Show documentation
[g / ]g Prev/next diagnostic
,rn Rename symbol
,ca Code action
,f Format selection
,F Format whole file
GIT
,gs Status | ,gd Diff | ,gb Blame
,gc Commit | ,gp Push | ,gl Pull
WINDOWS
Ctrl+h/j/k/l Move between panes
,tv Open terminal (vertical)
,th Open terminal (horizontal)
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.

599
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 Start
## Quick Install
```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
- **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
## Design Principles
### File Navigation
- **NERDTree**: Visual file explorer (`Ctrl+n`)
- **FZF**: Blazing fast fuzzy finder (`Ctrl+p`)
- **CtrlP**: Alternative fuzzy file finder
- **Easy Motion**: Jump to any location with minimal keystrokes
- **KISS**: No icon fonts, no unicode glyphs, plain ASCII throughout
- **Tiered LSP**: CoC (full) with vim-lsp fallback - works with or without Node.js
- **TTY-aware**: Automatic detection and optimization for console environments
- **Engineering-first**: Git workflow, session management, project-local config
### Git Integration
- **Fugitive**: Complete Git wrapper for Vim
- **GitGutter**: Show git diff in the sign column
---
### Code Editing
- **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
## Requirements
### Productivity Tools
- **UndoTree**: Visualize and navigate undo history (`F5`)
- **Tagbar**: Code structure browser (`F8`)
- **Smart Window Management**: Easy navigation with `Ctrl+hjkl`
- **Session Management**: Auto-save sessions with vim-obsession
- **Project-Specific Settings**: Per-project .vimrc support
- **Large File Optimization**: Automatic performance tuning for files >10MB
- **TTY/Basic Terminal Support**: Automatic optimization for console environments
| Requirement | Minimum | Notes |
|----------------|-------------|--------------------------------|
| Vim | 8.0+ | vim9script not required |
| git | any | For cloning and fugitive |
| curl | any | For vim-plug auto-install |
| Node.js | 14.14+ | Optional, enables CoC LSP |
| ripgrep (rg) | any | Optional, enables :Rg search |
| fzf | any | Optional, enables :Files/:GFiles |
| ctags | any | Optional, enables :TagbarToggle |
---
## Installation
### Automatic Installation (Recommended)
### Automatic
```bash
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
@ -56,417 +47,379 @@ cd ~/.vim
./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:
- 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
### Manual
```bash
# 1. Clone this repository
git clone https://github.com/m1ngsama/chopsticks.git ~/.vim
cd ~/.vim
# 2. Create symlink to .vimrc
ln -s ~/.vim/.vimrc ~/.vimrc
# 3. Install vim-plug
ln -sf ~/.vim/.vimrc ~/.vimrc
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
```
### 4. (Optional) Install recommended dependencies
---
For the best experience, install these optional dependencies:
## LSP: Tiered Backend System
```bash
# FZF (fuzzy finder)
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install
Code intelligence is provided by one of two backends, selected automatically:
# ripgrep (better grep)
# On Ubuntu/Debian
sudo apt install ripgrep
| Condition | Backend | Features |
|----------------------------------|----------------|-----------------------------------------------|
| 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
brew install ripgrep
Both backends expose identical key mappings (`gd`, `K`, `[g`, `]g`, `<leader>rn`, `<leader>ca`).
# Node.js (for CoC)
# Required for code completion
curl -sL install-node.now.sh/lts | bash
### CoC setup (with Node.js)
# Universal Ctags (for Tagbar)
# 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:
Install language server extensions from inside Vim:
```vim
" Python
:CocInstall coc-pyright
" JavaScript/TypeScript
:CocInstall coc-tsserver
" 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
:CocInstall coc-pyright " Python
:CocInstall coc-tsserver " JavaScript / TypeScript
:CocInstall coc-go " Go
:CocInstall coc-rust-analyzer " Rust
:CocInstall coc-json coc-yaml " JSON, YAML
:CocInstall coc-html coc-css " HTML, CSS
```
### 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
### General
Leader key: `,` (comma)
Press `,` and wait 500ms for an interactive guide to all bindings (vim-which-key).
### Files and Buffers
| Key | Action |
|-----|--------|
| `,w` | Quick save |
| `,q` | Quick quit |
| `,x` | Save and quit |
| `,,` + Enter | Clear search highlight |
### Window Navigation
| Key | Action |
|-----|--------|
| `Ctrl+h` | Move to left window |
| `Ctrl+j` | Move to bottom window |
| `Ctrl+k` | Move to top window |
| `Ctrl+l` | Move to right window |
### Buffer Management
| Key | Action |
|-----|--------|
|------------|-------------------------------------|
| `Ctrl+n` | Toggle file tree (NERDTree) |
| `,n` | Reveal current file in NERDTree |
| `Ctrl+p` | Fuzzy file search (FZF) |
| `,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 |
| `,ba` | Close all buffers |
| `,,` | Switch to last file |
### Tab Management
### Windows and Tabs
| Key | Action |
|-----|--------|
|--------------|---------------------------------|
| `Ctrl+h/j/k/l` | Navigate between windows |
| `<Leader>=` | Increase window height |
| `<Leader>-` | Decrease window height |
| `<Leader>+` | Increase window width |
| `<Leader>_` | Decrease window width |
| `,tn` | New tab |
| `,tc` | Close tab |
| `,tl` | Toggle to last tab |
### File Navigation
### Code Intelligence (CoC / vim-lsp)
| 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 |
| `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 |
Text objects (CoC only): `if`/`af` (function), `ic`/`ac` (class)
### Linting (ALE)
| Key | Action |
|-----|--------|
| `,aj` | Next error/warning |
| `,ak` | Previous error/warning |
| `,ad` | Show error details |
|----------|-----------------------|
| `[e` | Next error/warning |
| `]e` | Previous error/warning|
| `,aD` | Show error details |
### Git Workflow
Signs: `X` = error, `!` = warning
### Git Workflow (fugitive)
| Key | Action |
|-----|--------|
|--------|---------------------------------|
| `,gs` | Git status |
| `,gc` | Git commit |
| `,gp` | Git push |
| `,gl` | Git pull |
| `,gd` | Git diff |
| `,gb` | Git blame |
| `,gF` | Search git-tracked files (FZF) |
### Engineering Utilities
| Key | Action |
|-----|--------|
| `,ev` | Edit .vimrc |
| `,sv` | Reload .vimrc |
| `,F` | Format entire file |
| `,wa` | Save all buffers |
| `,cp` | Copy file path |
| `,cf` | Copy filename |
| `,*` | Search & replace word under cursor |
| `,<leader>` | Switch to last file |
|----------|-------------------------------------|
| `,ev` | Edit `~/.vimrc` |
| `,sv` | Reload `~/.vimrc` |
| `,F` | Format entire file (= indent) |
| `,W` | Strip trailing whitespace |
| `,wa` | Save all open buffers |
| `,wd` | Change CWD to current buffer's dir |
| `,cp` | Copy file path to clipboard |
| `,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 |
|-----|--------|
|------------|---------------------------------------------|
| `s`+2ch | EasyMotion jump to any location |
| `Space` | Toggle code fold |
| `Y` | Yank to end of line (like `D`, `C`) |
| `n` / `N` | Search next/prev (cursor centered) |
| `Ctrl+d/u` | Half-page scroll (cursor centered) |
| `>` | Indent (keeps visual selection) |
| `<` | 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 numbers |
| `F5` | Toggle UndoTree |
| `F8` | Toggle Tagbar |
| `Space` | Toggle fold |
| `s` + 2 chars | EasyMotion jump |
| `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
- **NERDTree**: File system explorer
- **FZF**: Fuzzy file finder
- **CtrlP**: Alternative fuzzy finder
## Features
### Git
- **vim-fugitive**: Git integration
- **vim-gitgutter**: Git diff in sign column
### vim-startify: Startup Screen
### UI
- **vim-airline**: Enhanced status line
- **gruvbox**: Color scheme
Opens when Vim is launched without a file argument. Shows:
- Recently opened files
- Sessions for the current directory
- Bookmarks
### Code Editing
- **vim-surround**: Manage surroundings
- **vim-commentary**: Code commenting
- **auto-pairs**: Auto close brackets
- **ALE**: Asynchronous linting
Session auto-saves on quit. Auto-loads `Session.vim` if found in the current
directory. Auto-changes to git root on file open.
### Language Support
- **vim-polyglot**: Language pack for 100+ languages
- **vim-go**: Go development
### vim-which-key: Keybinding Guide
### Productivity
- **UndoTree**: Undo history visualizer
- **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
Press `,` and pause for 500ms. A popup lists all available leader bindings
organized by group. Useful for onboarding and discovering shortcuts.
## 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
- **dracula** - Dark theme with vivid colors
- **solarized** - Precision colors for machines and people
- **onedark** - Atom's iconic One Dark theme
To change:
### Session Management
```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
" .vimrc in project root
" project/.vimrc
set shiftwidth=2
let g:ale_python_black_options = '--line-length=100'
```
The configuration automatically loads project-specific settings while maintaining security.
### Session Management
Sessions are automatically saved with vim-obsession:
```vim
" Start session tracking
:Obsess
" Stop session tracking
:Obsess!
" Sessions are saved to ~/.vim/sessions/
```
Loaded automatically. Security-restricted via `set secure`.
### Large File Handling
Files larger than 10MB automatically disable heavy features for better performance:
- Syntax highlighting optimized
- Undo levels reduced
- Swap files disabled
Files over 10MB automatically disable syntax highlighting and undo history
to prevent Vim from freezing.
### Terminal Integration
### TTY / Console Support
Open integrated terminal:
- `,tv` - Vertical terminal split
- `,th` - Horizontal terminal split (10 rows)
Detected automatically when `$TERM` is `linux` or `screen`, or when running
on a basic built-in terminal. In TTY mode:
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:**
- Disables true color mode for compatibility
- Uses simple ASCII separators instead of powerline fonts
- Falls back to default colorscheme
- Disables cursorline for better performance
- Simplifies signcolumn behavior
- Disables FZF preview windows
- Skips auto-opening NERDTree
- Uses simpler status line
- Reduces syntax highlighting complexity
- Faster startup and redraw
| Language | Indent | Formatter | Linter |
|----------------|--------|---------------|---------------------|
| Python | 4sp | black + isort | flake8, pylint |
| JavaScript | 2sp | prettier | eslint |
| TypeScript | 2sp | prettier | eslint, tsserver |
| Go | tab | gofmt, goimports | gopls, golint |
| Rust | 4sp | rustfmt | cargo |
| Shell | 2sp | - | shellcheck |
| YAML | 2sp | prettier | yamllint |
| HTML/CSS | 2sp | prettier | - |
| Markdown | 2sp | prettier | - |
| JSON | 2sp | prettier | - |
| Dockerfile | 2sp | - | hadolint |
**Detected Terminals:**
- Linux console (TERM=linux)
- Screen sessions (TERM=screen)
- Basic built-in terminals
Install linters separately (e.g. `pip install black flake8`, `npm i -g prettier`).
ALE runs them asynchronously and auto-fixes on save.
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
2. **Plugin Management**: vim-plug configuration
3. **Colors & Fonts**: Visual appearance
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
### Git
- **vim-fugitive** - Git commands inside Vim
- **vim-gitgutter** - Diff signs in the sign column
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
,ev " Opens .vimrc in Vim
colorscheme dracula " or: gruvbox, solarized, onedark
```
Reload configuration:
```vim
,sv " Sources .vimrc without restart
```
True color is enabled automatically when the terminal supports it
(`$COLORTERM=truecolor`). Falls back to 256-color, then 16-color (TTY).
## 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
### Plugins not working
**Plugins not installed:**
```vim
:PlugInstall
:PlugUpdate
```
### CoC not working
Make sure Node.js is installed:
**CoC not working:**
```bash
node --version # Should be >= 14.14
node --version # must be >= 14.14
```
### Colors look wrong
Enable true colors in your terminal emulator and add to your shell rc:
**vim-lsp server not starting:**
```vim
:LspInstallServer " install server for current filetype
:LspStatus " check server status
```
**Colors look wrong:**
```bash
# Add to ~/.bashrc or ~/.zshrc
export TERM=xterm-256color
```
**ALE not finding linters:**
```bash
which flake8 black prettier eslint # confirm tools are on PATH
```
---
## References
This configuration is inspired by:
- [amix/vimrc](https://github.com/amix/vimrc) - The ultimate vimrc
- [vim-plug](https://github.com/junegunn/vim-plug) - Minimalist plugin manager
- [Top 50 Vim Configuration Options](https://www.shortcutfoo.com/blog/top-50-vim-configuration-options)
- [Modern Vim Development Setup 2025](https://swedishembedded.com/developers/vim-in-minutes)
- [amix/vimrc](https://github.com/amix/vimrc)
- [vim-plug](https://github.com/junegunn/vim-plug)
- [coc.nvim](https://github.com/neoclide/coc.nvim)
- [vim-lsp](https://github.com/prabirshrestha/vim-lsp)
- [vim-lsp-settings](https://github.com/mattn/vim-lsp-settings)
## License
MIT License - Feel free to use and modify!
## Contributing
Suggestions and improvements are welcome! Feel free to open an issue or submit a pull request.
MIT

View file

@ -1,140 +1,138 @@
#!/usr/bin/env bash
# ============================================================================
# Vim Configuration - Quick Installation Script
# ============================================================================
# install.sh - chopsticks vim configuration installer
# Usage: cd ~/.vim && ./install.sh
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BOLD='\033[1m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
BOLD='\033[1m'
NC='\033[0m'
# Function to print status messages
print_status() {
echo -e "${GREEN}==>${NC} ${BOLD}$1${NC}"
}
ok() { echo -e "${GREEN}[OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
die() { echo -e "${RED}[ERR]${NC} $1" >&2; exit 1; }
step() { echo -e "\n${BOLD}==> $1${NC}"; }
print_warning() {
echo -e "${YELLOW}Warning:${NC} $1"
}
echo -e "${BOLD}chopsticks - Vim Configuration Installer${NC}"
echo "----------------------------------------"
print_error() {
echo -e "${RED}Error:${NC} $1"
}
# --- Preflight checks ---
echo -e "${BOLD}========================================${NC}"
echo -e "${BOLD}Vim Configuration Installer${NC}"
echo -e "${BOLD}========================================${NC}\n"
step "Checking environment"
# Verify .vimrc exists in script directory
if [ ! -f "$SCRIPT_DIR/.vimrc" ]; then
print_error "Cannot find .vimrc in $SCRIPT_DIR"
echo "Please run this script from the chopsticks directory:"
echo " cd ~/.vim && ./install.sh"
exit 1
[ -f "$SCRIPT_DIR/.vimrc" ] || die ".vimrc not found in $SCRIPT_DIR. Run from the cloned repo: cd ~/.vim && ./install.sh"
command -v vim >/dev/null 2>&1 || die "vim not found. Install it first:
Ubuntu/Debian: sudo apt install vim
Fedora: sudo dnf install vim
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
# Check if vim is installed
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
# --- Symlink ---
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
BACKUP_FILE="$HOME/.vimrc.backup.$(date +%Y%m%d_%H%M%S)"
print_warning "Backing up existing .vimrc to $BACKUP_FILE"
mv "$HOME/.vimrc" "$BACKUP_FILE"
TS=$(date +%Y%m%d_%H%M%S)
warn "Backing up existing ~/.vimrc to ~/.vimrc.backup.$TS"
mv "$HOME/.vimrc" "$HOME/.vimrc.backup.$TS"
fi
# Create symlink to .vimrc
print_status "Creating symlink: $HOME/.vimrc -> $SCRIPT_DIR/.vimrc"
ln -sf "$SCRIPT_DIR/.vimrc" "$HOME/.vimrc"
# Verify symlink was created correctly
if [ -L "$HOME/.vimrc" ]; then
LINK_TARGET=$(readlink "$HOME/.vimrc")
if [ "$LINK_TARGET" = "$SCRIPT_DIR/.vimrc" ]; then
echo -e "${GREEN}[OK]${NC} Symlink created successfully"
if [ "$(readlink "$HOME/.vimrc")" = "$SCRIPT_DIR/.vimrc" ]; then
ok "~/.vimrc -> $SCRIPT_DIR/.vimrc"
else
print_warning "Symlink points to unexpected target: $LINK_TARGET"
fi
else
print_error "Failed to create symlink"
exit 1
die "Symlink verification failed"
fi
# Install vim-plug if not already installed
VIM_PLUG_PATH="$HOME/.vim/autoload/plug.vim"
if [ ! -f "$VIM_PLUG_PATH" ]; then
print_status "Installing vim-plug..."
curl -fLo "$VIM_PLUG_PATH" --create-dirs \
# --- vim-plug ---
step "Installing vim-plug"
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
echo -e "${GREEN}[OK]${NC} vim-plug installed successfully"
ok "vim-plug installed"
else
echo -e "${GREEN}[OK]${NC} vim-plug already installed"
ok "vim-plug already present"
fi
# Install plugins
print_status "Installing Vim plugins..."
# --- Plugins ---
step "Installing Vim plugins"
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 -e "${BOLD}1. FZF (Fuzzy Finder):${NC}"
echo " Ubuntu/Debian: sudo apt install fzf ripgrep"
echo " macOS: brew install fzf ripgrep"
echo ""
echo -e "${BOLD}2. Node.js (for CoC completion):${NC}"
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
if [ "$HAS_NODE" -eq 1 ]; then
read -p "Install CoC language servers for common languages? [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
step "Installing CoC language servers"
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
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
# --- Done ---
echo ""
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 ""
echo -e "Quick tips:"
echo " - Press ${BOLD}Ctrl+n${NC} to toggle file explorer (NERDTree)"
echo " - Press ${BOLD}Ctrl+p${NC} to fuzzy search files (FZF)"
echo " - Press ${BOLD},w${NC} to quick save"
echo " - Press ${BOLD}K${NC} on a function to see documentation"
echo " - See README.md for complete key mappings"
echo "Optional tools (install for best experience):"
echo ""
echo " ripgrep (,rg project search)"
echo " Ubuntu: sudo apt install ripgrep"
echo " macOS: brew install ripgrep"
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 ""