├── .editorconfig ├── .gitignore ├── CLAUDE.md ├── LICENSE ├── Makefile ├── README.md ├── autoload ├── lib.vim └── settings.vim ├── coc-settings.json ├── colors └── tokyonight.vim ├── ftdetect ├── cmake.vim ├── json.vim ├── rst.txt.vim └── scss.vim ├── ftplugin ├── python.vim └── scss.vim ├── plugins.vim ├── settings ├── autocmd.vim ├── ignore.vim ├── keymappings.vim ├── sensible.vim └── settings.vim ├── tests ├── README.md ├── basic.vim ├── colorscheme.vim ├── filetype.vim ├── harness.vim └── simplification.vim └── vimrc /.editorconfig: -------------------------------------------------------------------------------- 1 | ;.editorconfig 2 | [**.js,**.jsx,**.ts,**.tsx] 3 | bin=node 4 | indent_style = space 5 | indent_size = 2 6 | jslint_happy = 1 7 | keep_array_indentation = 1 8 | keep_function_indentation = 1 9 | space_before_conditional = 1 10 | break_chained_methods = 0 11 | chain_extra_indentation = 1 12 | indent_style = space 13 | preserve_newlines = 1 14 | max_preserve_newlines = 2 15 | charset = utf8 16 | 17 | 18 | [**.json] 19 | indent_style = space 20 | indent_size = 2 21 | 22 | [**.css,**.scss,**.less] 23 | indent_style = space 24 | indent_size = 2 25 | 26 | [**.html, **.erb, **.hbs] 27 | ; Using special comments 28 | ; And such comments or apply only in global configuration 29 | ; So it's best to avoid them 30 | ;vim:max_char=78:brace_style=expand 31 | indent_style = space 32 | indent_size = 2 33 | 34 | [**.py] 35 | indent_style = space 36 | indent_size = 4 37 | 38 | [**.php] 39 | indent_style = tab 40 | end_of_line = lf 41 | insert_final_newline = true 42 | trim_trailing_whitespace = true 43 | 44 | [**.md] 45 | trim_trailing_whitespace = false 46 | 47 | ; Golang 48 | [*.go] 49 | indent_style = tab 50 | indent_size = 4 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | plugged/* 2 | sessions 3 | 4 | .netrwhist 5 | .netrwhist~ 6 | *.swp 7 | 8 | settings/*.vim 9 | settings/compat 10 | settings/quirks 11 | plugins.d/*.vim 12 | plugins.settings/*.vim 13 | 14 | # Plug 15 | autoload/plug.vim* 16 | 17 | # black 18 | black/ 19 | 20 | # Claude code 21 | **/CLAUDE.local.md 22 | **/.claude/settings.local.json 23 | -------------------------------------------------------------------------------- /CLAUDE.md: -------------------------------------------------------------------------------- 1 | # CLAUDE.md 2 | 3 | This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. 4 | 5 | ## Repository Overview 6 | 7 | This is a minimalist, modular Vim configuration designed for sustainability and portability. The configuration follows a philosophy of simplicity and reliability, with conditional loading to prevent breakage when dependencies are missing. 8 | 9 | ## Key Architecture 10 | 11 | ### Entry Points 12 | - `vimrc`: Main configuration entry that orchestrates all other components 13 | - `plugin_loader.vim`: Bootstraps vim-plug and handles automatic plugin installation 14 | - `plugins.vim`: Defines all plugins with conditional loading based on executable availability 15 | 16 | ### Directory Structure 17 | - `autoload/`: Core functions (settings.vim, lib.vim) 18 | - `settings/`: Modular configuration files loaded by autoload/settings.vim 19 | - `ftplugin/`: File-type specific settings 20 | - `plugged/`: Plugin installation directory (gitignored) 21 | - `coc-settings.json`: Language server configurations for CoC.nvim 22 | 23 | ### Plugin Management 24 | Uses vim-plug with automatic installation. Plugins are conditionally loaded based on executable availability (e.g., rust.vim only loads if `cargo` exists). 25 | 26 | ## Common Commands 27 | 28 | ### Plugin Management 29 | ```vim 30 | :PlugInstall " Install missing plugins 31 | :PlugUpdate " Update all plugins 32 | :PlugClean " Remove unused plugins 33 | ``` 34 | 35 | ### Build/Maintenance 36 | ```bash 37 | make nvim # Set up Neovim compatibility symlinks 38 | make vint # Lint vim configuration files 39 | make complete # Link contrib files for completion 40 | ``` 41 | 42 | ### Testing Changes 43 | When modifying configuration: 44 | 1. Source the file: `:source %` or `:source ~/.vim/vimrc` 45 | 2. Check for errors: `:messages` 46 | 3. Test conditional loading by checking executable availability 47 | 48 | ## Key Design Patterns 49 | 50 | ### Conditional Loading 51 | Plugins and settings are loaded conditionally based on: 52 | - Executable availability: `if executable('cargo')` 53 | - Vim version: `if v:version >= 704` 54 | - Platform detection: Uses `lib#platform#*()` functions 55 | 56 | ### Modular Settings 57 | Settings are split into files under `settings/` and loaded by `autoload/settings.vim`. This allows for organized, maintainable configuration. 58 | 59 | ### LSP Configuration 60 | Language servers are configured in `coc-settings.json` with format-on-save enabled for multiple languages. The configuration includes extensive setups for Python, TypeScript, Rust, and other languages. 61 | 62 | ### FZF Integration 63 | Custom FZF commands are defined in `autoload/settings.vim` with AG (silver searcher) integration for fast project-wide searching. 64 | 65 | ## Important Conventions 66 | 67 | 1. **Leader key**: Comma (,) is used as the leader key 68 | 2. **Clipboard**: System clipboard integration is enabled by default 69 | 3. **Root detection**: vim-rooter automatically changes to project root 70 | 4. **Color schemes**: Falls back through multiple schemes if primary is unavailable 71 | 5. **Session storage**: Sessions are stored in `~/.cache/vim/sessions/` 72 | 73 | ## Adding New Features 74 | 75 | ### New Plugin 76 | Add to `plugins.vim` with appropriate conditional: 77 | ```vim 78 | if executable('required-binary') 79 | Plug 'author/plugin-name' 80 | endif 81 | ``` 82 | 83 | ### New Key Mapping 84 | Add to `settings/keymappings.vim` or create a new file in `settings/`. 85 | 86 | ### New Language Support 87 | 1. Add language server config to `coc-settings.json` 88 | 2. Create ftplugin file if needed: `ftplugin/.vim` 89 | 3. Add any required plugins to `plugins.vim` -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2018 Tony Narlock 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | vint: 2 | python -c 'import vint' || pip install --user vim-vint 3 | vint *.vim 4 | 5 | nvim: 6 | ln -sf ~/.vim/autoload/ ~/.config/nvim/ 7 | ln -sf ~/.vim/.vimrc ~/.config/nvim/init.vim 8 | ln -sf ~/.vim/coc-settings.json ~/.config/nvim/coc-settings.json 9 | 10 | complete: 11 | ln -sf ~/.vim/plugins.settings/contrib/*.vim ~/.vim/plugins.settings/ 12 | ln -sf ~/.vim/settings/contrib/*.vim ~/.vim/settings/ 13 | 14 | test: 15 | @echo "Running Vim configuration tests..." 16 | @vim -Es -u tests/harness.vim -c "source tests/basic.vim" 2>&1 | grep -E '(PASS|FAIL|INFO)' || true 17 | @echo "Tests completed" 18 | 19 | test-simplification: 20 | @echo "Testing simplification opportunities..." 21 | @vim -Es -u tests/harness.vim -c "source tests/simplification.vim" 2>&1 | grep -E '(PASS|FAIL|INFO)' || true 22 | 23 | test-verbose: 24 | @vim -Es -u tests/harness.vim -c "source tests/basic.vim" 2>&1 || true 25 | 26 | test-startup: 27 | @echo "Testing Vim startup time..." 28 | @vim --startuptime /tmp/vim-startup.log -c quit 29 | @echo "=== Slowest operations ===" 30 | @sort -k2 -nr /tmp/vim-startup.log | head -20 31 | 32 | test-minimal: 33 | @echo "Testing minimal config (no plugins)..." 34 | @vim -u NONE -Es -c "source tests/harness.vim" -c "source tests/basic.vim" 2>&1 || true 35 | 36 | .PHONY: vint nvim complete test test-simplification test-verbose test-startup test-minimal 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lessons from having a complex vim config: don't do it 2 | 3 | It's a time sink. 4 | 5 | Having the vim configuration break all the time, and pasting in "nice to have" stuff has caused me 6 | more disruption / harm than it has benefitted me. I'm trying to turn my VIM into a lean editing 7 | system, and just learning plain-old VIM more effectively. 8 | 9 | If you want to go back to where I used to be to look feel free to see: 10 | 11 | 12 | I'm hoping to have a happier, healthier VIM experience, life, etc. with a simple vim config. 13 | 14 | ## Plugin Architecture 15 | 16 | This configuration implements an auto-installing, gracefully degrading plugin system built on vim-plug: 17 | 18 | - **Auto-Installation**: Automatically bootstraps vim-plug and installs plugins on first run 19 | - **Graceful Degradation**: Conditionally loads plugins based on available executables and features 20 | - **Modular Design**: Supports local customizations through `plugins.d/` and `plugins.settings/` directories 21 | - **Progressive Enhancement**: Basic functionality always works, advanced features added when dependencies exist 22 | 23 | See [notes/analysis.md](notes/analysis.md) for detailed architecture analysis. 24 | 25 | Please check out: 26 | 27 | - 28 | - 29 | - 30 | - 31 | 32 | ## License 33 | 34 | MIT 35 | 36 | Vendorizes sensible.vim, see [license permission]. 37 | 38 | [license permission]: https://github.com/tpope/vim-sensible/issues/106 39 | -------------------------------------------------------------------------------- /autoload/lib.vim: -------------------------------------------------------------------------------- 1 | " Set shell for Windows systems 2 | if has('win16') || has('win32') || has('win64') 3 | set shell=/bin/sh 4 | endif 5 | 6 | " Function to source only if file exists { 7 | function! lib#SourceIfExists(file) 8 | if filereadable(expand(a:file)) 9 | exe 'source' a:file 10 | endif 11 | endfunction 12 | " } 13 | 14 | 15 | function! lib#ColorSchemeExists(colorscheme) 16 | try 17 | exe 'colorscheme' a:colorscheme 18 | return 1 19 | catch /^Vim\%((\a\+)\)\=:E185/ 20 | return 0 21 | endtry 22 | endfunction 23 | -------------------------------------------------------------------------------- /autoload/settings.vim: -------------------------------------------------------------------------------- 1 | function! settings#LoadSettings() abort 2 | call lib#SourceIfExists("~/.vim/settings/autocmd.vim") 3 | call lib#SourceIfExists("~/.vim/settings/settings.vim") 4 | call lib#SourceIfExists("~/.vim/settings/ignore.vim") 5 | call lib#SourceIfExists("~/.vim/settings/sensible.vim") 6 | 7 | call lib#SourceIfExists("~/.vim/settings/keymappings.vim") 8 | call lib#SourceIfExists("~/.vim/plugin_loader.vim") 9 | 10 | " 11 | " vim-rooter 12 | " 13 | 14 | " This is checked for before initialization. 15 | " https://github.com/airblade/vim-rooter/blob/3509dfb/plugin/rooter.vim#L173 16 | let g:rooter_manual_only = 1 17 | 18 | " vim-rooter patterns 19 | let g:rooter_patterns = [ 20 | \ 'manage.py', 21 | \ '.venv/', 22 | \ '.env/', 23 | \ '.env3/', 24 | \ '.venv3/', 25 | \ 'Rakefile', 26 | \ '.git/', 27 | \ 'gulpfile.js', 28 | \ 'bower.json', 29 | \ 'Gruntfile.js', 30 | \ 'Gemfile', 31 | \ 'Procfile', 32 | \ '.svn', 33 | \ '.hg', 34 | \ 'Pipfile', 35 | \ ] 36 | let g:rooter_silent_chdir = 1 37 | 38 | " An action can be a reference to a function that processes selected lines 39 | function! s:build_quickfix_list(lines) 40 | call setqflist(map(copy(a:lines), '{ "filename": v:val }')) 41 | copen 42 | cc 43 | endfunction 44 | 45 | " This is the default extra key bindings 46 | let g:fzf_action = { 47 | \ 'ctrl-q': function('s:build_quickfix_list'), 48 | \ 'ctrl-t': 'tab split', 49 | \ 'ctrl-x': 'split', 50 | \ 'ctrl-v': 'vsplit' } 51 | 52 | if v:version >= 801 " Floating window on 8.1+ https://github.com/junegunn/fzf/blob/master/README-VIM.md 53 | let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } } 54 | endif 55 | 56 | " Customize fzf colors to match your color scheme 57 | let g:fzf_colors = 58 | \ { 'fg': ['fg', 'Normal'], 59 | \ 'bg': ['bg', 'Normal'], 60 | \ 'hl': ['fg', 'Comment'], 61 | \ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'], 62 | \ 'bg+': ['bg', 'CursorLine', 'CursorColumn'], 63 | \ 'hl+': ['fg', 'Statement'], 64 | \ 'info': ['fg', 'PreProc'], 65 | \ 'border': ['fg', 'Ignore'], 66 | \ 'prompt': ['fg', 'Conditional'], 67 | \ 'pointer': ['fg', 'Exception'], 68 | \ 'marker': ['fg', 'Keyword'], 69 | \ 'spinner': ['fg', 'Label'], 70 | \ 'header': ['fg', 'Comment'] } 71 | 72 | " Enable per-command history. 73 | " CTRL-N and CTRL-P will be automatically bound to next-history and 74 | " previous-history instead of down and up. If you don't like the change, 75 | " explicitly bind the keys to down and up in your $FZF_DEFAULT_OPTS. 76 | let g:fzf_history_dir = '~/.local/share/fzf-history' 77 | 78 | 79 | 80 | function! OnLoadFZF() 81 | if !exists(':FZF') 82 | return 83 | endif 84 | 85 | " Use vim-rooter's FindRootDirectory for project-aware file search 86 | if exists('*fzf#wrap') && exists('*FindRootDirectory') 87 | command! -bang FZFRoot 88 | \ call fzf#run(fzf#wrap({'dir': FindRootDirectory()}, 0)) 89 | nmap :FZFRoot 90 | endif 91 | 92 | " Use ripgrep for searching 93 | if exists(':Rg') 94 | nnoremap :Rg 95 | endif 96 | endfunction 97 | 98 | autocmd VimEnter * call OnLoadFZF() 99 | 100 | 101 | 102 | 103 | 104 | 105 | if executable('rg') 106 | command! -bang -nargs=* Rg 107 | \ call fzf#vim#grep( 108 | \ 'rg --column --line-number --no-heading --color=always --smart-case -- '.shellescape(), 1, 109 | \ fzf#vim#with_preview(), 0) 110 | 111 | function! RipgrepFzf(query, fullscreen) 112 | let command_fmt = 'rg --column --line-number --no-heading --color=always --smart-case -- %s || true' 113 | let initial_command = printf(command_fmt, shellescape(a:query)) 114 | let reload_command = printf(command_fmt, '{q}') 115 | let spec = {'options': ['--phony', '--query', a:query, '--bind', 'change:reload:'.reload_command]} 116 | call fzf#vim#grep(initial_command, 1, fzf#vim#with_preview(spec), a:fullscreen) 117 | endfunction 118 | 119 | command! -nargs=* -bang RG call RipgrepFzf(, 0) 120 | endif 121 | 122 | endfunction 123 | 124 | " Statusline settings 125 | " set laststatus=2 " Already set by sensible.vim 126 | set cmdheight=2 " Two lines for command area (useful for linting messages) 127 | -------------------------------------------------------------------------------- /coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[typescript][typescriptreact][javascript][markdown][python]": { 3 | "coc.preferences.formatOnSave": true 4 | }, 5 | "coc.preferences.jumpCommand": "vsplit", 6 | "workspace.rootPatterns": [ 7 | ".git", 8 | ".hg", 9 | "pyproject.toml", 10 | "setup.py", 11 | ".venv", 12 | ".env", 13 | "package.json" 14 | ], 15 | "coc.preferences.useQuickfixForLocations": true, 16 | "coc.source.around.enable": false, 17 | "coc.source.buffer.enable": false, 18 | "coc.source.tmuxcomplete.filetypes": [], 19 | "diagnostic.level": "information", 20 | "diagnostic.messageTarget": "echo", 21 | "languageserver": { 22 | "ccls": { 23 | "command": "ccls", 24 | "initializationOptions": { 25 | "cache": { 26 | "directory": "/tmp/ccls" 27 | } 28 | }, 29 | "filetypes": [ 30 | "c", 31 | "cpp", 32 | "cuda", 33 | "objc", 34 | "objcpp" 35 | ], 36 | "shell": true, 37 | "rootPatterns": [ 38 | ".ccls", 39 | "compile_commands.json", 40 | ".vim/", 41 | ".git/", 42 | ".hg/" 43 | ] 44 | } 45 | }, 46 | "npm.binPath": "yarn", 47 | "prettier.disableLanguages": [ 48 | "json", 49 | "golang", 50 | "python" 51 | ], 52 | "prettier.requireConfig": true, 53 | "prettier.onlyUseLocalVersion": true, 54 | "python.analysis.autoSearchPaths": true, 55 | "python.analysis.diagnosticMode": "openFilesOnly", 56 | "python.analysis.typeCheckingMode": "basic", 57 | "python.analysis.useLibraryCodeForTypes": true, 58 | "python.formatting.provider": "ruff", 59 | "python.linting.enabled": true, 60 | "python.linting.ruffEnabled": true, 61 | "python.linting.mypyEnabled": true, 62 | "pyright.inlayHints.functionReturnTypes": false, 63 | "pyright.inlayHints.parameterTypes": false, 64 | "pyright.inlayHints.variableTypes": false, 65 | "pyright.organizeimports.provider": "ruff", 66 | "pyright.testing.provider": "pytest", 67 | "signature.target": "echo", 68 | "typescript.validate.enable": false, 69 | "elixir.pathToElixirLS": "~/.elixir-ls/release/language_server.sh", 70 | "workspace.ignoredFolders": [ 71 | "$HOME", 72 | "$HOME/.cargo/**", 73 | "$HOME/.rustup/**" 74 | ], 75 | "coc.source.file.triggerCharacters": ["/", "\\"], 76 | "coc.source.file.trimSameExts": [".ts", ".js"], 77 | "coc.source.file.ignoreHidden": false, 78 | "coc.source.file.ignorePatterns": [] 79 | } -------------------------------------------------------------------------------- /colors/tokyonight.vim: -------------------------------------------------------------------------------- 1 | set background=dark 2 | hi clear 3 | 4 | let g:colors_name = "tokyonight" 5 | 6 | hi Added gui=NONE term=NONE cterm=NONE guifg=#b3f6c0 guibg=NONE ctermfg=157 ctermbg=NONE 7 | hi link Boolean Constant 8 | hi Changed gui=NONE term=NONE cterm=NONE guifg=#8cf8f7 guibg=NONE ctermfg=123 ctermbg=NONE 9 | hi Character gui=NONE term=NONE cterm=NONE guifg=#c3e88d guibg=NONE ctermfg=150 ctermbg=NONE 10 | hi ColorColumn gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#1b1d2b ctermfg=NONE ctermbg=234 11 | hi Comment gui=italic term=italic cterm=italic guifg=#636da6 guibg=NONE ctermfg=242 ctermbg=NONE 12 | hi Conceal gui=NONE term=NONE cterm=NONE guifg=#737aa2 guibg=NONE ctermfg=243 ctermbg=NONE 13 | hi link Conditional Statement 14 | hi Constant gui=NONE term=NONE cterm=NONE guifg=#ff966c guibg=NONE ctermfg=209 ctermbg=NONE 15 | hi link CurSearch IncSearch 16 | hi Cursor gui=NONE term=NONE cterm=NONE guifg=#222436 guibg=#c8d3f5 ctermfg=235 ctermbg=252 17 | hi CursorColumn gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#2f334d ctermfg=NONE ctermbg=236 18 | hi CursorIM gui=NONE term=NONE cterm=NONE guifg=#222436 guibg=#c8d3f5 ctermfg=235 ctermbg=252 19 | hi CursorLine gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#2f334d ctermfg=NONE ctermbg=236 20 | hi link CursorLineFold FoldColumn 21 | hi CursorLineNr gui=bold term=bold cterm=bold guifg=#ff966c guibg=NONE ctermfg=209 ctermbg=NONE 22 | hi link CursorLineSign SignColumn 23 | hi Debug gui=NONE term=NONE cterm=NONE guifg=#ff966c guibg=NONE ctermfg=209 ctermbg=NONE 24 | hi link Define PreProc 25 | hi link Delimiter Special 26 | hi DiffAdd gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#273849 ctermfg=NONE ctermbg=237 27 | hi DiffChange gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#252a3f ctermfg=NONE ctermbg=235 28 | hi DiffDelete gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#3a273a ctermfg=NONE ctermbg=236 29 | hi DiffText gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#394b70 ctermfg=NONE ctermbg=238 30 | hi Directory gui=NONE term=NONE cterm=NONE guifg=#82aaff guibg=NONE ctermfg=111 ctermbg=NONE 31 | hi EndOfBuffer gui=NONE term=NONE cterm=NONE guifg=#222436 guibg=NONE ctermfg=235 ctermbg=NONE 32 | hi Error gui=NONE term=NONE cterm=NONE guifg=#c53b53 guibg=NONE ctermfg=167 ctermbg=NONE 33 | hi ErrorMsg gui=NONE term=NONE cterm=NONE guifg=#c53b53 guibg=NONE ctermfg=167 ctermbg=NONE 34 | hi link Exception Statement 35 | hi link Float Constant 36 | hi FoldColumn gui=NONE term=NONE cterm=NONE guifg=#636da6 guibg=#222436 ctermfg=242 ctermbg=235 37 | hi Folded gui=NONE term=NONE cterm=NONE guifg=#82aaff guibg=#3b4261 ctermfg=111 ctermbg=238 38 | hi Function gui=NONE term=NONE cterm=NONE guifg=#82aaff guibg=NONE ctermfg=111 ctermbg=NONE 39 | hi Identifier gui=NONE term=NONE cterm=NONE guifg=#c099ff guibg=NONE ctermfg=141 ctermbg=NONE 40 | hi link Ignore NormalFloat 41 | hi IncSearch gui=NONE term=NONE cterm=NONE guifg=#1b1d2b guibg=#ff966c ctermfg=234 ctermbg=209 42 | hi link Include PreProc 43 | hi Keyword gui=italic term=italic cterm=italic guifg=#86e1fc guibg=NONE ctermfg=117 ctermbg=NONE 44 | hi link Label Statement 45 | hi LineNr gui=NONE term=NONE cterm=NONE guifg=#3b4261 guibg=NONE ctermfg=238 ctermbg=NONE 46 | hi LineNrAbove gui=NONE term=NONE cterm=NONE guifg=#3b4261 guibg=NONE ctermfg=238 ctermbg=NONE 47 | hi LineNrBelow gui=NONE term=NONE cterm=NONE guifg=#3b4261 guibg=NONE ctermfg=238 ctermbg=NONE 48 | hi link Macro PreProc 49 | hi MatchParen gui=bold term=bold cterm=bold guifg=#ff966c guibg=NONE ctermfg=209 ctermbg=NONE 50 | hi ModeMsg gui=bold term=bold cterm=bold guifg=#828bb8 guibg=NONE ctermfg=103 ctermbg=NONE 51 | hi MoreMsg gui=NONE term=NONE cterm=NONE guifg=#82aaff guibg=NONE ctermfg=111 ctermbg=NONE 52 | hi NonText gui=NONE term=NONE cterm=NONE guifg=#545c7e guibg=NONE ctermfg=60 ctermbg=NONE 53 | hi link Normal NormalFloat 54 | hi link Number Constant 55 | hi Operator gui=NONE term=NONE cterm=NONE guifg=#89ddff guibg=NONE ctermfg=117 ctermbg=NONE 56 | hi Pmenu gui=NONE term=NONE cterm=NONE guifg=#c8d3f5 guibg=#1e2030 ctermfg=252 ctermbg=234 57 | hi link PmenuExtra Pmenu 58 | hi link PmenuExtraSel PmenuSel 59 | hi link PmenuKind Pmenu 60 | hi link PmenuKindSel PmenuSel 61 | hi PmenuSbar gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#27293a ctermfg=NONE ctermbg=235 62 | hi PmenuSel gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#363c58 ctermfg=NONE ctermbg=237 63 | hi PmenuThumb gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#3b4261 ctermfg=NONE ctermbg=238 64 | hi link PreCondit PreProc 65 | hi PreProc gui=NONE term=NONE cterm=NONE guifg=#86e1fc guibg=NONE ctermfg=117 ctermbg=NONE 66 | hi Question gui=NONE term=NONE cterm=NONE guifg=#82aaff guibg=NONE ctermfg=111 ctermbg=NONE 67 | hi QuickFixLine gui=bold term=bold cterm=bold guifg=NONE guibg=#2d3f76 ctermfg=NONE ctermbg=237 68 | hi Removed gui=NONE term=NONE cterm=NONE guifg=#ffc0b9 guibg=NONE ctermfg=217 ctermbg=NONE 69 | hi link Repeat Statement 70 | hi Search gui=NONE term=NONE cterm=NONE guifg=#c8d3f5 guibg=#3e68d7 ctermfg=252 ctermbg=62 71 | hi SignColumn gui=NONE term=NONE cterm=NONE guifg=#3b4261 guibg=#222436 ctermfg=238 ctermbg=235 72 | hi Special gui=NONE term=NONE cterm=NONE guifg=#65bcff guibg=NONE ctermfg=75 ctermbg=NONE 73 | hi link SpecialChar Special 74 | hi link SpecialComment Special 75 | hi SpecialKey gui=NONE term=NONE cterm=NONE guifg=#545c7e guibg=NONE ctermfg=60 ctermbg=NONE 76 | hi SpellBad gui=undercurl term=undercurl cterm=undercurl guifg=NONE guibg=NONE ctermfg=NONE ctermbg=NONE guisp=#c53b53 77 | hi SpellCap gui=undercurl term=undercurl cterm=undercurl guifg=NONE guibg=NONE ctermfg=NONE ctermbg=NONE guisp=#ffc777 78 | hi SpellLocal gui=undercurl term=undercurl cterm=undercurl guifg=NONE guibg=NONE ctermfg=NONE ctermbg=NONE guisp=#0db9d7 79 | hi SpellRare gui=undercurl term=undercurl cterm=undercurl guifg=NONE guibg=NONE ctermfg=NONE ctermbg=NONE guisp=#4fd6be 80 | hi Statement gui=NONE term=NONE cterm=NONE guifg=#c099ff guibg=NONE ctermfg=141 ctermbg=NONE 81 | hi StatusLine gui=NONE term=NONE cterm=NONE guifg=#828bb8 guibg=#1e2030 ctermfg=103 ctermbg=234 82 | hi StatusLineNC gui=NONE term=NONE cterm=NONE guifg=#3b4261 guibg=#1e2030 ctermfg=238 ctermbg=234 83 | hi link StorageClass Type 84 | hi String gui=NONE term=NONE cterm=NONE guifg=#c3e88d guibg=NONE ctermfg=150 ctermbg=NONE 85 | hi link Structure Type 86 | hi TabLine gui=NONE term=NONE cterm=NONE guifg=#3b4261 guibg=#1e2030 ctermfg=238 ctermbg=234 87 | hi TabLineFill gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#1b1d2b ctermfg=NONE ctermbg=234 88 | hi TabLineSel gui=NONE term=NONE cterm=NONE guifg=#1b1d2b guibg=#82aaff ctermfg=234 ctermbg=111 89 | hi link Tag Special 90 | hi Title gui=bold term=bold cterm=bold guifg=#82aaff guibg=NONE ctermfg=111 ctermbg=NONE 91 | hi Todo gui=NONE term=NONE cterm=NONE guifg=#222436 guibg=#ffc777 ctermfg=235 ctermbg=222 92 | hi Type gui=NONE term=NONE cterm=NONE guifg=#65bcff guibg=NONE ctermfg=75 ctermbg=NONE 93 | hi link Typedef Type 94 | hi Underlined gui=underline term=underline cterm=underline guifg=NONE guibg=NONE ctermfg=NONE ctermbg=NONE 95 | hi VertSplit gui=NONE term=NONE cterm=NONE guifg=#1b1d2b guibg=NONE ctermfg=234 ctermbg=NONE 96 | hi Visual gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#2d3f76 ctermfg=NONE ctermbg=237 97 | hi VisualNOS gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#2d3f76 ctermfg=NONE ctermbg=237 98 | hi WarningMsg gui=NONE term=NONE cterm=NONE guifg=#ffc777 guibg=NONE ctermfg=222 ctermbg=NONE 99 | hi WildMenu gui=NONE term=NONE cterm=NONE guifg=NONE guibg=#2d3f76 ctermfg=NONE ctermbg=237 100 | hi lCursor gui=NONE term=NONE cterm=NONE guifg=#222436 guibg=#c8d3f5 ctermfg=235 ctermbg=252 101 | hi NormalFloat gui=NONE term=NONE cterm=NONE guifg=#c8d3f5 guibg=#1e2030 ctermfg=252 ctermbg=234 102 | -------------------------------------------------------------------------------- /ftdetect/cmake.vim: -------------------------------------------------------------------------------- 1 | autocmd BufRead,BufNewFile *.cmake,CMakeLists.txt,*.cmake.in setf cmake 2 | autocmd BufRead,BufNewFile *.ctest,*.ctest.in setf cmake 3 | -------------------------------------------------------------------------------- /ftdetect/json.vim: -------------------------------------------------------------------------------- 1 | " JSON and JSON5 file detection 2 | autocmd BufRead,BufNewFile *.json set filetype=json 3 | autocmd BufRead,BufNewFile tsconfig.json set filetype=json5 4 | autocmd BufRead,BufNewFile api-extractor.json set filetype=json5 5 | 6 | " JSON configuration files that should be treated as JavaScript 7 | autocmd BufNewFile,BufRead .bowerrc,.jshintrc,.watchmanconfig set filetype=javascript -------------------------------------------------------------------------------- /ftdetect/rst.txt.vim: -------------------------------------------------------------------------------- 1 | " Autodetect reStructuredText on .txt files with reST signatures. 2 | " Author: Tony Narlock (tony@git-pull.com) 3 | " License: MIT 4 | " 5 | 6 | autocmd BufNewFile,BufRead *.txt :call IsTxtReStructuredText() 7 | 8 | function! IsTxtReStructuredText() 9 | if getline(1) =~ '=\{3,}' || getline(1) =~ '\.\{2} ' 10 | setfiletype rst.text 11 | setlocal filetype=rst.text 12 | endif 13 | endfunction 14 | -------------------------------------------------------------------------------- /ftdetect/scss.vim: -------------------------------------------------------------------------------- 1 | " https://github.com/cakebaker/scss-syntax.vim#filetype 2 | autocmd BufRead,BufNewFile *.scss set filetype=scss.css -------------------------------------------------------------------------------- /ftplugin/python.vim: -------------------------------------------------------------------------------- 1 | " normally: autocmd FileType python 2 | 3 | setlocal colorcolumn=88 4 | setlocal foldlevelstart=0 5 | setlocal expandtab shiftwidth=4 tabstop=8 softtabstop=4 6 | setlocal textwidth=88 7 | setlocal formatoptions+=croq softtabstop=4 smartindent 8 | setlocal cinwords=if,elif,else,for,while,try,except,finally,def,class,with 9 | 10 | " ALE linters/fixers configured globally with g:ale_linters_explicit = 1 11 | 12 | " Highlight everything possible for python 13 | let g:python_highlight_all=1 14 | let g:python_highlight_builtin_funcs=0 " Don't highlight type 15 | let g:python_highlight_builtin_funcs_kwarg=0 16 | -------------------------------------------------------------------------------- /ftplugin/scss.vim: -------------------------------------------------------------------------------- 1 | " SCSS specific settings 2 | if exists(":EditorConfig") == 2 3 | exe ":EditorConfig" 4 | else 5 | setlocal expandtab shiftwidth=2 tabstop=2 softtabstop=2 6 | endif -------------------------------------------------------------------------------- /plugins.vim: -------------------------------------------------------------------------------- 1 | " vim-plug auto-installation is handled by plugin_loader.vim 2 | 3 | "------------------------------------------------------------------------------ 4 | " Helper Function: Conditionally load a plugin if an executable is found 5 | "------------------------------------------------------------------------------ 6 | function! PlugIfCommand(cmd, plugin_spec, ...) abort 7 | if executable(a:cmd) 8 | if !empty(a:000) 9 | Plug a:plugin_spec, a:000[0] 10 | else 11 | Plug a:plugin_spec 12 | endif 13 | endif 14 | endfunction 15 | 16 | "------------------------------------------------------------------------------ 17 | " Begin Plugin Section 18 | "------------------------------------------------------------------------------ 19 | call plug#begin('~/.vim/plugged') 20 | 21 | " Unconditional Plugins 22 | Plug 'qpkorr/vim-bufkill' 23 | Plug 'editorconfig/editorconfig-vim' 24 | 25 | " fzf + fzf.vim 26 | Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all --no-update-rc' } 27 | Plug 'junegunn/fzf.vim' 28 | 29 | " JSON5 30 | Plug 'GutenYe/json5.vim' 31 | 32 | " Unix helpers (e.g., :Move, :Rename, etc.) 33 | Plug 'tpope/vim-eunuch' 34 | 35 | " ALE linting 36 | Plug 'dense-analysis/ale' 37 | " Consolidated ALE settings 38 | let g:ale_linters_explicit = 1 39 | let g:ale_set_highlights = 0 40 | let g:ale_set_loclist = 0 41 | let g:ale_set_quickfix = 1 42 | let g:ale_list_window_size = 5 43 | let g:ale_lint_on_enter = 0 44 | 45 | " Enable echo/hover functionality for linting messages 46 | let g:ale_echo_cursor = 1 47 | let g:ale_echo_msg_format = '[%linter%] %s [%severity%]' 48 | let g:ale_cursor_detail = 0 49 | let g:ale_hover_cursor = 1 50 | let g:ale_set_balloons = has('balloon_eval') && has('gui_running') 51 | 52 | " Per-language linters 53 | let g:ale_linters = { 54 | \ 'javascript': ['eslint'], 55 | \ 'typescript': ['eslint', 'tsserver', 'typecheck'], 56 | \ } 57 | 58 | " Per-language fixers 59 | let g:ale_fixers = { 60 | \ 'javascript': ['eslint'], 61 | \ 'typescript': ['trim_whitespace', 'prettier'], 62 | \ } 63 | 64 | " Comments 65 | Plug 'tomtom/tcomment_vim' 66 | 67 | " Mustache / Handlebars 68 | Plug 'mustache/vim-mustache-handlebars', { 69 | \ 'for': ['html', 'mustache', 'hbs'] 70 | \ } 71 | 72 | " Markdown 73 | Plug 'tpope/vim-markdown', {'for': ['markdown']} 74 | 75 | " Root dir detection 76 | Plug 'airblade/vim-rooter' 77 | 78 | " Extra syntax for C/C++ 79 | Plug 'justinmk/vim-syntax-extra', { 'for': ['c', 'cpp'] } 80 | 81 | " Word motion 82 | Plug 'chaoren/vim-wordmotion' 83 | 84 | " Colorschemes 85 | Plug 'rainux/vim-desert-warm-256' 86 | Plug 'morhetz/gruvbox' 87 | " Plug 'gruvbox-material/vim', {'as': 'gruvbox-material'} 88 | Plug 'sainnhe/sonokai' 89 | Plug 'sainnhe/everforest' 90 | Plug 'catppuccin/vim', { 'as': 'catppuccin' } 91 | 92 | " NERDTree 93 | Plug 'preservim/nerdtree' 94 | let NERDTreeShowHidden=1 95 | 96 | " GraphQL 97 | Plug 'jparise/vim-graphql' 98 | 99 | " SCSS 100 | Plug 'cakebaker/scss-syntax.vim' 101 | 102 | " JSON for GitHub Actions 103 | Plug 'yasuhiroki/github-actions-yaml.vim' 104 | 105 | " Autoformat 106 | Plug 'vim-autoformat/vim-autoformat' 107 | let g:formatdef_dprint = '"dprint stdin-fmt --file-name ".@%' 108 | let g:formatters_json = ['dprint'] 109 | let g:formatters_toml = ['dprint'] 110 | 111 | " Copilot 112 | Plug 'github/copilot.vim' 113 | let g:copilot_filetypes = { 114 | \ 'markdown': v:false, 115 | \ 'rst': v:false, 116 | \ 'zsh': v:false, 117 | \ 'bash': v:false, 118 | \ 'fish': v:false, 119 | \ 'json': v:false, 120 | \ } 121 | 122 | " Python syntax improvements 123 | Plug 'vim-python/python-syntax' 124 | 125 | " Rainbow parentheses 126 | Plug 'frazrepo/vim-rainbow' 127 | let g:rainbow_active = 1 128 | 129 | " Quickfix enhancements 130 | Plug 'yssl/QFEnter' 131 | let g:qfenter_keymap = {} 132 | let g:qfenter_keymap.vopen = [''] 133 | let g:qfenter_keymap.hopen = ['', '', ''] 134 | 135 | " Coc.nvim (the main LSP plugin) 136 | Plug 'neoclide/coc.nvim', {'branch': 'release', 'do': 'yarn install --frozen-lockfile'} 137 | 138 | " Wilder for better command-line completion 139 | if has('nvim') 140 | Plug 'gelguy/wilder.nvim', { 'do': { -> UpdateRemotePlugins() } } 141 | " Neovim-specific colorscheme 142 | Plug 'folke/tokyonight.nvim' 143 | " Nvim requires remote plugins update 144 | function! UpdateRemotePlugins() 145 | let &rtp=&rtp " refresh runtime 146 | UpdateRemotePlugins 147 | endfunction 148 | else 149 | Plug 'gelguy/wilder.nvim' 150 | " For Python remote features in Vim 8: 151 | Plug 'roxma/nvim-yarp' 152 | Plug 'roxma/vim-hug-neovim-rpc' 153 | endif 154 | 155 | " Conditional Plugins Based on Executables 156 | " Format: 'command': ['plugin1', 'plugin2', ...] 157 | let s:conditional_plugins = { 158 | \ 'ag': ['rking/ag.vim'], 159 | \ 'pipenv': ['cespare/vim-toml'], 160 | \ 'docker': ['ekalinin/Dockerfile.vim'], 161 | \ 'git': ['tpope/vim-fugitive', 'iberianpig/tig-explorer.vim'], 162 | \ 'psql': ['lifepillar/pgsql.vim'], 163 | \ 'node': ['leafgarland/typescript-vim', 'HerringtonDarkholme/yats.vim', 164 | \ 'posva/vim-vue', 'jxnblk/vim-mdx-js', 165 | \ 'neoclide/vim-jsx-improve', 'jonsmithers/vim-html-template-literals'], 166 | \ 'tmux': ['wellle/tmux-complete.vim'], 167 | \ 'cargo': ['rust-lang/rust.vim'], 168 | \ 'terraform': ['hashivim/vim-terraform'], 169 | \ 'mix': ['elixir-editors/vim-elixir'], 170 | \ } 171 | 172 | " Load conditional plugins 173 | for [cmd, plugins] in items(s:conditional_plugins) 174 | for plugin in plugins 175 | call PlugIfCommand(cmd, plugin) 176 | endfor 177 | endfor 178 | 179 | " End of plugin block 180 | call plug#end() 181 | 182 | "------------------------------------------------------------------------------ 183 | " BufRead / BufNewFile Autocommands for certain filetypes 184 | "------------------------------------------------------------------------------ 185 | if executable('pipenv') 186 | augroup MyPipenvFiles 187 | autocmd! 188 | autocmd BufNewFile,BufRead Pipfile setf toml 189 | autocmd BufNewFile,BufRead Pipfile.lock setf json 190 | augroup END 191 | endif 192 | 193 | " Quick JSONC style for coc-settings or some other JSON with comments 194 | autocmd FileType json syntax match Comment +\/\/.\+$+ 195 | autocmd FileType scss setlocal iskeyword+=@-@ 196 | 197 | " Additional root patterns for certain filetypes 198 | autocmd FileType python let b:coc_root_patterns = ['.git', '.env', 'pyproject.toml', 'Pipfile'] 199 | autocmd FileType javascript,typescript,typescript.tsx let b:coc_root_patterns = ['.git', 'package-lock.json', 'yarn.lock'] 200 | 201 | " If we have bibtex-tidy installed, auto-clean .bib files 202 | if executable('bibtex-tidy') 203 | autocmd BufWritePost *.bib silent! !bibtex-tidy % --quiet --no-backup 204 | endif 205 | 206 | "------------------------------------------------------------------------------ 207 | " General Settings for CoC, signcolumn, etc. 208 | "------------------------------------------------------------------------------ 209 | 210 | " CoC global extensions 211 | let g:coc_global_extensions = [ 212 | \ 'coc-json', 213 | \ 'coc-pyright', 214 | \ 'coc-tsserver', 215 | \ 'coc-rust-analyzer', 216 | \ 'coc-prettier', 217 | \ 'coc-yaml', 218 | \ 'coc-toml', 219 | \ 'coc-git', 220 | \ 'coc-lists', 221 | \ ] 222 | 223 | " Faster updates (for lint / diagnostics) 224 | set updatetime=300 225 | 226 | " Don't show messages in completion popups 227 | set shortmess+=c 228 | 229 | " Show signcolumn so text doesn't shift 230 | if has('nvim-0.5.0') || has('patch-8.1.1564') 231 | set signcolumn=number 232 | else 233 | set signcolumn=yes 234 | endif 235 | 236 | "------------------------------------------------------------------------------ 237 | " OnLoadCoc Function 238 | "------------------------------------------------------------------------------ 239 | function! OnLoadCoc() abort 240 | " If coc.nvim isn't properly loaded, bail out 241 | if !exists('*CocActionAsync') || !exists('*CocAction') 242 | echo "coc.nvim not initialized, skipping CoC config" 243 | return 244 | endif 245 | 246 | " to navigate completions (simplified) 247 | inoremap 248 | \ coc#pum#visible() ? coc#pum#next(1) : "\" 249 | inoremap 250 | \ coc#pum#visible() ? coc#pum#prev(1) : "\" 251 | inoremap 252 | \ coc#pum#visible() ? coc#pum#confirm() 253 | \: "\u\\=coc#on_enter()\" 254 | 255 | " Goto / references 256 | nmap gd (coc-definition) 257 | nmap gy (coc-type-definition) 258 | nmap gi (coc-implementation) 259 | nmap gr (coc-references) 260 | 261 | " Additional vim-style mappings 262 | nmap (coc-definition) 263 | nmap g (coc-definition) 264 | nmap G (coc-type-definition) 265 | 266 | " VS Code / Visual Studio compatible mappings 267 | nmap (coc-definition) 268 | nmap (coc-implementation) 269 | nmap (coc-references) 270 | " Note: Alt+F12 would be peek definition, but Vim doesn't have peek mode 271 | " Note: Ctrl+Shift+F12 for type definition conflicts with terminal behavior 272 | 273 | " Navigation history (VS Code compatible) 274 | " Note: Alt+Left/Right often conflicts with terminal, using Ctrl+O/I instead 275 | " Vim already has Ctrl+O (back) and Ctrl+I (forward) for jump list 276 | 277 | " Highlight references on CursorHold 278 | autocmd CursorHold * silent! call CocActionAsync('highlight') 279 | 280 | " Show documentation with K 281 | nnoremap K :call show_documentation() 282 | function! s:show_documentation() abort 283 | if index(['vim','help'], &filetype) >= 0 284 | execute 'h '.expand('') 285 | else 286 | call CocAction('doHover') 287 | endif 288 | endfunction 289 | 290 | augroup MyCoCFormat 291 | autocmd! 292 | autocmd FileType typescript,json setlocal formatexpr=CocAction('formatSelected') 293 | autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp') 294 | augroup END 295 | endfunction 296 | 297 | " Trigger the above function once CoC is loaded 298 | autocmd VimEnter * call OnLoadCoc() 299 | 300 | "------------------------------------------------------------------------------ 301 | " Wilder (better command-line UI) 302 | "------------------------------------------------------------------------------ 303 | function! OnLoadWilder() abort 304 | autocmd CmdlineEnter * ++once call s:wilder_init() | call g:wilder#main#start() 305 | function! s:wilder_init() abort 306 | call wilder#setup({'modes': [':', '/', '?']}) 307 | call wilder#set_option('use_python_remote_plugin', 0) 308 | endfunction 309 | endfunction 310 | 311 | autocmd VimEnter * call OnLoadWilder() 312 | 313 | "------------------------------------------------------------------------------ 314 | " Optional: source any additional plugin definitions for Neovim 315 | "------------------------------------------------------------------------------ 316 | " Neovim-specific plugins are now included above 317 | -------------------------------------------------------------------------------- /settings/autocmd.vim: -------------------------------------------------------------------------------- 1 | "=============================================================================== 2 | " Autocommands 3 | "=============================================================================== 4 | 5 | " Set augroup 6 | augroup MyAutoCmd 7 | autocmd! 8 | augroup END 9 | 10 | " Redraw since vim gets corrupt for no reason 11 | au FocusGained * redraw! " redraw screen on focus 12 | 13 | " Automatically open quickfix window after grep 14 | autocmd QuickFixCmdPost *grep* cwindow 15 | 16 | " Format entire file with f (preserves cursor position) 17 | autocmd FileType * noremap f mzgg=G`z 18 | 19 | "------------------------------------------------------------------------------ 20 | " Data-driven file type settings 21 | "------------------------------------------------------------------------------ 22 | " Format: 'filetypes': [shiftwidth, tabstop, expandtab, softtabstop] 23 | " If softtabstop is omitted, it defaults to shiftwidth 24 | " If tabstop is omitted, it defaults to shiftwidth 25 | let s:filetype_settings = { 26 | \ 'javascript,typescript,typescript.tsx': [2, 2, 1], 27 | \ 'html,mustache,jst,ejs,erb,handlebars,html.handlebars': [2, 2, 1], 28 | \ 'html,xhtml,xml,htmldjango,jinja.html,jinja,eruby,mako': [2, 2, 1], 29 | \ 'css,scss,less': [2, 2, 1], 30 | \ 'ruby': [2, 2, 1], 31 | \ 'lua': [2, 2, 1], 32 | \ 'vim': [2, 8, 1, 2], 33 | \ 'yaml': [2, 8, 1, 2], 34 | \ 'sh,csh,tcsh,zsh': [4, 4, 1], 35 | \ 'c,cpp': [4, 4, 1], 36 | \ 'go': [4, 8, 1, 4], 37 | \ 'php': [4, 8, 1, 4], 38 | \ 'rust': [4, 8, 1, 4], 39 | \ 'rst': [4, 4, 1], 40 | \ } 41 | 42 | " Apply file type settings 43 | for [filetypes, settings] in items(s:filetype_settings) 44 | let [sw, ts, expand] = settings[0:2] 45 | let sts = get(settings, 3, sw) 46 | let ts = get(settings, 1, sw) 47 | execute printf('autocmd FileType %s setlocal shiftwidth=%d tabstop=%d softtabstop=%d %s', 48 | \ filetypes, sw, ts, sts, expand ? 'expandtab' : 'noexpandtab') 49 | endfor 50 | 51 | " Special settings that don't fit the pattern 52 | autocmd FileType vim setlocal autoindent smarttab keywordprg=:help 53 | autocmd FileType rst setlocal formatoptions+=nqt textwidth=74 54 | autocmd FileType markdown setlocal textwidth=80 55 | autocmd FileType git,gitcommit setlocal foldmethod=syntax foldlevel=1 56 | autocmd FileType gitcommit setlocal spell 57 | autocmd FileType gitrebase nnoremap S :Cycle 58 | 59 | "------------------------------------------------------------------------------ 60 | " File type detection 61 | "------------------------------------------------------------------------------ 62 | autocmd BufNewFile,BufRead *.ejs,*.jst setlocal filetype=html.jst 63 | autocmd BufNewFile,BufRead *.handlebars setlocal filetype=html.mustache 64 | autocmd! BufNewFile,BufRead *.js.php set filetype=javascript 65 | autocmd BufNewFile,BufRead *.tmpl,*.jinja,*.jinja2 setlocal ft=jinja.html 66 | autocmd BufNewFile,BufRead *.py_tmpl setlocal ft=python 67 | 68 | "------------------------------------------------------------------------------ 69 | " Other autocommands 70 | "------------------------------------------------------------------------------ 71 | autocmd BufWritePost,FileWritePost ~/.Xdefaults,~/.Xresources silent! !xrdb -load % >/dev/null 2>&1 72 | 73 | " map :BufClose to :bq and configure it to open a file browser on close 74 | let g:BufClose_AltBuffer = '.' 75 | cnoreabbr bq 'BufClose' 76 | 77 | let javascript_enable_domhtmlcss=1 -------------------------------------------------------------------------------- /settings/ignore.vim: -------------------------------------------------------------------------------- 1 | " Single source of truth for ignore patterns 2 | let s:ignore_patterns = { 3 | \ 'temp_files': ['*~', '*.swp', '*.tmp', '*.bak', '*.BAK', '*.DAT'], 4 | \ 'python': ['*.pyc', '*.pyo', '__pycache__', '*.egg', '*.egg-info', '.tox', '.mypy_cache', '.ruff_cache', '.pytest_cache', '.coverage'], 5 | \ 'vcs': ['.git', '.hg', '.svn', '.bzr'], 6 | \ 'env': ['.env', '.env[0-9]', '.env-pypy', '.venv', '.venv[0-9]', '.venv-pypy'], 7 | \ 'ide': ['.idea', '.vscode', '.ropeproject'], 8 | \ 'web': ['.sass-cache', '.webassets-cache', 'node_modules', 'bower_components'], 9 | \ 'os': ['.DS_Store', '.Trash'], 10 | \ 'build': ['*.o', '*.obj', '*.debug.d', '*.debug.o', '*.so', 'vendor/rails', 'vendor/cache', '*.gem'], 11 | \ 'logs': ['log', 'tmp'], 12 | \ 'media': ['*.png', '*.jpg', '*.gif', '*.pdf', '*.dmg', '*.zip', '*.tar.gz'], 13 | \ 'misc': ['.gitkeep', '.vagrant', '.splinter-screenshots', '.ipynb_checkpoints', '.*_cache', '.nx', '*.app'] 14 | \ } 15 | 16 | " Flatten all patterns into a single list 17 | let s:all_patterns = [] 18 | for patterns in values(s:ignore_patterns) 19 | let s:all_patterns += patterns 20 | endfor 21 | 22 | " Configure NERDTree 23 | let g:NERDTreeIgnore = [] 24 | for pattern in s:all_patterns 25 | " NERDTree uses regex, so escape special chars and handle extensions 26 | if pattern =~ '^\*\.' 27 | " Convert *.ext to \.ext$ 28 | call add(g:NERDTreeIgnore, '\' . pattern[1:] . '$') 29 | elseif pattern =~ '^\.' 30 | " Directory patterns 31 | call add(g:NERDTreeIgnore, pattern) 32 | else 33 | " Other patterns 34 | call add(g:NERDTreeIgnore, pattern) 35 | endif 36 | endfor 37 | 38 | " Configure wildignore 39 | set wildignore= 40 | for pattern in s:all_patterns 41 | execute 'set wildignore+=' . pattern 42 | endfor 43 | " Add directory-specific patterns 44 | set wildignore+=*/.__pycache__/** 45 | set wildignore+=*/.sass-cache/** 46 | set wildignore+=*/.vscode/** 47 | set wildignore+=*/vendor/rails/** 48 | set wildignore+=*/vendor/cache/** 49 | set wildignore+=*/log/** 50 | set wildignore+=*/tmp/** 51 | set wildignore+=*/.tox/** 52 | set wildignore+=*/.idea/** 53 | set wildignore+=*/.vagrant/** 54 | set wildignore+=*/.coverage/** 55 | 56 | " Configure netrw 57 | let g:netrw_list_hide = '' 58 | for pattern in s:all_patterns 59 | if pattern =~ '^\*\.' 60 | " Convert *.ext to \.ext, 61 | let g:netrw_list_hide .= '\' . pattern[1:] . ',' 62 | elseif pattern =~ '\[.\]' 63 | " Handle patterns with brackets 64 | let g:netrw_list_hide .= substitute(pattern, '\[', '\\[', 'g') . ',' 65 | else 66 | let g:netrw_list_hide .= pattern . ',' 67 | endif 68 | endfor 69 | " Add directory patterns 70 | let g:netrw_list_hide .= '__pycache__/,\.sass-cache/,\.vscode/,vendor/rails/,vendor/cache/,log/,tmp/,\.tox/,\.idea/,\.vagrant/,\.coverage/,' 71 | 72 | -------------------------------------------------------------------------------- /settings/keymappings.vim: -------------------------------------------------------------------------------- 1 | " Map leader and localleader key to comma 2 | let mapleader = "," 3 | let maplocalleader = "," 4 | 5 | " Format / indentation - use marks to preserve position 6 | nnoremap 3 mzgg=G`z 7 | 8 | " 4: Toggle between paste mode 9 | nnoremap 4 :set paste! 10 | 11 | 12 | " thanks terryma: https://github.com/terryma/dotfiles/blob/master/.vimrc 13 | " d: Delete into the blackhole register to not clobber the last yank 14 | nnoremap d "_d 15 | " dd: I use this often to yank a single line, retain its original behavior 16 | nnoremap dd dd 17 | 18 | " Show line numbers - simple toggles 19 | " http://jeffkreeftmeijer.com/2012/relative-line-numbers-in-vim-for-super-fast-movement/ 20 | nnoremap 6 :set relativenumber! 21 | nnoremap 7 :set number! 22 | nnoremap b :BLines 23 | 24 | 25 | 26 | " p: Copy the full path of the current file to the clipboard 27 | nnoremap p :let @+=expand("%:p"):echo "Copied current file 28 | \ path '".expand("%:p")."' to clipboard" 29 | 30 | " Q: Closes the window 31 | nnoremap Q :q 32 | 33 | 34 | " Clear search highlight and close CoC popup if visible 35 | nnoremap :nohlsearch:silent! call coc#pum#visible() ? coc#pum#_close() : "" 36 | 37 | " Up Down Left Right resize splits 38 | " nnoremap + 39 | " nnoremap - 40 | " nnoremap < 41 | " nnoremap > 42 | 43 | "=============================================================================== 44 | " Visual Mode Ctrl Key Mappings 45 | "=============================================================================== 46 | 47 | " Ctrl-c: Copy (works with system clipboard due to clipboard setting) 48 | " vnoremap y`] 49 | 50 | " Ctrl-r: Easier search and replace 51 | vnoremap "hy:%s/h//gc 52 | 53 | " Ctrl-s: Easier substitue 54 | vnoremap :s/\%V//g 55 | 56 | 57 | 58 | 59 | 60 | "=============================================================================== 61 | " Visual Mode Key Mappings 62 | "=============================================================================== 63 | 64 | " y: Yank and go to end of selection 65 | xnoremap y y`] 66 | 67 | " p: Paste in visual mode should not replace the default register with the 68 | " deleted text 69 | xnoremap p "_dP 70 | 71 | " d: Delete into the blackhole register to not clobber the last yank. To 'cut', 72 | " use 'x' instead 73 | xnoremap d "_d 74 | 75 | " \: Toggle comment 76 | " nerdcommenter: 77 | " xmap \ c 78 | " tcomment: 79 | xmap \ gc 80 | 81 | " Enter: Highlight visual selections 82 | xnoremap y:let @/ = @":set hlsearch 83 | 84 | " Backspace: Delete selected and go into insert mode 85 | xnoremap c 86 | 87 | " <|>: Reselect visual block after indent 88 | xnoremap < >gv 90 | 91 | " .: repeats the last command on every line 92 | xnoremap . :normal. 93 | 94 | " @: repeats macro on every line 95 | xnoremap @ :normal@ 96 | 97 | " Tab: Indent 98 | xmap > 99 | 100 | " shift-tab: unindent 101 | xmap < 102 | 103 | noremap x :Ex 104 | 105 | " Buffer Traversal {{{ 106 | nnoremap d :BD 107 | 108 | " Buffer navigation - Leader p/n for previous/next 109 | nnoremap p :bprevious 110 | nnoremap n :bnext 111 | 112 | nnoremap c :BB 113 | nnoremap :BB 114 | nnoremap :BB 115 | 116 | " Traversal 117 | nnoremap h 118 | nnoremap j 119 | nnoremap k 120 | nnoremap l 121 | 122 | " Netrw traversal 123 | " https://gist.github.com/danidiaz/37a69305e2ed3319bfff9631175c5d0f#file-netrw-txt-L4 124 | augroup netrw_window_fix 125 | autocmd! 126 | autocmd filetype netrw call Set_netrw_maps() 127 | augroup END 128 | function! Set_netrw_maps() 129 | noremap l 130 | endfunction 131 | 132 | 133 | nnoremap = 134 | 135 | " Buffer navigation - using Leader key for consistency 136 | map ] :bnext 137 | map [ :bprev 138 | 139 | nnoremap e :NERDTreeFocus 140 | 141 | " Quickfix window toggles 142 | nnoremap q :cwindow 143 | nnoremap :cclose 144 | -------------------------------------------------------------------------------- /settings/sensible.vim: -------------------------------------------------------------------------------- 1 | " sensible.vim - Defaults everyone can agree on 2 | " Maintainer: Tim Pope 3 | " Version: 1.2 4 | 5 | if exists('g:loaded_sensible') || &compatible 6 | finish 7 | else 8 | let g:loaded_sensible = 'yes' 9 | endif 10 | 11 | if has('autocmd') 12 | filetype plugin indent on 13 | endif 14 | if has('syntax') && !exists('g:syntax_on') 15 | syntax enable 16 | endif 17 | 18 | " Use :help 'option' to see the documentation for the given option. 19 | 20 | set autoindent 21 | set backspace=indent,eol,start 22 | set complete-=i 23 | set smarttab 24 | 25 | set nrformats-=octal 26 | 27 | if !has('nvim') && &ttimeoutlen == -1 28 | set ttimeout 29 | set ttimeoutlen=100 30 | endif 31 | 32 | set incsearch 33 | " Use to clear the highlighting of :set hlsearch. 34 | if maparg('', 'n') ==# '' 35 | nnoremap :nohlsearch=has('diff')?'diffupdate':'' 36 | endif 37 | 38 | set laststatus=2 39 | set ruler 40 | set wildmenu 41 | 42 | if !&scrolloff 43 | set scrolloff=1 44 | endif 45 | if !&sidescrolloff 46 | set sidescrolloff=5 47 | endif 48 | set display+=lastline 49 | 50 | if &encoding ==# 'latin1' && has('gui_running') 51 | set encoding=utf-8 52 | endif 53 | 54 | if &listchars ==# 'eol:$' 55 | set listchars=tab:>\ ,trail:-,extends:>,precedes:<,nbsp:+ 56 | endif 57 | 58 | if v:version > 703 || v:version == 703 && has("patch541") 59 | set formatoptions+=j " Delete comment character when joining commented lines 60 | endif 61 | 62 | if has('path_extra') 63 | setglobal tags-=./tags tags-=./tags; tags^=./tags; 64 | endif 65 | 66 | if &shell =~# 'fish$' && (v:version < 704 || v:version == 704 && !has('patch276')) 67 | set shell=/bin/bash 68 | endif 69 | 70 | set autoread 71 | 72 | if &history < 1000 73 | set history=1000 74 | endif 75 | if &tabpagemax < 50 76 | set tabpagemax=50 77 | endif 78 | if !empty(&viminfo) 79 | set viminfo^=! 80 | endif 81 | set sessionoptions-=options 82 | 83 | " Allow color schemes to do bright colors without forcing bold. 84 | if &t_Co == 8 && $TERM !~# '^linux\|^Eterm' 85 | set t_Co=16 86 | endif 87 | 88 | " Load matchit.vim, but only if the user hasn't installed a newer version. 89 | if !exists('g:loaded_matchit') && findfile('plugin/matchit.vim', &rtp) ==# '' 90 | runtime! macros/matchit.vim 91 | endif 92 | 93 | inoremap u 94 | 95 | " vim:set ft=vim et sw=2: 96 | -------------------------------------------------------------------------------- /settings/settings.vim: -------------------------------------------------------------------------------- 1 | " filetype and syntax are handled in vimrc 2 | " autoindent and backspace are set in sensible.vim 3 | 4 | set foldenable " Auto fold code 5 | 6 | " wildmenu is set in sensible.vim 7 | set wildmode=list:longest,full " Command completion, list matches, then longest common part, then all. 8 | 9 | set showmatch " Show matching brackets/parenthesis 10 | " incsearch is set in sensible.vim 11 | set hlsearch " Highlight search terms 12 | set winminheight=0 " Windows can be 0 line high 13 | set ignorecase " Case insensitive search 14 | set smartcase " Case sensitive when uc present 15 | 16 | if has('cmdline_info') 17 | " ruler is set in sensible.vim 18 | set rulerformat=%30(%=\:b%n%y%m%r%w\ %l,%c%V\ %P%) " A ruler on steroids 19 | set showcmd " Show partial commands in status line and 20 | " Selected characters/lines in visual mode 21 | endif 22 | 23 | " Statusline configuration removed - use default or plugin statuslines 24 | 25 | " noswapfile is already set in vimrc 26 | " vim-rooter handles directory changes, so we don't need autocmd BufEnter 27 | 28 | "------------------------------------------------------------------------------ 29 | " Highlight Settings (from highlight.vim) 30 | "------------------------------------------------------------------------------ 31 | " Show trailing whitespace using list/listchars 32 | set list 33 | set listchars=tab:▸\ ,trail:·,extends:»,precedes:«,nbsp:+ 34 | 35 | " Dark background 36 | set background=dark 37 | 38 | " Simple spell highlighting for terminal 39 | if !has('gui_running') 40 | hi clear SpellBad 41 | hi SpellBad cterm=underline ctermfg=red 42 | endif 43 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # Vim Configuration Test Suite 2 | 3 | This directory contains tests for validating the Vim configuration. 4 | 5 | ## Available Tests 6 | 7 | ### Basic Tests 8 | ```bash 9 | make test # Run basic configuration tests 10 | make test-verbose # Show full test output 11 | ``` 12 | 13 | ### Analysis Tests 14 | ```bash 15 | make test-simplification # Analyze simplification opportunities 16 | make test-startup # Profile startup time 17 | make test-minimal # Test without plugins 18 | ``` 19 | 20 | ### Linting 21 | ```bash 22 | make vint # Lint Vim files (requires vim-vint) 23 | ``` 24 | 25 | ## Test Files 26 | 27 | - `harness.vim` - Test framework with assertion helpers 28 | - `basic.vim` - Basic configuration validation 29 | - `simplification.vim` - Validates simplification opportunities 30 | 31 | ## Running Tests 32 | 33 | The tests use Vim in Ex mode (`-Es`) for headless execution. All tests are designed to: 34 | 1. Load the configuration 35 | 2. Validate expected behavior 36 | 3. Exit with appropriate status 37 | 38 | ## Adding New Tests 39 | 40 | 1. Create a new test file in `tests/` 41 | 2. Use the test harness functions: 42 | - `TestAssert(condition, message)` 43 | - `TestExists(item, type, message)` 44 | 3. Add a new make target if needed 45 | 46 | ## Test Results 47 | 48 | From the startup time analysis, the slowest operations are: 49 | 1. Warning delay (2009ms) - First-time plugin installation warning 50 | 2. Loading vimrc (146ms) 51 | 3. Loading plugins.vim (127ms) 52 | 4. NERDTree plugin (35ms) 53 | 54 | This confirms that the auto-installing plugin system works but has an initial delay on first run. -------------------------------------------------------------------------------- /tests/basic.vim: -------------------------------------------------------------------------------- 1 | " Test script to validate configuration works correctly 2 | 3 | " Test 1: Verify plugin system loads 4 | call TestExists('plug#begin', 'function', 'vim-plug loaded') 5 | call TestExists('PlugInstall', 'command', 'PlugInstall command available') 6 | 7 | " Test 2: Verify autoload functions 8 | call TestExists('lib#SourceIfExists', 'function', 'lib#SourceIfExists exists') 9 | call TestExists('lib#ColorSchemeExists', 'function', 'lib#ColorSchemeExists exists') 10 | call TestExists('settings#LoadSettings', 'function', 'settings#LoadSettings exists') 11 | 12 | " Test 3: Verify key settings 13 | call TestAssert(&nocompatible == 1, 'nocompatible is set') 14 | call TestAssert(&syntax == 'on', 'syntax highlighting enabled') 15 | call TestAssert(&filetype == 'on', 'filetype detection enabled') 16 | 17 | " Test 4: Verify leader key 18 | call TestAssert(mapleader == ',', 'leader key is comma') 19 | 20 | " Test 5: Check if FindRootDirectory is available (from vim-rooter) 21 | if exists('*FindRootDirectory') 22 | echom "PASS: FindRootDirectory exists (from vim-rooter)" 23 | else 24 | echom "INFO: FindRootDirectory not loaded (plugin may be lazy-loaded)" 25 | endif 26 | 27 | " Test 6: Verify ignore patterns loaded 28 | call TestExists('g:NERDTreeIgnore', 'variable', 'NERDTreeIgnore patterns loaded') 29 | 30 | " Test 7: Check colorscheme 31 | if exists('g:colors_name') 32 | echom "PASS: Colorscheme loaded: " . g:colors_name 33 | else 34 | echom "INFO: No colorscheme loaded (may not be available)" 35 | endif 36 | 37 | echom "All critical tests passed!" 38 | quit -------------------------------------------------------------------------------- /tests/colorscheme.vim: -------------------------------------------------------------------------------- 1 | " Test colorscheme loading logic 2 | 3 | " Test 1: Verify colorscheme variable structure exists 4 | call TestExists('s:colorschemes', 'variable', 'Colorscheme list defined') 5 | 6 | " Test 2: Check if a colorscheme was loaded 7 | if exists('g:colors_name') 8 | echom "PASS: Colorscheme loaded: " . g:colors_name 9 | else 10 | " This is okay - no colorscheme plugins may be installed 11 | echom "INFO: No colorscheme loaded (plugins may not be installed)" 12 | endif 13 | 14 | " Test 3: Verify lib#ColorSchemeExists is available 15 | call TestExists('lib#ColorSchemeExists', 'function', 'ColorSchemeExists function available') 16 | 17 | quit -------------------------------------------------------------------------------- /tests/filetype.vim: -------------------------------------------------------------------------------- 1 | " Test file type settings 2 | 3 | " Test that filetype settings are applied correctly 4 | function! TestFiletypeSettings(ft, expected_sw, expected_ts, expected_expand) 5 | execute 'set filetype=' . a:ft 6 | let actual_sw = &shiftwidth 7 | let actual_ts = &tabstop 8 | let actual_expand = &expandtab 9 | 10 | call TestAssert(actual_sw == a:expected_sw, 11 | \ printf('%s: shiftwidth=%d (expected %d)', a:ft, actual_sw, a:expected_sw)) 12 | call TestAssert(actual_ts == a:expected_ts, 13 | \ printf('%s: tabstop=%d (expected %d)', a:ft, actual_ts, a:expected_ts)) 14 | call TestAssert(actual_expand == a:expected_expand, 15 | \ printf('%s: expandtab=%d (expected %d)', a:ft, actual_expand, a:expected_expand)) 16 | endfunction 17 | 18 | " Test a few key filetypes 19 | call TestFiletypeSettings('javascript', 2, 2, 1) 20 | call TestFiletypeSettings('python', 4, 4, 1) 21 | call TestFiletypeSettings('go', 4, 8, 1) 22 | call TestFiletypeSettings('vim', 2, 8, 1) 23 | 24 | echom "PASS: File type settings test completed" 25 | quit -------------------------------------------------------------------------------- /tests/harness.vim: -------------------------------------------------------------------------------- 1 | " Test harness for validating Vim configuration changes 2 | " Usage: vim -u test_harness.vim -c "source test_script.vim" -c "qa!" 3 | 4 | " Load the main vimrc 5 | source ~/.vim/vimrc 6 | 7 | " Test helper functions 8 | function! TestAssert(condition, message) 9 | if !a:condition 10 | echohl ErrorMsg 11 | echom "FAIL: " . a:message 12 | echohl None 13 | cquit 1 14 | else 15 | echom "PASS: " . a:message 16 | endif 17 | endfunction 18 | 19 | function! TestExists(item, type, message) 20 | if a:type == 'function' 21 | call TestAssert(exists('*' . a:item), a:message) 22 | elseif a:type == 'command' 23 | call TestAssert(exists(':' . a:item), a:message) 24 | elseif a:type == 'variable' 25 | call TestAssert(exists(a:item), a:message) 26 | endif 27 | endfunction 28 | 29 | " Report success 30 | echom "Test harness loaded successfully" -------------------------------------------------------------------------------- /tests/simplification.vim: -------------------------------------------------------------------------------- 1 | " Test to validate simplification opportunities 2 | 3 | " Test duplicate SourceIfExists functions 4 | let s:count = 0 5 | if exists('*SourceIfExists') 6 | let s:count += 1 7 | endif 8 | if exists('*lib#SourceIfExists') 9 | let s:count += 1 10 | endif 11 | call TestAssert(s:count >= 1, 'At least one SourceIfExists function exists') 12 | echom "INFO: Found " . s:count . " SourceIfExists implementations" 13 | 14 | " Test ALE settings locations 15 | let s:ale_settings = [] 16 | if exists('g:ale_set_loclist') 17 | call add(s:ale_settings, 'ale_set_loclist') 18 | endif 19 | if exists('g:ale_set_quickfix') 20 | call add(s:ale_settings, 'ale_set_quickfix') 21 | endif 22 | if exists('g:ale_linters_explicit') 23 | call add(s:ale_settings, 'ale_linters_explicit') 24 | endif 25 | if exists('g:ale_set_highlights') 26 | call add(s:ale_settings, 'ale_set_highlights') 27 | endif 28 | echom "INFO: Found " . len(s:ale_settings) . " ALE settings: " . join(s:ale_settings, ', ') 29 | 30 | " Test ignore patterns duplication 31 | let s:ignore_lists = 0 32 | if exists('g:NERDTreeIgnore') 33 | let s:ignore_lists += 1 34 | endif 35 | if exists('&wildignore') 36 | let s:ignore_lists += 1 37 | endif 38 | if exists('g:netrw_list_hide') 39 | let s:ignore_lists += 1 40 | endif 41 | if exists('g:vimfiler_ignore_pattern') 42 | let s:ignore_lists += 1 43 | endif 44 | echom "INFO: Found " . s:ignore_lists . " ignore pattern lists" 45 | 46 | " Test platform functions usage 47 | let s:platform_funcs = ['lib#platform#OSX', 'lib#platform#LINUX', 'lib#platform#WINDOWS', 'lib#platform#CYGWIN', 'lib#platform#UNIXLIKE'] 48 | let s:unused = [] 49 | for func in s:platform_funcs 50 | if exists('*' . func) 51 | " Could grep for usage here, but for now just report existence 52 | call add(s:unused, func) 53 | endif 54 | endfor 55 | if len(s:unused) > 0 56 | echom "INFO: Platform functions defined: " . join(s:unused, ', ') 57 | endif 58 | 59 | quit -------------------------------------------------------------------------------- /vimrc: -------------------------------------------------------------------------------- 1 | "------------------------------------------------------------------------------ 2 | " Basic Recommended Settings 3 | "------------------------------------------------------------------------------ 4 | if v:version >= 800 5 | " nocompatible is default in Vim 8+ 6 | " syntax and filetype are handled by sensible.vim 7 | endif 8 | 9 | "------------------------------------------------------------------------------ 10 | " Helper Function for Conditional Sourcing 11 | "------------------------------------------------------------------------------ 12 | " Use lib#SourceIfExists from autoload/lib.vim instead of defining here 13 | 14 | 15 | "------------------------------------------------------------------------------ 16 | " ALE Configuration 17 | "------------------------------------------------------------------------------ 18 | " Buffer & File Handling 19 | "------------------------------------------------------------------------------ 20 | " Allow switching away from unsaved buffers 21 | set hidden 22 | 23 | " Fix backspace behavior (sensible.vim sets backspace=indent,eol,start) 24 | " set backspace=2 25 | 26 | " Disable swap/backup files 27 | set nobackup 28 | set nowritebackup 29 | set noswapfile 30 | 31 | " Performance settings (from rice.vim) 32 | set ttyfast 33 | set lazyredraw 34 | 35 | " Disable matchparen plugin (avoid glitchy behavior) 36 | let g:loaded_matchparen = 1 " or use `:NoMatchParen` 37 | 38 | " Automatically cd to directory of opened file 39 | set autochdir 40 | 41 | "------------------------------------------------------------------------------ 42 | " Clipboard Behavior 43 | "------------------------------------------------------------------------------ 44 | if has('unnamedplus') 45 | set clipboard=unnamedplus 46 | else 47 | set clipboard=unnamed 48 | endif 49 | 50 | "------------------------------------------------------------------------------ 51 | " Netrw Tweak 52 | "------------------------------------------------------------------------------ 53 | augroup MyNetrwFix 54 | autocmd! 55 | " Fix netrw so that its buffer is hidden on exit 56 | autocmd FileType netrw setlocal bufhidden=delete 57 | augroup END 58 | 59 | "------------------------------------------------------------------------------ 60 | " Truecolor Support (especially under tmux) 61 | "------------------------------------------------------------------------------ 62 | if exists('+termguicolors') 63 | let &t_8f = "\[38;2;%lu;%lu;%lum" 64 | let &t_8b = "\[48;2;%lu;%lu;%lum" 65 | set termguicolors 66 | endif 67 | 68 | "------------------------------------------------------------------------------ 69 | " Auto-install vim-plug if not present 70 | "------------------------------------------------------------------------------ 71 | if empty(glob('~/.vim/autoload/plug.vim')) 72 | silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs 73 | \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim 74 | autocmd VimEnter * PlugInstall | source $MYVIMRC 75 | endif 76 | 77 | "------------------------------------------------------------------------------ 78 | " Load Plugins and Settings 79 | "------------------------------------------------------------------------------ 80 | call plug#begin('~/.vim/plugged') 81 | source ~/.vim/plugins.vim 82 | call plug#end() 83 | 84 | " Automatically install missing plugins on startup 85 | if !empty(filter(copy(g:plugs), '!isdirectory(v:val.dir)')) 86 | autocmd VimEnter * PlugInstall | q 87 | endif 88 | 89 | call settings#LoadSettings() 90 | " highlight.vim merged into settings.vim 91 | 92 | "------------------------------------------------------------------------------ 93 | " Color Schemes - Simplified Fallback Logic 94 | "------------------------------------------------------------------------------ 95 | " Define colorschemes in order of preference 96 | let s:colorschemes = [ 97 | \ {'name': 'tokyonight-moon', 'only_nvim': 1}, 98 | \ {'name': 'tokyonight'}, 99 | \ {'name': 'catppuccin_mocha'}, 100 | \ {'name': 'gruvbox'}, 101 | \ {'name': 'gruvbox-material', 'setup': 'let g:gruvbox_material_disable_italic_comment = 1'}, 102 | \ {'name': 'everforest', 'setup': 'set background=dark | let g:everforest_background = "hard" | let g:everforest_transparent_background = 2 | let g:everforest_disable_italic_comment = 1'}, 103 | \ {'name': 'desert-warm-256'}, 104 | \ ] 105 | 106 | " Try each colorscheme in order 107 | if exists('*lib#ColorSchemeExists') 108 | for scheme in s:colorschemes 109 | if has_key(scheme, 'only_nvim') && !has('nvim') 110 | continue 111 | endif 112 | if lib#ColorSchemeExists(scheme.name) 113 | if has_key(scheme, 'setup') 114 | execute scheme.setup 115 | endif 116 | execute 'colorscheme' scheme.name 117 | break 118 | endif 119 | endfor 120 | else 121 | " Fallback if ColorSchemeExists is not available 122 | colorscheme desert 123 | endif 124 | 125 | "------------------------------------------------------------------------------ 126 | " Local Customizations 127 | "------------------------------------------------------------------------------ 128 | call lib#SourceIfExists('$HOME/.vimrc.local') --------------------------------------------------------------------------------