Dotfiles, utilities, and other apparatus.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1270 lines
42 KiB

" vim:foldmethod=marker:foldlevel=0:foldenable
"
" this is my vimrc; part of https://code.p1k3.com/gitea/brennen/bpb-kit
"
" to use:
"
" mkdir -p ~/.vim
" cp [this file] ~/vim/vimrc
" mkdir -p ~/.vim/bundle
" git clone https://github.com/VundleVim/Vundle.vim ~/.vim/bundle/Vundle.vim
" vim +PluginInstall
"
" if there are funny-looking folded sections below and you're confused,
" hitting zR will unfold them all, while zr will unfold the one your
" cursor is on. this note is as much for my benefit as yours.
"
" an increasing percentage of this config is very specific to my preferences.
" there are keybindings for filters i use regularly, things that automatically
" happen when i open certain files, and shortcuts bound to the F-keys. quite
" a lot of the behavior here also assumes it'll have scripts found in ~/bin
" - see home/bin in this repo - and may rely on tools i haven't yet published.
"
" items particularly likely to be personal preference are marked with the
" string CUSTOMIZE and a note.
"
" -- bpb | https://p1k3.com | https://code.p1k3.com
set nocompatible
" Temporarily disable modelines (like the one at the top of this file), per:
" https://github.com/numirias/security/blob/master/doc/2019-06-04_ace-vim-neovim.md
" TODO: Patch and/or look at securemodelines plugin
set nomodeline
" use comma for the leader key - this is used as a prefix for
" a bunch of bindings, mostly in the keybindings section. it's up
" here for things that might require it before plugins are invoked,
" such as vimwiki mappings.
let mapleader = ","
" let mapleader = " "
" vundle setup & vundle-managed plugins {{{
filetype off
set rtp+=~/.vim/bundle/Vundle.vim/
call vundle#begin()
" let Vundle manage Vundle - required:
Plugin 'VundleVim/Vundle.vim'
" https://langserver.org/
" TODO: language server stuff
" Plugin 'prabirshrestha/async.vim'
" Plugin 'prabirshrestha/vim-lsp'
" if executable('pyls')
" " pip install python-language-server
" au User lsp_setup call lsp#register_server({
" \ 'name': 'pyls',
" \ 'cmd': {server_info->['pyls']},
" \ 'whitelist': ['python'],
" \ })
" endif
" really nice file tree - see keybindings section below for some tweaks:
Plugin 'preservim/nerdtree'
Plugin 'Xuyuanp/nerdtree-git-plugin'
" double click to open nodes:
" (for directory nodes with a single click, set to 2)
" (for all nodes with a single click, set to 3)
let NERDTreeMouseMode = 1
" fancy start screen with recent files & bookmarks
" CUSTOMIZE: you'll probably want different bookmarks
let g:startify_bookmarks = [
\ {'v': '~/.vimrc'},
\ {'l': '~/notes/vimwiki/log/index.wiki' },
\ '~/.zshrc',
\ '~/notes/',
\ '~/p1k3',
\ ]
Plugin 'mhinz/vim-startify'
let g:startify_custom_header_quotes = [
\ ['the purpose of the system is what it does'],
\ ['incremental progress is the only kind'],
\ ['reality has a surprising amount of detail'],
\ ]
let g:startify_change_to_dir = 0
let g:startify_change_to_vcs_root = 1
" Vim Outliner of Markups - see :help voom - really nice
Plugin 'vim-voom/VOoM'
" align text vertically on a string:
Plugin 'Align'
" wrap common version control commands:
Plugin 'vcscommand.vim'
Plugin 'tpope/vim-fugitive'
" visual marking of changes in working tree:
Plugin 'airblade/vim-gitgutter'
" match lots of things - this repo seems defunct; not sure who is
" currently maintaining this one:
" Plugin 'edsono/vim-matchit'
" commands for surrounding chars:
Plugin 'tpope/vim-repeat' " used by vim-surround, commentary
Plugin 'tpope/vim-surround'
" readline-style keybindings in command line / insert:
Plugin 'tpope/vim-rsi'
" gc[motion] to comment, gcc to comment current line
Plugin 'https://tpope.io/vim/commentary.git'
" a yank/paste ring - hit ctrl-p after pasting:
" let g:yankring_history_dir = '$HOME/.vim'
" Plugin 'vim-scripts/YankRing.vim'
" a bunch of colorschemes + a gui menu listing them:
Plugin 'flazz/vim-colorschemes'
Plugin 'altercation/vim-colors-solarized'
Plugin 'chriskempson/vim-tomorrow-theme.git'
Plugin 'desert-warm-256'
Plugin 'ColorSchemeMenuMaker'
Plugin 'ScrollColors'
" some useful icons in various plugins, if you were willing to deal
" with the font hassles (i am not)
" Plugin 'ryanoasis/vim-devicons'
" beyondgrep.com:
Plugin 'mileszs/ack.vim'
" navigate & control tmux windows + vim buffers - see also .tmux.conf
" Plugin 'christoomey/vim-tmux-navigator'
" Plugin 'benmills/vimux'
" find files / buffers / etc.:
" Plugin 'L9' " - required by FuzzyFinder
" Plugin 'FuzzyFinder'
" this seems really powerful & i've never quite gotten my head around it
" Plugin 'Shougo/unite.vim'
" fzf - fuzzy finding {{{
" https://github.com/junegunn/fzf
let g:fzf_launcher = '/usr/bin/xterm'
Plugin 'junegunn/fzf'
" Some utility wrappers around fzf stuff:
Plugin 'junegunn/fzf.vim'
" Example git grep wrapper from fzf.vim readme
command! -bang -nargs=* GGrep
\ call fzf#vim#grep(
\ 'git grep --line-number -- '.shellescape(<q-args>), 0,
\ fzf#vim#with_preview({'dir': systemlist('git rev-parse --show-toplevel')[0]}), <bang>0)
" Use fzf for multi-definition tags:
Plugin 'zackhsi/fzf-tags'
nmap <C-]> <Plug>(fzf_tags)
" }}}
" distraction-free mode:
Plugin 'junegunn/goyo.vim'
" preview contents of named registers - this is brilliant
Plugin 'junegunn/vim-peekaboo'
" ASCII art
Plugin 'DrawIt'
" most recently used files - my fork allows for a top-level menu
let g:MRU_Menu_Path = '&Recent\ Files'
let g:MRU_Max_Menu_Entries = 30
let g:MRU_Max_Submenu_Entries = 30
Plugin 'https://code.p1k3.com/gitea/brennen/mru.git'
" database stuffs
" Plugin 'dbext.vim'
" do stuff with tables - used by some vim-markdown features
Plugin 'godlygeek/tabular'
" filetypes / modes / language support {{{
let g:go_version_warning = 0
Plugin 'fatih/vim-go' " golang
Plugin 'rust-lang/rust.vim'
Plugin 'chikamichi/mediawiki.vim'
Plugin 'plasticboy/vim-markdown'
" Plugin 'nginx.vim'
" Plugin 'jceb/vim-orgmode'
" }}}
" apt-get install shellcheck for shell linting
" apt-get install perl-critic for perl
" syntax checking {{{
Plugin 'dense-analysis/ale'
" an alternative is syntastic - used this for ages, works pretty well but
" doesn't have the async thing going on:
" Plugin 'vim-syntastic/syntastic'
" let g:syntastic_check_on_open = 1
" let g:syntastic_php_checkers = ['php']
" let g:syntastic_enable_perl_checker = 1
" let g:syntastic_perl_lib_path = ['./lib', './lib/auto']
" let g:syntastic_perl_checkers = ['perl', 'podchecker']
" " shut up, pylint:
" let g:syntastic_python_checkers = []
" amenu Syntax.Toggle\ Syntastic :SyntasticToggleMode<CR>
" }}}
" add option to show a diff when there's a swapfile on disk:
" Plugin 'chrisbra/Recover.vim'
" CUSTOMIZE: fancy status line; laststatus can be set so it always shows up
Plugin 'vim-airline/vim-airline'
Plugin 'vim-airline/vim-airline-themes'
" set laststatus=2
" let g:airline#extensions#tabline#enabled = 1
let g:airline_theme = 'luna'
if has("gui_running")
let g:airline_theme = 'base16_ashes'
endif
" integrate ale with airline:
let g:airline#extensions#ale#enabled = 1
" Dr. Chip's debugging for syntax highlighting:
Plugin 'gerw/vim-HiLinkTrace'
" GUI font size - use <Leader><Leader>+ or - to adjust
Plugin 'drmikehenry/vim-fontsize'
" Ctrl-A increment / Ctrl-X decrement various date formats with this one:
" try, for example: Tue, 26 Jan 2016 23:59:59 +0000
Plugin 'tpope/vim-speeddating'
" open files at the cursor position where you left off (awesome):
Plugin 'farmergreg/vim-lastplace'
" handle .editorconfig files:
" https://editorconfig.org/
" https://github.com/editorconfig/editorconfig-vim
Plugin 'editorconfig/editorconfig-vim'
" a calendar - used in conjunction with vimwiki diaries
let g:calendar_keys = {
\ 'goto_next_month': '<C-Right>',
\ 'goto_prev_month': '<C-Left>',
\ 'goto_next_year': '<C-Up>',
\ 'goto_prev_year': '<C-Down>'
\ }
Plugin 'mattn/calendar-vim'
Plugin 'mbbill/undotree'
" Vdebug should work with xdebug - see help for XDEBUG_CONFIG stuffs,
" although they don't seem to have been translated for Xdebug 3.x. I've
" namespaced all the keymaps here so that when this is enabled it doesn't
" stomp all over my usual bindings.
" let g:vdebug_keymap = {
" \ "run" : "<Leader><F5>",
" \ "run_to_cursor" : "<Leader><F9>",
" \ "step_over" : "<Leader><F2>",
" \ "step_into" : "<Leader><F3>",
" \ "step_out" : "<Leader><F4>",
" \ "close" : "<Leader><F6>",
" \ "detach" : "<Leader><F7>",
" \ "set_breakpoint" : "<Leader><F10>",
" \ "get_context" : "<Leader><F11>",
" \ "eval_under_cursor" : "<Leader><F12>",
" \ "eval_visual" : "<Leader>e",
" \}
" let g:vdebug_options = { 'port' : 9003 }
" Plugin 'https://github.com/vim-vdebug/vdebug'
" minimap of code
" TODO: does this actually work?
" Plugin 'severin-lemaignan/vim-minimap'
" CUSTOMIZE: vimwikis - for notes, daily logs, etc. {{{
" main personal wiki
let wiki = {}
let wiki.name = 'notes'
let wiki.path = '~/notes/vimwiki/'
let wiki.path_html = '~/workspace/notes-html/'
let wiki.auto_tags = 1
let wiki.auto_diary_index = 1
let wiki.automatic_nested_syntaxes = 1
" i don't use this, but it seems to have regressed recently and I'll
" need to test it again eventually
" let wiki.links_space_char = '-'
" a markdown wiki for testing purposes
let markdownwiki = {}
let markdownwiki.name = 'markdownwiki'
let markdownwiki.path = '~/notes/markdownwiki'
let markdownwiki.path_html = '~/notes/markdownwiki/html/'
let markdownwiki.auto_tags = 1
let markdownwiki.auto_diary_index = 1
let markdownwiki.automatic_nested_syntaxes = 1
let markdownwiki.syntax = 'markdown'
let markdownwiki.ext = '.md'
" testing for https://github.com/vimwiki/vimwiki/issues/1256
" let g:vimwiki_markdown_link_ext = 1
" To test customwiki2html:
" let markdownwiki.custom_wiki2html = $HOME . '/.vim/bundle/vimwiki/autoload/vimwiki/customwiki2html.sh'
" do syntax highlight in preformatted blocks - it's worth noting that if
" wiki.automatic_nested_syntaxes is on (it defaults to 1) this may not
" be necessary. it's off here for the moment because it was causing
" some weird collisions between embedded syntaxen - notably if the
" markdown one was loaded before the mediawiki one, indented lists in
" mediawiki blocks were getting false hits for markdown's bold. this
" may be a bug in vim-markdown, which is a little flaky to begin with.
"
" let wiki.nested_syntaxes = {
" \ 'python': 'python',
" \ 'ruby': 'ruby',
" \ 'perl': 'perl',
" \ 'sh': 'sh',
" \ 'dockerfile': 'dockerfile',
" \ 'go': 'go',
" \ 'yaml': 'yaml',
" \ 'mediawiki': 'mediawiki',
" \ 'markdown': 'markdown',
" \ }
" completion and dictionary stuff for Ctrl-P,Ctrl-N - uses an
" index built by an embedded script on my vimwiki index for
" keyword completion:
set dictionary+=~/notes/tag-index
set complete=.,w,b,u,t,i,k
" You can adjust this to set the header level for a contents section
let g:vimwiki_toc_header_level = 1
" Don't change working directory to page of current wiki, since
" that'd mess with how I use my ~/notes (this is the default,
" just wanted it documented here):
let g:vimwiki_auto_chdir = 0
" there can be many of these
let g:vimwiki_list = [wiki, markdownwiki]
" span is here so :VimwikiColorize will work - it's weird that it's not in
" the default list, since that's supported.
let g:vimwiki_valid_html_tags = 'b,i,s,u,sub,sup,kbd,br,hr,span'
" i think this _replaces_ the existing comment markers, in theory - not
" clear if it works:
" let g:vimwiki_commentstring = '<!--%s-->'
" don't make temporary wikis based on file extensions in the list - this
" is necessary to avoid .md files getting a filetype of vimwiki instead of
" markdown:
let g:vimwiki_global_ext = 0
" let g:vimwiki_folding = ''
let g:vimwiki_folding = 'expr'
" let g:vimwiki_folding = 'syntax'
" let g:vimwiki_folding = 'list'
" links concealing, etc.
" let g:vimwiki_conceallevel = 0
" don't obscure URLs in links
let g:vimwiki_url_maxsave = 0
" make links clickable and such
let g:vimwiki_use_mouse = 1
" use colors in header highlighting
let g:vimwiki_hl_headers = 1
" highlight checked list items
" highlight VimwikiCheckBoxDone ctermbg=darkgrey ctermfg=white guibg=darkgrey guifg=white
let g:vimwiki_hl_cb_checked = 2
" set to 0 to have newlines in list items get rendered to <br>
let g:vimwiki_list_ignore_newline = 1
" disable table mappings:
let g:vimwiki_key_mappings =
\ {
\ 'table_mappings': 0,
\ 'table_format': 0
\ }
" hit ,S to debug current syntax highlighting groups
" https://vim.fandom.com/wiki/Identify_the_syntax_highlighting_group_used_at_the_cursor
"
map <Leader>S :echo "hi<" . synIDattr(synID(line("."),col("."),1),"name") . '> trans<'
\ . synIDattr(synID(line("."),col("."),0),"name") . "> lo<"
\ . synIDattr(synIDtrans(synID(line("."),col("."),1)),"name") . ">"<CR>
" map <Leader> b to go back - the plugin will check for this
" mapping and not associate it with regular backspace (which
" i kept hitting by accident)
" NOTE: <C-BS> doesn't work here; I tried
nmap <Leader>b <Plug>VimwikiGoBackLink
" au FileType vimwiki :set tw=80
" override default vimwiki link handling - could be extended to add
" custom link types, etc. Right now all it does is use vim itself
" to handle files, crudely.
function! VimwikiLinkHandler(link)
if a:link =~# '^file:'
try
" chop off the leading file: - see :h expr-[:] for syntax:
execute ':split ' . a:link[5:]
return 1
catch
echo "Failed opening file in vim."
endtry
elseif a:link =~# '^workspace:'
try
" chop off the leading file: - see :h expr-[:] for syntax:
execute ':split ' . '~/workspace/' . a:link[10:]
return 1
catch
echo "Failed opening workspace location in vim."
endtry
" elseif a:link =~# '^https\?:'
" try
" execute ':terminal lynx ' . a:link
" return 1
" catch
" echo "Failed executing Lynx."
" endtry
endif
return 0
endfunction
Plugin 'vimwiki/vimwiki'
augroup bpb_vimwiki
" TODO: i _think_ a lot of this could be pushed out into some file under
" ~/.vim/ftplugin/vimwiki/*.vim - should it be? maybe!
" clear any existing commands in this group:
autocmd!
" selectively activate foldcolumn:
au FileType vimwiki setlocal foldcolumn=3
" vimwiki diary links for the ,td datestamp alias:
au FileType vimwiki map <buffer> <Leader>td :.-1r !fragment-vimwiki-diarylink<Esc>
" regenerate vimwiki diary on file load:
" (with auto_diary_index, the index is updated every time you use
" ,wi to open - this covers the rest of the cases, i guess)
au BufReadPost,BufNewFile *vimwiki/diary/diary.wiki :VimwikiDiaryGenerateLinks
" run new diary entry template:
au BufNewFile *vimwiki/diary/*.wiki :0r !fragment-vimwiki-diary '%'
" run new log entry template:
au BufNewFile *vimwiki/log/*.wiki :0r !fragment-vimwiki-log
" set up linewrapping so that long lines more or less work
au BufRead,BufNewFile *.wiki call <SID>LonglineMode()
" XXX: this is a vulnerability - should only happen in _my specific_
" vimwiki:
au BufReadPost *vimwiki/*.wiki call <SID>WikiBufReadPostOverrides()
au BufWritePost *vimwiki/*.wiki call <SID>WikiBufWritePostOverrides()
augroup END
" }}}
" snippets
" Plugin 'SirVer/ultisnips'
" Plugin 'honza/vim-snippets'
" " trigger configuration
" " don't use <tab> if you use https://github.com/Valloric/YouCompleteMe
" let g:UltiSnipsExpandTrigger="<tab>"
" let g:UltiSnipsJumpForwardTrigger="<c-b>"
" let g:UltiSnipsJumpBackwardTrigger="<c-z>"
" " if you want :UltiSnipsEdit to split your window.
" let g:UltiSnipsEditSplit="vertical"
call vundle#end()
filetype plugin on
filetype indent on
" }}}
" misc UI {{{
" set the window title (usually to filename plus some metadata)
set title
" pretty colors
set t_Co=256
syntax on
" pretty characters
set encoding=utf-8
" do not beep or flash at me
" vb is needed to stop beep
" t_vb sets visual bell action, we're nulling it out here
" note also that this may need to be repeated in .gvimrc
set visualbell
set t_vb=
" enable mouse for (a)ll, (n)ormal, (v)isual, (i)nsert, or (c)ommand line
" mode - seems to work in most terminals
set mouse=a
" https://unix.stackexchange.com/questions/50733/cant-use-mouse-properly-when-running-vim-in-tmux
set ttymouse=xterm2
" render a useful popup menu for right-click instead of extending
" selection (good for spellchecking, etc.):
set mousemodel=popup_setpos
" let me delete stuff like crazy in insert mode
set backspace=indent,eol,start
" see :help virtualedit - you probably don't want this
" set virtualedit=onemore
" display commands as-typed + current position in file
set showcmd
set ruler
" height of command line area - having it greater than one avoids
" some hit-enter prompts
set cmdheight=2
" display a visual menu for tab-completion of files
set wildmenu
" add git status to statusline; otherwise emulate standard line with ruler
" -- mostly supplanted for the moment by vim-airline
set statusline=%<%{fugitive#statusline()}\ %f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
" keep lots of command-line history - 10000 is currently the max value:
set history=10000
" search:
set incsearch
set ignorecase
set smartcase
set wrapscan
" CUSTOMIZE: neovim defaults hlsearch to on, which annoys me personally
set nohlsearch
" for gvim. no toolbar, otherwise these are the defaults
" set guioptions=aegimrLt
" use + register (x window clipboard) as unnamed register (copy to system
" clipboard on yy, for example):
if has('nvim')
set clipboard+=unnamedplus
else
set clipboard=unnamedplus,autoselect
endif
" include '-' in words. counts for both movement commands and autocomplete.
" to test, try moving across and autocompleting for some-words-bunched-up
" this is an experiment - mainly i want to use inline dashes in identifiers
" in markdown documents, and so forth
set iskeyword+=-
" }}}
" file saving/loading/swap/backups {{{
" read (unchanged) buffers when they're modified on filesystem.
" this saves me a lot of time and agony because i switch git branches
" constantly, but it might not be what you want.
set autoread
" CUSTOMIZE: disable swapfiles (you may not want this (but you probably do)):
set noswapfile
" }}}
" CUSTOMIZE: whitespace {{{
" display tabs and trailing spaces:
set listchars=tab:⇾\ ,trail
set list
" display tab characters as 8 spaces, indent 2 spaces,
" always use spaces instead of tabs:
set tabstop=8
set shiftwidth=2
set softtabstop=2
set expandtab
set autoindent
" set smarttab
" set smartindent
" for c code, no tab expansion, turn off softtabstop
au FileType c setlocal noexpandtab
au FileType c setlocal shiftwidth=8
au FileType c setlocal softtabstop=0
" turn off tab expansion for Makefiles and calendar files:
au FileType make setlocal noexpandtab
au FileType calendar setlocal noexpandtab
" wrap entire words in markdown files
" http://stackoverflow.com/questions/19624105/how-can-i-make-vim-break-lines-only-on-whitespace
au FileType markdown setlocal wrap linebreak breakat&vim
" }}}
" misc. autocommands {{{
" to get a list of current autocommands:
" http://vim.wikia.com/wiki/Capture_ex_command_output
" :redir @a
" :autocmd
" :redir END
" "ap
" assume *.t files are PHP - i was doing this to override the assumption
" that they're perl
" au BufRead,BufNewFile *.t set filetype=php
" retain view/folds on a specific file:
" au BufWinLeave notes.txt mkview
" au BufWinEnter notes.txt silent loadview
au BufReadPost,BufNewFile *.md set filetype=markdown
" CUSTOMIZE: this invokes a function for doing some custom filetype
" overrides, like treating blog entries as markdown. it is mostly
" for places where i couldn't figure out an autocmd, or needed something
" more complex than the pattern matching offered by au
"
" this used to fail for files named `index`, because of a fugitive bug:
" https://github.com/tpope/vim-fugitive/issues/834
au BufReadPost,BufNewFile * call <SID>FiletypeOverrides()
au BufNewFile * call <SID>NewFileOverrides()
" TODO: make a colorscheme logger here - it'd be nice to know all the
" schemes i ever use for later reference:
" au ColorScheme * call <SID>ColorSchemeOverrides()
" }}}
" keybindings {{{
" CUSTOMIZE: my keybinding habits may be idiosyncratic
" aside from function keys, i try not to stomp on the main keybinding
" 'namespace' too much, with the exception of replacing K with something
" useful.
" a handful of functions are called here, all with a prefix of <SID> -
" they can be found in the "functions" section below
" many things here have menu entries under 'Cheatsheet', as a cheatsheet for
" all the stuff i've defined. these can also be accessed with :emenu in
" terminal vim.
" wait longer than the default (1000ms) for keycodes and mapped keys:
set timeoutlen=3000
" i use the F-keys a _lot_. this is what makes NERDTree usable.
" F2 toggles the nerdtree file browser pane
map <F2> :NERDTreeToggle<CR>
imap <F2> <Esc>:NERDTreeToggle<CR>
650amenu Cheatsheet.NERDTree<Tab>F2 <F2>
" F3 finds the current file in nerdtree
map <F3> :NERDTreeFind<CR>
amenu Cheatsheet.NERDTreeFind<Tab>F3 <F3>
" F4 toggles line numbers
map <F4> :set invnumber<CR>
imap <F4> <Esc>:set invnumber<CR>
" this version cycles through a couple versions of relative and absolute
" line numbers:
" map <F4> :call <SID>CycleLineNumbers()<CR>
" imap <F4> <Esc>:call <SID>CycleLineNumbers()<CR>
amenu Cheatsheet.Toggle\ Line\ Numbers<Tab>F4 <F4>
" F5 saves everything
map <F5> :wall<CR>
imap <F5> <Esc><F5>
amenu Cheatsheet.Write\ All<Tab>F5 <F5>
" F6 brings up a recently-used file list using MRU
" map <F6> :MRU<CR>
" Bring up an fzf history window
map <F6> :History<CR>
imap <F6> <Esc><F6>
amenu Cheatsheet.Most\ Recently\ Used<Tab>F6 <F6>
" F7 opens ~/.vim/vimrc (in existing tab if open, new otherwise)
" (7 kind of looks like a rotated v)
" see http://learnvimscriptthehardway.stevelosh.com/chapters/07.html for
" rationale - the idea is to make changing vim configuration trivial
if has('nvim')
map <F7> :call <SID>TabDrop("~/.vim/vimrc")<CR>
else
map <F7> :call <SID>TabDrop($MYVIMRC)<CR>
endif
imap <F7> <Esc><F7>
amenu Cheatsheet.Open\ vimrc<Tab>F7 <F7>
" F8 inserts an ISO-8601 datestamp (mnemonic: eight rhymes with date)
" (used to open the options window; use :options for that)
" map <F8> :r !date -I<CR>kJ
map <F8> <Leader>w<Leader>w
imap <F8> <Esc><F8>
amenu Cheatsheet.Current\ Diary<Tab>F8 <F8>
" ,td / ,tD insert dates (mnemonic: toDay)
" this is overridden in vimwiki files to link to diary pages
map <Leader>td :r !date -I<CR>kJ
map <Leader>tD :r !date -Is<CR>kJ
" F9 toggles search highlighting and some other noise
map <F9> :call <SID>Crosshairs()<CR>
imap <F9> <Esc><F9>
amenu Cheatsheet.Crosshairs<Tab>F9 <F9>
" F10 starts a git commit for recent changes
map <F10> :Gcommit -av<CR>
amenu Cheatsheet.Gcommit<Tab>F10 <F10>
" F11 i'm leaving unbound because of fullscreen shortcuts in various
" terminals and window managers
" in normal or insert mode, <F12> copies all in buffer
" in visual/select modes, it just yanks the selected bit
nmap <F12> :%y+<CR>
imap <F12> <Esc><F12>
vmap <F12> y+
amenu Cheatsheet.Copy\ All<Tab>F12 <F12>
" add a menu separator
menu Cheatsheet.-misc- :
" split lines under the cursor (modeled on, maybe, emacs?)
map K i<CR><Esc>g;
amenu Cheatsheet.Split\ Line<Tab>K K
" an FZF fragment menu
nmap <Leader>F :call <SID>FragmentMenu()<CR>
amenu Cheatsheet.Fragment\ Menu<Tab>,F <Leader>F
" CUSTOMIZE: randomize certain text decorations - silly
nmap <Leader>D :call <SID>RunFilter("filter-decorate")<CR>
amenu Cheatsheet.Randomize\ Decorations<Tab>,D <Leader>D
nmap <Leader>d i<p class="centerpiece"> <Esc>:r !fragment-bullet<CR>kJA </p><Esc>
amenu Cheatsheet.Insert\ Decoration<Tab>,d <Leader>d
" CUSTOMIZE: find files with fzf fuzzy-finder (assumes FZF is installed)
" https://github.com/junegunn/fzf
" was :FZF, but :Files has a preview pane - which is awesome
nmap <Leader>f :Files<CR>
amenu Cheatsheet.FZF\ Find<Tab>,f <Leader>f
" i didn't wind up using this much, and it potentially messes
" with vimwiki mappings:
" nmap <Leader>w :call <SID>CommandOutputInNewWindow("dict <cword>"))<CR>
" visual select inner word
nmap <Leader>v viW
" pull up the last hundred git commits in a scratch buffer
" nmap <Leader>l :vnew<CR>:set buftype=nofile<CR>:set bufhidden=hide<CR>:setlocal noswapfile<CR>:r !git log -100<CR>:set ft=git<CR>gg<C-w>r<C-w>l
nmap <Leader>gl :Glog<CR>:copen<CR>
amenu Cheatsheet.Git\ Log<Tab>,gl <Leader>gl
nmap <leader>m :make<CR>
amenu Cheatsheet.Make<Tab>,m <Leader>m
" requires git-do, from bpb-kit, to execute make in root of current git repo
nmap <leader>M :!git do make<CR>
amenu Cheatsheet.Make\ (git\ root)<Tab>,M <Leader>M
" jump to next, previous errors
nmap <Leader>n :cnext<CR>
amenu Cheatsheet.Next\ Error<Tab>,n <Leader>n
nmap <Leader>p :cprev<CR>
amenu Cheatsheet.Prev\ Error<Tab>,p <Leader>p
" generate a password-like string with apg
" nmap <Leader>pw :r !apg -a 0 -m 20 -n 1<CR>
" -a 0: use fully random string instead of pronounceable
nmap <Leader>pw :r !apg -a 1 -m 20 -n 1<CR>
amenu Cheatsheet.APG<Tab>,pw <Leader>pw
" reformat a paragraph
nmap <Leader>q gqip
amenu Cheatsheet.Reformat\ Para<Tab>,q <Leader>q
" Q mapping (it usually enters ex mode) based on this mail from bram:
" https://groups.google.com/forum/#!search/vim/vim_use/iXH_Zxj8iBA/H7YDtbACBAAJ
" note this is done by default in neovim
map Q gq
" CUSTOMIZE: these are simple filter scripts to preprocess some
" shell commands in HTML or Markdown files - see scripts for details
nmap <Leader>r :call <SID>RunFilter("filter-exec-raw")<CR>:call <SID>RunFilter("filter-exec")<CR>:call <SID>RunFilter("filter-exec-stdin")<CR>
amenu Cheatsheet.Run\ Filters<Tab>,r <Leader>r
" delete trailing whitespace, file-wide
nmap <Leader>s :%s/\s\+$//e<CR>
amenu Cheatsheet.Zap\ Trailing\ Space<Tab>,s <Leader>s
" tab navigation somewhat like firefox
" http://vim.wikia.com/wiki/Alternative_tab_navigation
nmap <C-S-Tab> :tabprevious<CR>
nmap <C-Tab> :tabnext<CR>
map <C-S-Tab> :tabprevious<CR>
map <C-Tab> :tabnext<CR>
imap <C-S-Tab> <Esc>:tabprevious<CR>i
imap <C-Tab> <Esc>:tabnext<CR>i
" new tab:
nmap <Leader>tn :tabnew<CR>
amenu Cheatsheet.New\ Tab<Tab>,tn <Leader>tn
" run timeslice script for current file:
nmap <Leader>ts :call TimesliceForFile()<CR>
amenu Cheatsheet.Timeslice<Tab>,ts :call TimesliceForFile()<CR>
" trigger unite.vim
map <Leader>u :Unite<CR>
" split window navigation (ctrl-j/k, alt-arrows)
map <C-J> <C-W>j<C-W>_
map <M-Down> <C-W>j
map <C-K> <C-W>k<C-W>_
map <M-Up> <C-W>k
map <M-Right> <C-W>l
map <M-Left> <C-W>h
" search the current vimwiki - fails if not in a vimwiki, which i should
" really do something about
map <Leader>w/ :GGrep<Space>
" create a new 'log' entry in vimwiki
map <Leader>l :tab drop `fragment-vimwiki-log-path`<CR>kA<Space>
" view log for current file
" TODO: consider extending this to all files in some way...
map <Leader>wl :call <SID>NotesLogsForFile()<CR>
map <Leader>wf :call <SID>NotesFullLogsForFile()<CR>
" view backlinks for current file
map <Leader>wL :call <SID>NotesLinksForFile()<CR>
" view summary for current wiki page
map <Leader>wS :call <SID>NotesMeta()<CR>
map <Leader>. :call <SID>VimwikiMakeLink()<CR>
map <Leader>J :call <SID>VimwikiJumpToPage()<CR>
" }}}
" functions {{{
" run the file through a custom filter, leaving the cursor at its original
" location in the file (or close) - there might be a better way to do this,
" but i don't know what it is
function! s:RunFilter(filter)
let l:currentline = line('.')
execute ":%!" . a:filter
execute ":" . l:currentline
endfunction
" do some normal-mode commands and return the cursor to its previous location
function! s:ExecNormalAndReturnCursor(commands)
let l:currentline = line('.')
" see http://learnvimscriptthehardway.stevelosh.com/chapters/30.html
execute "normal! " . a:commands
execute ":" . l:currentline
endfunction
" set custom filetypes for some things - invoked by an autocommand above
function! s:FiletypeOverrides()
" make sure NERDTree windows don't get messed up
if bufname("%") =~ "NERD_tree"
return
endif
" using expand('%:p') instead of bufname("%") for full path, per:
" http://vim.wikia.com/wiki/Get_the_name_of_the_current_file
" \v is "very magic" - see :help \v
" the initial slash in the regex seems to be necessary to make \v work
" =~? is ignore case
" =~# is match case
" =~ uses the value of ignorecase
if expand('%:p') =~# "\\vp1k3\/archives.*\/([0-9]|[a-z])+$"
" echom 'p1k3 match - setting filetype to markdown'
set filetype=markdown
endif
endfunction
" take some custom actions after reading a wiki page:
function! s:WikiBufReadPostOverrides()
let realpath = system('readlink -fn ' . shellescape(expand('%')))
" regenerate wiki pages with `%% exec-raw auto` on load
" (except for log scratch files - that could get real messy)
if search("%% exec-raw auto", "nw")
if match(realpath, '_logscratch') > -1
" no-op for the moment, might be other things to do here?
" i'm not honestly sure if this is reachable because i'm not sure
" that the postread here actually gets triggered at all.
echom "logscratch - not honoring exec-raw auto"
else
call <SID>RunFilter("filter-exec-raw")
endif
endif
" turn off wrapping for wiki pages with `%% nowrap` on load
if search("%% nowrap", "nw")
set nowrap
endif
endfunction
" take some custom actions after writing a wiki page:
function! s:WikiBufWritePostOverrides()
" update link database
let realpath = system('readlink -fn ' . shellescape(expand('%')))
if match(realpath, '_logscratch') > -1
return
endif
silent execute ":!notes-collect-metadata " . realpath
endfunction
" if editing a new p1k3 entry, auto-populate with a datestamp
function! s:NewFileOverrides()
if expand('%:p') =~# "\\vp1k3\/archives.*\/([0-9]|[a-z])+$"
silent 0r !fragment-entry
endif
endfunction
" spit out a date for today, using ~/bin/fragment-today, on the current line
" TODO: ideally this would context sensitive: if called inside a vimwiki
" diary file or a p1k3 blog entry, it would use that date instead.
function! s:Datestamp()
" . is current line, -1 is 1 line above that, r would otherwise read
" the output onto the line below the cursor
.-1r !fragment-today
endfunction
" select a fragment script using fzf and include its output in the
" current buffer
function! s:FragmentMenu()
call fzf#run({
\ 'options': ['--reverse', '--preview={}'],
\ 'sink': '.r !',
\ 'source': 'find ~/bin/ -maxdepth 1 -name "fragment-*" -printf "%f\n"',
\ 'down': '50%'
\ })
endfunction
" spit out a current timestamp
function! s:Timestamp()
.-1r !rightnow
endfunction
function! s:ColorSchemeOverrides()
endfunction
" make things more amenable to editing long soft-wrapped lines
" mostly an attempt to make vimwiki a bit more ergonomic, this
" version adapted from:
" http://www.baryudin.com/blog/vim-line-wrapping-and-word-boundary.html
function! s:LonglineMode()
setlocal wrap linebreak
set virtualedit=
setlocal display+=lastline
noremap <buffer> <silent> <Up> gk
noremap <buffer> <silent> k gk
noremap <buffer> <silent> <Down> gj
noremap <buffer> <silent> j gj
noremap <buffer> <silent> <Home> g<Home>
noremap <buffer> <silent> <End> g<End>
inoremap <buffer> <silent> <Up> <C-o>gk
inoremap <buffer> <silent> <Down> <C-o>gj
inoremap <buffer> <silent> <Home> <C-o>g<Home>
inoremap <buffer> <silent> <End> <C-o>g<End>
endfunction
" via maya:
" https://occult.institute/@maya/111325120027749937
function! TwoWide()
call setpos(".", [0, 1, 1, 0])
wincmd v
call setpos(".", [0, 1, 1, 0])
execute "normal L"
execute "normal zt"
set scrollopt "ver,jump"
windo set scrollbind
endfunction
" add some display sugar that helps highlight cursor, searches, and
" textwidth. good for fiddling with alignment, reflowing text, etc.
function! s:Crosshairs()
set invhlsearch
set invcursorcolumn
set invcursorline
" toggle a colorcolumn - will get weird if it's set outside this function
if &colorcolumn == "+1"
set colorcolumn=0
else
" i think this is relative to textwidth
set colorcolumn=+1
endif
endfunction
" cycle between no, absolute, and relative line numbers
function! s:CycleLineNumbers()
if (&number)
set nonumber
return
endif
if (&relativenumber)
set number norelativenumber
else
set number relativenumber
endif
endfunction
" this is pretty much horked from:
" http://vim.wikia.com/wiki/Display_output_of_shell_commands_in_new_window
function! s:CommandOutputInNewWindow(cmdline)
echo a:cmdline
let expanded_cmdline = a:cmdline
for part in split(a:cmdline, ' ')
if part[0] =~ '\v[%#<]'
let expanded_part = fnameescape(expand(part))
let expanded_cmdline = substitute(expanded_cmdline, part, expanded_part, '')
endif
endfor
botright new
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
" uncomment calls here for debug info:
" call setline(1, 'Command: ' . a:cmdline)
" call setline(2, 'Expanded: ' . expanded_cmdline)
" display underline with = to length of previous line (pretty clever):
" call setline(3, substitute(getline(2), '.', '=', 'g'))
execute '$read !' . expanded_cmdline
0delete " delete blank first line - get rid of this if you need debug msgs
setlocal nomodifiable
" enable folding with a column:
setlocal foldenable
setlocal foldcolumn=3
1
endfunction
" tab drop (edit in existing or new tab) a file's real path, in case it is a
" symlink - useful for, frex, symlinked .vimrc. does wildcard expansion on
" the path. as usual, there are probably better ways to do all of this.
function! s:TabDrop(path)
let realpath = system('readlink -fn ' . shellescape(expand(a:path)))
echom realpath
execute 'tab drop ' . realpath
endfunction
" try to run timeslice for current path
function! g:TimesliceForFile()
let realpath = system('readlink -fn ' . shellescape(expand('%')))
call <SID>CommandOutputInNewWindow('timeslice -f ' . realpath)
endfunction
" run notes-links for current path and populate location list,
" like using grep:
function! s:NotesLinksForFile()
let realpath = system('readlink -fn ' . shellescape(expand('%')))
" override default grep so we can populate the location list:
setlocal grepprg=notes\ links\ --format\ location\ --file\ $*
silent execute "silent lgrep! " . shellescape(realpath)
" https://vim.fandom.com/wiki/Avoiding_the_%22Hit_ENTER_to_continue%22_prompts
" https://vi.stackexchange.com/questions/2809/silent-makes-my-vim-go-blank
" in short, this is necessary because otherwise the silent grep above can
" leave the display in a bonk state:
redraw!
" an alternative to the above:
" call <SID>CommandOutputInNewWindow('notes links --file ' . realpath)
" restore global setting for grepprg:
setlocal grepprg<
lopen
endfunction
" this is fucking ridiculous
" https://vi.stackexchange.com/questions/21825/how-to-insert-text-from-a-variable-at-current-cursor-position
function! s:AppendAtCursor(string)
execute "normal! a\<C-r>\<C-r>=a:string\<CR>\<Space>\<Esc>"
endfunc
function! s:AppendAtCursorAsVimwikiLink(string)
let bracketed = '[[/' . a:string . ']]'
call <SID>AppendAtCursor(bracketed)
endfunc
" Make a link from an fzf-found known tag name:
function! s:VimwikiMakeLink()
call fzf#run({
\ 'options': [
\ "--reverse",
\ "--multi",
\ "--preview=notes-tag-summary --color {}",
\ ],
\ 'sink': function("<SID>AppendAtCursorAsVimwikiLink"),
\ 'source': "notes-tag-index",
\ 'up': '50%'
\ })
endfunction
" Open a page in the default Vimwiki:
function! s:VimwikiGotoPage(page)
if ! exists(':VimwikiGoto')
" :VimwikiGoto isn't a global command, so is only available if there's
" a wiki open. Jump to the index of the default one:
execute ':VimwikiIndex'
endif
execute ':VimwikiGoto ' . a:page
endfunction
" Jump to an fzf-found page or known tag name:
function! s:VimwikiJumpToPage()
call fzf#run({
\ 'options': ["--reverse", "--multi", "--preview=notes-tag-summary --color {}"],
\ 'sink': function("<SID>VimwikiGotoPage"),
\ 'source': "notes-tag-index",
\ })
endfunction
" Catenate log entries for current wiki page
function! s:NotesFullLogsForFile()
let realpath = system('readlink -fn ' . shellescape(expand('%')))
let hash = sha256(realpath)
echom 'Finding logs for ' . realpath
botright new
" XXX: This should use the current wiki, not a harcoded path:
execute 'edit ~/notes/vimwiki/_logscratch/' . hash . '.wiki'
1,$d " delete everything in file
execute '$read !' . 'notes links --with-date --format full --file ' . shellescape(realpath)
0delete " delete blank first line - get rid of this if you need debug msgs
1
endfunction
" Location list with log entries for current file:
function! s:NotesLogsForFile()
let realpath = system('readlink -fn ' . shellescape(expand('%')))
" override default grep so we can populate the location list:
setlocal grepprg=notes\ links\ --with-date\ --format\ location\ --file\ $*
silent execute "silent lgrep! " . shellescape(realpath)
redraw!
" restore global setting for grepprg:
setlocal grepprg<
lopen
endfunction
" Jump to an fzf-found page or known tag name:
function! s:NotesMeta()
let realpath = system('readlink -fn ' . shellescape(expand('%')))
let hash = sha256(realpath)
echom 'Finding logs for ' . realpath
botright new
" XXX: This should use the current wiki, not a harcoded path:
execute 'edit ~/notes/vimwiki/_logscratch/meta-' . hash . '.wiki'
1,$d " delete everything in file
execute '$read !' . 'notes tag-summary --file ' . shellescape(realpath)
0delete " delete blank first line - get rid of this if you need debug msgs
1
endfunction
" get a list of key bindings, along with where they were defined, and
" open it in a tab. this variant of redir and map seen at:
" https://stackoverflow.com/questions/7642746/is-there-any-way-to-view-the-currently-mapped-keys-in-vim#7642762
function! g:ListBindings()
redir! > ~/vim_keys.txt
silent verbose map
redir END
call <SID>TabDrop("~/vim_keys.txt")
endfunction
amenu Cheatsheet.List\ Keys<Tab>:call\ ListBindings() :call ListBindings()<CR>
" }}}
" colors {{{
" CUSTOMIZE: you are gonna want some other colors i bet - i have used
" these all at one time or another and liked them for various reasons
" colorscheme brookstream
" colorscheme mustang
" colorscheme dark-ruby
" colorscheme Tomorrow-Night-Bright
" colorscheme pyte
" colorscheme wargrey
" colorscheme hybrid
" colorscheme icansee
" colorscheme candycode
" colorscheme peppers
" colorscheme inkpot
" colorscheme ingretu
colorscheme iceberg
" colorscheme earthburn
" }}}
" folding {{{
" turn off folding by default - i constantly open some file and have to
" expand folds to see what's going on; this is easy to get back with zi
set nofoldenable
" use {{{ and }}} to denote a folded section (these can be adjusted by
" setting foldmarker, but i'm sticking with the vim defaults):
set foldmethod=marker
" for custom foldline colors:
" highlight Folded guibg=grey guifg=blue
highlight FoldColumn ctermbg=darkgrey ctermfg=white guibg=darkgrey guifg=white
" forked from: http://dhruvasagar.com/2013/03/28/vim-better-foldtext
function! BPB_NeatFoldText()
let line = ' ' . substitute(getline(v:foldstart), '^\s*"\?\s*\|\s*"\?\s*{{' . '{\d*\s*', '', 'g') . ' '
let lines_count = v:foldend - v:foldstart + 1
let lines_count_text = '| ' . printf("%10s", lines_count . ' lines') . ' |'
let foldchar = matchstr(&fillchars, 'fold:\zs.')
let foldtextstart = strpart('+' . repeat(foldchar, v:foldlevel*2) . line, 0, (winwidth(0)*2)/3)
let foldtextend = lines_count_text . repeat(foldchar, 8)
let foldtextlength = strlen(substitute(foldtextstart . foldtextend, '.', 'x', 'g')) + &foldcolumn
return foldtextstart . repeat(foldchar, winwidth(0)-foldtextlength) . foldtextend
endfunction
set foldtext=BPB_NeatFoldText()
" }}}