mirror of
https://oauth2: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@github.com/m1ngsama/chopsticks.git
synced 2026-05-10 19:10:59 +08:00
refactor: modular architecture — split .vimrc into 12 self-contained modules
Replace the monolithic 1268-line .vimrc with a thin loader that sources 12 modules under modules/ (env, plugins, core, ui, editing, navigation, lsp, lint, git, writing, languages, tools). Each module is independently readable and can be toggled by commenting one line. Add interactive tutorial (tutor/chopsticks.tutor) with 10 lessons covering all features. Users can run :ChopsticksLearn to start.
This commit is contained in:
parent
84d999f91f
commit
6044fc5fcb
16 changed files with 1470 additions and 1261 deletions
|
|
@ -26,6 +26,7 @@ Vim is **modal** — the keyboard behaves differently depending on which mode yo
|
||||||
| `,w` or `Ctrl+s` | Save |
|
| `,w` or `Ctrl+s` | Save |
|
||||||
|
|
||||||
Once in Normal mode, press `,?` to open the cheat sheet.
|
Once in Normal mode, press `,?` to open the cheat sheet.
|
||||||
|
Run `:ChopsticksLearn` for a full interactive tutorial.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
49
README.md
49
README.md
|
|
@ -260,10 +260,55 @@ let g:ale_python_black_options = '--line-length=100'
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Learn
|
||||||
|
|
||||||
|
New to chopsticks? Run the interactive tutorial:
|
||||||
|
|
||||||
|
```vim
|
||||||
|
:ChopsticksLearn
|
||||||
|
```
|
||||||
|
|
||||||
|
It walks you through every feature — file finding, LSP, git, zen mode,
|
||||||
|
and more — with exercises you can try in real time. (For Vim basics, run
|
||||||
|
`:Tutor` first.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
chopsticks follows the Unix philosophy: each concern lives in its own file.
|
||||||
|
|
||||||
|
```
|
||||||
|
~/.vim/
|
||||||
|
├── .vimrc ← thin loader (sources modules in order)
|
||||||
|
├── modules/
|
||||||
|
│ ├── env.vim ← environment detection (TTY, truecolor)
|
||||||
|
│ ├── plugins.vim ← vim-plug bootstrap + 30 plugin declarations
|
||||||
|
│ ├── core.vim ← general settings, keymaps, performance
|
||||||
|
│ ├── ui.vim ← colorscheme, statusline, startify
|
||||||
|
│ ├── editing.vim ← EasyMotion, yank highlight, search auto-clear
|
||||||
|
│ ├── navigation.vim ← FZF, netrw, window management, terminal
|
||||||
|
│ ├── lsp.vim ← vim-lsp + asyncomplete
|
||||||
|
│ ├── lint.vim ← ALE linting and format-on-save
|
||||||
|
│ ├── git.vim ← Fugitive, GitGutter, conflict navigation
|
||||||
|
│ ├── writing.vim ← Markdown, previm, goyo + limelight
|
||||||
|
│ ├── languages.vim ← vim-go, per-filetype settings
|
||||||
|
│ └── tools.vim ← cheat sheet, run file, helpers
|
||||||
|
└── tutor/
|
||||||
|
└── chopsticks.tutor ← interactive tutorial
|
||||||
|
```
|
||||||
|
|
||||||
|
Each module is self-contained. Want to disable git integration? Remove
|
||||||
|
`call s:load('git')` from `.vimrc`. Want to add your own module? Create
|
||||||
|
`modules/mine.vim` and add `call s:load('mine')`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Customization
|
## Customization
|
||||||
|
|
||||||
Edit `~/.vimrc` directly (`,ev` opens it, `,sv` reloads). Per-project overrides
|
Edit `~/.vimrc` directly (`,ev` opens it, `,sv` reloads), or edit individual
|
||||||
go in a `.vimrc` at your project root.
|
modules under `modules/`. Per-project overrides go in a `.vimrc` at your
|
||||||
|
project root.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
220
modules/core.vim
Normal file
220
modules/core.vim
Normal file
|
|
@ -0,0 +1,220 @@
|
||||||
|
" core.vim — general settings, basic keymaps, performance, indentation
|
||||||
|
|
||||||
|
filetype on
|
||||||
|
filetype plugin on
|
||||||
|
filetype indent on
|
||||||
|
syntax on
|
||||||
|
|
||||||
|
set number
|
||||||
|
set relativenumber
|
||||||
|
|
||||||
|
if !g:is_tty
|
||||||
|
set cursorline
|
||||||
|
endif
|
||||||
|
|
||||||
|
set nobackup
|
||||||
|
set scrolloff=10
|
||||||
|
set nowrap
|
||||||
|
set incsearch
|
||||||
|
set ignorecase
|
||||||
|
set smartcase
|
||||||
|
set showcmd
|
||||||
|
set showmode
|
||||||
|
set hlsearch
|
||||||
|
set history=1000
|
||||||
|
set wildmenu
|
||||||
|
set wildmode=list:longest
|
||||||
|
set wildignorecase
|
||||||
|
set wildignore=*.docx,*.jpg,*.png,*.gif,*.pdf,*.pyc,*.exe,*.flv,*.img,*.xlsx
|
||||||
|
set wildignore+=*/node_modules/*,*/.git/*,*/__pycache__/*,*/dist/*,*/build/*
|
||||||
|
set mouse=a
|
||||||
|
set encoding=utf-8
|
||||||
|
set foldmethod=indent
|
||||||
|
set foldlevel=99
|
||||||
|
set splitbelow
|
||||||
|
set splitright
|
||||||
|
set backspace=indent,eol,start
|
||||||
|
set nrformats-=octal
|
||||||
|
set autoread
|
||||||
|
set cmdheight=1
|
||||||
|
set hidden
|
||||||
|
set whichwrap+=<,>,h,l
|
||||||
|
set magic
|
||||||
|
set showmatch
|
||||||
|
set mat=2
|
||||||
|
set noerrorbells
|
||||||
|
set novisualbell
|
||||||
|
set t_vb=
|
||||||
|
set ttimeout
|
||||||
|
set ttimeoutlen=10
|
||||||
|
|
||||||
|
if $COLORTERM ==# 'gnome-terminal'
|
||||||
|
set t_Co=256
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has("gui_running")
|
||||||
|
set guioptions-=T
|
||||||
|
set guioptions-=e
|
||||||
|
set t_Co=256
|
||||||
|
set guitablabel=%M\ %t
|
||||||
|
endif
|
||||||
|
|
||||||
|
set display+=lastline
|
||||||
|
set ffs=unix,dos,mac
|
||||||
|
set nowb
|
||||||
|
set noswapfile
|
||||||
|
|
||||||
|
if has('persistent_undo')
|
||||||
|
set undofile
|
||||||
|
let &undodir = expand('~/.vim/.undo')
|
||||||
|
silent! call mkdir(&undodir, 'p', 0700)
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── Text, Tab and Indent ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if g:is_tty
|
||||||
|
set listchars=tab:>-,trail:.,extends:>,precedes:<,nbsp:_
|
||||||
|
else
|
||||||
|
set listchars=tab:→\ ,trail:·,extends:▸,precedes:◂,nbsp:·
|
||||||
|
endif
|
||||||
|
|
||||||
|
set expandtab
|
||||||
|
set smarttab
|
||||||
|
set shiftwidth=4
|
||||||
|
set tabstop=4
|
||||||
|
set lbr
|
||||||
|
set tw=0
|
||||||
|
set autoindent
|
||||||
|
set smartindent
|
||||||
|
|
||||||
|
" ── Leader ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
let mapleader = ","
|
||||||
|
|
||||||
|
" ── Basic Keymaps ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
nnoremap <leader>w :w!<cr>
|
||||||
|
nnoremap <leader>q :q<cr>
|
||||||
|
nnoremap <leader>x :x<cr>
|
||||||
|
|
||||||
|
nnoremap <silent> <leader><cr> :noh<cr>
|
||||||
|
|
||||||
|
nnoremap <leader>bd :Bclose<cr>
|
||||||
|
nnoremap <leader>ba :bufdo bd<cr>
|
||||||
|
nnoremap <leader>l :bnext<cr>
|
||||||
|
nnoremap <leader>h :bprevious<cr>
|
||||||
|
|
||||||
|
nnoremap <leader>tn :tabnew<cr>
|
||||||
|
nnoremap <leader>to :tabonly<cr>
|
||||||
|
nnoremap <leader>tc :tabclose<cr>
|
||||||
|
nnoremap <leader>tm :tabmove
|
||||||
|
nnoremap <leader>t<leader> :tabnext<cr>
|
||||||
|
|
||||||
|
let g:lasttab = 1
|
||||||
|
nnoremap <Leader>tl :exe "tabn ".g:lasttab<CR>
|
||||||
|
augroup ChopstickTabHistory
|
||||||
|
autocmd!
|
||||||
|
autocmd TabLeave * let g:lasttab = tabpagenr()
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
nnoremap <leader>te :tabedit <C-r>=expand("%:p:h")<cr>/
|
||||||
|
nnoremap <leader>cd :lcd %:p:h<cr>:pwd<cr>
|
||||||
|
|
||||||
|
nnoremap 0 ^
|
||||||
|
nnoremap gV `[v`]
|
||||||
|
|
||||||
|
cnoremap <C-p> <Up>
|
||||||
|
cnoremap <C-n> <Down>
|
||||||
|
|
||||||
|
nnoremap <M-j> :m .+1<CR>==
|
||||||
|
nnoremap <M-k> :m .-2<CR>==
|
||||||
|
vnoremap <M-j> :m '>+1<CR>gv=gv
|
||||||
|
vnoremap <M-k> :m '<-2<CR>gv=gv
|
||||||
|
|
||||||
|
nnoremap <leader>ss :setlocal spell!<cr>
|
||||||
|
nnoremap <leader>sn ]s
|
||||||
|
nnoremap <leader>sp [s
|
||||||
|
nnoremap <leader>sa zg
|
||||||
|
nnoremap <leader>s? z=
|
||||||
|
|
||||||
|
set pastetoggle=<F2>
|
||||||
|
nnoremap <F3> :set invnumber<CR>
|
||||||
|
nnoremap <F4> :set invrelativenumber<CR>
|
||||||
|
nnoremap <F6> :set list!<CR>
|
||||||
|
|
||||||
|
nnoremap <space> za
|
||||||
|
|
||||||
|
nnoremap Y y$
|
||||||
|
nnoremap Q <nop>
|
||||||
|
|
||||||
|
inoremap jk <Esc>
|
||||||
|
|
||||||
|
vnoremap < <gv
|
||||||
|
vnoremap > >gv
|
||||||
|
|
||||||
|
nnoremap n nzzzv
|
||||||
|
nnoremap N Nzzzv
|
||||||
|
|
||||||
|
vnoremap // y/\V<C-r>=escape(@",'/\')<CR><CR>
|
||||||
|
|
||||||
|
nnoremap <silent> <C-s> :w<CR>
|
||||||
|
inoremap <silent> <C-s> <C-o>:w<CR>
|
||||||
|
|
||||||
|
nnoremap <C-d> <C-d>zz
|
||||||
|
nnoremap <C-u> <C-u>zz
|
||||||
|
|
||||||
|
if has('clipboard')
|
||||||
|
nnoremap <leader>y "+y
|
||||||
|
vnoremap <leader>y "+y
|
||||||
|
nnoremap <leader>Y "+Y
|
||||||
|
nnoremap <leader>p "+p
|
||||||
|
nnoremap <leader>P "+P
|
||||||
|
endif
|
||||||
|
|
||||||
|
nnoremap <leader>qo :copen<CR>
|
||||||
|
nnoremap <leader>qc :cclose<CR>
|
||||||
|
|
||||||
|
augroup ChopstickResize
|
||||||
|
autocmd!
|
||||||
|
autocmd VimResized * wincmd =
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
" ── Performance ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
set synmaxcol=200
|
||||||
|
set ttyfast
|
||||||
|
set lazyredraw
|
||||||
|
set complete-=i
|
||||||
|
set updatetime=300
|
||||||
|
set shortmess+=c
|
||||||
|
|
||||||
|
if g:is_tty
|
||||||
|
set signcolumn=auto
|
||||||
|
set synmaxcol=120
|
||||||
|
else
|
||||||
|
if has("patch-8.1.1564")
|
||||||
|
set signcolumn=number
|
||||||
|
else
|
||||||
|
set signcolumn=yes
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── Project-Local Config ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
set exrc
|
||||||
|
set secure
|
||||||
|
set sessionoptions=blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal
|
||||||
|
|
||||||
|
" ── Format Options ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
augroup ChopstickFormatOptions
|
||||||
|
autocmd!
|
||||||
|
autocmd FileType * setlocal formatoptions-=c formatoptions-=r formatoptions-=o formatoptions+=j
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
augroup ChopstickPaste
|
||||||
|
autocmd!
|
||||||
|
autocmd InsertLeave * set nopaste
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
set timeoutlen=500
|
||||||
41
modules/editing.vim
Normal file
41
modules/editing.vim
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
" editing.vim — EasyMotion, yank highlight, search auto-clear, undotree
|
||||||
|
|
||||||
|
" ── EasyMotion ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
let g:EasyMotion_do_mapping = 0
|
||||||
|
let g:EasyMotion_smartcase = 1
|
||||||
|
|
||||||
|
if exists('g:plugs["vim-easymotion"]')
|
||||||
|
nmap s <Plug>(easymotion-overwin-f2)
|
||||||
|
nmap <Leader>j <Plug>(easymotion-j)
|
||||||
|
nmap <Leader>k <Plug>(easymotion-k)
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── UndoTree ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if exists('g:plugs["undotree"]')
|
||||||
|
nnoremap <F5> :UndotreeToggle<CR>
|
||||||
|
nnoremap <leader>u :UndotreeToggle<CR>
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── Yank Highlight ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if exists('##TextYankPost') && has('timers')
|
||||||
|
function! s:YankHighlight() abort
|
||||||
|
if v:event.operator !=# 'y' | return | endif
|
||||||
|
let l:m = matchadd('IncSearch',
|
||||||
|
\ printf('\%%>%dl\%%<%dl', line("'[") - 1, line("']") + 1))
|
||||||
|
call timer_start(150, {-> matchdelete(l:m)})
|
||||||
|
endfunction
|
||||||
|
augroup ChopstickYankHL
|
||||||
|
autocmd!
|
||||||
|
autocmd TextYankPost * call s:YankHighlight()
|
||||||
|
augroup END
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── Auto-Clear Search Highlight ─────────────────────────────────────────────
|
||||||
|
|
||||||
|
augroup ChopstickSearchHL
|
||||||
|
autocmd!
|
||||||
|
autocmd CursorHold * if get(v:, 'hlsearch', 0) | let v:hlsearch = 0 | endif
|
||||||
|
augroup END
|
||||||
7
modules/env.vim
Normal file
7
modules/env.vim
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
" env.vim — environment detection (must load first)
|
||||||
|
|
||||||
|
set nocompatible
|
||||||
|
|
||||||
|
let g:is_tty = empty($TERM) || $TERM ==# 'dumb' || $TERM =~# 'linux'
|
||||||
|
\ || $TERM =~# 'screen' || &term =~# 'builtin'
|
||||||
|
let g:has_true_color = ($COLORTERM ==# 'truecolor' || $COLORTERM ==# '24bit')
|
||||||
25
modules/git.vim
Normal file
25
modules/git.vim
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
" git.vim — Fugitive mappings, GitGutter config, conflict navigation
|
||||||
|
|
||||||
|
" ── GitGutter ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
let g:gitgutter_sign_added = '+'
|
||||||
|
let g:gitgutter_sign_modified = '~'
|
||||||
|
let g:gitgutter_sign_removed = '-'
|
||||||
|
let g:gitgutter_sign_removed_first_line = '^'
|
||||||
|
let g:gitgutter_sign_modified_removed = '~'
|
||||||
|
|
||||||
|
" ── Fugitive ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if exists('g:plugs["vim-fugitive"]')
|
||||||
|
nnoremap <leader>gs :Git status<CR>
|
||||||
|
nnoremap <leader>gc :Git commit<CR>
|
||||||
|
nnoremap <leader>gp :Git push<CR>
|
||||||
|
nnoremap <leader>gl :Git pull<CR>
|
||||||
|
nnoremap <leader>gd :Gdiffsplit<CR>
|
||||||
|
nnoremap <leader>gb :Git blame<CR>
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── Conflict Navigation ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
nnoremap <silent> ]x /^\(<<<<<<<\\|=======\\|>>>>>>>\)<CR>
|
||||||
|
nnoremap <silent> [x ?^\(<<<<<<<\\|=======\\|>>>>>>>\)<CR>
|
||||||
52
modules/languages.vim
Normal file
52
modules/languages.vim
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
" languages.vim — vim-go config, per-filetype autocmds
|
||||||
|
|
||||||
|
" ── vim-go (syntax only — vim-lsp handles intelligence) ─────────────────────
|
||||||
|
|
||||||
|
let g:go_gopls_enabled = 0
|
||||||
|
let g:go_code_completion_enabled = 0
|
||||||
|
let g:go_fmt_autosave = 0
|
||||||
|
let g:go_imports_autosave = 0
|
||||||
|
let g:go_highlight_types = 1
|
||||||
|
let g:go_highlight_fields = 1
|
||||||
|
let g:go_highlight_functions = 1
|
||||||
|
let g:go_highlight_function_calls = 1
|
||||||
|
|
||||||
|
" ── Filetype Detection ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
augroup ChopstickFiletype
|
||||||
|
autocmd!
|
||||||
|
|
||||||
|
autocmd BufReadPost *
|
||||||
|
\ if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif
|
||||||
|
|
||||||
|
autocmd BufNewFile,BufRead *.json setlocal filetype=json
|
||||||
|
autocmd BufNewFile,BufRead *.md setlocal filetype=markdown
|
||||||
|
autocmd BufNewFile,BufRead *.jsx setlocal filetype=javascript.jsx
|
||||||
|
autocmd BufNewFile,BufRead *.tsx setlocal filetype=typescript.tsx
|
||||||
|
autocmd BufNewFile,BufRead Dockerfile* setlocal filetype=dockerfile
|
||||||
|
|
||||||
|
autocmd FileType python
|
||||||
|
\ setlocal expandtab shiftwidth=4 tabstop=4 textwidth=88 colorcolumn=+1
|
||||||
|
autocmd FileType javascript,typescript
|
||||||
|
\ setlocal expandtab shiftwidth=2 tabstop=2 textwidth=100 colorcolumn=+1
|
||||||
|
autocmd FileType go
|
||||||
|
\ setlocal noexpandtab shiftwidth=4 tabstop=4 textwidth=120 colorcolumn=+1
|
||||||
|
autocmd FileType rust
|
||||||
|
\ setlocal expandtab shiftwidth=4 tabstop=4 textwidth=100 colorcolumn=+1
|
||||||
|
autocmd FileType c,cpp
|
||||||
|
\ setlocal expandtab shiftwidth=4 tabstop=4 textwidth=80 colorcolumn=+1
|
||||||
|
autocmd FileType html,css
|
||||||
|
\ setlocal expandtab shiftwidth=2 tabstop=2
|
||||||
|
autocmd FileType yaml
|
||||||
|
\ setlocal expandtab shiftwidth=2 tabstop=2
|
||||||
|
autocmd FileType markdown
|
||||||
|
\ setlocal wrap linebreak spell textwidth=0 colorcolumn=0 conceallevel=2
|
||||||
|
autocmd FileType sh
|
||||||
|
\ setlocal expandtab shiftwidth=2 tabstop=2 textwidth=80 colorcolumn=+1
|
||||||
|
autocmd FileType make
|
||||||
|
\ setlocal noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
autocmd FileType json
|
||||||
|
\ setlocal expandtab shiftwidth=2 tabstop=2
|
||||||
|
autocmd FileType dockerfile
|
||||||
|
\ setlocal expandtab shiftwidth=2 tabstop=2
|
||||||
|
augroup END
|
||||||
51
modules/lint.vim
Normal file
51
modules/lint.vim
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
" lint.vim — ALE async linting and format-on-save
|
||||||
|
|
||||||
|
let g:ale_disable_lsp = 1
|
||||||
|
|
||||||
|
let g:ale_linters = {
|
||||||
|
\ 'python': ['flake8', 'pylint'],
|
||||||
|
\ 'javascript': ['eslint'],
|
||||||
|
\ 'typescript': ['eslint'],
|
||||||
|
\ 'go': ['staticcheck'],
|
||||||
|
\ 'rust': ['cargo'],
|
||||||
|
\ 'c': ['cc'],
|
||||||
|
\ 'sh': ['shellcheck'],
|
||||||
|
\ 'yaml': ['yamllint'],
|
||||||
|
\ 'dockerfile': ['hadolint'],
|
||||||
|
\ 'css': ['stylelint'],
|
||||||
|
\ 'scss': ['stylelint'],
|
||||||
|
\ 'markdown': ['markdownlint'],
|
||||||
|
\ 'sql': ['sqlfluff'],
|
||||||
|
\}
|
||||||
|
|
||||||
|
let g:ale_fixers = {
|
||||||
|
\ '*': ['remove_trailing_lines', 'trim_whitespace'],
|
||||||
|
\ 'python': ['black', 'isort'],
|
||||||
|
\ 'javascript': ['prettier', 'eslint'],
|
||||||
|
\ 'typescript': ['prettier', 'eslint'],
|
||||||
|
\ 'go': ['goimports'],
|
||||||
|
\ 'rust': ['rustfmt'],
|
||||||
|
\ 'c': ['clang-format'],
|
||||||
|
\ 'json': ['prettier'],
|
||||||
|
\ 'yaml': ['prettier'],
|
||||||
|
\ 'html': ['prettier'],
|
||||||
|
\ 'css': ['prettier'],
|
||||||
|
\ 'scss': ['prettier'],
|
||||||
|
\ 'less': ['prettier'],
|
||||||
|
\ 'markdown': ['prettier'],
|
||||||
|
\ 'sql': ['sqlfluff'],
|
||||||
|
\}
|
||||||
|
|
||||||
|
let g:ale_fix_on_save = 1
|
||||||
|
let g:ale_python_isort_options = '--profile black'
|
||||||
|
let g:ale_sign_error = 'X'
|
||||||
|
let g:ale_sign_warning = '!'
|
||||||
|
let g:ale_lint_on_text_changed = 'normal'
|
||||||
|
let g:ale_lint_on_insert_leave = 1
|
||||||
|
let g:ale_lint_on_enter = 1
|
||||||
|
|
||||||
|
if exists('g:plugs["ale"]')
|
||||||
|
nnoremap <silent> [e :ALEPrevious<cr>
|
||||||
|
nnoremap <silent> ]e :ALENext<cr>
|
||||||
|
nnoremap <silent> <leader>aD :ALEDetail<cr>
|
||||||
|
endif
|
||||||
74
modules/lsp.vim
Normal file
74
modules/lsp.vim
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
" lsp.vim — vim-lsp settings, asyncomplete, LSP buffer keymaps
|
||||||
|
|
||||||
|
let g:lsp_settings_filetype_python = ['pylsp']
|
||||||
|
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_c = ['clangd']
|
||||||
|
let g:lsp_settings_filetype_sh = ['bash-language-server']
|
||||||
|
let g:lsp_settings_filetype_html = ['vscode-html-language-server']
|
||||||
|
let g:lsp_settings_filetype_css = ['vscode-css-language-server']
|
||||||
|
let g:lsp_settings_filetype_scss = ['vscode-css-language-server']
|
||||||
|
let g:lsp_settings_filetype_json = ['vscode-json-language-server']
|
||||||
|
let g:lsp_settings_filetype_yaml = ['yaml-language-server']
|
||||||
|
let g:lsp_settings_filetype_markdown = ['marksman']
|
||||||
|
let g:lsp_settings_filetype_sql = ['sqls']
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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': '>'}
|
||||||
|
|
||||||
|
" ── Completion ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if has('patch-8.1.1517')
|
||||||
|
set completeopt=menuone,noinsert,noselect,popup
|
||||||
|
else
|
||||||
|
set completeopt=menuone,noinsert,noselect
|
||||||
|
endif
|
||||||
|
set pumheight=15
|
||||||
|
let g:asyncomplete_auto_popup = 1
|
||||||
|
let g:asyncomplete_auto_completeopt = 0
|
||||||
|
let g:asyncomplete_popup_delay = 50
|
||||||
|
|
||||||
|
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
|
||||||
|
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
|
||||||
|
inoremap <expr> <CR> pumvisible() ? asyncomplete#close_popup() : "\<CR>"
|
||||||
|
|
||||||
|
" ── Buffer Keymaps ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function! s:on_lsp_buffer_enabled() abort
|
||||||
|
setlocal omnifunc=lsp#complete
|
||||||
|
setlocal signcolumn=yes
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
nmap <buffer> K <plug>(lsp-hover)
|
||||||
|
|
||||||
|
nmap <buffer> <leader>rn <plug>(lsp-rename)
|
||||||
|
nmap <buffer> <leader>ca <plug>(lsp-code-action)
|
||||||
|
nmap <buffer> <leader>f <plug>(lsp-document-format)
|
||||||
|
xmap <buffer> <leader>f <plug>(lsp-document-range-format)
|
||||||
|
|
||||||
|
nmap <buffer> <leader>o <plug>(lsp-document-symbol-search)
|
||||||
|
nmap <buffer> <leader>ws <plug>(lsp-workspace-symbol-search)
|
||||||
|
nmap <buffer> <leader>cD <plug>(lsp-document-diagnostics)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
augroup lsp_install
|
||||||
|
autocmd!
|
||||||
|
autocmd User lsp_buffer_enabled call s:on_lsp_buffer_enabled()
|
||||||
|
augroup END
|
||||||
98
modules/navigation.vim
Normal file
98
modules/navigation.vim
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
" navigation.vim — FZF, netrw, buffer/window management, terminal
|
||||||
|
|
||||||
|
" ── netrw (built-in file browser) ───────────────────────────────────────────
|
||||||
|
|
||||||
|
let g:netrw_liststyle = 3
|
||||||
|
let g:netrw_banner = 0
|
||||||
|
let g:netrw_browse_split = 0
|
||||||
|
let g:netrw_winsize = 25
|
||||||
|
let g:netrw_list_hide = '\(^\|\s\s\)\zs\.\S\+'
|
||||||
|
let g:netrw_list_hide .= ',\.pyc$,node_modules,\.git,__pycache__,\.DS_Store'
|
||||||
|
|
||||||
|
nnoremap <leader>e :Explore<CR>
|
||||||
|
nnoremap <leader>E :Vexplore<CR>
|
||||||
|
|
||||||
|
" ── FZF ─────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function! s:SmartFiles() abort
|
||||||
|
if isdirectory('.git') || finddir('.git', '.;') !=# ''
|
||||||
|
GFiles
|
||||||
|
else
|
||||||
|
Files
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
if exists('g:plugs["fzf.vim"]')
|
||||||
|
nnoremap <C-p> :call <SID>SmartFiles()<CR>
|
||||||
|
nnoremap <leader>b :Buffers<CR>
|
||||||
|
nnoremap <leader>rg :Rg<CR>
|
||||||
|
nnoremap <leader>rG :RgWord<CR>
|
||||||
|
nnoremap <leader>rt :Tags<CR>
|
||||||
|
nnoremap <leader>gF :GFiles<CR>
|
||||||
|
nnoremap <leader>fh :History<CR>
|
||||||
|
nnoremap <leader>fc :Commands<CR>
|
||||||
|
nnoremap <leader>fm :Marks<CR>
|
||||||
|
nnoremap <leader>fl :BLines<CR>
|
||||||
|
nnoremap <leader>fL :Lines<CR>
|
||||||
|
nnoremap <leader>f/ :History/<CR>
|
||||||
|
nnoremap <leader>f: :History:<CR>
|
||||||
|
endif
|
||||||
|
|
||||||
|
let g:fzf_layout = { 'down': '40%' }
|
||||||
|
|
||||||
|
if g:is_tty
|
||||||
|
let g:fzf_preview_window = []
|
||||||
|
else
|
||||||
|
let g:fzf_preview_window = ['right:50%', 'ctrl-/']
|
||||||
|
endif
|
||||||
|
|
||||||
|
if g:is_tty
|
||||||
|
command! -bang -nargs=* Rg
|
||||||
|
\ call fzf#vim#grep(
|
||||||
|
\ 'rg --column --line-number --no-heading --color=always --smart-case -- '
|
||||||
|
\ .shellescape(<q-args>), 1, <bang>0)
|
||||||
|
command! -bang GFiles call fzf#vim#gitfiles('', <bang>0)
|
||||||
|
else
|
||||||
|
command! -bang -nargs=* Rg
|
||||||
|
\ call fzf#vim#grep(
|
||||||
|
\ 'rg --column --line-number --no-heading --color=always --smart-case -- '
|
||||||
|
\ .shellescape(<q-args>), 1, fzf#vim#with_preview(), <bang>0)
|
||||||
|
command! -bang GFiles call fzf#vim#gitfiles('', fzf#vim#with_preview(), <bang>0)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if g:is_tty
|
||||||
|
command! -bang -nargs=* RgWord
|
||||||
|
\ call fzf#vim#grep(
|
||||||
|
\ 'rg --column --line-number --no-heading --color=always --smart-case -F -- '
|
||||||
|
\ .shellescape(expand('<cword>')), 1, <bang>0)
|
||||||
|
else
|
||||||
|
command! -bang -nargs=* RgWord
|
||||||
|
\ call fzf#vim#grep(
|
||||||
|
\ 'rg --column --line-number --no-heading --color=always --smart-case -F -- '
|
||||||
|
\ .shellescape(expand('<cword>')), 1, fzf#vim#with_preview(), <bang>0)
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── Window Maximize Toggle ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function! s:ToggleMaximize() abort
|
||||||
|
if exists('t:maximize_session')
|
||||||
|
execute t:maximize_session
|
||||||
|
unlet t:maximize_session
|
||||||
|
else
|
||||||
|
let t:maximize_session = winrestcmd()
|
||||||
|
resize | vertical resize
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
nnoremap <silent> <leader>z :call <SID>ToggleMaximize()<CR>
|
||||||
|
|
||||||
|
" ── Terminal ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if has('terminal')
|
||||||
|
nnoremap <leader>tv :terminal<CR>
|
||||||
|
nnoremap <leader>th :terminal ++rows=10<CR>
|
||||||
|
tnoremap <Esc><Esc> <C-\><C-n>
|
||||||
|
tnoremap <C-h> <C-\><C-n><C-w>h
|
||||||
|
tnoremap <C-j> <C-\><C-n><C-w>j
|
||||||
|
tnoremap <C-k> <C-\><C-n><C-w>k
|
||||||
|
tnoremap <C-l> <C-\><C-n><C-w>l
|
||||||
|
endif
|
||||||
65
modules/plugins.vim
Normal file
65
modules/plugins.vim
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
" plugins.vim — vim-plug declarations
|
||||||
|
|
||||||
|
let data_dir = has('nvim') ? stdpath('data') . '/site' : '~/.vim'
|
||||||
|
if empty(glob(data_dir . '/autoload/plug.vim'))
|
||||||
|
silent execute '!curl -fLo '.data_dir.'/autoload/plug.vim --create-dirs '
|
||||||
|
\ . 'https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
|
||||||
|
augroup PlugBootstrap
|
||||||
|
autocmd!
|
||||||
|
autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
|
||||||
|
augroup END
|
||||||
|
endif
|
||||||
|
|
||||||
|
call plug#begin('~/.vim/plugged')
|
||||||
|
|
||||||
|
" ── Navigation & Search ──────────────────────────────────────────────────────
|
||||||
|
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
|
||||||
|
Plug 'junegunn/fzf.vim'
|
||||||
|
|
||||||
|
" ── Git ──────────────────────────────────────────────────────────────────────
|
||||||
|
Plug 'tpope/vim-fugitive'
|
||||||
|
Plug 'airblade/vim-gitgutter'
|
||||||
|
|
||||||
|
" ── Editing ──────────────────────────────────────────────────────────────────
|
||||||
|
Plug 'tpope/vim-surround'
|
||||||
|
Plug 'tpope/vim-commentary'
|
||||||
|
Plug 'tpope/vim-repeat'
|
||||||
|
Plug 'tpope/vim-unimpaired'
|
||||||
|
Plug 'tpope/vim-sleuth'
|
||||||
|
Plug 'wellle/targets.vim'
|
||||||
|
Plug 'jiangmiao/auto-pairs'
|
||||||
|
Plug 'easymotion/vim-easymotion'
|
||||||
|
|
||||||
|
" ── Linting & Formatting ────────────────────────────────────────────────────
|
||||||
|
Plug 'dense-analysis/ale'
|
||||||
|
|
||||||
|
" ── LSP + Completion (no Node.js required) ──────────────────────────────────
|
||||||
|
Plug 'prabirshrestha/vim-lsp'
|
||||||
|
Plug 'mattn/vim-lsp-settings'
|
||||||
|
Plug 'prabirshrestha/asyncomplete.vim'
|
||||||
|
Plug 'prabirshrestha/asyncomplete-lsp.vim'
|
||||||
|
|
||||||
|
" ── Language Syntax ──────────────────────────────────────────────────────────
|
||||||
|
Plug 'pangloss/vim-javascript'
|
||||||
|
Plug 'HerringtonDarkholme/yats.vim'
|
||||||
|
Plug 'preservim/vim-markdown'
|
||||||
|
Plug 'fatih/vim-go'
|
||||||
|
|
||||||
|
" ── Markdown Preview & Writing ───────────────────────────────────────────────
|
||||||
|
Plug 'previm/previm'
|
||||||
|
Plug 'junegunn/goyo.vim'
|
||||||
|
Plug 'junegunn/limelight.vim'
|
||||||
|
|
||||||
|
" ── UI ───────────────────────────────────────────────────────────────────────
|
||||||
|
Plug 'mbbill/undotree'
|
||||||
|
Plug 'mhinz/vim-startify'
|
||||||
|
Plug 'lifepillar/vim-solarized8'
|
||||||
|
if !g:is_tty
|
||||||
|
Plug 'Yggdroot/indentLine'
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── Session & Navigation ────────────────────────────────────────────────────
|
||||||
|
Plug 'tpope/vim-obsession'
|
||||||
|
Plug 'christoomey/vim-tmux-navigator'
|
||||||
|
|
||||||
|
call plug#end()
|
||||||
272
modules/tools.vim
Normal file
272
modules/tools.vim
Normal file
|
|
@ -0,0 +1,272 @@
|
||||||
|
" tools.vim — cheat sheet, run file, sudo save, quickfix, helpers
|
||||||
|
|
||||||
|
" ── Helper Functions ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function! HasPaste()
|
||||||
|
if &paste | return 'PASTE MODE ' | endif
|
||||||
|
return ''
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
command! Bclose call <SID>BufcloseCloseIt()
|
||||||
|
function! <SID>BufcloseCloseIt()
|
||||||
|
let l:currentBufNum = bufnr("%")
|
||||||
|
let l:alternateBufNum = bufnr("#")
|
||||||
|
if buflisted(l:alternateBufNum)
|
||||||
|
buffer #
|
||||||
|
else
|
||||||
|
bnext
|
||||||
|
endif
|
||||||
|
if bufnr("%") == l:currentBufNum
|
||||||
|
new
|
||||||
|
endif
|
||||||
|
if buflisted(l:currentBufNum)
|
||||||
|
execute("bdelete! " . l:currentBufNum)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
fun! CleanExtraSpaces()
|
||||||
|
let save_cursor = getpos(".")
|
||||||
|
let old_query = getreg('/')
|
||||||
|
silent! %s/\s\+$//e
|
||||||
|
call setpos('.', save_cursor)
|
||||||
|
call setreg('/', old_query)
|
||||||
|
endfun
|
||||||
|
|
||||||
|
function! ToggleNumber()
|
||||||
|
if(&relativenumber == 1)
|
||||||
|
set norelativenumber
|
||||||
|
set number
|
||||||
|
else
|
||||||
|
set relativenumber
|
||||||
|
endif
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" ── Additional Utilities ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
nnoremap <leader>F gg=G``
|
||||||
|
nnoremap <leader>wa :wa<CR>
|
||||||
|
|
||||||
|
nnoremap <silent> <Leader>= :exe "resize " . (winheight(0) * 3/2)<CR>
|
||||||
|
nnoremap <silent> <Leader>- :exe "resize " . (winheight(0) * 2/3)<CR>
|
||||||
|
nnoremap <silent> <Leader>+ :exe "vertical resize " . (winwidth(0) * 3/2)<CR>
|
||||||
|
nnoremap <silent> <Leader>_ :exe "vertical resize " . (winwidth(0) * 2/3)<CR>
|
||||||
|
|
||||||
|
nnoremap <leader><leader> <c-^>
|
||||||
|
|
||||||
|
nnoremap <leader>W :%s/\s\+$//<CR>:let @/=''<CR>
|
||||||
|
|
||||||
|
nnoremap <leader>so :if &filetype ==# 'vim' <Bar> source % <Bar> echo "Sourced " . expand('%') <Bar> else <Bar> echo "Not a vim file" <Bar> endif<CR>
|
||||||
|
nnoremap <leader>ev :edit $MYVIMRC<CR>
|
||||||
|
nnoremap <leader>sv :source $MYVIMRC<CR>:echo "vimrc reloaded"<CR>
|
||||||
|
|
||||||
|
nnoremap <leader>* :%s/\<<C-r><C-w>\>//g<Left><Left>
|
||||||
|
|
||||||
|
if has('clipboard')
|
||||||
|
nnoremap <leader>cp :let @+ = expand("%:p")<CR>:echo "Copied: " . expand("%:p")<CR>
|
||||||
|
nnoremap <leader>cf :let @+ = expand("%:t")<CR>:echo "Copied: " . expand("%:t")<CR>
|
||||||
|
endif
|
||||||
|
|
||||||
|
nnoremap <leader>ms :e ~/buffer.md<cr>
|
||||||
|
|
||||||
|
" ── Auto-Create Directories ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function! s:MkNonExDir(file, buf)
|
||||||
|
if empty(getbufvar(a:buf, '&buftype')) && a:file !~# '\v^\w+\:\/'
|
||||||
|
let dir = fnamemodify(a:file, ':h')
|
||||||
|
if !isdirectory(dir)
|
||||||
|
call mkdir(dir, 'p')
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
augroup BWCCreateDir
|
||||||
|
autocmd!
|
||||||
|
autocmd BufWritePre *
|
||||||
|
\ if !empty(expand('<afile>')) |
|
||||||
|
\ call s:MkNonExDir(expand('<afile>'), +expand('<abuf>')) |
|
||||||
|
\ endif
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
" ── Large File Handling (>10 MB) ────────────────────────────────────────────
|
||||||
|
|
||||||
|
let g:LargeFile = 1024 * 1024 * 10
|
||||||
|
augroup LargeFile
|
||||||
|
autocmd!
|
||||||
|
autocmd BufReadPre *
|
||||||
|
\ if !empty(expand('<afile>')) |
|
||||||
|
\ let f = getfsize(expand('<afile>')) |
|
||||||
|
\ if f > g:LargeFile || f == -2 | call LargeFileSettings() | endif |
|
||||||
|
\ endif
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
function! LargeFileSettings()
|
||||||
|
setlocal bufhidden=unload
|
||||||
|
setlocal undolevels=-1
|
||||||
|
setlocal noswapfile
|
||||||
|
setlocal syntax=
|
||||||
|
let b:ale_enabled = 0
|
||||||
|
echo "Large file (>10 MB): syntax, undo, and linting disabled."
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
if g:is_tty
|
||||||
|
augroup ChopstickTTYLargeFile
|
||||||
|
autocmd!
|
||||||
|
autocmd BufReadPre *
|
||||||
|
\ if !empty(expand('<afile>')) && getfsize(expand('<afile>')) > 512000 |
|
||||||
|
\ setlocal syntax= |
|
||||||
|
\ endif
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
if !exists("g:tty_message_shown")
|
||||||
|
augroup TTYMessage
|
||||||
|
autocmd!
|
||||||
|
autocmd VimEnter * echom "TTY mode — visual features disabled"
|
||||||
|
augroup END
|
||||||
|
let g:tty_message_shown = 1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── Run Current File (,cr) ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function! s:RunFile() abort
|
||||||
|
write
|
||||||
|
let l:ft = &filetype
|
||||||
|
let l:file = shellescape(expand('%:p'))
|
||||||
|
if l:ft ==# 'python' | execute '!python3 ' . l:file
|
||||||
|
elseif l:ft ==# 'javascript' | execute '!node ' . l:file
|
||||||
|
elseif l:ft ==# 'typescript' | execute '!npx ts-node ' . l:file
|
||||||
|
elseif l:ft ==# 'go' | execute '!go run ' . l:file
|
||||||
|
elseif l:ft ==# 'rust' | execute '!cargo run'
|
||||||
|
elseif l:ft ==# 'sh' | execute '!bash ' . l:file
|
||||||
|
elseif l:ft ==# 'c' | execute '!gcc -o /tmp/a.out ' . l:file . ' && /tmp/a.out'
|
||||||
|
elseif l:ft ==# 'lua' | execute '!lua ' . l:file
|
||||||
|
elseif l:ft ==# 'ruby' | execute '!ruby ' . l:file
|
||||||
|
elseif l:ft ==# 'perl' | execute '!perl ' . l:file
|
||||||
|
else | echo 'No runner for filetype: ' . l:ft
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
nnoremap <leader>cr :call <SID>RunFile()<CR>
|
||||||
|
|
||||||
|
" ── Sudo Save ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
cnoremap w!! w !sudo tee > /dev/null %
|
||||||
|
|
||||||
|
" ── QuickFix Improvements ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
augroup ChopstickQF
|
||||||
|
autocmd!
|
||||||
|
autocmd QuickFixCmdPost [^l]* cwindow
|
||||||
|
autocmd QuickFixCmdPost l* lwindow
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
nnoremap <silent> ]q :cnext<CR>
|
||||||
|
nnoremap <silent> [q :cprev<CR>
|
||||||
|
|
||||||
|
" ── Debug Helpers ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
nnoremap <leader>sh :call <SID>SynStack()<CR>
|
||||||
|
function! <SID>SynStack()
|
||||||
|
if !exists("*synstack") | return | endif
|
||||||
|
echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" ── Cheat Sheet (,?) ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function! s:CheatSheet() abort
|
||||||
|
let l:name = '__ChopsticksCheatSheet__'
|
||||||
|
if bufwinnr(l:name) > 0
|
||||||
|
execute bufwinnr(l:name) . 'wincmd w'
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
execute 'botright new ' . l:name
|
||||||
|
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile
|
||||||
|
call setline(1, [
|
||||||
|
\ '=== chopsticks — Quick Reference ===',
|
||||||
|
\ '',
|
||||||
|
\ 'SURVIVAL',
|
||||||
|
\ ' Esc / jk Exit insert or visual mode',
|
||||||
|
\ ' :q! + Enter Quit without saving',
|
||||||
|
\ ' ,x Save+quit ,w Save Ctrl+s Save (any mode)',
|
||||||
|
\ ' :w!! Sudo save (when you forgot to open as root)',
|
||||||
|
\ '',
|
||||||
|
\ 'FILES & SEARCH',
|
||||||
|
\ ' Ctrl+p Fuzzy find file (git-aware)',
|
||||||
|
\ ' ,e / ,E File browser / vertical split',
|
||||||
|
\ ' ,b Search open buffers',
|
||||||
|
\ ' ,rg Search project contents (ripgrep)',
|
||||||
|
\ ' ,rG Ripgrep word under cursor',
|
||||||
|
\ ' ,fh Recent files history',
|
||||||
|
\ ' ,fl / ,fL Search lines in buffer / all buffers',
|
||||||
|
\ ' ,fc Commands | ,fm Marks',
|
||||||
|
\ ' ,f/ / ,f: Search / command history',
|
||||||
|
\ ' ,, Switch to last file (Ctrl+^)',
|
||||||
|
\ '',
|
||||||
|
\ 'CODE INTELLIGENCE (vim-lsp)',
|
||||||
|
\ ' gd Definition gy Type def gi Impl gr Refs',
|
||||||
|
\ ' K Hover documentation',
|
||||||
|
\ ' [g / ]g Prev / next LSP diagnostic',
|
||||||
|
\ ' [e / ]e Prev / next ALE error',
|
||||||
|
\ ' ,ca Code action ,rn Rename ,f Format',
|
||||||
|
\ ' ,o File outline ,ws Workspace symbols',
|
||||||
|
\ ' ,cr Run current file',
|
||||||
|
\ '',
|
||||||
|
\ 'MARKDOWN & WRITING',
|
||||||
|
\ ' ,mp Live browser preview (previm)',
|
||||||
|
\ ' ,mt Table of contents',
|
||||||
|
\ ' ,zen Zen mode (Goyo + Limelight)',
|
||||||
|
\ ' zr / zm Unfold / fold all headings',
|
||||||
|
\ '',
|
||||||
|
\ 'EDITING',
|
||||||
|
\ ' gc Toggle comment (visual mode too)',
|
||||||
|
\ ' s + 2 chars EasyMotion jump anywhere',
|
||||||
|
\ ' ,u / F5 Undo tree',
|
||||||
|
\ ' ,y / ,Y Yank to system clipboard',
|
||||||
|
\ ' Alt+j / Alt+k Move line down / up',
|
||||||
|
\ ' ,F Re-indent file ,W Strip trailing whitespace',
|
||||||
|
\ ' ,* Search and replace word under cursor',
|
||||||
|
\ '',
|
||||||
|
\ 'GIT',
|
||||||
|
\ ' ,gs Status ,gd Diff ,gb Blame',
|
||||||
|
\ ' ,gc Commit ,gp Push ,gl Pull',
|
||||||
|
\ ' [x / ]x Navigate git conflict markers',
|
||||||
|
\ '',
|
||||||
|
\ 'WINDOWS & PANES',
|
||||||
|
\ ' Ctrl+h/j/k/l Navigate splits and tmux panes',
|
||||||
|
\ ' ,h / ,l Prev / next buffer ,bd Close buffer',
|
||||||
|
\ ' ,z Maximize / restore current window',
|
||||||
|
\ ' ,tv / ,th Terminal (vertical / horizontal)',
|
||||||
|
\ ' Esc Esc Exit terminal mode',
|
||||||
|
\ ' ,= / ,- Resize height ,+ / ,_ Resize width',
|
||||||
|
\ '',
|
||||||
|
\ 'QUICKFIX',
|
||||||
|
\ ' ,qo / ,qc Open / close quickfix',
|
||||||
|
\ ' ]q / [q Next / prev quickfix entry',
|
||||||
|
\ '',
|
||||||
|
\ 'UTILITIES',
|
||||||
|
\ ' ,ev / ,sv Edit / reload ~/.vimrc',
|
||||||
|
\ ' ,cp / ,cf Copy file path / filename to clipboard',
|
||||||
|
\ ' ,ms Scratch buffer ,cd CD to file dir',
|
||||||
|
\ ' ,ss Toggle spell ,so Source current vim file',
|
||||||
|
\ ' F2 Paste F3 Line# F4 Relative# F6 Invisible',
|
||||||
|
\ '',
|
||||||
|
\ '(press q to close)',
|
||||||
|
\ ])
|
||||||
|
setlocal nomodifiable readonly
|
||||||
|
nnoremap <buffer> <silent> q :bd<CR>
|
||||||
|
endfunction
|
||||||
|
nnoremap <silent> <leader>? :call <SID>CheatSheet()<CR>
|
||||||
|
|
||||||
|
" ── Interactive Tutorial ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function! s:ChopsticksLearn() abort
|
||||||
|
let l:tutor = g:chopsticks_dir . '/tutor/chopsticks.tutor'
|
||||||
|
if !filereadable(l:tutor)
|
||||||
|
echo "Tutorial not found: " . l:tutor
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
execute 'edit ' . fnameescape(l:tutor)
|
||||||
|
setlocal nomodifiable readonly
|
||||||
|
setlocal buftype=nofile bufhidden=wipe
|
||||||
|
setlocal filetype=text
|
||||||
|
setlocal wrap linebreak
|
||||||
|
endfunction
|
||||||
|
command! ChopsticksLearn call s:ChopsticksLearn()
|
||||||
164
modules/ui.vim
Normal file
164
modules/ui.vim
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
" ui.vim — colorscheme, statusline, startify, indentline
|
||||||
|
|
||||||
|
" ── Colorscheme (Solarized Dark — matches tmux palette) ────────────────────
|
||||||
|
|
||||||
|
if g:has_true_color && has('termguicolors') && !g:is_tty
|
||||||
|
let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
|
||||||
|
let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
|
||||||
|
set termguicolors
|
||||||
|
endif
|
||||||
|
|
||||||
|
set background=dark
|
||||||
|
|
||||||
|
if !g:is_tty
|
||||||
|
try
|
||||||
|
colorscheme solarized8
|
||||||
|
catch
|
||||||
|
colorscheme default
|
||||||
|
endtry
|
||||||
|
else
|
||||||
|
colorscheme default
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has("gui_running")
|
||||||
|
if has("gui_gtk2") || has("gui_gtk3")
|
||||||
|
set guifont=Hack\ 12,Source\ Code\ Pro\ 12,Monospace\ 12
|
||||||
|
elseif has("gui_win32")
|
||||||
|
set guifont=Consolas:h11:cANSI
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── IndentLine (non-TTY only) ───────────────────────────────────────────────
|
||||||
|
|
||||||
|
if !g:is_tty && exists('g:plugs["indentLine"]')
|
||||||
|
let g:indentLine_char = '|'
|
||||||
|
let g:indentLine_first_char = '|'
|
||||||
|
let g:indentLine_showFirstIndentLevel = 1
|
||||||
|
let g:indentLine_fileTypeExclude = ['text', 'help', 'startify', 'markdown']
|
||||||
|
let g:indentLine_bufTypeExclude = ['help', 'terminal', 'nofile']
|
||||||
|
let g:indentLine_setConceal = 2
|
||||||
|
let g:indentLine_concealcursor = ''
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── Startify ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if exists('g:plugs["vim-startify"]')
|
||||||
|
let g:startify_custom_header = [
|
||||||
|
\ ' ██████╗██╗ ██╗ ██████╗ ██████╗ ███████╗████████╗██╗ ██████╗██╗ ██╗███████╗',
|
||||||
|
\ ' ██╔════╝██║ ██║██╔═══██╗██╔══██╗██╔════╝╚══██╔══╝██║██╔════╝██║ ██╔╝██╔════╝',
|
||||||
|
\ ' ██║ ███████║██║ ██║██████╔╝███████╗ ██║ ██║██║ █████╔╝ ███████╗',
|
||||||
|
\ ' ██║ ██╔══██║██║ ██║██╔═══╝ ╚════██║ ██║ ██║██║ ██╔═██╗ ╚════██║',
|
||||||
|
\ ' ╚██████╗██║ ██║╚██████╔╝██║ ███████║ ██║ ██║╚██████╗██║ ██╗███████║',
|
||||||
|
\ ' ╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝',
|
||||||
|
\ '',
|
||||||
|
\ ]
|
||||||
|
|
||||||
|
let g:startify_lists = [
|
||||||
|
\ { 'type': 'sessions', 'header': [' Sessions'] },
|
||||||
|
\ { 'type': 'files', 'header': [' Recent Files'] },
|
||||||
|
\ { 'type': 'dir', 'header': [' Current Dir'] },
|
||||||
|
\ { 'type': 'bookmarks', 'header': [' Bookmarks'] },
|
||||||
|
\ ]
|
||||||
|
|
||||||
|
let g:startify_bookmarks = [{'v': '~/.vimrc'}]
|
||||||
|
if filereadable(expand('~/.zshrc'))
|
||||||
|
call add(g:startify_bookmarks, {'z': '~/.zshrc'})
|
||||||
|
endif
|
||||||
|
if filereadable(expand('~/.bashrc'))
|
||||||
|
call add(g:startify_bookmarks, {'b': '~/.bashrc'})
|
||||||
|
endif
|
||||||
|
if filereadable(expand('~/.config/fish/config.fish'))
|
||||||
|
call add(g:startify_bookmarks, {'f': '~/.config/fish/config.fish'})
|
||||||
|
endif
|
||||||
|
|
||||||
|
let g:startify_session_persistence = 1
|
||||||
|
let g:startify_session_autoload = 1
|
||||||
|
let g:startify_change_to_vcs_root = 1
|
||||||
|
let g:startify_fortune_use_unicode = 0
|
||||||
|
let g:startify_enable_special = 0
|
||||||
|
let g:startify_files_number = 8
|
||||||
|
let g:startify_padding_left = 4
|
||||||
|
|
||||||
|
if !g:is_tty
|
||||||
|
augroup ChopstickStartup
|
||||||
|
autocmd!
|
||||||
|
autocmd StdinReadPre * let s:std_in = 1
|
||||||
|
autocmd VimEnter *
|
||||||
|
\ if argc() == 1 && isdirectory(argv()[0]) && !exists('s:std_in') |
|
||||||
|
\ exe 'cd ' . fnameescape(argv()[0]) |
|
||||||
|
\ if exists(':Startify') == 2 | Startify | else | enew | endif |
|
||||||
|
\ endif
|
||||||
|
augroup END
|
||||||
|
endif
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── Status Line (native — Solarized palette, seamless with tmux bar) ───────
|
||||||
|
|
||||||
|
set laststatus=2
|
||||||
|
set noshowmode
|
||||||
|
|
||||||
|
function! s:SLDefineColors() abort
|
||||||
|
hi SLNormal ctermbg=136 ctermfg=234 cterm=bold guibg=#b58900 guifg=#002b36 gui=bold
|
||||||
|
hi SLInsert ctermbg=33 ctermfg=234 cterm=bold guibg=#268bd2 guifg=#002b36 gui=bold
|
||||||
|
hi SLVisual ctermbg=125 ctermfg=234 cterm=bold guibg=#d33682 guifg=#002b36 gui=bold
|
||||||
|
hi SLReplace ctermbg=160 ctermfg=234 cterm=bold guibg=#dc322f guifg=#002b36 gui=bold
|
||||||
|
hi SLCommand ctermbg=37 ctermfg=234 cterm=bold guibg=#2aa198 guifg=#002b36 gui=bold
|
||||||
|
hi SLBody ctermbg=235 ctermfg=245 cterm=none guibg=#073642 guifg=#93a1a1
|
||||||
|
hi SLFlag ctermbg=235 ctermfg=136 cterm=none guibg=#073642 guifg=#b58900
|
||||||
|
hi SLRight ctermbg=235 ctermfg=240 cterm=none guibg=#073642 guifg=#586e75
|
||||||
|
hi SLGit ctermbg=235 ctermfg=37 cterm=none guibg=#073642 guifg=#2aa198
|
||||||
|
hi SLFtype ctermbg=235 ctermfg=244 cterm=none guibg=#073642 guifg=#839496
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
augroup SLColors
|
||||||
|
autocmd!
|
||||||
|
autocmd ColorScheme * call s:SLDefineColors()
|
||||||
|
augroup END
|
||||||
|
call s:SLDefineColors()
|
||||||
|
|
||||||
|
function! SLMode() abort
|
||||||
|
let l:m = mode()
|
||||||
|
if l:m ==# 'n' | return [' N ', 'SLNormal' ]
|
||||||
|
elseif l:m ==# 'i' | return [' I ', 'SLInsert' ]
|
||||||
|
elseif l:m =~# '[vV]' || l:m ==# "\<C-v>" | return [' V ', 'SLVisual' ]
|
||||||
|
elseif l:m ==# 'R' | return [' R ', 'SLReplace']
|
||||||
|
elseif l:m ==# 'c' | return [' C ', 'SLCommand']
|
||||||
|
elseif l:m ==# 't' | return [' T ', 'SLInsert' ]
|
||||||
|
else | return [' ' . l:m . ' ', 'SLNormal']
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! SLGit() abort
|
||||||
|
if !exists('*FugitiveHead') | return '' | endif
|
||||||
|
let l:b = FugitiveHead()
|
||||||
|
return empty(l:b) ? '' : ' ' . l:b . ' '
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! SLAle() abort
|
||||||
|
if !exists('*ale#statusline#Count') | return '' | endif
|
||||||
|
let l:c = ale#statusline#Count(bufnr(''))
|
||||||
|
let l:e = l:c.error + l:c.style_error
|
||||||
|
let l:w = l:c.warning + l:c.style_warning
|
||||||
|
if l:e == 0 && l:w == 0 | return '' | endif
|
||||||
|
return printf(' E:%d W:%d ', l:e, l:w)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! SLBuild() abort
|
||||||
|
let [l:label, l:hl] = SLMode()
|
||||||
|
let l:s = '%#' . l:hl . '#' . l:label
|
||||||
|
let l:s .= '%#SLBody# %f '
|
||||||
|
let l:s .= '%#SLFlag#%m%r'
|
||||||
|
let l:s .= '%#SLBody#%='
|
||||||
|
let l:s .= '%#SLFlag#' . SLAle()
|
||||||
|
let l:s .= '%#SLGit#' . SLGit()
|
||||||
|
let l:s .= '%#SLFtype# %y '
|
||||||
|
let l:s .= '%#SLRight# %l:%c %P '
|
||||||
|
return l:s
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
set statusline=%!SLBuild()
|
||||||
|
|
||||||
|
if g:is_tty
|
||||||
|
set statusline=%f\ %h%w%m%r\ %=%(%l,%c%V\ %=\ %P%)
|
||||||
|
endif
|
||||||
56
modules/writing.vim
Normal file
56
modules/writing.vim
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
" writing.vim — vim-markdown, previm, goyo + limelight zen mode
|
||||||
|
|
||||||
|
" ── vim-markdown ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
let g:vim_markdown_conceal = 1
|
||||||
|
let g:vim_markdown_conceal_code_blocks = 0
|
||||||
|
let g:vim_markdown_folding_disabled = 0
|
||||||
|
let g:vim_markdown_folding_level = 2
|
||||||
|
let g:vim_markdown_frontmatter = 1
|
||||||
|
let g:vim_markdown_toml_frontmatter = 1
|
||||||
|
let g:vim_markdown_json_frontmatter = 1
|
||||||
|
let g:vim_markdown_follow_anchor = 1
|
||||||
|
let g:vim_markdown_new_list_item_indent = 2
|
||||||
|
let g:vim_markdown_strikethrough = 1
|
||||||
|
|
||||||
|
if exists('g:plugs["vim-markdown"]')
|
||||||
|
nnoremap <leader>mt :Toc<CR>
|
||||||
|
endif
|
||||||
|
|
||||||
|
" ── previm (Markdown browser preview) ───────────────────────────────────────
|
||||||
|
|
||||||
|
if has('macunix')
|
||||||
|
let g:previm_open_cmd = '/usr/bin/open'
|
||||||
|
elseif executable('xdg-open')
|
||||||
|
let g:previm_open_cmd = 'xdg-open'
|
||||||
|
endif
|
||||||
|
if exists('g:plugs["previm"]')
|
||||||
|
nnoremap <leader>mp :PrevimOpen<CR>
|
||||||
|
endif
|
||||||
|
let g:previm_enable_realtime = 1
|
||||||
|
|
||||||
|
" ── Goyo + Limelight (zen mode) ────────────────────────────────────────────
|
||||||
|
|
||||||
|
if exists('g:plugs["goyo.vim"]')
|
||||||
|
let g:goyo_width = 80
|
||||||
|
let g:goyo_height = '85%'
|
||||||
|
nnoremap <leader>zen :Goyo<CR>
|
||||||
|
|
||||||
|
function! s:goyo_enter()
|
||||||
|
if exists('g:plugs["limelight.vim"]') | Limelight | endif
|
||||||
|
set wrap linebreak scrolloff=999
|
||||||
|
endfunction
|
||||||
|
function! s:goyo_leave()
|
||||||
|
if exists('g:plugs["limelight.vim"]') | Limelight! | endif
|
||||||
|
set nowrap nolinebreak scrolloff=10
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
augroup ChopstickGoyo
|
||||||
|
autocmd!
|
||||||
|
autocmd User GoyoEnter nested call s:goyo_enter()
|
||||||
|
autocmd User GoyoLeave nested call s:goyo_leave()
|
||||||
|
augroup END
|
||||||
|
endif
|
||||||
|
|
||||||
|
let g:limelight_conceal_ctermfg = 240
|
||||||
|
let g:limelight_conceal_guifg = '#586e75'
|
||||||
269
tutor/chopsticks.tutor
Normal file
269
tutor/chopsticks.tutor
Normal file
|
|
@ -0,0 +1,269 @@
|
||||||
|
================================================================================
|
||||||
|
= C H O P S T I C K S I N T E R A C T I V E T U T O R =
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
This tutorial teaches the key features of the chopsticks Vim configuration.
|
||||||
|
It assumes you already know basic Vim (if not, run :Tutor first).
|
||||||
|
|
||||||
|
Leader key is , (comma) throughout this tutorial.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 1: SURVIVAL BASICS
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
These four commands get you out of any situation:
|
||||||
|
|
||||||
|
1. Press Esc or type jk to return to Normal mode
|
||||||
|
2. Type ,w to save the current file
|
||||||
|
3. Type ,x to save and quit
|
||||||
|
4. Type ,q to quit (without saving)
|
||||||
|
|
||||||
|
TIP: You can also press Ctrl+s to save from ANY mode (normal, insert,
|
||||||
|
or visual). Try it now — press i to enter insert mode, then Ctrl+s
|
||||||
|
to save without leaving insert mode.
|
||||||
|
|
||||||
|
When completely lost, press ,? to open the cheat sheet with every
|
||||||
|
keybinding. Press q to close it.
|
||||||
|
|
||||||
|
>>> Try it now: press ,? then read through the sheet, then press q
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 2: FINDING FILES
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
chopsticks uses FZF (fuzzy finder) for fast navigation.
|
||||||
|
|
||||||
|
Ctrl+p Fuzzy find files (git-aware — ignores .gitignore'd files)
|
||||||
|
,b Search open buffers
|
||||||
|
,fh Recent file history
|
||||||
|
,rg Search file contents with ripgrep
|
||||||
|
,rG Search for the word under your cursor
|
||||||
|
|
||||||
|
>>> Try it now: press Ctrl+p and start typing a filename
|
||||||
|
|
||||||
|
You can also browse files with the built-in file browser:
|
||||||
|
|
||||||
|
,e Open netrw file browser in current window
|
||||||
|
,E Open netrw in a vertical split
|
||||||
|
|
||||||
|
Inside netrw:
|
||||||
|
Enter Open file
|
||||||
|
- Go up one directory
|
||||||
|
% Create new file
|
||||||
|
d Create new directory
|
||||||
|
gh Toggle hidden files
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 3: CODE INTELLIGENCE
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
chopsticks uses vim-lsp for code intelligence — no Node.js required.
|
||||||
|
|
||||||
|
First, install a language server for your filetype:
|
||||||
|
|
||||||
|
:LspInstallServer (auto-detects the language)
|
||||||
|
:LspStatus (check if it's running)
|
||||||
|
|
||||||
|
Once a server is running, these keys become available:
|
||||||
|
|
||||||
|
gd Go to definition
|
||||||
|
gy Go to type definition
|
||||||
|
gi Go to implementation
|
||||||
|
gr List all references
|
||||||
|
K Show hover documentation
|
||||||
|
|
||||||
|
[g / ]g Jump to previous / next diagnostic
|
||||||
|
,rn Rename symbol under cursor
|
||||||
|
,ca Code action (auto-fix)
|
||||||
|
,f Format buffer (or selection in visual mode)
|
||||||
|
,o File outline (symbols)
|
||||||
|
|
||||||
|
>>> Open a source file and try: gd on a function call, then Ctrl+o
|
||||||
|
to jump back
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 4: EDITING POWER
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
These editing features make chopsticks faster than vanilla Vim.
|
||||||
|
|
||||||
|
EASYMOTION — jump anywhere on screen:
|
||||||
|
Press s then type two characters from your target location.
|
||||||
|
Matching positions light up — press the highlighted letter to jump.
|
||||||
|
|
||||||
|
>>> Try it now: press s then type two letters you can see on screen
|
||||||
|
|
||||||
|
MOVE LINES — rearrange code without cut/paste:
|
||||||
|
Alt+j Move current line down
|
||||||
|
Alt+k Move current line up
|
||||||
|
(Works in visual mode too — select lines first with V )
|
||||||
|
|
||||||
|
SURROUND — change surrounding characters:
|
||||||
|
cs"' Change surrounding " to '
|
||||||
|
cs'<div> Change surrounding ' to <div>...</div>
|
||||||
|
ds( Delete surrounding parentheses
|
||||||
|
ysiw" Surround word with "
|
||||||
|
|
||||||
|
COMMENT — toggle comments:
|
||||||
|
gc Toggle comment (works in visual mode on selections)
|
||||||
|
gcc Toggle comment on current line
|
||||||
|
|
||||||
|
VISUAL FEEDBACK:
|
||||||
|
- Yanked text flashes briefly so you know what was copied
|
||||||
|
- Search highlights auto-clear after you stop moving
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 5: GIT WORKFLOW
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
All git operations through vim-fugitive:
|
||||||
|
|
||||||
|
,gs Git status (press s to stage, press cc to commit)
|
||||||
|
,gd Diff current file (side-by-side split)
|
||||||
|
,gb Git blame (who changed each line)
|
||||||
|
,gc Git commit
|
||||||
|
,gp Git push
|
||||||
|
,gl Git pull
|
||||||
|
|
||||||
|
GitGutter shows changes in the sign column (left margin):
|
||||||
|
+ Added line
|
||||||
|
~ Modified line
|
||||||
|
- Deleted line
|
||||||
|
|
||||||
|
Navigate git conflict markers:
|
||||||
|
]x Jump to next conflict marker
|
||||||
|
[x Jump to previous conflict marker
|
||||||
|
|
||||||
|
>>> Try ,gs in a git repository to see the status view
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 6: MARKDOWN & WRITING
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Markdown files get special treatment automatically:
|
||||||
|
- Word wrap enabled
|
||||||
|
- Spell checking enabled
|
||||||
|
- Syntax concealment (bold renders as bold, headings hide # markers)
|
||||||
|
- Folding by heading level
|
||||||
|
|
||||||
|
Key bindings for markdown:
|
||||||
|
|
||||||
|
,mp Open live browser preview (auto-refreshes as you type)
|
||||||
|
,mt Table of contents in a side window
|
||||||
|
,zen Enter zen mode — Goyo + Limelight
|
||||||
|
(distraction-free writing, only current paragraph highlighted)
|
||||||
|
zr Unfold all headings
|
||||||
|
zm Fold all headings
|
||||||
|
|
||||||
|
>>> Open a .md file and try ,zen to enter zen mode.
|
||||||
|
Press ,zen again to leave.
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 7: WINDOW MANAGEMENT
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Navigate between splits (works with tmux panes too):
|
||||||
|
|
||||||
|
Ctrl+h Move to left split
|
||||||
|
Ctrl+j Move to split below
|
||||||
|
Ctrl+k Move to split above
|
||||||
|
Ctrl+l Move to right split
|
||||||
|
|
||||||
|
Buffer navigation:
|
||||||
|
|
||||||
|
,h Previous buffer
|
||||||
|
,l Next buffer
|
||||||
|
,bd Close buffer (keeps window layout)
|
||||||
|
,, Switch to last file (toggle between two files)
|
||||||
|
|
||||||
|
Window tricks:
|
||||||
|
|
||||||
|
,z Maximize current window (press again to restore)
|
||||||
|
,= / ,- Resize window height (bigger / smaller)
|
||||||
|
,+ / ,_ Resize window width (bigger / smaller)
|
||||||
|
|
||||||
|
Terminal:
|
||||||
|
|
||||||
|
,tv Open terminal (vertical split)
|
||||||
|
,th Open terminal (horizontal, 10 rows)
|
||||||
|
Esc Esc Exit terminal mode back to normal
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 8: LINTING & FORMATTING
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
ALE runs linters and formatters automatically:
|
||||||
|
|
||||||
|
- Linting happens as you type (normal mode) and on save
|
||||||
|
- Format-on-save is enabled by default (black, prettier, gofmt, etc.)
|
||||||
|
|
||||||
|
Navigate errors:
|
||||||
|
|
||||||
|
[e / ]e Previous / next ALE error
|
||||||
|
,aD Show error detail in a popup
|
||||||
|
|
||||||
|
Supported out of the box:
|
||||||
|
Python: flake8 + pylint (lint), black + isort (format)
|
||||||
|
JS/TS: eslint (lint), prettier + eslint (format)
|
||||||
|
Go: staticcheck (lint), goimports (format)
|
||||||
|
Rust: cargo (lint), rustfmt (format)
|
||||||
|
Shell: shellcheck (lint)
|
||||||
|
And more: yaml, dockerfile, css, markdown, sql
|
||||||
|
|
||||||
|
>>> Write some intentionally bad code and watch the sign column
|
||||||
|
light up with X (error) and ! (warning) markers
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 9: RUNNING CODE
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Press ,cr to run the current file. It auto-detects the language:
|
||||||
|
|
||||||
|
Python → python3 file.py
|
||||||
|
JavaScript → node file.js
|
||||||
|
TypeScript → npx ts-node file.ts
|
||||||
|
Go → go run file.go
|
||||||
|
Rust → cargo run
|
||||||
|
Shell → bash file.sh
|
||||||
|
C → gcc + run
|
||||||
|
Lua, Ruby, Perl also supported
|
||||||
|
|
||||||
|
>>> Create a test file (e.g. test.py with: print("hello"))
|
||||||
|
and press ,cr to run it
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 10: DAILY TIPS
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
SEARCH AND REPLACE:
|
||||||
|
,* Replace word under cursor throughout the file
|
||||||
|
// In visual mode, search for selected text
|
||||||
|
|
||||||
|
USEFUL SHORTCUTS:
|
||||||
|
Y Yank to end of line (consistent with D and C)
|
||||||
|
,y / ,Y Yank to system clipboard
|
||||||
|
,F Re-indent entire file
|
||||||
|
,W Strip all trailing whitespace
|
||||||
|
:w!! Sudo save (when you forgot to open as root)
|
||||||
|
,ev Edit your vimrc
|
||||||
|
,sv Reload your vimrc
|
||||||
|
|
||||||
|
SESSIONS:
|
||||||
|
:Obsess Start recording session (auto-restores next time)
|
||||||
|
:Obsess! Stop recording
|
||||||
|
|
||||||
|
The startup screen (Startify) shows recent files, sessions, and bookmarks.
|
||||||
|
|
||||||
|
>>> Press ,? one more time to review the full cheat sheet.
|
||||||
|
You now know the essential chopsticks features. Happy editing!
|
||||||
|
|
||||||
|
================================================================================
|
||||||
Loading…
Reference in a new issue