Last active
May 29, 2025 11:48
-
-
Save yowu/30b93d50505dfb2ced42d9cbe993847a to your computer and use it in GitHub Desktop.
.vimrc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
vim9script | |
# Basic Settings | |
set nocp # No compability | |
set number # Show line numbers | |
set tabstop=4 # Number of spaces for a tab | |
set shiftwidth=4 # Number of spaces for auto-indent | |
set expandtab # Use spaces instead of tabs | |
set ignorecase # Case-insensitive search | |
set smartcase # Case-sensitive if uppercase is used | |
set hlsearch # Highlight search matches | |
set incsearch # Enable incremental search | |
set splitbelow # Always split below | |
set splitright # Always split right | |
set ruler | |
set shortmess=atI # Shorten common messages | |
set fillchars=vert:\│ | |
set completeopt=menuone,noinsert | |
set bs=2 # backspace | |
set ai # AutoIndent | |
set hidden # Not close really but stay in memory | |
set encoding=utf-8 | |
set clipboard=unnamed | |
set belloff=all | |
set report=0 | |
set timeoutlen=500 | |
syntax on | |
filetype plugin on | |
filetype plugin indent on | |
set tags="./tags;,./tags;./.tags;,./.tmp_tags;" | |
# Enable true color support | |
if $TERM_PROGRAM != "Apple_Terminal" | |
set termguicolors | |
endif | |
# Leader keys | |
g:mapleader = ' ' | |
g:maplocalleader = ',' | |
# Platform specific settings | |
if has("win32") | |
source $VIMRUNTIME/mswin.vim | |
behave mswin | |
command Eb browse e | |
command Ew browse w | |
set renderoptions=type:directx | |
endif | |
# GUI settings | |
if has('gui_running') | |
set lines=60 columns=140 | |
set guioptions-=T | |
set guifont=LiterationMono_Nerd_Font_Mono:h14:cANSI:qDRAFT | |
set linespace=2 | |
endif | |
# Unified vim directory - always use ~/.vim regardless of platform/shell | |
var vim_dir = $HOME .. '/.vim/' | |
# Add unified vim directory to runtime path if not already present | |
if stridx(&runtimepath, vim_dir) == -1 | |
set runtimepath^=~/.vim | |
set runtimepath+=~/.vim/after | |
endif | |
# Install vim-plug if not found | |
var plug_file = vim_dir .. 'autoload/plug.vim' | |
if !filereadable(plug_file) | |
system('curl -fLo ' .. plug_file .. ' --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim') | |
if v:shell_error == 0 | |
execute 'source ' .. plug_file | |
g:plug_fresh_installed = 1 | |
else | |
echoerr "Failed to install vim-plug! Exit code: " .. v:shell_error | |
quit | |
endif | |
endif | |
# Plugin Manager | |
call plug#begin($MYVIMDIR .. 'plugged') | |
# UI and Theme | |
Plug 'joshdick/onedark.vim' | |
Plug 'vim-airline/vim-airline' | |
Plug 'ryanoasis/vim-devicons' | |
Plug 'Yggdroot/indentLine' | |
# File Navigation | |
Plug 'preservim/nerdtree' | |
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } | |
Plug 'junegunn/fzf.vim' | |
Plug 'airblade/vim-rooter' | |
# Editor Enhancement | |
Plug 'machakann/vim-highlightedyank' | |
Plug 'Raimondi/delimitMate' | |
Plug 'easymotion/vim-easymotion' | |
Plug 'tpope/vim-surround' | |
Plug 'tpope/vim-repeat' | |
Plug 'tpope/vim-commentary' | |
Plug 'liuchengxu/vim-which-key' | |
Plug 'girishji/vimcomplete' | |
# Git Integration | |
Plug 'tpope/vim-fugitive' | |
Plug 'airblade/vim-gitgutter' | |
# Misc | |
Plug 'mhinz/vim-startify' | |
Plug 'romainl/vim-cool' | |
call plug#end() | |
# Auto-install missing plugins if plug is fresh installed. | |
if exists('g:plug_fresh_installed') && len(filter(values(g:plugs), '!isdirectory(v:val.dir)')) > 0 | |
echo "Installing missing plugins..." | |
PlugInstall --sync | |
echo "Plugins installed! Please restart vim to load them properly." | |
quit | |
endif | |
# Plugin Configurations | |
# Theme | |
colorscheme onedark | |
# Startify | |
g:startify_change_to_dir = 0 | |
# Rooter | |
g:rooter_cd_cmd = 'lcd' | |
g:rooter_patterns = ['.git', 'Makefile', 'package.json', '.vs', '*.sln', 'lazy-lock.json'] | |
# IndentLine | |
g:indentLine_char = '┊' | |
# NERDTree | |
g:NERDTreeShowHidden = 1 | |
g:NERDTreeRespectWildIgnore = 1 | |
g:NERDTreeIgnore = ['.git$', '__pycache__$'] | |
g:NERDTreeDirArrowExpandable = '' | |
g:NERDTreeDirArrowCollapsible = '' | |
# Airline | |
g:airline_theme = 'dark' | |
g:airline_left_sep = '' | |
g:airline_right_sep = '' | |
g:airline_left_alt_sep = '' | |
g:airline_right_alt_sep = 'ᚲ' | |
g:airline_powerline_fonts = 1 | |
g:airline#extensions#whitespace#enabled = 0 | |
g:airline#extensions#wordcount#enabled = 0 | |
g:airline#extensions#tabline#enabled = 1 | |
g:airline#extensions#tabline#fnamemod = ':t' | |
# Git Gutter | |
g:gitgutter_enabled = 0 | |
g:gitgutter_sign_added = '▎' | |
g:gitgutter_sign_modified = '▎' | |
g:gitgutter_sign_removed = '▎' | |
g:gitgutter_sign_removed_first_line = '▎' | |
g:gitgutter_sign_removed_above_and_below = '▎' | |
g:gitgutter_sign_modified_removed = '▎' | |
# FZF | |
g:fzf_vim = {} | |
g:fzf_vim.preview_window = ['hidden,right,50%,<70(up,40%)', 'ctrl-/'] | |
g:fzf_layout = { 'down': '~40%' } | |
# Complete | |
g:vimcomplete_tab_enable = 1 | |
var vcoptions = { | |
completor: { | |
noNewlineInCompletionEver: true, | |
triggerWordLen: 2, | |
setCompleteOpt: false, | |
}, | |
} | |
autocmd VimEnter * g:VimCompleteOptionsSet(vcoptions) | |
# Which-Key | |
# Which-key base configuration | |
g:which_key_use_floating_win = 0 | |
g:which_key_timeout = 100 | |
# Main mappings | |
g:which_key_map = { | |
'f': ['Files', 'Files'], | |
'b': ['Buffers', 'Buffers'], | |
'e': ['NERDTreeToggle', 'Toggle explorer'], | |
'q': 'Smart close', | |
} | |
# Local mappings | |
g:which_key_local_map = { | |
'g': { | |
'name': 'Goto', | |
'a': 'Goto related files', | |
'f': 'Goto file', | |
't': 'Goto tag', | |
}, | |
} | |
# FZF pickers | |
g:which_key_map[' '] = { | |
'name': '+Fzf Pickers', | |
'c': [':Commands', 'Commands'], | |
'h': [':History', 'History'], | |
'm': [':Marks', 'Marks'], | |
'w': [':Windows', 'Windows'], | |
'l': [':Lines', 'Lines'], | |
'C': [':Colors', 'Colors'], | |
'H': [':Helptags', 'Helptags'], | |
't': [':Filetypes', 'Filetypes'], | |
'T': [':Tags', 'Tags'], | |
'B': [':BCommits', 'Buffer Commits'], | |
'g': [':GFiles', 'Git Files'], | |
'L': [':Locate', 'Locate'], | |
'a': [':Ag', 'Ag'], | |
'r': [':Rg', 'Ripgrep'], | |
} | |
# Plugin management | |
g:which_key_map.p = { | |
'name': '+Plug', | |
'i': [':PlugInstall', 'Install plugins'], | |
'u': [':PlugUpdate', 'Update plugins'], | |
'c': [':PlugClean', 'Clean plugins'], | |
'e': [':e $MYVIMRC', 'Edit vimrc'], | |
'r': [':source $MYVIMRC', 'Reload all'], | |
} | |
# Git operations | |
g:which_key_map.g = { | |
'name': '+Git', | |
'b': [':Gblame', 'fugitive-blame'], | |
'C': [':Gcommit', 'fugitive-commit'], | |
'd': [':Gdiff', 'fugitive-diff'], | |
'l': [':Glog', 'fugitive-log'], | |
'r': [':Gread', 'fugitive-read'], | |
'w': [':Gwrite', 'fugitive-write'], | |
'y': [':Goyo', 'goyo-mode'], | |
} | |
# Edit operations | |
g:which_key_map.e = { | |
'name': '+Edit', | |
'a': { | |
'name': 'add surrounding', | |
"1": ["ysiw'", "surround with '"], | |
'2': ['ysiw\"', 'surround with "'], | |
'3': ['ysiwb', 'surround with ('], | |
'4': ['ysiwr', 'surround with ['], | |
'5': ['ysiw\{', 'surround with {'], | |
"6": ["yss'", "surround line with '"], | |
'7': ['yss\"', 'surround line with "'], | |
'8': ['yssb', 'surround line with ('], | |
'9': ['yssr', 'surround line with ['], | |
'0': ['yss\{', 'surround line with {'], | |
}, | |
'd': { | |
'name': '+remove surrounding', | |
"1": ["ds'", "remove surrounding '"], | |
'2': ['ds\"', 'remove surrounding "'], | |
'3': ['dsb', 'remove surrounding ('], | |
'4': ['dsr', 'remove surrounding ['], | |
'5': ['ds\{', 'remove surround with {'], | |
}, | |
'c': { | |
'name': '+change surrounding', | |
'1': ['csbr', 'change ( to ['], | |
'2': ['csb\{', 'change ( to {'], | |
'3': ['csrb', 'change [ to ('], | |
'4': ['csr\{', 'change [ to {' ], | |
'5': ['cs\{b', 'change { to ('], | |
'6': ['cs\{r', 'change { to [' ], | |
}, | |
} | |
# Movement operations | |
g:which_key_map.m = { | |
'name': '+Move', | |
'/': ['<Plug>(easymotion-sn)', 'search'], | |
'l': ['<Plug>(easymotion-lineforward)', 'beginning/ending of WORD forward'], | |
'h': ['<Plug>(easymotion-linebackward)', 'beginning/ending of WORD backward'], | |
'f': ['<plug>(easymotion-prefix)f', 'find {char} to the right'], | |
'F': ['<plug>(easymotion-prefix)F', 'find {char} to the left'], | |
't': ['<plug>(easymotion-prefix)t', 'till before the {char} to the right'], | |
'T': ['<plug>(easymotion-prefix)T', 'till after the {char} to the left'], | |
'w': ['<plug>(easymotion-prefix)w', 'beginning of word forward'], | |
'W': ['<plug>(easymotion-prefix)W', 'beginning of WORD forward'], | |
'b': ['<plug>(easymotion-prefix)b', 'beginning of word backward'], | |
'B': ['<plug>(easymotion-prefix)B', 'beginning of WORD backward'], | |
'e': ['<plug>(easymotion-prefix)e', 'end of word forward'], | |
'E': ['<plug>(easymotion-prefix)E', 'end of WORD forward'], | |
'g': { | |
'name': '+Backwards', | |
'e': ['<plug>(easymotion-prefix)ge', 'end of word backward'], | |
'E': ['<plug>(easymotion-prefix)gE', 'end of WORD backward'], | |
}, | |
'j': ['<plug>(easymotion-prefix)j', 'line downward'], | |
'k': ['<plug>(easymotion-prefix)k', 'line upward'], | |
'n': ['<plug>(easymotion-prefix)n', 'jump to latest "/" or "?" forward'], | |
'N': ['<plug>(easymotion-prefix)N', 'jump to latest "/" or "?" backward'], | |
's': ['<plug>(easymotion-prefix)s', 'find(search) {char} forward and backward'], | |
' ': { | |
'name': 'Move in buffer', | |
'h': ['h', 'Left'], | |
'j': ['j', 'Down'], | |
'k': ['k', 'Up'], | |
'l': ['l', 'Right'], | |
'0': ['0', 'Start of line'], | |
'^': ['^', 'Start of line (non-blank)'], | |
'$': ['$', 'End of line'], | |
'b': ['b', 'Previous word'], | |
'w': ['w', 'Next word'], | |
'e': ['e', 'Next end of word'], | |
'%': ['%', 'Match (), [], and {}'], | |
'G': ['G', 'Last line'], | |
'{': ['{', 'Previous empty line'], | |
'}': ['}', 'Next empty line'], | |
}, | |
} | |
which_key#register('<Space>', g:which_key_map) | |
which_key#register(',', g:which_key_local_map) | |
# AutoCommands | |
# Hide status line for specific filetypes | |
augroup HideStatusLine | |
autocmd! | |
autocmd FileType fzf,which_key set laststatus=0 noshowmode noruler | |
\| autocmd BufLeave <buffer> set laststatus=2 showmode ruler | |
augroup END | |
# Auto map 'q' to close buffer for specific buffer types | |
augroup QClose | |
autocmd! | |
autocmd BufWinEnter * if index(['nofile', 'help', 'quickfix'], &buftype) >= 0 && maparg('q', 'n') ==# '' | |
\| nnoremap <buffer> q :close<CR> | |
\| endif | |
autocmd BufWipeout * if index(['nofile', 'help', 'quickfix'], &buftype) >= 0 | |
\| silent! nunmap <buffer> q | |
\| endif | |
augroup END | |
# Close vim if help/quickfix is the last buffer | |
autocmd BufEnter * if winnr('$') == 1 && ( | |
\ &buftype ==# 'help' || | |
\ &buftype ==# 'quickfix' || | |
\ &filetype ==# 'nerdtree' | |
\ ) | |
\| quit | |
\| endif | |
# | |
# Key Mappings | |
# | |
# File Operations | |
nnoremap <C-s> :wi<CR> # Save file | |
nnoremap <C-S-s> :wa<CR> # Save all | |
nnoremap <C-q> :close<CR> # Close Window | |
# Window Navigation | |
nnoremap <silent> <C-h> <C-w>h | |
nnoremap <silent> <C-j> <C-w>j | |
nnoremap <silent> <C-k> <C-w>k | |
nnoremap <silent> <C-l> <C-w>l | |
# Window Resize | |
nnoremap <M-Up> :resize +2<CR> | |
nnoremap <M-Down> :resize -2<CR> | |
nnoremap <M-Left> :vertical resize -4<CR> | |
nnoremap <M-Right> :vertical resize +4<CR> | |
# Line Movement | |
nnoremap <M-j> :move .+1<CR>== | |
nnoremap <M-k> :move .-2<CR>== | |
xnoremap <M-j> :move '>+1<CR>gv=gv | |
xnoremap <M-k> :move '<-2<CR>gv=gv | |
snoremap <M-j> <Esc>:move '>+1<CR>gv=gv | |
snoremap <M-k> <Esc>:move '<-2<CR>gv=gv | |
# FZF Mappings | |
nnoremap <silent> <localleader>gt :execute 'Tags ' .. expand('<cword>')<CR> | |
nnoremap <silent> <localleader>ga :call FindFilesWithPattern(expand('%:t:r') .. '*')<CR> | |
nnoremap <silent> <localleader>gf :call FindFilesWithPattern(expand('<cfile>'))<CR> | |
nmap <silent> <Leader>q :call SmartCloseWindow()<CR> # QClose | |
# which-key | |
nnoremap <silent> <Leader> :<c-u>WhichKey ' '<CR> | |
vnoremap <silent> <Leader> :<c-u>WhichKeyVisual ' '<CR> | |
nnoremap <localleader> :<c-u>WhichKey ','<CR> | |
vnoremap <localleader> :<c-u>WhichKeyVisual ','<CR> | |
# Functions | |
# Custom FZF Functions | |
def g:FindFilesWithPattern(pattern: string) | |
fzf#run(fzf#wrap({ | |
'source': 'rg --files --iglob ' .. pattern, | |
'sink': 'e', | |
'options': '--select-1 --exit-0', | |
})) | |
enddef | |
# Smart Close Window | |
def g:SmartCloseWindow() | |
# Step 1: Do nothing if only 1 window | |
if winnr('$') == 1 | |
return | |
endif | |
# Define tool buftypes and special filetypes | |
var tool_buftypes = ['nofile', 'help', 'quickfix'] | |
var special_filetypes = ['nerdtree', 'startify'] | |
# Step 2: Close a tool windows (high priority) | |
for winid in range(winnr('$'), 1, -1) | |
var bufnr = winbufnr(winid) | |
var bt = getbufvar(bufnr, '&buftype') | |
if index(tool_buftypes, bt) >= 0 | |
execute ':' .. winid .. 'wincmd c' | |
return | |
endif | |
endfor | |
# Step 3: Close a special filetype windows (secondary priority) | |
for winid in range(winnr('$'), 1, -1) | |
var bufnr = winbufnr(winid) | |
var ft = getbufvar(bufnr, '&filetype') | |
if index(special_filetypes, ft) >= 0 | |
execute ':' .. winid .. 'wincmd c' | |
return | |
endif | |
endfor | |
# Step 4: close one other than current | |
var curwin = winnr() | |
for winid in range(winnr('$'), 1, -1) | |
if winid != curwin | |
execute ':' .. winid .. 'wincmd c' | |
return | |
endif | |
endfor | |
enddef |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment