dotfiles/.vimrc

1776 lines
71 KiB
VimL
Raw Normal View History

2023-05-21 22:02:21 +00:00
"-----------------------------------------------------------------------------------------------------------------------
2023-01-27 20:20:51 +00:00
" The config is chopped up into sections. Search for these headings to quickly jump to a particular section.
2019-12-31 05:37:09 +00:00
"
2021-02-08 20:40:32 +00:00
" #0 GLOBALS
" #1 PLUGINS
" #2 BASE CONFIG
2023-01-27 20:20:51 +00:00
" #3 CUSTOM AUTOCMDS
" #4 KEY MAPPINGS
" #5 PLUGIN CONFIGS
" #6 VISUALS (COLORS, HIGHLIGHTING)
" #7 CUSTOM FUNCTIONS & COMMANDS
2019-12-31 05:37:09 +00:00
"
2023-01-27 20:20:51 +00:00
" @incomplete Add setup steps (plugins, cache setup, search tool, etc).
"-----------------------------------------------------------------------------------------------------------------------
2019-12-31 05:37:09 +00:00
2023-12-05 21:58:04 +00:00
if !exists("g:campo_vimrc_initialized")
let g:campo_vimrc_initialized = 0 " Will be set to 1 at the end of the file. Can be used to avoid changes on subsequent vimrc reloads.
endif
scriptencoding utf-8
2023-01-27 20:20:51 +00:00
" @note If the file contains a BOM then vim will automatically set `bomb` for the buffer so that the BOM is written out again.
2017-03-27 18:39:07 +00:00
set encoding=utf-8 fileencoding=utf-8 fileencodings=ucs-bom,utf8,prc
2017-07-28 15:20:08 +00:00
set nocompatible
filetype off
2023-01-27 20:20:51 +00:00
" Store the current system name so that we can conditionally set configs for different platforms.
let s:uname = system("echo -n \"$(uname)\"")
let g:vim_dir = $HOME . "/.vim"
let mapleader=","
2023-06-13 02:51:42 +00:00
fu! IsWindows()
2023-12-06 23:12:18 +00:00
if s:uname =~? "mingw" || s:uname =~? "msys"
2019-12-31 05:37:09 +00:00
return 1
endif
if has("win64") || has("win32") || has("win16")
return 1
endif
2019-12-31 05:37:09 +00:00
return 0
2023-06-13 02:51:42 +00:00
endfu
if has('termguicolors')
set termguicolors
2023-01-27 20:20:51 +00:00
" Set Vim-specific sequences for RGB colors.
let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
endif
2023-06-13 02:51:42 +00:00
fu! PrintError(msg) abort
exec 'normal! \<Esc>'
echohl ErrorMsg
echomsg a:msg
echohl None
2023-06-13 02:51:42 +00:00
endfu
2023-01-27 20:20:51 +00:00
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
" #0 GLOBALS
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"-----------------------------------------------------------------------------------------------------------------------
" @note The following globals can be used to customize various functions in
2023-01-27 20:20:51 +00:00
" this file. The easiest way to set them is in ~/.vimrc.private or an .lvimrc
" file in the root folder that you want it applied to.
"
2023-01-27 20:20:51 +00:00
" Some variables cannot be customized in an .lvimrc because their value is
" used by settings in this file when it's sourced. These have been flagged
" with the note :unsupported-in-lvimrc.
"
" Also take note that an .lvimrc has precedence because it's loaded after this
" and the private vimrc.
2023-01-27 20:20:51 +00:00
"-----------------------------------------------------------------------------------------------------------------------
2021-10-14 18:20:40 +00:00
" @note :unsupported-in-lvimrc
2022-11-05 04:48:21 +00:00
let g:campo_max_line_length = 120 " Display a vertical bar at x=<n>.
" Set the row height of the quickfix pane, which is used to display results
" from various plugins (like ctrlp, ripgrep, compilation errors, etc), in rows
let g:quickfix_pane_height = 20
2023-01-27 20:20:51 +00:00
"##################################################################################
" COLORS
2023-01-27 20:20:51 +00:00
"##################################################################################
2022-12-29 23:53:54 +00:00
let g:campo_light_dark_mode = 'dark' " Start vim with the dark theme. Set to 'light' for the light theme.
let g:campo_dark_theme = 'campo-dark-simple' "'campo-dark-blue'
let g:campo_light_theme = 'campo-light-simple' "'campo-light'
2023-01-27 20:20:51 +00:00
"##################################################################################
" FORMATTING
2023-01-27 20:20:51 +00:00
"##################################################################################
" When set to 1, all files will be stripped of trailing whitespace when the
" file is saved. Set to 0 to disable. You can customize which files are
" ignored or always stripped; see below.
let g:campo_strip_trailing_whitespace = 1
2022-12-06 02:12:30 +00:00
" When set to 1, the whitespace stripping force/ignore file filters below will
" be expected to have full paths to the files, otherwise just the filename is
" required.
let g:campo_use_full_paths_for_whitespace_stripping_file_filters = 1
" If g:campo_strip_trailing_whitespace is 1 then you can stop stripping in
2022-12-06 02:12:30 +00:00
" specific directories by setting this to a list of full directory paths.
" This has no effect when g:campo_strip_trailing_whitespace is 0.
"
2022-12-06 02:12:30 +00:00
" e.g. let g:campo_directories_to_ignore_when_stripping_trailing_whitespace = ['/z/modules', '/d/build']
let g:campo_directories_to_ignore_when_stripping_trailing_whitespace = []
" If g:campo_strip_trailing_whitespace is 1 then you can stop stripping in
" specific files by setting this to a list of full file paths.
" This has no effect when g:campo_strip_trailing_whitespace is 0.
"
" e.g. let g:campo_files_to_ignore_when_stripping_trailing_whitespace = ['/z/modules/test.h', '/d/build/config.h']
let g:campo_files_to_ignore_when_stripping_trailing_whitespace = []
2022-12-06 02:12:30 +00:00
" If g:campo_strip_trailing_whitespace is 0 then you can force whitespace
2022-12-06 02:12:30 +00:00
" stripping in specific directories by setting this to a list of full paths.
" This has no effect when g:campo_strip_trailing_whitespace is 1.
"
" e.g. let g:campo_directories_to_force_stripping_trailing_whitespace = ['/z/modules '/d/build']
let g:campo_directories_to_force_stripping_trailing_whitespace = []
2022-12-06 02:12:30 +00:00
" If g:campo_strip_trailing_whitespace is 0 then you can force whitespace
" stripping in specific files by setting this to a list of full file paths.
" This has no effect when g:campo_strip_trailing_whitespace is 1.
"
" e.g. let g:campo_files_to_force_stripping_trailing_whitespace = ['/z/modules/test.h', '/d/build/config.h']
let g:campo_files_to_force_stripping_trailing_whitespace = []
2023-01-27 20:20:51 +00:00
"##################################################################################
" SEARCH
2023-01-27 20:20:51 +00:00
"##################################################################################
" This is included in the ripgrep args. You can use this to do things like
" ignore folders in your project or limit the search to specific file types.
" For example, if you want to ignore the 3rd_party dir and only search C files
" (remove the backslash from the first quote as that's just here to escape it
" in this comment string)
" let g:campo_custom_search_args = \"-g \"!3rd_party/*\" -tc"
let g:campo_custom_search_args = ""
2023-01-27 20:20:51 +00:00
"##################################################################################
" CTAGS
2023-01-27 20:20:51 +00:00
"##################################################################################
2022-11-29 04:37:35 +00:00
" I use the ctags executable from https://github.com/universal-ctags/ctags-win32/releases
"
2023-01-27 20:20:51 +00:00
" Be sure to check out the ctags plugin config in section #5 for additional API functions.
2022-11-29 04:37:35 +00:00
2021-12-03 02:07:47 +00:00
" If != 0 then ctag generation will always happen on a file save, otherwise
" it'll only be triggered if the file being saved has an extension in the
" g:campo_extensions_that_run_ctags list.
let g:campo_force_ctags_regardless_of_extension = 0
" If one of these file types are saved then the ctags creation function will be called.
2021-12-03 02:07:47 +00:00
" You can append to this list in another config like so:
" let g:campo_extensions_that_run_ctags = g:campo_extensions_that_run_ctags + ['foo', 'bar']
2021-12-10 00:54:08 +00:00
let g:campo_extensions_that_run_ctags = ['c','cpp','h','hpp','inc','cs','py','asm','ex','exs']
2021-12-03 02:07:47 +00:00
" Default files and directories that ctags should ignore when doing a
" recursive crawl.
" @note The CreateCtags function will always ignore .git and node_modules
2021-12-03 02:07:47 +00:00
" regardless of this variable's value.
2023-12-06 23:12:18 +00:00
let g:campo_ctags_exclude = ['*.txt', '*.config', '.cache', 'run_tree']
" This is included in the ctags autocmd args. You can use this to customize
2021-12-03 02:07:47 +00:00
" how ctags are built.
" Examples:
" * Recursive ctag generation with `let g:campo_custom_ctags_args = '-R'`
" * Create tags for specific langauges: `let g:campo_custom_ctags_args = '--languages=C,C++,Elixir'
" * You can see a list of languages with `ctags --list-languages`
" * For C# you have to escape the ampersand like so: `--languages=C\\#`
2023-12-06 23:12:18 +00:00
" * Exclude directories using g:campo_ctags_exclude
let g:campo_custom_ctags_args = ""
2023-01-27 20:20:51 +00:00
" Set extra paths to use when searching for ctags files. By default the current
" directory is always checked. You can use this to combine tag lookups from
" different projects, e.g. set it to the Jai directory and you can look up
" current project tags and Jai module tags (the latter isn't needed if you
" have Jai module tags in your local file, which can be generated using the
" ctags module at compile time). Related, if you're generating jai ctags and
" the editor isn't finding module references then check if the current
" directory is set to where the tags file exists. I've been caught up by this
" because I have a build.jai in the root and my code in a src/ folder, so the
" tags file gets created in the root and won't be seen if I've cd'd into src/
" when editing code.
"
" This destructively overwrites the tags option value.
"
" Call this from a .vimrc.private or .lvimrc file, e.g.
" call g:SetExtraCtagsPaths([g:campo_jai_path.'/tags'])
"
" You can see what your ctags search list is set to in the editor with :echo &tags
2023-06-13 02:51:42 +00:00
fu! g:SetExtraCtagsPaths(paths_array)
let l:list = './tags,tags' " This is the default tags list set by vim.
for path in a:paths_array
let l:list .= ',' . path
endfor
let &tags=l:list
2023-06-13 02:51:42 +00:00
endfu
2023-01-27 20:20:51 +00:00
"##################################################################################
" JAI
2023-01-27 20:20:51 +00:00
"##################################################################################
" Set to your Jai install path. Used for various commands, like for example
" searching the modules and how_to directories with CtrlP
let g:campo_jai_path = ''
2023-01-19 23:13:38 +00:00
" Args to include when compiling a Jai file.
let g:campo_jai_compiler_args = ''
let g:campo_jai_metaprogram_args = ''
2023-01-19 23:13:38 +00:00
2023-01-27 20:20:51 +00:00
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
" #1 PLUGINS
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2017-07-10 15:08:49 +00:00
2015-11-29 19:41:56 +00:00
call plug#begin('~/.vim/plugged')
2015-02-24 04:34:00 +00:00
2023-12-06 23:12:18 +00:00
" I've locked the plugins to stable commits. No need to upgrade them unless there are bug fixes.
"""""""""""""""""""
" # MISC
"""""""""""""""""""
Plug 'sir-pinecone/errormarker.vim' " Build error highlighting (requires skywind3000/asyncrun.vim).
Plug 'sir-pinecone/vim-ripgrep' " Fast grep-like search. Requires ripgrep; install Rust package: `cargo install ripgrep`.
Plug 'sir-pinecone/vim-qargs', " For the GlobalReplaceIt function (i.e. search and replace).
Plug 'sir-pinecone/AnsiEsc.vim' " Ansi escape sequences concealed, but highlighted as specified.
2024-01-21 03:15:21 +00:00
Plug 'sir-pinecone/ctrlp.vim', " Fuzzy file, buffer, mru, tag, etc finder.
2023-12-06 23:12:18 +00:00
Plug 'vim-airline/vim-airline', { 'commit': 'c7460aa' } " Enhanced status/tabline.
Plug 'embear/vim-localvimrc', { 'commit': '0206f5f' } " Add a .lvimrc to a folder to override .vimrc config.
Plug 'tpope/vim-fugitive', { 'commit': '46eaf89' } " Git wrapper (I particularly like :Gblame, which I've wrapped as :Blame)
Plug 'tpope/tpope-vim-abolish', { 'commit': 'dcbfe06' } " Search for, substitute, and abbreviate multiple variants of a word. Add to `after/plugin/abolish.vim`
Plug 'tpope/vim-obsession', { 'commit': 'fe9d3e1' } " @flagged for removal. Continuously updated session files (tracks window positions, open folds, etc).
Plug 'itchyny/vim-cursorword', { 'commit': '74a97c4' } " Underlines all instances of the symbol under the cursor. Requires a ctags file.
Plug 'skywind3000/asyncrun.vim', { 'commit': '61cc308' } " (prev stable: 58d23e7) Async commands.
Plug 'airblade/vim-gitgutter', { 'commit': 'fe0e8a2' } " Displays a git diff in the vim gutter and allows staging/unstaging of hunks.
Plug 'majutsushi/tagbar', { 'commit': '5d6990e' } " Generates ctags on-demand and shows the current file's symbols. Doesn't support existing ctag files, so no Jai support.
Plug 'tommcdo/vim-lion', { 'commit': 'ce46593' } " For text alignment, use gl= and gL=
Plug 'editorconfig/editorconfig-vim', { 'commit': '95cb75e' } " Adds support for .editorconfig files.
"""""""""""""""""""
" # SYNTAX
"""""""""""""""""""
Plug 'sir-pinecone/jai.vim' " Jai
Plug 'sir-pinecone/fasm.vim' " Flat Assembler
Plug 'bfrg/vim-cpp-modern', { 'commit': 'cc7019b' } " C/C++
Plug 'elixir-editors/vim-elixir', { 'commit': '6dd03f8' } " Elixir
Plug 'pprovost/vim-ps1', { 'commit': '308aac5' } " PowerShell
Plug 'tpope/vim-markdown', { 'commit': 'f2b82b7' } " Markdown
"Plug 'vim-ruby/vim-ruby' { 'commit': 'f06f069' } " Ruby
"""""""""""""""""""
" # THEMES
"""""""""""""""""""
Plug 'vim-airline/vim-airline-themes', { 'commit': '04fa4fc' }
Plug 'dracula/vim', { 'commit': '6495b4f', 'as': 'dracula' }
2015-11-29 19:41:56 +00:00
call plug#end()
2015-03-21 19:13:17 +00:00
filetype plugin indent on
2015-02-24 04:34:00 +00:00
2023-01-27 20:20:51 +00:00
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
" #2 BASE CONFIG
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2017-07-10 15:08:49 +00:00
2012-04-19 14:23:13 +00:00
set hidden
set history=10000
set expandtab
2019-05-15 18:00:25 +00:00
set tabstop=4
set shiftwidth=4
set softtabstop=4
2011-04-15 18:44:28 +00:00
set autoindent
2012-04-19 14:23:13 +00:00
set laststatus=2
2019-12-31 05:37:09 +00:00
set showcmd " Display incomplete commands.
2012-04-19 14:23:13 +00:00
set showmatch
2019-12-31 05:37:09 +00:00
set incsearch " Highlight matches as you type.
set hlsearch " Highlight matches.
2013-04-20 18:00:26 +00:00
set dictionary+=/usr/share/dict/words
2019-12-31 05:37:09 +00:00
"set clipboard=unnamed " Yank and paste with the system clipboard.
2018-03-15 18:39:50 +00:00
set number
2019-12-31 05:37:09 +00:00
set ignorecase smartcase " Make searches case-sensitive only if they contain upper-case characters.
set visualbell " No bell sounds.
2017-07-28 15:20:08 +00:00
set ttyfast
2012-04-19 14:23:13 +00:00
set cmdheight=2
2017-06-09 22:48:02 +00:00
set switchbuf=useopen,split
2012-04-19 14:23:13 +00:00
set numberwidth=5
set showtabline=2
set winwidth=79
" Use abbreviations.
set shortmess=a
" Remove gvim Menubar and Toolbar
"set guioptions -=m
"set guioptions -=T
2019-12-31 05:37:09 +00:00
" @warning: This must come AFTER `set ignorecase smartcase` otherwise vim spews out a ton of errors. No idea why!
if IsWindows()
" Just assume we don't have a zsh shell
set shell=bash
else
2020-03-15 18:44:36 +00:00
"set shell=zsh
set shell=bash
endif
2019-12-31 05:37:09 +00:00
set t_ti= t_te= " Prevent Vim from clobbering the scrollback buffer. See http://www.shallowsky.com/linux/noaltscreen.html
set scrolloff=3 " keep more context when scrolling off the end of a buffer
2019-07-17 16:00:31 +00:00
set cursorline
set cursorcolumn
" Store swap, backup and undo files in a central spot. I have my settings in a
" `vimrc.private` so that my drive paths aren't in this config. If you want to
" set them here then add:
2020-06-25 17:30:08 +00:00
"
" set directory=<dir path for swap files>
" set backupdir=<dir path for backup files>
" if has('persistent_undo')
" set undodir=<dir path for undo files>
" endif
"
" And make sure those directories exist before opening vim.
"
2012-04-19 14:23:13 +00:00
set backup
2018-03-15 18:39:50 +00:00
set backupcopy=yes
augroup backupCmds
autocmd!
autocmd BufWritePre * let &bex = '.' . strftime("%Y-%m-%d-%T") . '.bak'
augroup END
set writebackup " Make buckup before overwriting the current buffer.
" Keep undo history across sessions by storing it in a file. The undo save
" location is set in the vimrc.private file. You can also set it here with:
" set undodir=<path>
"
set undolevels=1000 " Allow undo when going back into a closed file
set undoreload=10000
if has('persistent_undo')
set undofile
endif
2017-07-17 16:38:17 +00:00
2019-12-31 05:37:09 +00:00
set backspace=indent,eol,start " Allow backspacing over everything in insert mode.
set complete+=kspell " Spell checking autocomplete.
set complete-=i " Don't scan all included files since it's really slow.
2019-03-28 00:15:55 +00:00
set termguicolors
2023-12-05 21:58:04 +00:00
" Disabled this because it clears my custom syntax highlights (see campoSyntax augroup)
" when the vimrc file is resourced. I guess I don't need to set this to have
" syntax highlighting. It's probably being enabled by a plugin.
"set syntax on
2019-03-28 00:15:55 +00:00
2013-08-30 17:11:59 +00:00
set wildmenu
set wildmode=longest,list,full
2019-03-28 00:15:55 +00:00
set wildignore+=*/log/*,*.so,*.swp,*.zip,*/rdoc/*
2023-09-20 18:00:23 +00:00
" Allow <tab> inserts in the command bar to autocomplete, e.g. see <leader>e
set wildcharm=<tab>
if executable('rg')
set grepprg=rg\ --vimgrep\ --hidden " Requires ripgrep to be installed.
endif
2019-03-28 00:15:55 +00:00
" Show trailing tabs and whitespace.
set listchars=tab:»\ ,trail,extends:>,precedes:<,nbsp:+
2019-03-28 00:15:55 +00:00
2023-05-21 22:02:21 +00:00
set timeoutlen=250 ttimeoutlen=0 " Don't set it too low otherwise you won't be able to type use multi-key sequences.
2011-04-15 18:44:28 +00:00
2023-12-05 21:58:04 +00:00
" Keeping this a bit low to make git-gutter updates faster. The original value
" was 4000. I tried 250 and eventually started seeing some plugin errors
" related to paren formatting. 800 seems to be the sweet spot.
set updatetime=800
2019-12-31 05:37:09 +00:00
" Fix vim's background colour erase - http://snk.tuxfamily.org/log/vim-256color-bce.html
if &term =~ '256color'
2019-12-31 05:37:09 +00:00
" Disable Background Color Erase (BCE) so that color schemes
" work properly when Vim is used inside tmux and GNU screen.
" See also http://snk.tuxfamily.org/log/vim-256color-bce.html
set t_ut=
endif
2023-01-27 20:20:51 +00:00
" Status line
set statusline=%<%f\ (%{&ft})\ %-4(%m%)%=%-19(%3l,%02c%03V%)
2019-12-31 05:37:09 +00:00
" Disable arrow keys.
noremap <up> <nop>
noremap <down> <nop>
noremap <left> <nop>
noremap <right> <nop>
inoremap <up> <nop>
inoremap <down> <nop>
inoremap <left> <nop>
inoremap <right> <nop>
2013-08-16 20:50:47 +00:00
2023-01-27 20:20:51 +00:00
"/////////////////////////////////////////////////
" LOAD PRIVATE VIMRC
"/////////////////////////////////////////////////
" This should be done after above base settings that don't use the global
" campo variables.
"
" You can further customize things in a private vimrc. I use this for things
" that I don't want included in my public dotfiles repo such as temp file settings.
if filereadable($HOME . "/.vimrc.private")
source $HOME/.vimrc.private
endif
2023-01-27 20:20:51 +00:00
" Settings that use the global campo variables:
let &colorcolumn=g:campo_max_line_length
2023-01-27 20:20:51 +00:00
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
" #3 CUSTOM AUTOCMDS
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2017-07-26 16:06:00 +00:00
augroup campoCmds
2020-07-25 23:39:09 +00:00
" Clear all autocmds in the group.
autocmd!
" Automatically wrap at N characters.
autocmd FileType gitcommit setlocal colorcolumn=72
2022-02-10 20:00:15 +00:00
" @flagged for removal. It's a bit annoying. autocmd BufRead,BufNewFile *.{md,txt,plan} exec "setlocal textwidth=".g:campo_max_line_length
2020-07-25 23:39:09 +00:00
2022-12-28 05:48:50 +00:00
" Enable spell checking by default.
2020-07-25 23:39:09 +00:00
autocmd FileType gitcommit,markdown,text setlocal spell
" Jump to last cursor position unless it's invalid or in an event handler.
autocmd BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
" Properly indent schemes (scheme, racket, etc).
autocmd BufRead,BufNewFile *.{lisp,scm,rkt} setlocal equalprg=scmindent.vim.rkt
2020-07-25 23:39:09 +00:00
" Elixir indent
autocmd FileType elixir setlocal tabstop=2 | setlocal shiftwidth=2 | setlocal softtabstop=2
2020-10-09 15:54:01 +00:00
" Fasm indent; uses the fedorenchik/fasm.vim plugin.
autocmd BufReadPre *.asm let g:asmsyntax = "fasm"
2020-07-25 23:39:09 +00:00
" Auto reload VIM when settings changed.
" Need to use silent! now because the save commands call a custom function
" and without the silent we would see an error after sourcing saying that
" we can't redefine the function that initiated the save. :ReloadVimrcError
"
" @fixme Reload lvimrc after sourcing this file on a save. I tried calling
" a function that does the source and a call to lvimrc's API but got an
" error complaining that the function cannot be created while it's in use.
2023-12-05 21:58:04 +00:00
autocmd BufWritePost $MYVIMRC silent! source $MYVIMRC
autocmd BufWritePost *.vim silent! source $MYVIMRC
autocmd BufWritePost ~/.vimrc.private silent! source $MYVIMRC
autocmd BufWritePost ~/.vimrc_templates.private silent! source $MYVIMRC
2020-07-25 23:39:09 +00:00
" Remove trailing whitespace when saving any file.
2023-06-13 02:51:42 +00:00
fu! StripTrailingWhitespaces()
if g:campo_strip_trailing_whitespace == 1
2022-12-06 02:12:30 +00:00
if len(g:campo_directories_to_ignore_when_stripping_trailing_whitespace)
for path in g:campo_directories_to_ignore_when_stripping_trailing_whitespace
if path == expand('%:p:h')
return
endif
endfor
endif
if len(g:campo_files_to_ignore_when_stripping_trailing_whitespace)
2022-12-06 02:12:30 +00:00
for filename in g:campo_files_to_ignore_when_stripping_trailing_whitespace
if (g:campo_use_full_paths_for_whitespace_stripping_file_filters == 1 && filename == expand('%:p')) || (g:campo_use_full_paths_for_whitespace_stripping_file_filters == 0 && filename == expand('%:t'))
return
endif
endfor
endif
else
2022-12-06 02:12:30 +00:00
let l:found_match = 0
if len(g:campo_directories_to_force_stripping_trailing_whitespace)
for path in g:campo_directories_to_force_stripping_trailing_whitespace
if path == expand('%:p:h')
let l:found_match = 1
break
endif
endfor
2022-12-06 02:12:30 +00:00
endif
if l:found_match == 0 && len(g:campo_files_to_force_stripping_trailing_whitespace)
for filename in g:campo_files_to_force_stripping_trailing_whitespace
if (g:campo_use_full_paths_for_whitespace_stripping_file_filters == 1 && filename == expand('%:p')) || (g:campo_use_full_paths_for_whitespace_stripping_file_filters == 0 && filename == expand('%:t'))
let l:found_match = 1
break
endif
endfor
endif
if l:found_match == 0
return
endif
2020-07-25 23:39:09 +00:00
endif
let l = line(".")
let c = col(".")
%s/\s\+$//e
call cursor(l, c)
2020-07-25 23:39:09 +00:00
endfun
autocmd BufWritePre * call StripTrailingWhitespaces()
2017-07-26 16:06:00 +00:00
augroup END
2015-03-21 19:13:17 +00:00
2023-01-27 20:20:51 +00:00
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
" #4 KEY MAPPINGS
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2023-05-21 22:02:21 +00:00
" Note: if there are two+ mappings that start with the same sequence then vim
" will introduce a delay before the mapping is handled in order to wait for
" the entire sequence to be typed. e.g. <leader>s and <leader>sg will
" introduce a timeout delay, which will be noticed when you're trying to use
" <leader>s. If you type <leader>sg then it'll be handled immediately, unless
" there is a third mapping with that initial sequence, e.g. <leader>sgn.
"
" You can adjust the timeout duration by modidying the timeoutlen option.
"
" You can see when a keysequence is mapped to by entering :map <sequence>
" e.g. :map ,s
" This is helpful when you are experiencing a timeout but you only have one
" mapping defined in your vimrc. It's likely that a plugin added a similar
" mapping sequence.
"
" The difference between map and noremap is that the former does recursive
" expansion and the latter doesn't. The expansion means that if the mapped key
" sequence contains any mappings then those mappings will be expanded as well.
" This can lead to issues and confusion, so it's best to use noremap unless
" you really have a reason not to.
2023-01-27 20:20:51 +00:00
"##################################################################################
" MISC
"##################################################################################
" Lowercase the e (have a habit of making it uppercase).
:ca E e
" Bail out of insert mode by double-pressing 'j'.
" Disabling because it's annoying and I now have a keyboard that I can use
" through the Steam Link that lets me map caps to ctrl, so I no longer need
" this.
" imap jj <Esc>
2011-04-15 18:44:28 +00:00
2019-12-31 05:37:09 +00:00
" Suspend vim process and return to the shell. Can return to vim with `fg`.
nnoremap <leader>z <c-z>
2019-12-31 05:37:09 +00:00
" Open the vimrc file for editing / reload vimrc file.
nnoremap <silent> <leader>ev :vsp $MYVIMRC<cr>
nnoremap <silent> <leader>pv :vsp ~/.vimrc.private<cr>
nnoremap <silent> <leader>rv :source $MYVIMRC<cr>
2019-12-31 05:37:09 +00:00
" Type %/ in the command bar to have it replaced with the current buffer's
" path if the file is on disk. One thing I noticed is that you have to type
" the full %/ quickly otherwise it won't replace it.
cmap %/ %:p:h/
2017-10-10 23:50:00 +00:00
2023-01-27 20:20:51 +00:00
" Open a terminal within vim. Use `exit` to close it.
" DISABLING because I don't use this and I want to use the <leader>t for opening my todo file.
"if exists(':terminal')
" noremap <leader>t :terminal<cr>
" tnoremap <leader>te <C-\><C-n>
" tnoremap <A-h> <C-\><C-n><C-w>h
" tnoremap <A-j> <C-\><C-n><C-w>j
" tnoremap <A-k> <C-\><C-n><C-w>k
" tnoremap <A-l> <C-\><C-n><C-w>l
" nnoremap <A-h> <C-w>h
" nnoremap <A-j> <C-w>j
" nnoremap <A-k> <C-w>k
" nnoremap <A-l> <C-w>l
"endif
" Jump to other buffers.
noremap <c-k> <c-w><Up>
noremap <c-j> <c-w><Down>
noremap <c-l> <c-w><Right>
noremap <c-h> <c-w><Left>
" Make it easier to jump around the command line. The default behaviour is
" using the arrow keys with or without shift.
:cnoremap <C-J> <S-Left>
:cnoremap <C-K> <S-Right>
" Window splitting - couldn't figure out how to remap <c-w>v & <c-w>n to <c-m>
" & <c-n>
noremap <leader>m :vsplit<cr>
noremap <leader>mm :split<cr>
" Disable treating special characters as regex when doing searches as it's so
" fucking annoying having to escape them, particularly periods and asterisk.
" This is done by setting the 'very nomagic' setting \V.
nnoremap / /\V
"-----------------------------------------------------
" 'a' register helpers
"
" Faster way to activate the 'a' named register. These registers can be used
" for various operations like yanking (copying), deleting, and pasting text.
" Each register is identified by a single character. For example, there are
" named registers 'a' to 'z', where text yanked or deleted can be specifically
" stored and later retrieved.
"
" First activate the register with <leader>a and then do your yank, delete or
" paste. Subsequent yanks into <leader>a will overwrite existing data. You can
" append to the register by using <leader>aa
"
" This overwrites the contents of a.
noremap <leader>a "a
" This appends to a.
noremap <leader>aa "A
"-----------------------------------------------------
" Backward replace word including cursor character.
noremap <leader>d cvb
2023-01-27 20:20:51 +00:00
" Allow fast pasting by accessing the system clipboard register.
noremap <leader>p "+p
" Likely won't need to use this if pasting with <leader>p, but just in case here ya go.
noremap <leader>pp :set paste! paste?<cr>
" Toggle line numbers.
2023-05-21 22:02:21 +00:00
nnoremap <leader>o :set number! number?<cr>
2023-01-27 20:20:51 +00:00
" Show spell checking.
" You can add new entries to the dict by moving the cursor over the word and pressing `zg`.
noremap <leader>j :exec &spell==&spell? "se spell! spelllang=en_us" : "se spell!"<cr>
noremap <leader>= z=
" Clear the search buffer (highlighting) when hitting return.
nnoremap <cr> :nohlsearch<cr>
" Switch to the previous file.
nnoremap <leader><leader> <c-^>
" Replace currently selected text with default register without yanking it.
vnoremap p "_dP
" Switch between C++ source and header files.
noremap <leader>v :e %:p:s,.h$,.X123X,:s,.cpp$,.h,:s,.X123X$,.cpp,<CR>
2023-07-14 21:29:59 +00:00
noremap <leader>vv :e %:p:s,.h$,.X123X,:s,.c$,.h,:s,.X123X$,.c,<CR>
2023-01-27 20:20:51 +00:00
"noremap <leader>vvv :e %:p:s,.h$,.X123X,:s,.cc$,.h,:s,.X123X$,.cc,<CR>
" Replace all instances of the highlighted text with whatever you enter.
nnoremap <c-g> :%s///g<left><left>
"##################################################################################
" SAVING AND QUITING
"##################################################################################
" I used to have a BufWritePost autocommand that ran the ctags generator but
" it ends up running multiple times when saving multiple buffers at once. In
" order to only call it once for a group of saves I've had to remap the
" various save commands to a function call.
2023-06-13 02:51:42 +00:00
fu! CreateCtags()
" Only allow one instance of ctags to run in this directory at any given time.
let l:lock_file = "ctags.lock"
if filereadable(l:lock_file) || filereadable("newtags")
" Don't print a warning because this will always show when saving multiple files at the same time with a :wa or :xa
return
endif
let l:extension = tolower(expand('%:e'))
if (g:campo_force_ctags_regardless_of_extension == 0) && (index(g:campo_extensions_that_run_ctags, l:extension) < 0)
2022-12-06 02:12:30 +00:00
"echo "Skipping ctags generation"
return
endif
" Abort if we're editing a text file. This won't be an exhaustive
" filter. We can restrict what goes into the tag file
" First determine if we're in a root drive directory. If we are then
" we bail because we don't want to recurse across the entire drive!
let l:path = expand('%:p:h')
2023-12-10 23:37:18 +00:00
if IsRootDrive(l:path)
call PrintError("Not going to run ctags because the file is in a root drive directory")
return
endif
" Always ignore .git and node_modules
let g:campo_ctags_exclude = g:campo_ctags_exclude + ['.git', 'node_modules']
let l:exclude_list = ""
for name in g:campo_ctags_exclude
let l:exclude_list .= "--exclude=" . name . " "
endfor
" Include local variables for C-like languages.
let l:ctags_cmd = 'ctags '.l:exclude_list.' '.g:campo_custom_ctags_args.' --c-types=+l --c++-types=+l -o newtags'
" Add the filename to the ctags command if not running in recursive mode.
let l:recursive = matchstr(g:campo_custom_ctags_args, '\(-R\s\)\|\(-R$\)\|\(--recurse=yes\)\|\(--recurse\s\)\|\(--recurse$\)')
if l:recursive == ''
let l:ctags_cmd .= ' ' . expand('%:t')
echo "Creating non-recursive ctags"
else
echo "Creating recursive ctags"
endif
" The ampersand at the end is to make this run in the background. I had to group the
" commands in parens to make the chained commands run in the background.
let l:cmd = '!(touch '.l:lock_file.'; '.l:ctags_cmd.'; mv newtags tags &>/dev/null; rm '.l:lock_file.') &'
silent! exec l:cmd
endfun
" @note We have an autocmd that reloads the vimrc files after they're saved.
" These write functions below will not be reloaded because they initiate the
" save. So if you make changes to them then you need to manually reload this
" file using <leader>rv or whatever. :ReloadVimrcError
2023-06-13 02:51:42 +00:00
fu! WriteCurrentFileAndCreateCtags()
2022-01-01 18:41:53 +00:00
write!
call CreateCtags()
2023-06-13 02:51:42 +00:00
endfu
2023-06-13 02:51:42 +00:00
fu! WriteCurrentFileAndCreateCtagsThenQuit()
2022-01-01 18:41:53 +00:00
write!
call CreateCtags()
quit
2023-06-13 02:51:42 +00:00
endfu
" @fixme Sometimes a :wa that saves multiple files causes vim to hang and use a lot of CPU.
2023-06-13 02:51:42 +00:00
fu! WriteAllModifiedFilesAndCreateCtags()
wall!
call CreateCtags()
2023-06-13 02:51:42 +00:00
endfu
" Create a command abbreviation that only applies when it's at the beginning
" of a ex command. If you were to do a normal cnoreabbrev or cabbrev then the
" subsitution can happen anywhere in the command line. It was mostly affecting
" my text search; I'd type '/w' and it would be replaced with the call to save
" and create ctags.
2023-06-13 02:51:42 +00:00
fu! Cabbrev(key, value)
exe printf('cabbrev <expr> %s (getcmdtype() == ":" && getcmdpos() <= %d) ? %s : %s',
\ a:key, len(a:key)+1, string(a:value), string(a:key))
2023-06-13 02:51:42 +00:00
endfu
call Cabbrev('w', 'call WriteCurrentFileAndCreateCtags()')
call Cabbrev('W', 'call WriteCurrentFileAndCreateCtags()')
call Cabbrev('wa', 'call WriteAllModifiedFilesAndCreateCtags()')
call Cabbrev('Wa', 'call WriteAllModifiedFilesAndCreateCtags()')
call Cabbrev('WA', 'call WriteAllModifiedFilesAndCreateCtags()')
call Cabbrev('wq', 'call WriteCurrentFileAndCreateCtagsThenQuit()')
call Cabbrev('Wq', 'call WriteCurrentFileAndCreateCtagsThenQuit()')
call Cabbrev('WQ', 'call WriteCurrentFileAndCreateCtagsThenQuit()')
2023-09-20 18:00:23 +00:00
" Faster way to open a file in the same directory.
" <tab> will autocomplete the expansion here because we set wildcharm to <tab>.
nnoremap <leader>e :e %:p:h/<tab>
" Jai folders
nnoremap <leader>ee :e <C-r>=g:campo_jai_path<CR>/<tab>
nnoremap <leader>em :e <C-r>=g:campo_jai_path<CR>/modules/<tab>
nnoremap <leader>eh :e <C-r>=g:campo_jai_path<CR>/how_to/<tab>
2023-09-20 18:00:23 +00:00
nnoremap <leader>w :call WriteCurrentFileAndCreateCtags()<cr>
nnoremap <leader>x :call WriteCurrentFileAndCreateCtagsThenQuit()<cr>
nnoremap <leader>q :q<cr>
call Cabbrev('Q', 'q')
call Cabbrev('Qa', 'qa')
2018-06-11 17:39:04 +00:00
command! Qa qall
2019-12-31 05:37:09 +00:00
" Disable Ex mode.
noremap Q <Nop>
2013-07-10 16:13:13 +00:00
2023-01-27 20:20:51 +00:00
"##################################################################################
2012-04-19 14:23:13 +00:00
" MULTIPURPOSE TAB KEY
2023-01-27 20:20:51 +00:00
"##################################################################################
2023-06-13 02:51:42 +00:00
fu! InsertTabWrapper()
2016-08-03 04:28:39 +00:00
let l:col = col('.') - 1
if !l:col || getline('.')[l:col - 1] !~ '\k'
2012-04-19 14:23:13 +00:00
return "\<tab>"
else
return "\<c-p>"
2011-04-15 18:44:28 +00:00
endif
2023-06-13 02:51:42 +00:00
endfu
2012-04-19 14:23:13 +00:00
inoremap <tab> <c-r>=InsertTabWrapper()<cr>
inoremap <s-tab> <c-n>
2023-01-27 20:20:51 +00:00
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
" #5 PLUGIN CONFIGS
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2012-04-19 14:23:13 +00:00
2023-01-27 20:20:51 +00:00
"##################################################################################
" LOCAL VIMRC
2023-01-27 20:20:51 +00:00
"##################################################################################
let g:localvimrc_sandbox = 0
let g:localvimrc_ask = 0
"##################################################################################
" EDITOR CONFIG
"##################################################################################
let g:EditorConfig_exclude_patterns = ['fugitive://.*']
2023-01-27 20:20:51 +00:00
"##################################################################################
" LION (TEXT ALIGNMENT)
"##################################################################################
let b:lion_squeeze_spaces = 1
"##################################################################################
" TAGBAR
2023-01-27 20:20:51 +00:00
"##################################################################################
2017-09-22 21:16:30 +00:00
noremap <F12> :TagbarToggle<cr>
2022-01-01 18:41:53 +00:00
" Sort tags by their order in the source file. Press 's' to sort them alphabetically.
let g:tagbar_sort = 0
2023-01-27 20:20:51 +00:00
"##################################################################################
2018-06-11 17:39:04 +00:00
" GITGUTTER
2023-01-27 20:20:51 +00:00
"##################################################################################
2019-12-31 05:37:09 +00:00
let g:gitgutter_enabled = 1
let g:gitgutter_highlight_lines = 0
nnoremap <leader>hh :GitGutterToggle<cr>
nmap <leader>ha <Plug>(GitGutterStageHunk)
nmap [h <Plug>(GitGutterNextHunk)
2018-06-11 17:39:04 +00:00
nmap ]h <Plug>GitGutterPrevHunk
augroup gitGutterPluginCmds
autocmd!
" Update marks on save
autocmd BufWritePost * GitGutter
augroup END
2017-11-15 16:30:09 +00:00
2023-01-27 20:20:51 +00:00
"##################################################################################
" SYNTASTIC
2023-01-27 20:20:51 +00:00
"##################################################################################
" NOTE: there is a status line config in the status line section
let g:syntastic_always_populate_loc_list = 1
let g:syntastic_auto_loc_list = 1
let g:syntastic_check_on_open = 0
let g:syntastic_check_on_wq = 0
" Customize Rust
" https://github.com/rust-lang/rust.vim/issues/130
" Can remove once this Syntastic PR is merged https://github.com/rust-lang/rust.vim/pull/132
"let g:syntastic_rust_rustc_exe = 'cargo check'
"let g:syntastic_rust_rustc_fname = ''
"let g:syntastic_rust_checkers = ['rustc']
2023-01-27 20:20:51 +00:00
"##################################################################################
2019-03-28 00:15:55 +00:00
" RIPGREP
2023-01-27 20:20:51 +00:00
"##################################################################################
2019-03-28 00:15:55 +00:00
let g:rg_highlight = 1
2021-10-14 18:20:40 +00:00
let g:rg_window_height = g:quickfix_pane_height
2023-01-27 20:20:51 +00:00
"##################################################################################
2019-03-28 01:35:59 +00:00
" CTRL-P
2023-01-27 20:20:51 +00:00
"##################################################################################
2019-03-28 01:35:59 +00:00
" keybindings:
"
" leader-f = open CtrlP in tag searching mode.
" leader-g = open CtrlP in file searching mode.
" ctrl-f = toggle search mode
" enter = open result in a current buffer or in an already open buffer for that file.
" ctrl-v = open result in a vertically-split buffer.
" ctrl-h = open result in a horizontally-split buffer.
" ctrl-t = open result in a new tab.
" ctrl-j | ctrl-k = move up and down the search results.
" ctrl-y = create file and open it.
" ctrl-z = mark multiple file search results to open (I think you can only use ctrl-v or ctrl-x and not enter).
" ctrl-o = ask how to open a file search result.
" ctrl-o = ask how to open a file search result.
" ctrl-p | ctrl-n = traverse search history.
" CtrlP finds the tags file by using vim's 'tags' option value. I initially
" tried changing the tags value to the working_path if one is provided. I made
" a copy of the current tags value and attempted to restore it when CtrlP was
" exited without an action or a tag action took place. I wasn't able to get
" the tags restored because there's no vim event that gets triggered when a
" tag is opened using the :tag comment. I tried a bunch of autocmds on buffer,
" window and cmdline events but wasn't able to find anything that fired AFTER
" the tag command. So we're instead just setting the tags list once for the
" session and not bothering with changing it on the fly. See g:SetExtraCtagsPaths
2023-06-13 02:51:42 +00:00
fu! CtrlP_Search(search_path)
" If a:search_path is empty then ctrlp will use g:ctrlp_working_path_mode to determine the cwd to search in.
execute 'CtrlP ' . a:search_path
2023-06-13 02:51:42 +00:00
endfu
2023-06-13 02:51:42 +00:00
fu! CtrlP_JaiSearch(jai_rel_search_path)
if g:campo_jai_path == ''
call PrintError("g:campo_jai_path isn't set!")
return
endif
let l:path = g:campo_jai_path
if a:jai_rel_search_path != ''
let l:path .= '/' . a:jai_rel_search_path
endif
if !isdirectory(l:path)
call PrintError("Directory ".l:path." doesn't exist.")
return
endif
call CtrlP_Search(l:path)
2023-06-13 02:51:42 +00:00
endfu
" CtrlP File Searching
noremap <leader>g :call CtrlP_Search('')<cr> " Search in current directory
noremap <leader>gg :call CtrlP_JaiSearch('')<cr> " Search in Jai directory
noremap <leader>gm :call CtrlP_JaiSearch('modules')<cr> " Search in Jai modules
noremap <leader>gh :call CtrlP_JaiSearch('how_to')<cr> " Search in Jai how_to
noremap <leader>ge :call CtrlP_JaiSearch('examples')<cr> " Search in Jai examples
2019-03-28 01:35:59 +00:00
let g:ctrlp_map = '<leader>f'
let g:ctrlp_cmd = 'CtrlPTag' " Search tags by default.
let g:ctrlp_by_filename = 1 " File search by filename as opposed to full path.
2021-10-14 18:20:40 +00:00
let g:ctrlp_match_window = 'bottom,order:ttb,min:10,max:'.g:quickfix_pane_height.',results:'.g:quickfix_pane_height
let g:ctrlp_use_caching = 1
2019-03-28 01:35:59 +00:00
let g:ctrlp_clear_cache_on_exit = 1 " No need to keep cache for now since I mostly work in git repos. Press F5 inside CtrlP to rebuild the cache.
2021-10-14 18:20:40 +00:00
let g:ctrlp_working_path_mode = 'ra' " Search from nearest ancestor of the current file that contains .git OR directory of the current file unless it's a subdirectory of the cwd
let g:ctrlp_switch_buffer = 'et' " If a file is already open, open it again in a new pane instead of switching to the existing pane
let g:ctrlp_custom_ignore = '\v[\/]\.(git|hg|svn)$'
let g:ctrlp_user_command = ['.git', 'cd %s && git ls-files -co --exclude-standard'] " If a git repo, use checked in files (ignore things in .gitignore); fallback to globpath()
2019-03-28 01:35:59 +00:00
2023-01-27 20:20:51 +00:00
"##################################################################################
" GIT
2023-01-27 20:20:51 +00:00
"##################################################################################
noremap <leader>gb :Git blame -w<cr>
2018-03-15 18:39:50 +00:00
" Ignore whitespace changes; follow renames and copies.
2021-10-22 00:06:44 +00:00
command! -bar -bang -nargs=* Blame :Git blame<bang> -wCM <args>
command! -bar -bang -nargs=* Gblame :Git blame<bang> -wCM <args>
2023-01-27 20:20:51 +00:00
"##################################################################################
" VIM-CLOJURE-STATIC
2023-01-27 20:20:51 +00:00
"##################################################################################
" Default
let g:clojure_fuzzy_indent = 1
let g:clojure_align_multiline_strings = 1
let g:clojure_fuzzy_indent_patterns = ['^match', '^with', '^def', '^let']
let g:clojure_fuzzy_indent_blacklist = ['-fn$', '\v^with-%(meta|out-str|loading-context)$']
2023-01-27 20:20:51 +00:00
"##################################################################################
" RUST.VIM
2023-01-27 20:20:51 +00:00
"##################################################################################
"let g:rustfmt_autosave = 1 " auto run rust formatter when saving
2023-01-27 20:20:51 +00:00
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
" #6 VISUALS (COLORS, HIGHLIGHTING)
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2017-07-10 15:08:49 +00:00
2023-01-27 20:20:51 +00:00
"###########################################################################
2017-07-10 15:08:49 +00:00
" COLORS
2023-01-27 20:20:51 +00:00
"###########################################################################
2023-12-05 21:58:04 +00:00
" Custom notes highlights. These are used in my color schemes.
"
" @incomplete I can't get these to only match in comments. Not a big deal but
" would be nice to fix.
augroup campoSyntax
autocmd!
autocmd Syntax * syntax match MyAnnotatedNote /@\S\+/ containedin=.*Comment,vimCommentTitle display
autocmd Syntax * syntax match MyTitle /#\+ .\+$/ containedin=.*Comment,vimCommentTitle display
autocmd Syntax * syntax match MyNote /\v<(NOTE|IDEA|TODO):/ containedin=.*Comment,vimCommentTitle display
autocmd Syntax * syntax match MyEmphasis /\v<(WARNING|IMPORTANT):/ containedin=.*Comment,vimCommentTitle display
autocmd Syntax * syntax match MyBug /\v<(FIXME|BUG|DEPRECATED):/ containedin=.*Comment,vimCommentTitle display
highlight link MyAnnotatedNote CampoAnnotatedNote
highlight link MyTitle CampoTitle
highlight link MyNote CampoNote
highlight link MyEmphasis CampoEmphasis
highlight link MyBug CampoBug
augroup END
2022-12-29 23:53:54 +00:00
" Toggle between light and dark themes.
noremap <leader>l :call ToggleLightDarkTheme()<cr>
let s:current_light_dark_mode = g:campo_light_dark_mode
2017-07-10 15:08:49 +00:00
2023-06-13 02:51:42 +00:00
fu! ToggleLightDarkTheme()
2022-12-29 23:53:54 +00:00
if s:current_light_dark_mode == 'light'
call ChangeLightDarkMode('dark', 0)
else
call ChangeLightDarkMode('light', 0)
endif
2023-06-13 02:51:42 +00:00
endfu
2022-12-29 23:53:54 +00:00
2023-06-13 02:51:42 +00:00
fu! ChangeLightDarkMode(mode, onlySetTheme)
2022-12-29 23:53:54 +00:00
if a:mode == 'light'
2020-07-25 23:39:09 +00:00
let s:theme = g:campo_light_theme
exe 'colorscheme ' . s:theme
set background=light
else
let s:theme = g:campo_dark_theme
exe 'colorscheme ' . s:theme
set background=dark
endif
2022-12-29 23:53:54 +00:00
let s:current_light_dark_mode = a:mode
2020-07-25 23:39:09 +00:00
if !a:onlySetTheme
2022-12-29 23:53:54 +00:00
exec 'AirlineTheme' a:mode
2020-07-25 23:39:09 +00:00
endif
2023-06-13 02:51:42 +00:00
endfu
2017-07-10 15:08:49 +00:00
2022-12-29 23:53:54 +00:00
" Set the intial light/dark mode.
if g:campo_light_dark_mode =~ 'light'
2023-03-01 20:27:26 +00:00
call ChangeLightDarkMode('light', 1)
2017-07-10 15:08:49 +00:00
else
2023-03-01 20:27:26 +00:00
call ChangeLightDarkMode('dark', 1)
2017-07-10 15:08:49 +00:00
endif
" Open the current color scheme for editing.
2023-06-13 02:51:42 +00:00
fu! EditColorScheme()
let l:path = g:vim_dir . '/colors/' . s:theme . '.vim'
if filereadable(l:path)
execute 'vsplit ' . l:path
else
call PrintError("Failed to open " . l:path . " for editing.")
endif
2023-06-13 02:51:42 +00:00
endfu
command -nargs=0 EditColorScheme call EditColorScheme()
2017-07-10 15:08:49 +00:00
2023-01-27 20:20:51 +00:00
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
" #7 CUSTOM FUNCTIONS & COMMANDS
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2023-12-10 23:37:18 +00:00
fu! IsRootDrive(path) abort
let l:path_without_slashes = substitute(a:path, "/", "", "g")
return strchars(l:path_without_slashes) <= 1
endfu
fu! IsPathContained(path1, path2) abort
let l:normalized_path1 = substitute(fnamemodify(a:path1, ':p'), '\', '/', 'g')
let l:normalized_path2 = substitute(fnamemodify(a:path2, ':p'), '\', '/', 'g')
" Ensure paths end with a directory separator
if l:normalized_path1[-1:] != '/'
let l:normalized_path1 .= '/'
endif
if l:normalized_path2[-1:] != '/'
let l:normalized_path2 .= '/'
endif
echo l:normalized_path1
echo l:normalized_path2
return match(l:normalized_path1, '^' . escape(l:normalized_path2, '\')) != -1
endfu
fu! CountChar(str, char) abort
" Remove all characters that are not the target character.
let l:filtered = substitute(a:str, '[^' . a:char . ']', '', 'g')
return strlen(l:filtered)
endfu
2023-01-27 20:20:51 +00:00
fu! WindowsToUnixPath(str) abort
let l:result = substitute(a:str, '\\', '/', 'g')
return l:result
endfu
fu! ConvertQuickfixPathsToUnixSlashes()
let l:qflist = getqflist()
for i in range(len(l:qflist))
let l:bufnr = l:qflist[i]['bufnr']
if l:bufnr != -1 && bufexists(l:bufnr)
let l:filename = bufname(l:bufnr)
let l:filename = substitute(l:filename, '\\', '/', 'g')
let l:qflist[i]['module'] = l:filename
endif
endfor
call setqflist(l:qflist)
endfu
2023-01-27 20:20:51 +00:00
"##################################################################################
" COMPILING CODE
"##################################################################################
2017-07-10 15:08:49 +00:00
" AsyncRun status line
let g:airline_section_error = airline#section#create_right(['%{g:asyncrun_status}'])
" "make" value is needed for asyncrun to work with the errormarker plugin
" https://github.com/skywind3000/asyncrun.vim/wiki/FAQ#can-asyncrunvim-trigger-an-autocommand-quickfixcmdpost-to-get-some-plugin-like-errormaker-processing-the-content-in-quickfix-
2017-07-10 15:08:49 +00:00
let g:asyncrun_auto = "make"
" Error and warning gutter characters.
2017-07-10 15:08:49 +00:00
let errormarker_errortext = "E"
let errormarker_warningtext = "W"
let errormarker_infotext = "I"
" Gutter character colors. See color file for the group definition.
let errormarker_errortextgroup = "BuildError"
let errormarker_warningtextgroup = "BuildWarn"
let errormarker_infotextgroup = "BuildInfo"
" Colors for the marked lines. See color file for the group definition.
let errormarker_errorgroup = "BuildError"
let errormarker_warninggroup = "BuildWarn"
let errormarker_infogroup = "BuildInfo"
2017-07-10 15:08:49 +00:00
" I don't know how to map to a plugin command, so I'm wrapping it with a function...ugh.
2023-06-13 02:51:42 +00:00
fu! ShowErrorAtCursor()
" This is defined in errormarker.vim
ErrorAtCursor
2023-06-13 02:51:42 +00:00
endfu
nnoremap <leader>ce :call ShowErrorAtCursor()<cr>
2023-01-27 20:20:51 +00:00
"/////////////////////////////////////////////////
" CUSTOM ERROR FORMATS
"/////////////////////////////////////////////////
" @note: You can debug the error parsing by running :ShowErrorEntries
" This will print the valid entries. You'll know parsing is correct when the
" entries have a type, line num, error message, etc.
2023-06-13 02:51:42 +00:00
fu! ShowErrorEntries()
" Prints out valid quickfix errors.
redraw!
for l:d in getqflist()
if l:d.valid == 1
echomsg l:d
endif
endfor
2023-06-13 02:51:42 +00:00
endfu
command -nargs=0 ShowErrorEntries call ShowErrorEntries()
2022-11-29 04:40:04 +00:00
" Jai
"
" Z:\path\main.jai:100,10: Error: Undeclared identifier 's1'.
set errorformat=\\\ %#%f:%l\\,%c:\ %t%[A-z]%#:\ %m
2023-01-27 20:20:51 +00:00
" Microsoft compiler: cl.exe
2021-02-08 20:40:32 +00:00
"
" Z:\path\main.cpp(2808): error C2220: the following warning is treated as an error
2022-11-29 04:40:04 +00:00
set errorformat+=\\\ %#%f(%l):\ %#%t%[A-z]%#\ %[A-z]%#%n:\ %m
2023-01-27 20:20:51 +00:00
2017-07-10 15:08:49 +00:00
" Microsoft MSBuild errors
"
" @note I got this off the Internet and haven't tested it yet.
"
" Z:\path\main.cpp(2808): error C2220: the following warning is treated as an error
set errorformat+=\\\ %#%f(%l\\,%c):\ %m
2023-01-27 20:20:51 +00:00
2017-07-10 15:08:49 +00:00
" Microsoft HLSL compiler: fxc.exe
"
" @note I got this off the Internet and haven't tested it yet.
" @todo Add an example
2017-07-10 15:08:49 +00:00
set errorformat+=\\\ %#%f(%l\\\,%c-%*[0-9]):\ %#%t%[A-z]%#\ %m
2023-01-27 20:20:51 +00:00
"/////////////////////////////////////////////////
" BUILD FUNCTIONS
"/////////////////////////////////////////////////
2023-06-13 02:51:42 +00:00
fu! HideBuildResultsAndClearErrors()
2020-07-25 23:39:09 +00:00
RemoveErrorMarkers
2021-10-14 18:20:40 +00:00
call asyncrun#quickfix_toggle(g:quickfix_pane_height, 0)
2023-06-13 02:51:42 +00:00
endfu
2017-07-10 15:08:49 +00:00
2023-06-13 02:51:42 +00:00
fu! HideAsyncResults()
2021-10-14 18:20:40 +00:00
call asyncrun#quickfix_toggle(g:quickfix_pane_height, 0)
2023-06-13 02:51:42 +00:00
endfu
2017-08-21 18:26:22 +00:00
2023-06-13 02:51:42 +00:00
fu! ToggleBuildResults()
2021-10-14 18:20:40 +00:00
call asyncrun#quickfix_toggle(g:quickfix_pane_height)
2023-06-13 02:51:42 +00:00
endfu
2017-07-10 15:08:49 +00:00
2023-06-13 02:51:42 +00:00
fu! StopRunTask()
2020-07-25 23:39:09 +00:00
AsyncStop
call HideAsyncResults()
2023-06-13 02:51:42 +00:00
endfu
2017-07-10 15:08:49 +00:00
2024-01-21 03:16:52 +00:00
" @incomplete use the same path searching from RunProgram
" @incomplete use the same path searching from RunProgram
" @incomplete use the same path searching from RunProgram
" @incomplete use the same path searching from RunProgram
" @incomplete use the same path searching from RunProgram
" @incomplete use the same path searching from RunProgram
" @incomplete use the same path searching from RunProgram
fu! Build(optimized=0, silent=0) abort
let l:async_cmd = "AsyncRun! "
if a:silent
let l:async_cmd .= "-post=call\\ HideAsyncResults() "
endif
2023-03-01 20:27:26 +00:00
2023-01-19 23:13:38 +00:00
let l:is_jai = 0
2023-05-07 02:01:03 +00:00
let l:has_jai_build_file = 0
2024-01-21 03:16:52 +00:00
let l:has_jai_first_file = 0
2023-03-01 20:27:26 +00:00
let l:ext = tolower(expand('%:e'))
2023-06-03 20:22:13 +00:00
let l:current_dir = expand('%:p:h')
let l:one_dir_back = expand('%:p:h:h')
2023-03-01 20:27:26 +00:00
2023-05-07 02:01:03 +00:00
let l:cmd = ""
2023-03-01 20:27:26 +00:00
2023-05-07 02:01:03 +00:00
if l:ext == "jai"
2023-01-19 23:13:38 +00:00
let l:is_jai = 1
2023-03-01 20:27:26 +00:00
2023-09-20 18:00:23 +00:00
" Check for a build file in the current directory or one directory back when one directory back isn't the root of a drive.
2023-05-07 02:01:03 +00:00
" (e.g. we're in modules/ or src/, code/, etc)
2023-09-20 18:00:23 +00:00
if filereadable(l:current_dir . "/build.jai") || filereadable(l:current_dir . "/first.jai") || ((l:one_dir_back != "/") && (filereadable(l:one_dir_back . "/build.jai") || filereadable(l:one_dir_back . "/first.jai")))
2023-05-07 02:01:03 +00:00
let l:has_jai_build_file = 1
2023-03-01 20:27:26 +00:00
2024-01-21 03:16:52 +00:00
if filereadable(l:current_dir . "/build.jai")
2023-06-03 20:22:13 +00:00
let l:cmd = "jai ". l:current_dir . "/build.jai"
2024-01-21 03:16:52 +00:00
elseif filereadable(l:current_dir . "/first.jai")
let l:cmd = "jai ". l:current_dir . "/first.jai"
let l:has_jai_first_file = 1
2023-05-07 02:01:03 +00:00
else
2023-06-03 20:22:13 +00:00
" It's one directory back. We don't want to include '../' in
" the cmd because then our reported paths in the program get
" botched, e.g. path shown in an assert error.
2024-01-21 03:16:52 +00:00
if filereadable(l:one_dir_back . "/build.jai")
let l:cmd = "jai " . l:one_dir_back . "/build.jai"
else
let l:cmd = "jai " . l:one_dir_back . "/first.jai"
let l:has_jai_first_file = 1
endif
2023-05-07 02:01:03 +00:00
endif
else
2023-05-07 02:01:03 +00:00
let l:cmd = "jai % "
endif
2022-12-06 02:12:30 +00:00
else
2024-01-21 03:16:52 +00:00
if filereadable("build") && !isdirectory("build")
let l:cmd .= './build '
elseif filereadable("build.sh")
let l:cmd .= './build.sh '
elseif filereadable("build.bat")
let l:cmd .= './build.bat '
else
let l:cmd .= './build* '
endif
2022-12-06 02:12:30 +00:00
if a:optimized == 1
2023-03-01 20:27:26 +00:00
let l:cmd .= ' -o'
2022-12-06 02:12:30 +00:00
endif
2022-11-29 04:37:35 +00:00
endif
2023-03-01 20:27:26 +00:00
2023-01-19 23:13:38 +00:00
if l:is_jai
let l:cmd .= ' '.g:campo_jai_compiler_args
let l:set_metaprogram_args = 0
2023-05-07 02:01:03 +00:00
if l:has_jai_build_file
let l:filename = "build.jai"
if l:has_jai_first_file
let l:filename = "first.jai"
endif
2023-05-07 02:01:03 +00:00
if a:optimized == 1
echo "Compiling release " . l:filename
2023-05-07 02:01:03 +00:00
" @note We pass 'release' as a user metaprogram arg for the
2023-06-03 20:22:13 +00:00
" build file to parse in case it cares about that. -release is
" a compiler arg that we also include because some build
" scripts won't be looking at the user metaprogram args.
" We also don't bother adding an import directory for local modules
" because the build file should manage that sort of thing for us.
2023-06-20 02:27:36 +00:00
let l:cmd .= " -release - -release"
let l:set_metaprogram_args = 1
2023-05-07 02:01:03 +00:00
else
echo "Compiling debug " . l:filename
2023-05-07 02:01:03 +00:00
endif
else
if a:optimized == 1
echo "Compiling release " . expand('%:t')
let l:cmd .= " -release"
else
echo "Compiling debug " . expand('%:t')
endif
endif
2023-05-09 03:34:04 +00:00
if g:campo_jai_metaprogram_args != ""
if l:set_metaprogram_args == 1
let l:cmd .= ' '.g:campo_jai_metaprogram_args
else
let l:cmd .= ' - '.g:campo_jai_metaprogram_args
endif
endif
2023-01-19 23:13:38 +00:00
endif
2023-03-01 20:27:26 +00:00
" I was originally passing -save=2 to AsyncRun! in order to save all
" modified files (it just does a `silent! wall` call), but I want ctags to
" be generated so we're handling the save ourselves.
call WriteAllModifiedFilesAndCreateCtags()
exec l:async_cmd . l:cmd
2023-06-13 02:51:42 +00:00
endfu
2022-11-29 04:37:35 +00:00
2023-12-10 23:37:18 +00:00
fu! RunProgram() abort
if tolower(expand('%:e')) == "py"
exec "AsyncRun! python %"
return
endif
2023-05-10 18:56:43 +00:00
" Sometimes vim mixes unix and windows slashes so we need to normalize and
" use this in future fnamemodify calls (can't use expand with a string
" that doesn't contain wildcards).
let l:full_path = WindowsToUnixPath(expand('%'))
let l:file_exe_name = fnamemodify(l:full_path, ':t:r').'.exe' " Just the filename without the path
2023-12-10 23:37:18 +00:00
" Easy case is the current file has an exe with the same name in the
" same directory. We run that if found.
if filereadable(fnamemodify(l:full_path, ':p:h') . '/' . l:file_exe_name)
exec 'AsyncRun! ' . fnamemodify(l:full_path, ':p:h') . '/' . l:file_exe_name
2023-12-10 23:37:18 +00:00
return
endif
" We start by looking for something to run relative to the current file's
" path. If nothing is found then we start over looking in the current
" working directory (the directory vim was opened in).
let l:current_path = fnamemodify(l:full_path, ':p:h')
2023-12-10 23:37:18 +00:00
if !RunProgramInDirectory(l:current_path, l:file_exe_name)
let l:cwd = getcwd()
if !RunProgramInDirectory(l:cwd, l:file_exe_name)
call PrintError("No exe or run script found in current file path '" . l:current_path . "' or working directory '". l:cwd ."'")
2023-05-10 18:56:43 +00:00
endif
endif
2023-12-10 23:37:18 +00:00
endfu
2023-12-10 23:37:18 +00:00
fu! RunProgramInDirectory(starting_path, file_exe_name) abort
let l:search_path = a:starting_path
let l:ext = tolower(expand('%:e'))
let l:also_search_for_cpp_run_script = 0 " Covers the case of having a run-cpp file in a jai project.
2023-12-10 23:37:18 +00:00
if l:ext == "jai"
2023-12-10 23:37:18 +00:00
" Check if we're editing inside a modules file and if so then get a
" path that takes us outside of it. We'll use that path for finding an
" exe or run script.
let l:pos = match(l:search_path, "modules")
if l:pos != -1
" e.g. if the current path is
" /z/jai/examples/wasm/modules/Blah/blah.jai then this is /z/jai/examples/wasm/
let l:module_root_path = l:search_path[:l:pos-1]
" We don't want to proceed if the path is in the jai compiler's modules folder.
let l:jai_path = tolower(g:campo_jai_path)
if l:jai_path[-1:] != '/'
let l:jai_path .= '/'
endif
"echo 'modules root path: ' . l:module_root_path . ' | jai path: ' . l:jai_path
if tolower(l:module_root_path) == l:jai_path
"echo 'inside jai modules. Aborting run'
return 0
endif
2023-12-10 23:37:18 +00:00
let l:search_path = l:module_root_path
endif
elseif l:ext == "cpp" || l:ext == "c" || l:ext == "h" || l:ext == "inc"
let l:also_search_for_cpp_run_script = 1
2022-11-29 04:37:35 +00:00
endif
2023-12-10 23:37:18 +00:00
let l:search_path = fnamemodify(l:search_path, ':p') " Normalize the path just in case.
" Search the current path for a run script, an exe with the current
" filename, a bin/filename exe, a run_tree/filename exe - if nothing is
" found then repeat one directory back when the current folder doesn't
" contain a .git/ or it's not a root directory, e.g. /z/.
"
" If nothing is found after exhausting the search then we start over and
" find the first exe with any name.
fu! TryRun(path) abort
if filereadable(a:path)
exec "AsyncRun! " . a:path
return 1
endif
return 0
endfu
2023-12-10 23:37:18 +00:00
let l:current_path = l:search_path
while 1
" run script
if l:also_search_for_cpp_run_script
if TryRun(l:current_path . 'run-cpp') | return 1 | endif
2023-12-10 23:37:18 +00:00
endif
if TryRun(l:current_path . 'run') | return 1 | endif
2023-12-10 23:37:18 +00:00
" run_tree/run script
if l:also_search_for_cpp_run_script
if TryRun(l:current_path . 'run_tree/run-cpp') | return 1 | endif
2023-12-10 23:37:18 +00:00
endif
if TryRun(l:current_path . 'run_tree/run') | return 1 | endif
" filename exe
if TryRun(l:current_path . a:file_exe_name) | return 1 | endif
2023-12-10 23:37:18 +00:00
" bin/filename exe
if TryRun(l:current_path. 'bin/' . a:file_exe_name) | return 1 | endif
2023-12-10 23:37:18 +00:00
" run_tree/filename exe
if TryRun(l:current_path. 'run_tree/' . a:file_exe_name) | return 1 | endif
2023-12-10 23:37:18 +00:00
" Only go back a directory if the current path doesn't have a .git folder or we're not in a root drive path.
if isdirectory(l:current_path . '.git') || IsRootDrive(l:current_path)
break
endif
let l:current_path = fnamemodify(l:current_path."../", ':p')
endwhile
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Start over but look for the first exe. The user will confirm if they
" want to run it.
"
" @improve maybe provide the first 4 or 5 exes found and let them input
" which one they want?
fu! GetFirstExePath(path)
let l:files = systemlist('ls '.a:path.'*.exe 2>/dev/null')
if len(l:files) > 0
return l:files[0]
endif
return ""
endfu
let l:current_path = l:search_path
let l:exe_to_confirm = ""
while 1
let l:exe = GetFirstExePath(l:current_path)
if l:exe != ""
let l:exe_to_confirm = l:exe
break
endif
" bin/filename exe
let l:exe = GetFirstExePath(l:current_path."bin/")
if l:exe != ""
let l:exe_to_confirm = l:exe
break
endif
" run_tree/filename exe
let l:exe = GetFirstExePath(l:current_path."run_tree/")
if l:exe != ""
let l:exe_to_confirm = l:exe
break
endif
" Only go back a directory if the current path doesn't have a .git folder or we're not in a root drive path.
if isdirectory(l:current_path . '.git') || IsRootDrive(l:current_path)
break
endif
let l:current_path = fnamemodify(l:current_path."../", ':p')
endwhile
if l:exe_to_confirm != ""
let l:confirm = confirm("Found exe ".l:exe_to_confirm." - run this?", "&Yes\n&No")
if l:confirm == 1
exec "AsyncRun! " . l:exe_to_confirm
return 1
endif
redraw!
endif
return 0
2023-06-13 02:51:42 +00:00
endfu
2017-08-21 18:26:22 +00:00
2017-07-10 15:08:49 +00:00
" Show results window the moment the async job starts
augroup asyncPluginCmds
autocmd!
2021-10-14 18:20:40 +00:00
autocmd User AsyncRunStart call asyncrun#quickfix_toggle(g:quickfix_pane_height, 1)
2017-07-10 15:08:49 +00:00
augroup END
" Toggle build results
2017-10-25 15:01:42 +00:00
nnoremap <leader>bc :call ToggleBuildResults()<cr>
noremap <F11> :call ToggleBuildResults()<cr>
2017-07-10 15:08:49 +00:00
" Hide build results and clear errors
noremap <F10> :call HideBuildResultsAndClearErrors()<cr>
" Execute build script and display results.
nnoremap <silent><leader>b :call Build(0)<cr>
nnoremap <silent><F8> :call Build(0)<cr>
2022-12-06 02:12:30 +00:00
" Execute optimized build script
nnoremap <leader>bb :call Build(1)<cr>
2017-07-10 15:08:49 +00:00
" Execute run script
2023-03-01 20:27:26 +00:00
nnoremap <silent><leader>br :call RunProgram()<cr>
nnoremap <silent><F9> :call RunProgram()<cr>
2017-09-22 21:16:30 +00:00
2017-07-10 15:08:49 +00:00
nnoremap <leader>bs :AsyncStop<cr>
"Go to next build error
nnoremap <F7> :cn<CR>
nnoremap <C-n> :cn<CR>
2015-03-21 19:13:17 +00:00
2017-07-10 15:08:49 +00:00
"Go to previous build error
nnoremap <F6> :cp<CR>
nnoremap <C-p> :cp<CR>
2023-01-27 20:20:51 +00:00
"##################################################################################
" TEXT SEARCH
"##################################################################################
2019-03-28 00:15:55 +00:00
" Search using ripgrep (first install with Rust: cargo install ripgrep).
2023-06-13 02:51:42 +00:00
fu! Search(path, search_args, case_insensitive=0)
let l:helper = "Search '" . a:path . "' (" . (len(a:search_args) > 0 ? a:search_args . " | " : '') . (a:case_insensitive ? "INSENSITIVE" : "SENSITIVE") . "): "
2020-07-25 23:39:09 +00:00
let l:term = input(l:helper)
if empty(l:term)
return
endif
" @note --pretty (i.e. colors) is not enabled in vim-ripgrep because the
" quickfix window doesn't seem to parse the ansi color codes.
2022-06-11 21:16:29 +00:00
let l:rg_args = "--column --line-number --no-heading --fixed-strings --no-ignore --hidden --follow --trim -g \"!tags\" -g \"!.git/\" -g \"!AppData/\" " . a:search_args
2020-07-25 23:39:09 +00:00
if a:case_insensitive
2020-07-25 23:39:09 +00:00
let l:rg_args .= " --ignore-case"
endif
" Some characters need to be escaped.
let l:escaped_term = substitute(l:term, '[#%]', '\\\\\\&', 'g')
let l:format = 'Rg ' . l:rg_args . ' ' . a:path . ' -e %s'
let l:cmd = printf(l:format, shellescape(l:escaped_term))
exec l:cmd
call ConvertQuickfixPathsToUnixSlashes()
2023-06-13 02:51:42 +00:00
endfu
2023-06-13 02:51:42 +00:00
fu! SearchExt(path, search_args, case_insensitive=0)
call inputsave()
let l:ext = input('Enter extension to search on (leave blank for files with no ext): ')
call inputrestore()
redraw!
if empty(l:ext)
let l:ext = "!*.*"
else
let l:ext = "*.".l:ext
endif
let l:args = a:search_args." -g \"".l:ext."\""
call Search(a:path, l:args, a:case_insensitive)
2023-06-13 02:51:42 +00:00
endfu
2023-01-27 20:20:51 +00:00
"/////////////////////////////////////////////////
" SEARCH IN CURRENT WORKING DIRECTORY
2023-01-27 20:20:51 +00:00
"/////////////////////////////////////////////////
" Case insensitive:
nnoremap <leader>s :call Search( '.', g:campo_custom_search_args, 1)<cr>
nnoremap <leader>sd :call SearchExt('.', g:campo_custom_search_args, 1)<cr>
" Case sensitive:
nnoremap <leader>ss :call Search( '.', g:campo_custom_search_args, 0)<cr>
nnoremap <leader>ssd :call SearchExt('.', g:campo_custom_search_args, 0)<cr>
2023-01-27 20:20:51 +00:00
"/////////////////////////////////////////////////
" SEARCH IN DIRECTORY CONTAINING THE ACTIVE FILE
"/////////////////////////////////////////////////
" Case insensitive:
nnoremap <leader>sf :call Search( expand('%:p:h'), g:campo_custom_search_args, 1)<cr>
nnoremap <leader>sdf :call SearchExt(expand('%:p:h'), g:campo_custom_search_args, 1)<cr>
" Case sensitive:
nnoremap <leader>ssf :call Search( expand('%:p:h'), g:campo_custom_search_args, 0)<cr>
nnoremap <leader>ssdf :call SearchExt(expand('%:p:h'), g:campo_custom_search_args, 0)<cr>
2023-01-27 20:20:51 +00:00
"/////////////////////////////////////////////////
" SEARCH IN JAI FOLDERS
"/////////////////////////////////////////////////
" Case insensitive:
"
" ROOT
nnoremap <leader>sg :call Search( g:campo_jai_path, g:campo_custom_search_args, 1)<cr>
nnoremap <leader>sdg :call SearchExt(g:campo_jai_path, g:campo_custom_search_args, 1)<cr>
" MODULES
nnoremap <leader>sm :call Search( g:campo_jai_path.'/modules', g:campo_custom_search_args, 1)<cr>
nnoremap <leader>sdm :call SearchExt(g:campo_jai_path.'/modules', g:campo_custom_search_args, 1)<cr>
" HOW TO
nnoremap <leader>sh :call Search( g:campo_jai_path.'/how_to', g:campo_custom_search_args, 1)<cr>
nnoremap <leader>sdh :call SearchExt(g:campo_jai_path.'/how_to', g:campo_custom_search_args, 1)<cr>
" EXAMPLES
nnoremap <leader>se :call Search( g:campo_jai_path.'/examples', g:campo_custom_search_args, 1)<cr>
nnoremap <leader>sde :call SearchExt(g:campo_jai_path.'/examples', g:campo_custom_search_args, 1)<cr>
" Case sensitive:
"
" ROOT
nnoremap <leader>ssg :call Search( g:campo_jai_path, g:campo_custom_search_args, 0)<cr>
nnoremap <leader>ssdg :call SearchExt(g:campo_jai_path, g:campo_custom_search_args, 0)<cr>
" MODULES
nnoremap <leader>ssm :call Search( g:campo_jai_path.'/modules', g:campo_custom_search_args, 0)<cr>
nnoremap <leader>ssdm :call SearchExt(g:campo_jai_path.'/modules', g:campo_custom_search_args, 0)<cr>
" HOW TO
nnoremap <leader>ssh :call Search( g:campo_jai_path.'/how_to', g:campo_custom_search_args, 0)<cr>
nnoremap <leader>ssdh :call SearchExt(g:campo_jai_path.'/how_to', g:campo_custom_search_args, 0)<cr>
" EXAMPLES
nnoremap <leader>sse :call Search( g:campo_jai_path.'/examples', g:campo_custom_search_args, 0)<cr>
nnoremap <leader>ssde :call SearchExt(g:campo_jai_path.'/examples', g:campo_custom_search_args, 0)<cr>
2019-09-09 19:31:47 +00:00
" Navigation for the vim-ripgrep search results.
" Hit o on a result line to open the file at that line.
" Hit p on a result line to open the file at that line and return to the results pane.
nnoremap <expr> o (&buftype is# "quickfix" ? "<CR>\|:lopen<CR>" : "o")
nnoremap <expr> p (&buftype is# "quickfix" ? "<CR>\|:copen<CR>" : "p")
2023-01-27 20:20:51 +00:00
"##################################################################################
" TEXT SEARCH & REPLACE
"##################################################################################
2019-09-09 19:31:47 +00:00
" @warning I've stopped using this because it sometimes locks up vim and I
" have to force exit the process then clean up the swap files.
2023-12-06 23:12:18 +00:00
"
" @improve Figure out what's causing vim to freeze and fix it. Seems to happen
" when it quickly changes and saves a handful of buffers.
" Replace text in a git repo's committed files.
" The range identifier allows us to run this once when multiple lines are selected in a file.
2023-06-13 02:51:42 +00:00
fu! GlobalReplaceIt(confirm_replacement) range
2020-07-25 23:39:09 +00:00
if exists(':Ggrep')
call inputsave()
if a:confirm_replacement
let l:term = input('Enter search term (w/ confirmation): ')
else
let l:term = input('Enter search term (no confirmation): ')
endif
call inputrestore()
2020-07-25 23:39:09 +00:00
if empty(l:term)
return
endif
call inputsave()
let l:replacement = input('Enter replacement: ')
call inputrestore()
if empty(l:replacement)
return
endif
if a:confirm_replacement
let l:confirm = 'c'
2020-07-25 23:39:09 +00:00
else
let l:confirm = 'e'
endif
" Capture opened buffers and windows so that we can restore everything after running cdo.
exec 'mksession! _replace_session.vim'
" Search all committed files in the current directory
" Ignoring binary files (-I)
" Only including a matching filename once (--name-only)
exec 'Ggrep --threads 4 -I --name-only' l:term '.'
" cdo will run the command foreach file in the grep results. It opens
" the file in a window so we immediately write the changes and then
" wipe the buffer (closing the window). If we don't close it then vim
" will run out of space when modifying a lot of files. This will
" likely close buffers that were open before running the replace, but
" we will restore them below from the saved session file.
" Note that we don't run autocommands for optimization purposes!
:noautocmd exec 'cdo' '%s/'.l:term.'/'.l:replacement.'/g'.l:confirm '| write | bwipe'
" Restore the session.
if filereadable('_replace_session.vim')
silent! exec 'source _replace_session.vim | !rm _replace_session.vim &>/dev/null'
2020-07-25 23:39:09 +00:00
endif
call CreateCtags()
2017-07-10 15:08:49 +00:00
else
call PrintError("Unable to search since you're not in a git repo!")
2017-07-10 15:08:49 +00:00
endif
2023-06-13 02:51:42 +00:00
endfu
2023-12-06 23:12:18 +00:00
noremap <leader>r :call GlobalReplaceIt(0)<cr>
noremap <leader>rr :call GlobalReplaceIt(1)<cr>
2017-07-10 15:08:49 +00:00
2023-01-27 20:20:51 +00:00
"##################################################################################
2017-07-10 15:08:49 +00:00
" RENAME CURRENT FILE
2023-01-27 20:20:51 +00:00
"##################################################################################
2023-06-13 02:51:42 +00:00
fu! RenameFile()
2017-07-10 15:08:49 +00:00
let l:old_name = expand('%')
let l:new_name = input('New file name: ', expand('%'), 'file')
if l:new_name != '' && l:new_name != l:old_name
2022-12-06 02:12:30 +00:00
let l:confirm = confirm("Rename ".l:old_name." to ".l:new_name."?", "&Yes\n&No")
if l:confirm == 1
exec 'saveas' l:new_name
exec 'silent! !rm' l:old_name
endif
2017-07-10 15:08:49 +00:00
endif
2023-12-10 23:37:18 +00:00
redraw!
2023-06-13 02:51:42 +00:00
endfu
noremap <leader>n :call RenameFile()<cr>
2015-03-21 19:13:17 +00:00
2023-01-27 20:20:51 +00:00
"##################################################################################
" CENTER THE BUFFER
"##################################################################################
2023-06-13 02:51:42 +00:00
fu! CenterPane()
" Centers the current pane as the middle 2 of 4 imaginary columns should
" be called in a window with a single pane.
2023-01-27 20:20:51 +00:00
" Taken from https://dev.to/vinneycavallo/easily-center-content-in-vim
lefta vnew
wincmd w
exec 'vertical resize' string(&columns * 0.65)
2023-06-13 02:51:42 +00:00
endfu
2023-01-27 20:20:51 +00:00
2023-06-13 02:51:42 +00:00
fu! RemoveCenterPane()
2023-01-27 20:20:51 +00:00
wincmd w
close
2023-06-13 02:51:42 +00:00
endfu
nnoremap <leader>cc :call CenterPane()<cr>
nnoremap <leader>cd :call RemoveCenterPane()<cr>
"##################################################################################
" SIMPLE VIEW
"##################################################################################
" Applies a clean view of the current buffer by turning off line
" numbers, trailing spaces, tabs and git diff markers in the gutter.
2023-06-13 02:51:42 +00:00
fu! ToggleSimpleView()
" I wasn't able to get this to apply to every copy of the same buffer,
" e.g. you have a split view showing the same file; only the active one
" will be affected, but they will share the same state! I tried many
" different approaches (bufdo, looping over windows and buffers) and
" nothing worked. I looked at the gitgutter plugin since it supports
" toggling a buffer and it correctly modifies all instances, but the code
" is complex and there's so much just to do a simple thing. Fuck it. It's
" not worth the hassle and the inevitable hair pulling that I always
" experience when trying to do non-trivial things with this garbage
" scripting language.
if ! exists("b:simple_view_enabled")
let b:simple_view_enabled = 0
endif
if b:simple_view_enabled == 0
let b:simple_view_enabled = 1
setlocal nonumber
setlocal nolist
exec 'GitGutterBufferDisable'
else
let b:simple_view_enabled = 0
setlocal number
setlocal list
exec 'GitGutterBufferEnable'
endif
2023-06-13 02:51:42 +00:00
endfu
nnoremap <leader>c :call ToggleSimpleView()<cr>
2023-01-27 20:20:51 +00:00
"-----------------------------------------------------------------------------------------------------------------------
2015-03-21 19:13:17 +00:00
let g:campo_vimrc_initialized = 1