" .vimrc (vim auto-parse file) -- commands that vim runs at startup " v2.0 "# version 4.0 " avoid warning for wrong version " *** Mappings *** " == Fixes == " don't make it easy to quit without checking for changes nmap ZQ " == Random == map Q gq imap imap nmap g/ :nohlsearch xmap g/ :nohlsearchgv " not useful "# nmap g :redrawstatus " Make the Do key bring up the ex command prompt: nmap : xmap : imap : nmap vmap " == Command shortcut keys == " (note: doesn't work in gnome-terminal!) " through to (and through to ) " don't work in vim. This was tried but doesn't work: "# cmap O1;2S " -- list all buffers -- " imap O1;5Q :ls nmap O1;5Q :ls xmap O1;5Q :lsgv imap [1;5Q :ls nmap [1;5Q :ls xmap [1;5Q :lsgv " -- previous buffer -- nmap [b :bprevious xmap [b :bprevious imap :bprevious nmap :bprevious xmap :bprevious " splits the window if $TERM == 'linux' imap [25~ :sbprevious nmap [25~ :sbprevious xmap [25~ :sbprevious elseif $TERM == 'putty' imap [23~ :sbprevious nmap [23~ :sbprevious xmap [23~ :sbprevious else imap O1;2P :sbprevious nmap O1;2P :sbprevious xmap O1;2P :sbprevious imap [1;2P :sbprevious nmap [1;2P :sbprevious xmap [1;2P :sbprevious endif " -- next buffer -- nmap ]b :bnext xmap ]b :bnext imap :bnext nmap :bnext xmap :bnext " splits the window if $TERM == 'linux' imap [26~ :sbnext nmap [26~ :sbnext xmap [26~ :sbnext elseif $TERM == 'putty' imap [24~ :sbnext nmap [24~ :sbnext xmap [24~ :sbnext else imap O1;2Q :sbnext nmap O1;2Q :sbnext xmap O1;2Q :sbnext imap [1;2Q :sbnext nmap [1;2Q :sbnext xmap [1;2Q :sbnext endif " -- this buffer -- " splits the window nmap O1;6P :split xmap O1;6P :splitgv imap O1;6P :split nmap [1;6P :split xmap [1;6P :splitgv imap [1;6P :split nmap :split xmap :splitgv imap :split " -- window switching -- imap k nmap k xmap k imap j nmap j xmap j " -- window resizing -- " if $TERM == 'linux' imap [28~ - nmap [28~ - xmap [28~ - elseif $TERM == 'putty' imap [25~ - nmap [25~ - xmap [25~ - else imap O1;2R - nmap O1;2R - xmap O1;2R - imap [1;2R - nmap [1;2R - xmap [1;2R - endif " if $TERM == 'linux' imap [29~ + nmap [29~ + xmap [29~ + elseif $TERM == 'putty' imap [26~ + nmap [26~ + xmap [26~ + else imap O1;2S + nmap O1;2S + xmap O1;2S + imap [1;2S + nmap [1;2S + xmap [1;2S + endif " -- window closing -- " -- close all other windows imap o nmap o xmap ogv imap O1;5R o nmap O1;5R o xmap O1;5R ogv imap [1;5R o nmap [1;5R o xmap [1;5R ogv " (PuTTY has no key code) " -- close this window imap c nmap c xmap c imap O1;5S c nmap O1;5S c xmap O1;5S c imap [1;5S c nmap [1;5S c xmap [1;5S c " (PuTTY has no key code) " imap O1;6S :bunload nmap O1;6S :bunload xmap O1;6S :bunloadgv imap [1;6S :bunload nmap [1;6S :bunload xmap [1;6S :bunloadgv " -- file operations -- nmap ZE :edit nmap ZW :write nmap ZN :wnext " -- QuickFix commands (mostly error-jumps) -- nmap [e :cprevious xmap [e :cpreviousgv nmap :cprevious xmap :cpreviousgv imap :cprevious nmap [E :cpfile nmap :cpfile nmap ]e :cnext xmap ]e :cnextgv nmap :cnext xmap :cnextgv imap :cnext nmap ]E :cnfile nmap :cnfile " normal-mode shortcuts for various build-related commands nmap ZM :make nmap :make nmap :clist cmap :clist imap :clist nmap :setlocal makeprg= imap :setlocal makeprg= nmap :colder imap :colder " -- tab switching -- nmap gT xmap gT imap gT nmap gT xmap gT nmap gt xmap gt imap gt nmap 1 1gt nmap 2 2gt nmap 3 3gt nmap 4 4gt nmap 5 5gt nmap 6 6gt nmap 7 7gt nmap 8 8gt nmap 9 9gt nmap 0 10gt nmap :tabfirst xmap :tabfirst imap :tabfirst nmap :tablast xmap :tablast imap :tablast if exists('*function') " can't use because that can't handle a count " have to use the to avoid passing the count to :call nmap g :call JumpBetweenTabs(v:count) xmap g :call JumpBetweenTabs(v:count) let g:previous_tab = 1 " When no count is supplied, switch to the previous tab where this function " was called. When a count is supplied, act like "gt". " (Note that "gt" effectively forgets the current tab, so afterwards, this " function without a count will go back to the previous-previous tab.) function! JumpBetweenTabs(count) if a:count > 0 let g:previous_tab = tabpagenr() exe ":tabn" a:count else " have to figure things out first, because :exe must happen last let l:new_tab = g:previous_tab let g:previous_tab = tabpagenr() exe ":tabn" l:new_tab endif endfunction endif " -- toggles -- imap :silent set wrap! nmap :silent set wrap! xmap :silent set wrap!gv if $TERM == 'linux' imap [34~ :setlocal spell! spell? nmap [34~ :setlocal spell! spell? xmap [34~ :setlocal spell! spell?gv else imap :setlocal spell! spell? nmap :setlocal spell! spell? xmap :setlocal spell! spell?gv endif imap :set ignorecase! ignorecase? nmap :set ignorecase! ignorecase? xmap :set ignorecase! ignorecase?gv imap :set hlsearch! hlsearch? nmap :set hlsearch! hlsearch? xmap :set hlsearch! hlsearch?gv imap :set number! nmap :set number! imap :if &diff \| :diffoff \| :else \| :diffthis \| :endif nmap :if &diff \| :diffoff \| :else \| :diffthis \| :endif imap :set list! nmap :set list! xmap :set list! " -- other -- " == customisations == if exists('*function') " Jump to the start of the line if not already there, otherwise jump to the " first non-blank character. imap :call LineBeg() function! LineBeg() if getcurpos()[4] == 1 normal ^ else normal 0 endif endfunction else imap 0 endif imap $ imap " Replacement for original binding of , namely deindent (orthogonal to ) inoremap " Alt-d deletes next word: imap " Ctrl-Left (Alt-b) & Ctrl-Right (Alt-f) go to previous/next word respectively: inoremap inoremap cnoremap cnoremap map B map W " Operator-pending and Visual mode, but not Select mode nmap omap xmap " == Editing == " -- Special deletion/insertion -- " Capitalise word (cursor at start) -- see also g@ and 'operatorfunc' below nmap w gUllguww " Delete current line and send it to the "blackhole" register instead of a numbered register nmap d "_dd " Delete all lines of the visual selection and send it to the "blackhole" " register instead of a numbered register xmap d "_d " -- Parenthesise -- nmap pw ciw(") nmap ps cis(") nmap pb cab(") nmap pB caB(") xmap p c(") " == Strings == " Insert basename of current buffer's file " (Note that this makes a delay before the regular Ctrl-X options show up) "# imap % =expand("%:t") inoremap % expand("%:t") " Wait for a register name, then insert the contents converted to lowercase " (c_CTRL-R_CTRL-L is taken) noremap! tolower(getreg(nr2char(getchar()))) " Wait for a register name, then insert the contents converted to uppercase noremap! toupper(getreg(nr2char(getchar()))) " Timestamp with attribution " (E.g. "2021-09-14 15:25 by Alastair Irvine ") nmap t :r!date "+\%Y-\%m-\%d \%H:\%M by ${REPLYTO-`getent passwd $LOGNAME awk -F : '{ pos = index($5, ","); if (pos > 0) print substr($5, 1, pos-1); else print $5 }'`}":normal -J " List items (Uses :put to get around auto-indent for subsequent line items. " Doesn't work with i_^O .) nmap il :put =' + 'A nmap iL :put =' - 'A nmap in :put =' 1. 'A nmap iN :put =' 1. 'A " -- At EOF -- nmap it G:put =\"\n\n# vim: set noexpandtab :\n# Local Variables:\n# indent-tabs-mode: t\n# end:\" nmap i2 G:put =\"\n\n# vim: set tabstop=2 shiftwidth=2 :\n# Local Variables:\n# tab-width: 2\n# end:\" nmap i4 G:put =\"\n\n# vim: set tabstop=4 shiftwidth=4 :\n# Local Variables:\n# tab-width: 4\n# end:\" nmap ia G:put =\"\n\n# vim: set filetype=apache :\n# Local Variables:\n# mode: apache\n# end:\" " == other == " Yank function name and parens into 'a nmap f lb"ayf(;%"Ayl " Append a comma plus the text from the next movement onto 'b nnoremap , :let @b = @b . ','"By vnoremap , :let @b = @b . ','"By " Yank file name into '0 " (@" represents the unnamed register and '0) nmap y :let @" = bufname() " -- Useful searching commands -- map / imap / if $TERM == 'linux' nmap [31~ ? imap [31~ ? else nmap ? imap ? endif nmap n imap n nmap N imap N " -- Search for Martians -- " search for non-printing characters [Ctrl-/ (or ^_, i.e. Ctrl-shift--)] nmap :call search('[^][{};:''",.<>/?a-zA-Z!@#$%^&*()_+\|0-9\\\-=`~ ]') " search for whitespace at EOL [Ctrl-space (or ^@, i.e. Ctrl-shift-2)] nmap :call search('[[:space:]]$') xmap :call search('[[:space:]]$')gv nmap mn :call search('[[:space:]]$') xmap mn :call search('[[:space:]]$')gv nmap mN :%s/[[:space:]]\+$// " This will apply to the selection xmap mN :s/[[:space:]]\+$// nmap mt :call search('\t') xmap mt :call search('\t')gv " == UI commands == " open a tab with a new buffer nmap g :tabedit " open a new window vertically with a new buffer nmap g :vnew " open a tab with the current buffer nmap g :tab split " C-S-F2: list tabs & buffers nmap O1;6Q :tabs xmap O1;6Q :tabsgv imap O1;6Q :tabs nmap [1;6Q :tabs xmap [1;6Q :tabsgv imap [1;6Q :tabs nmap :tabs xmap :tabsgv imap :tabs nmap a :ls! xmap a ::ls!gv nmap b :echo BufInfo() xmap b :echo BufInfo()\|:silent sleep 2.5gv nmap g :digraphs xmap g ::digraphsgv nmap r :registers xmap r ::registersgv nnoremap R :echo "Type the name of a register: " :exe ":registers" nr2char(getchar()) " -- information -- nmap va :set autoindent? xmap va :set autoindent?\|:silent sleep 2gv nmap vb :set tabstop? xmap vb :set tabstop?\|:silent sleep 2gv nmap vc :set smartcase? xmap vc :set smartcase?\|:silent sleep 2gv nmap ve :set expandtab? xmap ve :set expandtab?\|:silent sleep 2gv nmap vf :set fileformat? xmap vf :set fileformat?\|:silent sleep 2gv nmap vh :set hlsearch? xmap vh :set hlsearch?\|:silent sleep 2gv nmap vi :set ignorecase? xmap vi :set ignorecase?\|:silent sleep 2gv nmap vl :set endofline? xmap vl :set endofline?\|:silent sleep 2gv nmap vm :set makeprg? xmap vm :set makeprg?\|:silent sleep 2gv nmap vn :set fileencoding? xmap vn :set fileencoding?\|:silent sleep 2gv nmap vo :set foldmethod? xmap vo :set foldmethod?\|:silent sleep 2gv nmap vp :set paste? xmap vp :set paste?\|:silent sleep 2gv nmap vq :set textwidth? xmap vq :set textwidth?\|:silent sleep 2gv nmap vr :set runtimepath? xmap vr :set runtimepath?\|:silent sleep 2gv nmap vs :set shiftwidth? xmap vs :set shiftwidth?\|:silent sleep 2gv nmap vt :set filetype? xmap vt :set filetype?\|:silent sleep 2gv nmap vv :set viminfofile? xmap vv :set viminfofile?\|:silent sleep 2gv nmap vw :set wrap? xmap vw :set wrap?\|:silent sleep 2gv nmap vA :abbr xmap vA ::abbr nmap vM :map buffer> xmap vM ::map buffer> " -- Misc UI stuff -- " Clear the popup and the message pane " (or set g:netrw_use_errorwindow=1) nmap :call popup_clear() \| :echo " == ex command prompt == cmap cmap " == terminal window running a shell == if has('terminal') map g :tab terminal map gS :terminal " -- :term mappings -- "# tmap NgT "# tmap Ngt tmap [5;3~ NgT tmap [6;3~ Ngt "# tmap :tabfirst "# tmap :tablast tmap [1;3H :tabfirst tmap [1;3F :tablast " For some reason, C-Up/Down are sent as regular Up/Down by default tnoremap [1;5A tnoremap [1;5B endif " == Settings toggles, etc. == " doesn't exist due to 'pastetoggle' " and above don't exist when $TERM == 'linux' nmap :set textwidth= xmap :set textwidth= imap :set textwidth= nmap :set textwidth=0 xmap :set textwidth=0gv imap :set textwidth=0 imap :set expandtab! expandtab? nmap :set expandtab! expandtab? xmap :set expandtab! expandtab?gv imap :set autoindent! autoindent? nmap :set autoindent! autoindent? xmap :set autoindent! autoindent?gv imap :silent set readonly! nmap :silent set readonly! xmap :silent set readonly!gv if exists('*function') nmap :call Mousetoggle() xmap :call Mousetoggle()gv imap :call Mousetoggle() function! Mousetoggle() if &mouse == '' || &mouse == 'hr' let s:old_mouse = &mouse set mouse=a else let &mouse = s:old_mouse endif endfunction endif " -- Other options -- nmap zfm :setlocal foldmethod=marker nmap zfe :setlocal foldmethod=expr nmap zfs :setlocal foldmethod=syntax " See also .vim/after/ftplugin/xml.vim " -- Tweaks -- nmap zn :set nocursorline nmap zc :colorscheme mine nmap zs :set selection=exclusive " == File operations == nmap x :!chmod +x "%" nmap n :!mkdir "%:h" nmap h :pwd xmap h :pwd\|:silent sleep 2.5gv nmap c :!md5sum "%" " -- Source control -- " \sd opens a diff window nmap sa :!smooth add "%" nmap sc :!smooth commit nmap sC :!smooth commit . nmap sd n:set ft=diff \| .!smooth diff:set nomodified nmap sD n:set ft=diff \| .!smooth diff -s:set nomodified nmap ss :!smooth status "%" nmap sS n:set ft=git \| .!smooth status:set nomodified nmap sl n:set ft=git \| .!git log --oneline --graph:set nomodified nmap sL n:set ft=git \| .!git log --stat:set nomodified nmap s n:set ft=git \| .!git log --patch:set nomodified " *** Features *** if has('syntax') " -- settings -- set background=dark if exists(':filetype') filetype plugin indent on let g:filetype_i = "c" let g:filetype_inc = "php" endif " -- activation -- syntax enable " -- customisation -- "# let mysyntaxfile = "~/.vim/mysyntax.vim" " my customised syntax highlights " See .vim/colors/mine.vim colorscheme mine endif if has('spell') set spelllang=en_au endif " Provides :Man runtime ftplugin/man.vim " == diff == nmap [c xmap [c imap [c nmap ]c xmap ]c imap ]c " == spell == if $TERM == 'linux' imap [32~ [s nmap [32~ [s xmap [32~ [s imap [33~ ]s nmap [33~ ]s xmap [33~ ]s else imap [s nmap [s xmap [s imap ]s nmap ]s xmap ]s endif " == netrw ("Explore") == let g:netrw_sort_sequence='[\/]$,\,README,\.h$,\.c$,\.cpp$,*,\.o$,\.obj$,\.info$,\.sw.$,\.bak$,\~$' "# let g:netrw_use_errorwindow=1 nmap e :Sexplore nmap V :Vexplore nmap E :Texplore nmap g :if exists('w:netrw_rexdir') :Rexplore :else :Explore :endif nmap e :Explore ~ nmap ee :Explore nmap eE :exe ":Explore" getcwd() nmap e :Sexplore ~ nmap es :Sexplore nmap eS :exe ":Sexplore" getcwd() nmap e :Vexplore ~ nmap ev :Vexplore nmap eV :exe ":Vexplore" getcwd() nmap e :Texplore ~ nmap et :Texplore nmap eT :exe ":Texplore" getcwd() nmap e :Lexplore ~ nmap el :Lexplore nmap eL :exe ":Lexplore" getcwd() nmap e :Lexplore! ~ nmap er :Lexplore! nmap eR :exe ":Lexplore!" getcwd() nmap en :Nexplore nmap ep :Pexplore " == Packages == if has('packages') packadd! matchit else runtime! macros/matchit.vim " TO-DO: package equivlents for taglist, etc. endif " *** Functions *** if exists('*function') " :Rename runtime include/rename4.vim " :BDE runtime include/bde.vim " Eat one character matching the given regex from the input stream, e.g. at " the end of an abbr expansion. " E.g. `:iabbr if if ()=Eatchar('\s')` function! Eatchar(pat) let c = nr2char(getchar(0)) return (c =~ a:pat) ? '' : c endfunction " A block is a set of hunks applying to a given file function! DiffBlock(extra_flags) "# call search('^\*\*\* [^0-9]', 's' . a:extra_flags) " diff -c, svn diff, git diff respectively " (Can't do diff -u because that only uses --- / +++ which is ambiguous with " the others) if search('^\*\*\* [^0-9]\|^Index: \|^diff ', 's' . a:extra_flags) == 0 " This doesn't work let v:warningmsg = "No more diff blocks" endif endfunction function! BufInfo() let flags1 = getbufvar('%', '&modifiable') ? \ (getbufvar('%', '&readonly') ? '=' : ' ') : '-' let flags2 = getbufvar('%', '&mod') ? '+' : ' ' if exists('*bufwinid') let id = bufwinid('%') else let id = -1 endif let name = bufname('%') if name == '' let name = '[No Name]' endif return printf("%d (%d, %d [%d])\t%s \"%s\"", \ bufnr("%"), id, bufwinnr("%"), tabpagenr(), flags1 . flags2, name) endfunction endif " *** Commands *** if exists('*function') " Do a word-diff of two files command! -nargs=+ -complete=file Wdiff :call Wdiff("") function! Wdiff(args) new set ft=wdiff exe '.!wdiff ' . a:args set nomodified endfunction " Diffs a file in source control with its working copy command! -nargs=1 -complete=file Diff :call Diff("") function! Diff(args) new set ft=diff exe '.!smooth diff "' . a:args . '"' set nomodified endfunction " Convenient command to see the difference between the current buffer and the " file it was loaded from, thus the changes you made. " Only define it when not defined already. " Revert with: ":delcommand DiffOrig". " (From /usr/share/vim/vim82/defaults.vim) if !exists(":DiffOrig") command DiffOrig vert new | set bt=nofile | r ++edit # | 0d_ | diffthis \ | wincmd p | diffthis endif endif " *** Settings *** set formatprg= set nobackup " don't keep a backup file set viminfo='100,<900,s10,h set nowrap sidescroll=1 set scrolloff=0 set ruler hidden laststatus=2 showcmd "# set confirm " unknown in Vim 5.0 set foldclose= " Automatic foldclosing is irritating too " Default is shortmess=filnxtToOS set shortmess=filtoOrmw set selection=exclusive " unknown in Vim 5.0; used to work in ???; back in 6.x set nohlsearch set noincsearch set smartcase " Override the 'ignorecase' option if the search pattern contains upper case characters " Help buffers and hit-enter and more-prompt prompts only "# set mouse=a set mouse=hr set mousemodel=popup_setpos set mousetime=180 " Selection ( etc. starts type-to-replace selection mode) set selectmode=key set keymodel=startsel " Don't use "stopsel" because that breaks Visual mode " Disable default: autoselect,exclude:cons\|linux set clipboard= " -- windows -- set splitbelow " -- editing -- set bs=indent,eol,start " allow backspacing over everything in insert mode set autoindent set textwidth=0 set expandtab "# set tabstop=2 set shiftwidth=1 set shiftround " > and < round indent to multiple of 'shiftwidth' set showfulltag "# set smartindent set pastetoggle= let maplocalleader = '_' " For g@ if exists('*function') set operatorfunc=Capitalise " Delete whatever was typed and replace it with the sentence-case version function! Capitalise(context) " If in Visual mode, '[ and '] are set to '< and '> before this function " is called, however '] is one char behind when &selection == 'exclusive' " Delete the text so the unnamed register can be modified and re-inserted later if a:context == 'block' throw "Capitalise() doesn't work in Visual block mode" elseif a:context == 'line' normal! '[d'] else " '] is at the end of the movement not beyond it, so d'] doesn't work " properly (inconsistent with gu etc.); it will always be one character " short and not work at all for a single-character motion. Use Visual " mode to fake the inclusive motion. let l:visual_start_save = getpos("'<") let l:visual_end_save = getpos("'>") let l:sel_save = &selection let &selection = "inclusive" normal! `[v`]d call setpos("'<", l:visual_start_save) call setpos("'>", l:visual_end_save) let &selection = l:sel_save endif " @@ represents the unnamed register let @@ = substitute(tolower(@@), '\<\(.\)', '\=toupper(submatch(1))', 'g') normal! P endfunction endif " -- contextual -- set iskeyword=-,@,48-57,_,192-255 " remove "=" from the list of filename characters set isfname-== " -- file -- " See 'fo-table' set formatoptions-=o formatoptions+=n if v:version >= 801 set formatoptions+=p endif set modeline set fileformats=unix,dos,mac " -- other -- set titleold=Terminal " == Bram Moolenaar's preferences == " /usr/share/vim/vim82/defaults.vim (overridden by /etc/vim/vimrc or /etc/vimrc) set wildmenu " display completion matches in a status line " Do not recognize octal numbers for Ctrl-A and Ctrl-X, most users find it " confusing. set nrformats-=octal " CTRL-U in insert mode deletes a lot. Use CTRL-G u to first break undo, " so that you can undo CTRL-U after inserting a line break. " Revert with ":iunmap ". inoremap u " == Turn off defaults == " -- Bram's vimStartup group -- " (When editing a file, always jump to the last known cursor position.) augroup vimStartup autocmd! augroup END " -- RedHat defaults -- " See /etc/vimrc augroup redhat autocmd! augroup END " *** Buffer auto commands *** augroup mine " -- From /etc/vimrc on RedHat -- " don't write swapfile on most commonly used directories for NFS mounts or USB sticks autocmd BufNewFile,BufReadPre /media/*,/run/media/* set directory=~/tmp,/var/tmp,/tmp " start with spec file template autocmd BufNewFile *.spec 0r $HOME/.vim/templates/template.spec augroup END " *** Misc *** runtime include/abbrevs.vim " -- digraphs -- if has('digraphs') digraphs a` 224 endif " -- Git support -- match ErrorMsg '^\(<\|=\|>\)\{7\}\([^=].\+\)\?$' " *** Fixups *** " == Terminal == " *** Extensibility *** if exists('*filereadable') && exists('$ZONE') " source the zone-specific rc file, if it exists let s:zone_rc_file = $HOME . "/.init/Zones/" . $ZONE . "/vimrc" if filereadable(s:zone_rc_file) execute "source" s:zone_rc_file endif endif