aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--README.md14
-rw-r--r--VERSION4
-rw-r--r--man/man7/dotfiles.7df24
-rw-r--r--vim/autoload/detect_background.vim24
-rw-r--r--vim/config/command.vim15
-rw-r--r--vim/config/format.vim37
-rw-r--r--vim/config/join.vim25
-rw-r--r--vim/config/syntax.vim27
-rw-r--r--vim/config/whitespace.vim59
-rw-r--r--vim/config/wrap.vim38
-rw-r--r--vim/doc/big_file.txt (renamed from vim/doc/bigfile.txt)2
-rw-r--r--vim/doc/command_typos.txt12
-rw-r--r--vim/doc/copy_linebreak.txt13
-rw-r--r--vim/doc/detect_background.txt14
-rw-r--r--vim/doc/fixed_join.txt11
-rw-r--r--vim/doc/strip_trailing_whitespace.txt12
-rw-r--r--vim/doc/toggle_option_flag.txt16
-rw-r--r--vim/plugin/big_file.vim (renamed from vim/plugin/bigfile.vim)25
-rw-r--r--vim/plugin/command_typos.vim19
-rw-r--r--vim/plugin/copy_linebreak.vim36
-rw-r--r--vim/plugin/fixed_join.vim29
-rw-r--r--vim/plugin/strip_trailing_whitespace.vim62
-rw-r--r--vim/plugin/toggle_option_flag.vim44
24 files changed, 368 insertions, 200 deletions
diff --git a/Makefile b/Makefile
index e80a1ed8..5b14d8dd 100644
--- a/Makefile
+++ b/Makefile
@@ -39,6 +39,7 @@
install-urxvt \
install-vim \
install-vim-after \
+ install-vim-autoload \
install-vim-bundle \
install-vim-config \
install-vim-ftdetect \
@@ -477,6 +478,7 @@ install-urxvt: urxvt/ext/select
-exec cp -p -- {} $(HOME)/.urxvt/ext \;
install-vim: install-vim-after \
+ install-vim-autoload \
install-vim-bundle \
install-vim-config \
install-vim-doc \
@@ -490,6 +492,10 @@ install-vim-after:
-type d -exec sh -c 'mkdir -p -- $(HOME)/."$$1"' _ {} \; -o \
-type f -exec sh -c 'cp -p -- "$$1" $(HOME)/."$$1"' _ {} \;
+install-vim-autoload:
+ mkdir -p -- $(HOME)/.vim/autoload
+ cp -p -- vim/autoload/*.vim $(HOME)/.vim/autoload
+
install-vim-bundle: install-vim-config
find vim/bundle -name .git -prune -o \
-type d -exec sh -c 'mkdir -p -- $(HOME)/."$$1"' _ {} \; -o \
diff --git a/README.md b/README.md
index 361cfa62..bc84d378 100644
--- a/README.md
+++ b/README.md
@@ -343,10 +343,22 @@ The configuration is broken into subfiles in `~/.vim/config/*.vim`, included by
extensively commented, mostly because I was reading through it one day and
realised I'd forgotten what half of it did.
-I define a few custom per-filetype rules for stuff I often edit in
+#### Plugins
+
+If the logic for doing something involves more than a few lines or any
+structures like functions, I like to implement it as a plugin in
+`~/.vim/plugin` and/or `~/.vim/autoload`. There's documentation for each of
+those in `~/.vim/doc`.
+
+I also define a few custom per-filetype rules for stuff I often edit in
`~/.vim/ftplugin`, including some local mappings for checking, linting, and
tidying.
+Any/all of the general or filetype plugins may eventually be spun off into
+their own repositories in the future, but for the moment they live here.
+Contact me if you find one of them useful and you'd like to see it in its own
+distribution.
+
Third-party plugins are in submodules in `~/.vim/bundle`, loaded using Tim
Pope's [pathogen.vim](https://github.com/tpope/vim-pathogen).
diff --git a/VERSION b/VERSION
index 7feb464a..2de1dcdb 100644
--- a/VERSION
+++ b/VERSION
@@ -1,2 +1,2 @@
-tejr dotfiles v0.6.1
-Fri Nov 3 12:46:45 UTC 2017
+tejr dotfiles v0.7.0
+Sat Nov 4 05:45:33 UTC 2017
diff --git a/man/man7/dotfiles.7df b/man/man7/dotfiles.7df
index fe56e138..fbb1da64 100644
--- a/man/man7/dotfiles.7df
+++ b/man/man7/dotfiles.7df
@@ -142,6 +142,8 @@ Fork of the rxvt terminal emulator with Unicode support
Subversion (https://subversion.apache.org/) \[en] Apache Subversion, a
version control system
.IP \[bu] 2
+tidy (http://www.html-tidy.org/) \[en] HTML/XHTML linter and tidier
+.IP \[bu] 2
tmux (https://tmux.github.io/) \[en] Terminal multiplexer similar to GNU
Screen
.IP \[bu] 2
@@ -475,13 +477,29 @@ I try not to deviate too much from the Vim defaults behaviour in terms
of interactive behavior and keybindings.
.PP
The configuration is broken into subfiles in
-\f[C]\&.vim/config/*.vim\f[], included by \f[C]~/.vimrc\f[] using
+\f[C]~/.vim/config/*.vim\f[], included by \f[C]~/.vimrc\f[] using
\f[C]:runtime\f[] (http://vimdoc.sourceforge.net/htmldoc/repeat.html#:runtime).
It's extensively commented, mostly because I was reading through it one
day and realised I'd forgotten what half of it did.
+.SS Plugins
+.PP
+If the logic for doing something involves more than a few lines or any
+structures like functions, I like to implement it as a plugin in
+\f[C]~/.vim/plugin\f[] and/or \f[C]~/.vim/autoload\f[].
+There's documentation for each of those in \f[C]~/.vim/doc\f[].
+.PP
+I also define a few custom per\-filetype rules for stuff I often edit in
+\f[C]~/.vim/ftplugin\f[], including some local mappings for checking,
+linting, and tidying.
+.PP
+Any/all of the general or filetype plugins may eventually be spun off
+into their own repositories in the future, but for the moment they live
+here.
+Contact me if you find one of them useful and you'd like to see it in
+its own distribution.
.PP
-Plugins are in submodules in \f[C]\&.vim/bundle\f[], loaded using Tim
-Pope's pathogen.vim (https://github.com/tpope/vim-pathogen).
+Third\-party plugins are in submodules in \f[C]~/.vim/bundle\f[], loaded
+using Tim Pope's pathogen.vim (https://github.com/tpope/vim-pathogen).
.SS Scripts
.PP
Where practical, I make short scripts into POSIX (but not Bourne)
diff --git a/vim/autoload/detect_background.vim b/vim/autoload/detect_background.vim
new file mode 100644
index 00000000..89e5d19e
--- /dev/null
+++ b/vim/autoload/detect_background.vim
@@ -0,0 +1,24 @@
+"
+" detect_background.vim: Invert Vim's built-in logic for choosing dark or
+" light backgrounds; we'll default to choosing a dark background unless we
+" find some reason *not* to.
+"
+" Author: Tom Ryder <tom@sanctum.geek.nz>
+" License: Same as Vim itself
+"
+function! detect_background#DetectBackground()
+
+ " Split up the value of $COLORFGBG (if any) by semicolons
+ let l:colorfgbg = split($COLORFGBG, ';')
+
+ " Get the background color value, or an empty string if none
+ let l:bg = len(l:colorfgbg) ? l:colorfgbg[-1] : ''
+
+ " Choose the background setting based on this value
+ if l:bg ==# 'default' || l:bg ==# '7' || l:bg ==# '15'
+ set background=light
+ else
+ set background=dark
+ endif
+
+endfunction
diff --git a/vim/config/command.vim b/vim/config/command.vim
index 2a60bab3..f339635f 100644
--- a/vim/config/command.vim
+++ b/vim/config/command.vim
@@ -25,18 +25,3 @@ set shellpipe=>
if exists('+shellslash')
set shellslash
endif
-
-" Tolerate typos like :Wq, :Q, or :Qa and do what I mean, including any
-" arguments or modifiers; I fat-finger these commands a lot because I type
-" them so rapidly, and they don't correspond to any other commands I use
-if has('user_commands')
- command! -bang -complete=file -nargs=? E e<bang> <args>
- command! -bang -complete=file -nargs=? W w<bang> <args>
- command! -bang -complete=file -nargs=? WQ wq<bang> <args>
- command! -bang -complete=file -nargs=? Wq wq<bang> <args>
- command! -bang Q q<bang>
- command! -bang Qa qa<bang>
- command! -bang QA qa<bang>
- command! -bang Wa wa<bang>
- command! -bang WA wa<bang>
-endif
diff --git a/vim/config/format.vim b/vim/config/format.vim
index b0de7621..572e9877 100644
--- a/vim/config/format.vim
+++ b/vim/config/format.vim
@@ -5,8 +5,8 @@ if v:version > 703 || v:version ==# 703 && has('patch541')
endif
"
-" Quick way to toggle flags in 'formatoptions' that I often want to change;
-" specifically:
+" Use toggle_option_flag.vim plugin to bind quick toggle actions for some
+" 'formatoptions' flags:
"
" a - Automatically format paragraphs, reapplying the wrap on every text
" insertion or deletion; sometimes I want this and sometimes I
@@ -16,30 +16,11 @@ endif
" to set for me)
" t - Automatically wrap text at 'textwidth' (as above)
"
-" So I just have to type e.g. \a to toggle the auto-format flag on and off;
-" very handy
-"
-if has('eval')
-
- " Declare function
- function! s:ToggleFormatFlag(flag)
-
- " Decide on whether we're adding or removing the flag
- if &l:formatoptions =~# a:flag
- let l:command = 'setlocal formatoptions-=' . a:flag
- else
- let l:command = 'setlocal formatoptions+=' . a:flag
- endif
-
- " Execute the command we determined and show the result
- silent! execute l:command
- setlocal formatoptions?
-
- endfunction
-
- " Map leader-letters to corresponding format option flags
- nnoremap <silent> <Leader>a :<C-U>call <SID>ToggleFormatFlag('a')<CR>
- nnoremap <silent> <Leader>c :<C-U>call <SID>ToggleFormatFlag('c')<CR>
- nnoremap <silent> <Leader>t :<C-U>call <SID>ToggleFormatFlag('t')<CR>
-
+if has('eval') && has('user_commands')
+ nnoremap <silent> <leader>a
+ \ :<C-U>ToggleOptionFlagLocal formatoptions a<CR>
+ nnoremap <silent> <leader>c
+ \ :<C-U>ToggleOptionFlagLocal formatoptions c<CR>
+ nnoremap <silent> <leader>t
+ \ :<C-U>ToggleOptionFlagLocal formatoptions t<CR>
endif
diff --git a/vim/config/join.vim b/vim/config/join.vim
index 7d764dce..ebf42a8b 100644
--- a/vim/config/join.vim
+++ b/vim/config/join.vim
@@ -2,26 +2,9 @@
" despite the noble Steve Losh's exhortations
set nojoinspaces
-" Keep my cursor in place when I join lines
+" Rebind normal J to run plugin-defined join that doesn't jump around, but
+" only if we have the eval feature, because otherwise this mapping won't exist
+" and we should keep the default behaviour
if has('eval')
-
- " Declare function
- function! s:StableNormalJoin()
-
- " Save current cursor position
- let l:lc = line('.')
- let l:cc = col('.')
-
- " Build and execute join command
- let l:command = '.,+' . v:count1 . 'join'
- execute l:command
-
- " Restore cursor position
- call cursor(l:lc, l:cc)
-
- endfunction
-
- " Remap J to the above function
- nnoremap <silent> J :<C-U>call <SID>StableNormalJoin()<CR>
-
+ nmap J <Plug>FixedJoin
endif
diff --git a/vim/config/syntax.vim b/vim/config/syntax.vim
index e7d94b1b..8cb1228b 100644
--- a/vim/config/syntax.vim
+++ b/vim/config/syntax.vim
@@ -5,32 +5,9 @@ if has('syntax')
silent! syntax enable
silent! syntax sync minlines=100
- " Invert Vim's built-in logic for choosing dark or light backgrounds; we'll
- " default to choosing a dark background unless we find some reason *not* to.
+ " If we can, detect a light background, but default to a dark one
if has('eval') && v:version >= 701
-
- " Wrap all this logic in a function
- function! s:DetectBackground()
-
- " Split up the value of $COLORFGBG (if any) by semicolons
- let l:colorfgbg = split($COLORFGBG, ';')
-
- " Get the background color value, or an empty string if none
- let l:bg = len(l:colorfgbg) ? l:colorfgbg[-1] : ''
-
- " Choose the background setting based on this value
- if l:bg ==# 'default' || l:bg ==# '7' || l:bg ==# '15'
- set background=light
- else
- set background=dark
- endif
-
- endfunction
-
- " Call the function just defined directly
- call s:DetectBackground()
-
- " Ancient or cut-down Vim? Just go dark
+ silent! call detect_background#DetectBackground()
else
set background=dark
endif
diff --git a/vim/config/whitespace.vim b/vim/config/whitespace.vim
index bfe2663d..75ab7173 100644
--- a/vim/config/whitespace.vim
+++ b/vim/config/whitespace.vim
@@ -1,57 +1,2 @@
-" Strip trailing whitespace with \x in the whole document
-if has('eval')
-
- " Define function for stripping whitespace
- function! s:StripTrailingWhitespace()
-
- " Iterating line number
- let l:li = 1
-
- " Line number of last line that had non-whitespace characters on it
- let l:lw = 0
-
- " Line number of the file's last line
- let l:ll = line('$')
-
- " Iterate over the lines
- while l:li <= l:ll
-
- " Get the line text
- let l:line = getline(l:li)
-
- " Replace the line with a subsitution of its text stripping extraneous
- " whitespace
- call setline(l:li, substitute(l:line, '\m\C\s\+$', '', 'g'))
-
- " If this line has any non-whitespace characters on it, update l:lw with
- " its index
- if l:line =~# '\m\C\S'
- let l:lw = l:li
- endif
-
- " Increment the line counter for the next iteration
- let l:li = l:li + 1
- endwhile
-
- " If the last non-whitespace line was before the last line proper, we can
- " delete all lines after it
- if l:lw < l:ll
-
- " Get the current line and column so we can return to it
- " (Yes I know about winsaveview() and winrestview(); I want this to work
- " even on very old versions of Vim if possible)
- let l:lc = line('.')
- let l:cc = col('.')
-
- " Delete the lines, which will move the cursor
- execute l:lw + 1.',$ delete'
-
- " Return the cursor to the saved position
- call cursor(l:lc, l:cc)
- endif
- endfunction
-
- " Map \x to the function just defined
- nnoremap <silent> <Leader>x :<C-U>call <SID>StripTrailingWhitespace()<CR>
-
-endif
+" \x strips trailing whitespace via a custom plugin
+nmap <leader>x <Plug>StripTrailingWhitespace
diff --git a/vim/config/wrap.vim b/vim/config/wrap.vim
index 7a442e89..5da843ce 100644
--- a/vim/config/wrap.vim
+++ b/vim/config/wrap.vim
@@ -23,42 +23,12 @@ if has('linebreak')
" Precede continued lines with '...'
set showbreak=...
- " If we have the option, indent wrapped lines as much as the first line;
- " keep the value as a script variable for the toggle function.
- let s:breakindent = v:version > 704
- \ || v:version ==# 704 && has('patch338')
- if s:breakindent
+ " If we have the option, indent wrapped lines as much as the first line
+ if has('&breakindent')
set breakindent
endif
- " Bind \b to turn off linebreak and toggle the showbreak characters on and
- " off for convenience of copypasting multiple lines from terminal emulators.
- if has('eval')
+ " \b toggles copy-pasteable linebreak settings
+ nmap <leader>b <Plug>CopyLinebreak
- " Define function
- function! s:ToggleBreak()
-
- " If linebreak is on, turn it off
- if &l:linebreak
- setlocal nolinebreak linebreak?
- setlocal showbreak=
- if s:breakindent
- setlocal nobreakindent
- endif
-
- " If it's off, turn it on
- else
- setlocal linebreak linebreak?
- setlocal showbreak=...
- if s:breakindent
- setlocal breakindent
- endif
- endif
-
- endfunction
-
- " Map \b to defined function
- nnoremap <silent> <Leader>b :<C-U>call <SID>ToggleBreak()<CR>
-
- endif
endif
diff --git a/vim/doc/bigfile.txt b/vim/doc/big_file.txt
index d7e56f28..aea0ee79 100644
--- a/vim/doc/bigfile.txt
+++ b/vim/doc/big_file.txt
@@ -1,4 +1,4 @@
-*bigfile.txt* Disable slow options for big files to speed things up
+*big_file.txt* Disable slow options for big files to speed things up
Author: Tom Ryder <tom@sanctum.geek.nz>
License: Same terms as Vim itself (see |license|)
diff --git a/vim/doc/command_typos.txt b/vim/doc/command_typos.txt
new file mode 100644
index 00000000..93f37df9
--- /dev/null
+++ b/vim/doc/command_typos.txt
@@ -0,0 +1,12 @@
+*command_typos.txt* Bind capital-letter versions of common commands
+
+Author: Tom Ryder <tom@sanctum.geek.nz>
+License: Same terms as Vim itself (see |license|)
+
+This plugin defines custom commands like :W, :Qa, and :Wq to match their
+lowercase analogues, to forgive me when my pinky finger doesn't roll off the
+Shift key quite soon enough after pressing the colon key.
+
+This plugin lives in Tom Ryder's "dotfiles" suite, and will eventually be spun
+off into a separate distribution as it solidifies and this documentation
+improves.
diff --git a/vim/doc/copy_linebreak.txt b/vim/doc/copy_linebreak.txt
new file mode 100644
index 00000000..c8463386
--- /dev/null
+++ b/vim/doc/copy_linebreak.txt
@@ -0,0 +1,13 @@
+*copy_linebreak.txt* Mapping to toggle copy-paste friendly linebreak options
+
+Author: Tom Ryder <tom@sanctum.geek.nz>
+License: Same terms as Vim itself (see |license|)
+
+This plugin provides a mapping target <Plug>CopyLinebreak to create a binding
+for a user to quickly toggle |'linebreak'|-related settings when |'wrap'| is
+enabled, to switch between human-readable output and a format friendly for
+copy-pasting with terminal emulators or screen/tmux.
+
+This plugin lives in Tom Ryder's "dotfiles" suite, and will eventually be spun
+off into a separate distribution as it solidifies and this documentation
+improves.
diff --git a/vim/doc/detect_background.txt b/vim/doc/detect_background.txt
new file mode 100644
index 00000000..ad42221c
--- /dev/null
+++ b/vim/doc/detect_background.txt
@@ -0,0 +1,14 @@
+*detect_background.txt* Figure out 'background' with a bias towards "dark"
+
+Author: Tom Ryder <tom@sanctum.geek.nz>
+License: Same terms as Vim itself (see |license|)
+
+This plugin inspects the $COLORFGBG environment variable to determine whether
+the user is using a terminal with a light background. It reverses Vim's
+built-in attempts to do this, which have the opposite default.
+
+It does not inspect the value of the $TERM variable or |'term'| at all.
+
+This plugin lives in Tom Ryder's "dotfiles" suite, and will eventually be spun
+off into a separate distribution as it solidifies and this documentation
+improves.
diff --git a/vim/doc/fixed_join.txt b/vim/doc/fixed_join.txt
new file mode 100644
index 00000000..0ee957d0
--- /dev/null
+++ b/vim/doc/fixed_join.txt
@@ -0,0 +1,11 @@
+*fixed_join.txt* Mapping to join lines in normal mode without moving cursor
+
+Author: Tom Ryder <tom@sanctum.geek.nz>
+License: Same terms as Vim itself (see |license|)
+
+This plugin provides a mapping target <Plug>FixedJoin to create a binding for a
+user to join lines in normal mode without the cursor jumping around.
+
+This plugin lives in Tom Ryder's "dotfiles" suite, and will eventually be spun
+off into a separate distribution as it solidifies and this documentation
+improves.
diff --git a/vim/doc/strip_trailing_whitespace.txt b/vim/doc/strip_trailing_whitespace.txt
new file mode 100644
index 00000000..670877c9
--- /dev/null
+++ b/vim/doc/strip_trailing_whitespace.txt
@@ -0,0 +1,12 @@
+*strip_trailing_whitespace.txt* Strip trailing whitespace from whole buffer
+
+Author: Tom Ryder <tom@sanctum.geek.nz>
+License: Same terms as Vim itself (see |license|)
+
+This plugin is the author's approach to stripping trailing whitespace from an
+entire buffer, including empty lines at the end, without making command noise
+and without moving the cursor from its current position.
+
+This plugin lives in Tom Ryder's "dotfiles" suite, and will eventually be spun
+off into a separate distribution as it solidifies and this documentation
+improves.
diff --git a/vim/doc/toggle_option_flag.txt b/vim/doc/toggle_option_flag.txt
new file mode 100644
index 00000000..16557d5c
--- /dev/null
+++ b/vim/doc/toggle_option_flag.txt
@@ -0,0 +1,16 @@
+*toggle_option_flag.txt* Commands to toggle single-character option flags
+
+Author: Tom Ryder <tom@sanctum.geek.nz>
+License: Same terms as Vim itself (see |license|)
+
+This plugin provides commands :ToggleOptionFlag and :ToggleOptionFlagLocal to
+toggle the values of options like |'formatoptions'| or |'complete'| that have
+values comprised of single-character flags. The author originally designed it
+for toggling flags in |'formatoptions'| quickly.
+
+ :ToggleOptionFlag formatoptions a
+ :ToggleOptionFlagLocal shortmess I
+
+This plugin lives in Tom Ryder's "dotfiles" suite, and will eventually be spun
+off into a separate distribution as it solidifies and this documentation
+improves.
diff --git a/vim/plugin/bigfile.vim b/vim/plugin/big_file.vim
index fece3d9b..ec30158a 100644
--- a/vim/plugin/bigfile.vim
+++ b/vim/plugin/big_file.vim
@@ -1,26 +1,25 @@
"
-" bigfile.vim: When opening a large file, take some measures to keep things
+" big_file.vim: When opening a large file, take some measures to keep things
" loading quickly.
"
" Author: Tom Ryder <tom@sanctum.geek.nz>
-" Copyright: 2017
" License: Same as Vim itself
"
if has('eval') && has('autocmd')
" Default threshold is 10 MiB
- if !exists('g:bigfile_size')
- let g:bigfile_size = 10 * 1024 * 1024
+ if !exists('g:big_file_size')
+ let g:big_file_size = 10 * 1024 * 1024
endif
" Default to leaving syntax highlighting off
- if !exists('g:bigfile_syntax')
- let g:bigfile_syntax = 0
+ if !exists('g:big_file_syntax')
+ let g:big_file_syntax = 0
endif
" Cut 'synmaxcol' down to this or smaller for big files
- if !exists('g:bigfile_size_synmaxcol')
- let g:bigfile_size_synmaxcol = 256
+ if !exists('g:big_file_synmaxcol')
+ let g:big_file_synmaxcol = 256
endif
" Declare function for turning off slow options
@@ -40,21 +39,21 @@ if has('eval') && has('autocmd')
endif
" Limit the number of columns of syntax highlighting
- if exists('&synmaxcol') && &synmaxcol > g:bigfile_size_synmaxcol
- execute 'setlocal synmaxcol=' . g:bigfile_size_synmaxcol
+ if exists('&synmaxcol') && &synmaxcol > g:big_file_synmaxcol
+ execute 'setlocal synmaxcol=' . g:big_file_synmaxcol
endif
" Disable syntax highlighting if configured to do so
- if !g:bigfile_syntax
+ if !g:big_file_syntax
setlocal syntax=OFF
endif
endfunction
" Define autocmd for calling to check filesize
- augroup bigfile_options_bufreadpre
+ augroup big_file_options_bufreadpre
autocmd!
- autocmd BufReadPre * call s:BigFileOptions(expand('<afile>'), g:bigfile_size)
+ autocmd BufReadPre * call s:BigFileOptions(expand('<afile>'), g:big_file_size)
augroup end
endif
diff --git a/vim/plugin/command_typos.vim b/vim/plugin/command_typos.vim
new file mode 100644
index 00000000..32d194fb
--- /dev/null
+++ b/vim/plugin/command_typos.vim
@@ -0,0 +1,19 @@
+"
+" Tolerate typos like :Wq, :Q, or :Qa and do what I mean, including any
+" arguments or modifiers; I fat-finger these commands a lot because I type
+" them so rapidly, and they don't correspond to any other commands I use
+"
+" Author: Tom Ryder <tom@sanctum.geek.nz>
+" License: Same as Vim itself
+"
+if has('eval') && has('user_commands')
+ command! -bang -complete=file -nargs=? E e<bang> <args>
+ command! -bang -complete=file -nargs=? W w<bang> <args>
+ command! -bang -complete=file -nargs=? WQ wq<bang> <args>
+ command! -bang -complete=file -nargs=? Wq wq<bang> <args>
+ command! -bang Q q<bang>
+ command! -bang Qa qa<bang>
+ command! -bang QA qa<bang>
+ command! -bang Wa wa<bang>
+ command! -bang WA wa<bang>
+endif
diff --git a/vim/plugin/copy_linebreak.vim b/vim/plugin/copy_linebreak.vim
new file mode 100644
index 00000000..1dc537d4
--- /dev/null
+++ b/vim/plugin/copy_linebreak.vim
@@ -0,0 +1,36 @@
+"
+" Bind a user-defined key sequence to turn off linebreak and toggle the
+" showbreak characters and breakindent mode on and off, for convenience of
+" copying multiple lines from terminal emulators.
+"
+" Author: Tom Ryder <tom@sanctum.geek.nz>
+" License: Same as Vim itself
+"
+if has('eval')
+
+ " Define function
+ function! s:CopyLinebreak()
+
+ " If linebreak is on, turn it off
+ if &l:linebreak
+ setlocal nolinebreak linebreak?
+ setlocal showbreak=
+ if exists('&breakindent')
+ setlocal nobreakindent
+ endif
+
+ " If it's off, turn it on
+ else
+ setlocal linebreak linebreak?
+ setlocal showbreak<
+ if exists('&breakindent')
+ setlocal breakindent
+ endif
+ endif
+
+ endfunction
+
+ " Provide mapping proxy to the function just defined
+ noremap <Plug>CopyLinebreak
+ \ :<C-U>call <SID>CopyLinebreak()<CR>
+endif
diff --git a/vim/plugin/fixed_join.vim b/vim/plugin/fixed_join.vim
new file mode 100644
index 00000000..c002f667
--- /dev/null
+++ b/vim/plugin/fixed_join.vim
@@ -0,0 +1,29 @@
+"
+" User-defined key mapping to keep cursor in place when joining lines in
+" normal mode
+"
+" Author: Tom Ryder <tom@sanctum.geek.nz>
+" License: Same as Vim itself
+"
+if has('eval')
+
+ " Declare function
+ function! s:FixedJoin()
+
+ " Save current cursor position
+ let l:lc = line('.')
+ let l:cc = col('.')
+
+ " Build and execute join command
+ let l:command = '.,+' . v:count1 . 'join'
+ execute l:command
+
+ " Restore cursor position
+ call cursor(l:lc, l:cc)
+
+ endfunction
+
+ " Create mapping proxy to the function just defined
+ noremap <Plug>FixedJoin
+ \ :<C-U>call <SID>FixedJoin()<CR>
+endif
diff --git a/vim/plugin/strip_trailing_whitespace.vim b/vim/plugin/strip_trailing_whitespace.vim
new file mode 100644
index 00000000..17fff33f
--- /dev/null
+++ b/vim/plugin/strip_trailing_whitespace.vim
@@ -0,0 +1,62 @@
+"
+" User-defined key mapping to strip trailing whitespace in the whole document
+"
+" Author: Tom Ryder <tom@sanctum.geek.nz>
+" License: Same as Vim itself
+"
+if has('eval')
+
+ " Define function for stripping whitespace
+ function! s:StripTrailingWhitespace()
+
+ " Iterating line number
+ let l:li = 1
+
+ " Line number of last line that had non-whitespace characters on it
+ let l:lw = 0
+
+ " Line number of the file's last line
+ let l:ll = line('$')
+
+ " Iterate over the lines
+ while l:li <= l:ll
+
+ " Get the line text
+ let l:line = getline(l:li)
+
+ " Replace the line with a subsitution of its text stripping extraneous
+ " whitespace
+ call setline(l:li, substitute(l:line, '\m\C\s\+$', '', 'g'))
+
+ " If this line has any non-whitespace characters on it, update l:lw with
+ " its index
+ if l:line =~# '\m\C\S'
+ let l:lw = l:li
+ endif
+
+ " Increment the line counter for the next iteration
+ let l:li = l:li + 1
+ endwhile
+
+ " If the last non-whitespace line was before the last line proper, we can
+ " delete all lines after it
+ if l:lw < l:ll
+
+ " Get the current line and column so we can return to it
+ " (Yes I know about winsaveview() and winrestview(); I want this to work
+ " even on very old versions of Vim if possible)
+ let l:lc = line('.')
+ let l:cc = col('.')
+
+ " Delete the lines, which will move the cursor
+ execute l:lw + 1.',$ delete'
+
+ " Return the cursor to the saved position
+ call cursor(l:lc, l:cc)
+ endif
+ endfunction
+
+ " Create mapping proxy to the function just defined
+ noremap <Plug>StripTrailingWhitespace
+ \ :<C-U>call <SID>StripTrailingWhitespace()<CR>
+endif
diff --git a/vim/plugin/toggle_option_flag.vim b/vim/plugin/toggle_option_flag.vim
new file mode 100644
index 00000000..10b4fe7a
--- /dev/null
+++ b/vim/plugin/toggle_option_flag.vim
@@ -0,0 +1,44 @@
+"
+" toggle_option_flag.vim: Provide commands to toggle flags in single-char
+" grouped options like 'formatoptions', 'shortmess', 'complete' etc.
+"
+" This will fail hilariously if you try to set e.g. 'switchbuf' with it!
+"
+" Author: Tom Ryder <tom@sanctum.geek.nz>
+" License: Same as Vim itself
+"
+if has('eval') && has('user_commands')
+
+ " Internal function to do the toggling
+ function! s:Toggle(option, flag, local)
+
+ " Check for weird options, we don't want to eval() anything funny
+ if a:option =~# '[^a-z]'
+ echoerr 'Illegal option name'
+ return
+ endif
+
+ " Weird flags, too; should be a single inoffensive char
+ if a:flag !~# '^[a-z0-9.]$'
+ echoerr 'Illegal flag'
+ return
+ endif
+
+ " Choose which set command to use
+ let l:set = a:local ? 'setlocal' : 'set'
+
+ " Use eval() to assign -= or += to l:op for the option toggle
+ " (I couldn't get {curly braces} indirection to work)
+ let l:op = ''
+ execute 'let l:op = &'.a:option.' =~# a:flag ? "-=" : "+="'
+
+ " Use eval() to perform the option toggle and then print the value
+ execute l:set . ' ' . a:option . l:op . a:flag . ' ' . a:option . '?'
+
+ endfunction
+
+ " User commands wrapping around calls to the above function
+ command! -nargs=+ ToggleOptionFlag :call <SID>Toggle(<f-args>, 0)
+ command! -nargs=+ ToggleOptionFlagLocal :call <SID>Toggle(<f-args>, 1)
+
+endif