Explorar el Código

Expand vimrc to be generally self-sufficient

We are updating the vimrc to contain all important settings and mappings
such that it can be dumped on most any machine and provide a comfortable
working environment. The vimrc should work well regardless of there
being additional settings or plugins. We also look to making it
increasingly compatible with various older or less feature-full versions
of vim, using conditionals.
Weiyi Lou hace 10 años
padre
commit
f74223f354

+ 0 - 2
vim/settings/colorscheme-statusline.vim

@@ -16,9 +16,7 @@ let g:solarized_palette = expand('~/dotfiles/vim/use-solarized-palette')
 
 " Status line defaults.
 let g:airline_powerline_fonts = 1
-set laststatus=2 " always show the status line.
 set noshowmode   " hide modes e.g. --INSERT-- with themed status lines.
-set showcmd      " display partial commands on the last line.
 
 " Toggle colour schemes.
 command! Dark set background=dark

+ 0 - 14
vim/settings/cursorposition.vim

@@ -1,14 +0,0 @@
-if has("autocmd")
-
-  " Restore Position
-  " Based on the last-position mark '"'. Go to it if it is not the first line,
-  " and if it is valid i.e. within the number of lines in the file.
-  " From `:help line()`
-  au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
-
-  " Git Commit Exception
-  " Instead of reverting the cursor to the last position in the buffer, we
-  " set it to the first line when editing a git commit message
-  au FileType gitcommit au! BufEnter COMMIT_EDITMSG call setpos('.', [0, 1, 1, 0])
-
-endif

+ 1 - 1
vim/settings/filetype-specifics.vim

@@ -1,5 +1,5 @@
 " Formatting for json files
-au FileType json setlocal equalprg=python\ -m\ json.tool
+"au FileType json setlocal equalprg=python\ -m\ json.tool
 
 " yaml highlighting
 au BufNewFile,BufRead *.yaml,*.yml so ~/.vim/plugged/yaml.vim/colors/yaml.vim

+ 0 - 41
vim/settings/folders.vim

@@ -1,41 +0,0 @@
-" Set up folders to be used for various temporary files, based on vim settings.
-" Features should be toggled in `vimrc`, or any other file before this is run.
-function! InitVimFolders()
-
-  " Vim folders will look like `~/.vimsomething`.
-  let prefix = $HOME . '/.vim'
-
-  " List the folders to be made.
-  let folders = {}
-  if &swapfile
-    let folders['swap'] = 'directory'
-  endif
-  if &backup
-    let folders['backup'] = 'backupdir'
-  endif
-  if has('persistent_undo') && &undofile
-    let folders['undo'] = 'undodir'
-  endif
-
-  " Create the folders.
-  for [folder, setting] in items(folders)
-    let path = prefix . folder . '/'
-
-    if !isdirectory(path)
-      if exists("*mkdir")
-        call mkdir(path, "p")
-      endif
-    endif
-
-    " Use the folders.
-    if isdirectory(path)
-      let path = substitute(path, " ", "\\\\ ", "g")
-      execute "set " . setting . "=" . path
-    else
-      echo "Warning! Could not create folder: " . path
-      echo "Try `mkdir -p " . path . "`"
-    endif
-  endfor
-endfunction
-
-call InitVimFolders()

+ 53 - 215
vim/settings/folding.vim

@@ -1,247 +1,85 @@
-" Folding - Modeline and Notes {{{
-" vim: set sw=2 ts=2 sts=2 et tw=78 foldmarker={{{,}}} foldlevel=1 foldmethod=marker:
+" These are settings to make folding easier to use and look at:
+"  - Indented folded lines to match origin line indentation.
+"  - Statbox to right displays line count and fold level.
 "
-"   cinaeco/dotfiles Folding Settings
-"
-"   These are settings to make folding easier to use and look at:
-"    - Indented Folds to match their first line.
-"    - Statbox to right displays line count and fold level.
-"    - SpaceBar toggles folds, if any.
-"        (much more convenient than the 'z' commands)
-"    - Quick foldlevel setting map: zf[0-9]
-"
-"   Note that custom foldtext will only work for vim 7.3+. For earlier
-"   versions of vim, only the colouring and spacebar mapping will take effect.
-"
-"   TODO:
-"    - Fold description is just the first line found. Haven't really
-"    understood the regex, but could perhaps make it better.
-"    - Fold description current truncation rule is 1/3 of the window width.
-"    Perhaps this could be some less arbitrary rule?
-"
-" }}}
+" Note that custom foldtext will only work for vim 7.3+.
 
 if has('folding')
 
-  " Default Settings {{{
-  set foldenable
-  set foldmethod=indent
-  set foldlevel=10
-  " }}}
-
-  " Keyboard Shortcuts {{{
-  " Space as a Folding toggle in normal mode.
-  nnoremap <silent> <Leader><Space>     @=(foldlevel('.')?'za':"\<Space>")<CR>
-
-  " Code folding options (spf13-vim)
-  nmap zf0 :set foldlevel=0<CR>
-  nmap zf1 :set foldlevel=1<CR>
-  nmap zf2 :set foldlevel=2<CR>
-  nmap zf3 :set foldlevel=3<CR>
-  nmap zf4 :set foldlevel=4<CR>
-  nmap zf5 :set foldlevel=5<CR>
-  nmap zf6 :set foldlevel=6<CR>
-  nmap zf7 :set foldlevel=7<CR>
-  nmap zf8 :set foldlevel=8<CR>
-  nmap zf9 :set foldlevel=9<CR>
-  " }}}
-
-  " Fold Highlighting {{{
-  "highlight Folded term=none cterm=none ctermfg=darkgrey ctermbg=none guifg=darkgrey guibg=none
-  " }}}
-
-  " Fold Text {{{
   set foldtext=CustomFoldText()
 
   function! CustomFoldText(...)
-
-    " At least vim 7.3 {{{
-    "  - Requirement for strdisplaywidth().
-    "  - strdisplaywidth() seems to work. If multi-byte characters start to give
-    "  trouble, consider checking the more primitive solution in strlen() help.
+    " At least vim 7.3
+    "  - Requirement for `strdisplaywidth` (If `strdisplaywidth` fails for
+    "  multi-byte chars, consider checking the `strlen` help).
     if v:version < 703
       return foldtext()
     endif
-    " }}}
 
-    " Common variables for all foldmethods {{{
+    " Common variables for all foldmethods.
     let lineCount = v:foldend - v:foldstart + 1
     let displayWidth = winwidth(0) - &foldcolumn
     if (&number || &relativenumber)
       let displayWidth -= &numberwidth
     endif
     let foldChar = '-'
-    " }}}
 
-    " Set fold fillchar {{{
-    "  - This complicated line is to ensure we replace the fold fillchar only.
+    " Set fold fillchar.
     let &l:fillchars = substitute(&l:fillchars,',\?fold:.','','gi')
     execute 'setlocal fillchars+=fold:' . foldChar
-    " }}}
 
-    " Handle diff foldmethod {{{
-    "  - Display a centre-aligned statbox with the number of lines.
+    " Fold text for Diffs - centre-aligned statbox with a line count.
     if &foldmethod == 'diff'
-
-      " Prepare the statbox {{{
       let statBox = printf('[ %s matching lines ]', lineCount)
-      " }}}
-
-      " Prepare filler lines {{{
       let filler = repeat(foldChar, (displayWidth - strchars(statBox)) / 2)
-      " }}}
-
-      " Output the combined fold text {{{
       return filler.statBox
-      " }}}
-
     endif
-    " }}}
-
-    " Handle all other foldmethods {{{
-
-      " Prepare fold indent and indicator {{{
-      "  - If indent allows, build the indicator into it.
-      let foldIndicator = '+ '
-      let indLen = strdisplaywidth(foldIndicator)
-      if indent(v:foldstart) >= indLen
-        let indent = repeat(' ', indent(v:foldstart) - indLen) . foldIndicator
-      else
-        let indent = repeat(' ', indent(v:foldstart))
-      endif
-      " }}}
-
-      " Prepare the statbox {{{
-      "  - Fixed statbox width at 18 characters.
-      "  - Count width by display cells instead of bytes if at least vim 7.4
-      if v:version >= 704
-        let countType = 'S'
-      else
-        let countType = 's'
-      endif
-      let statBox = '[ ' . printf('%14'.countType, lineCount.' lns, lv '.v:foldlevel) . ' ]'
-      " }}}
-
-      " Prepare fold description {{{
-      "  - Remove fold markers and comment markers.
-      "  - Truncate to 1/3 of the current window width.
-
-        " Use function argument as line text if provided {{{
-        let line = a:0 > 0 ? a:1 : getline(v:foldstart)
-        " }}}
-
-        " Remove fold markers {{{
-        let foldmarkers = split(&foldmarker, ',')
-        let line = substitute(line, '\V' . foldmarkers[0] . '\%(\d\+\)\?\s\*', '', '')
-        " }}}
-
-        " Remove surrounding whitespace {{{
-        let line = substitute(line, '^\s*\(.\{-}\)\s*$', '\1', '')
-        " }}}
-
-        " Add an extra space at the end {{{
-        let foldDesc = line.' '
-        " }}}
-
-      " }}}
-
-      " Prepare filler lines {{{
-      "  - midFiller is the fill between the description and statbox.
-      "  - midFiller compensates for column widths generated by foldcolumn, number
-      "  and relativenumber.
-      let endFiller = repeat(foldChar, 1)
-      let midFillerLength = displayWidth - strdisplaywidth(indent.foldDesc.statBox.endFiller)
-      let midFiller = repeat(foldChar, midFillerLength)
-      " }}}
-
-      " Output the combined fold text {{{
-      return indent.foldDesc.midFiller.statBox.endFiller
-      " }}}
-
-    " }}}
 
-  endfunction
-  " }}}
-
-  " Lokaltog's Fold Text for learning more stuff about fold description preparation {{{
-  function! FoldText(...)
-    " This function uses code from doy's vim-foldtext: https://github.com/doy/vim-foldtext
-    " Prepare fold variables {{{
-    " Use function argument as line text if provided
-    let l:line = a:0 > 0 ? a:1 : getline(v:foldstart)
-
-    let l:line_count = v:foldend - v:foldstart + 1
-    let l:indent = repeat(' ', indent(v:foldstart))
-
-    let l:w_win = winwidth(0)
-    let l:w_num = getwinvar(0, '&number') * getwinvar(0, '&numberwidth')
-    let l:w_fold = getwinvar(0, '&foldcolumn')
-    " }}}
-    " Handle diff foldmethod {{{
-    if &fdm == 'diff'
-      let l:text = printf('┤ %s matching lines ├', l:line_count)
-
-      " Center-align the foldtext
-      return repeat('┄', (l:w_win - strchars(l:text) - l:w_num - l:w_fold) / 2) . l:text
-    endif
-    " }}}
-    " Handle other foldmethods {{{
-    let l:text = l:line
-    " Remove foldmarkers {{{
-    let l:foldmarkers = split(&foldmarker, ',')
-    let l:text = substitute(l:text, '\V' . l:foldmarkers[0] . '\%(\d\+\)\?\s\*', '', '')
-    " }}}
-    " Remove comments {{{
-    let l:comment = split(&commentstring, '%s')
-
-    if l:comment[0] != ''
-      let l:comment_begin = l:comment[0]
-      let l:comment_end = ''
-
-      if len(l:comment) > 1
-        let l:comment_end = l:comment[1]
-      endif
-
-      let l:pattern = '\V' . l:comment_begin . '\s\*' . l:comment_end . '\s\*\$'
-
-      if l:text =~ l:pattern
-        let l:text = substitute(l:text, l:pattern, ' ', '')
-      else
-        let l:text = substitute(l:text, '.*\V' . l:comment_begin, ' ', '')
-
-        if l:comment_end != ''
-          let l:text = substitute(l:text, '\V' . l:comment_end, ' ', '')
-        endif
-      endif
+    " Fold text for all other situations.
+    "  - Fold description is a max length of 1/3 of the current window width.
+    "  - Fold & comment markers are removed from the fold description.
+
+    " Prepare fold indent, and if long enough, indicate folding with '+'.
+    let foldIndicator = '+ '
+    let indLen = strdisplaywidth(foldIndicator)
+    if indent(v:foldstart) >= indLen
+      let indent = repeat(' ', indent(v:foldstart) - indLen) . foldIndicator
+    else
+      let indent = repeat(' ', indent(v:foldstart))
     endif
-    " }}}
-    " Remove preceding non-word characters {{{
-    let l:text = substitute(l:text, '^\W*', '', '')
-    " }}}
-    " Remove surrounding whitespace {{{
-    let l:text = substitute(l:text, '^\s*\(.\{-}\)\s*$', '\1', '')
-    " }}}
-    " Make unmatched block delimiters prettier {{{
-    let l:text = substitute(l:text, '([^)]*$',   '⟯ ⋯ ⟮', '')
-    let l:text = substitute(l:text, '{[^}]*$',   '⟯ ⋯ ⟮', '')
-    let l:text = substitute(l:text, '\[[^\]]*$', '⟯ ⋯ ⟮', '')
-    " }}}
-    " Add arrows when indent level > 2 spaces {{{
-    if indent(v:foldstart) > 2
-      let l:cline = substitute(l:line, '^\s*\(.\{-}\)\s*$', '\1', '')
-      let l:clen = strlen(matchstr(l:cline, '^\W*'))
-
-      let l:indent = repeat(' ', indent(v:foldstart) - 2)
-      let l:text = '▸ ' . l:text
+
+    " Prepare the statbox.
+    "  - Fix statbox width at 18 chars.
+    "  - Count width by display cells instead of bytes (vim 7.4+).
+    if v:version >= 704
+      let countType = 'S'
+    else
+      let countType = 's'
     endif
-    " }}}
-    " Prepare fold text {{{
-    let l:fnum = printf('┤ %s ⭡ ', printf('%4s', l:line_count))
-    let l:ftext = printf('%s%s ', l:indent, l:text)
-    " }}}
-    return l:ftext . repeat('┄', l:w_win - strchars(l:fnum) - strchars(l:ftext) - l:w_num - l:w_fold) . l:fnum
-    " }}}
+    let statBox = '[ ' . printf('%14'.countType, lineCount.' lns, lv '.v:foldlevel) . ' ]'
+
+    " Prepare fold description.
+    "  - Use function argument as fold description text if provided.
+    let foldDesc = a:0 > 0 ? a:1 : getline(v:foldstart)
+
+    " Remove any fold markers.
+    let foldmarkers = split(&foldmarker, ',')
+    let foldDesc = substitute(foldDesc, '\V' . foldmarkers[0] . '\%(\d\+\)\?\s\*', '', '')
+
+    " Remove any surrounding whitespace.
+    let foldDesc = substitute(foldDesc, '^\s*\(.\{-}\)\s*$', '\1', '')
+
+    " Space the description away from the midfiller a bit.
+    let foldDesc = foldDesc . ' '
+
+    " Prepare filler lines.
+    "  - midFiller is the fill between the description and statbox, so its
+    "  length is the leftover space after all other elements.
+    let endFiller = repeat(foldChar, 1)
+    let midFillerLength = displayWidth - strdisplaywidth(indent.foldDesc.statBox.endFiller)
+    let midFiller = repeat(foldChar, midFillerLength)
+
+    return indent.foldDesc.midFiller.statBox.endFiller
   endfunction
-  " }}}
 
 endif

+ 0 - 10
vim/settings/quickfix.vim

@@ -1,10 +0,0 @@
-if has("autocmd")
-
-  " Open quickfix window after any grep invocation (Glog and Ggrep). {{{
-  autocmd QuickFixCmdPost *grep* cwindow |
-        \ setlocal nocursorline |
-        \ let g:qfix_win = bufnr("$") |
-        \ call MapQfPrevNext()
-  " }}}
-
-endif

+ 0 - 42
vim/settings/screenmovement.vim

@@ -1,42 +0,0 @@
-" Freedom of movement in visual block mode
-set virtualedit=block
-
-" Smart way to move between windows
-" Enchancing these mapping with vertical maximisation (<C-w>_) is interesting
-noremap <C-j> <C-w>j
-noremap <C-k> <C-w>k
-noremap <C-h> <C-w>h
-noremap <C-l> <C-w>l
-
-" Adjust viewports to the same size
-map <Leader>= <C-w>=
-
-" Easier horizontal scrolling
-map zl zL
-map zh zH
-
-" Easier jumping to beginning and end of line
-map H ^
-map L $
-
-" Move according to the screen when wrapped
-function! ScreenMove(move)
-  if &wrap
-    return 'g' . a:move
-  else
-    return a:move
-  endif
-endfunction
-
-" Map screen moves in normal, operator-pending and visual (but not select) modes
-function! MapScreenMove(move)
-  for mapmode in ['n', 'o', 'x']
-    execute mapmode."noremap <silent> <expr>" a:move 'ScreenMove("'.a:move.'")'
-  endfor
-endfunction
-
-call MapScreenMove("j")
-call MapScreenMove("k")
-call MapScreenMove("0")
-call MapScreenMove("^")
-call MapScreenMove("$")

+ 0 - 10
vim/settings/search.vim

@@ -1,13 +1,3 @@
-" Backspace to clear current search (and stop highlighting)
-nnoremap <silent> <backspace> :call ClearSearch()<CR>
-
-function! ClearSearch()
-  if (@/ != "")
-    let @/=""
-    redraw
-  endif
-endfunction
-
 " use faster search tools if available
 if executable('ag')
   set grepprg=ag\ --vimgrep\ $*

+ 0 - 7
vim/settings/toggles.vim

@@ -1,10 +1,3 @@
-" Toggle paste mode - no autoindenting of pasted material
-nnoremap <silent> <F2> :set paste! paste?<CR>
-set pastetoggle=<F2>
-
-" Toggle line numbers
-nnoremap <silent> <Leader>n :set number! relativenumber! number?<CR>
-
 " Toggle Undotree
 nnoremap <silent> <Leader>u :UndotreeToggle<CR>
 

+ 0 - 6
vim/settings/version_control.vim

@@ -17,9 +17,3 @@ nnoremap <silent> <Leader>gap :Git add -p<CR>
 nnoremap <silent> <Leader>gs :Gstatus<CR>
 nnoremap <silent> <Leader>gd :Gdiff<CR>
 nnoremap <silent> <Leader>gb :Gblame<CR>
-
-" Get what's changed in an as-yet-unsaved file
-if !exists(':DiffOrig')
-  command DiffOrig vert new | set buftype=nofile | read ++edit # | 0d_
-      \ | diffthis | wincmd p | diffthis
-endif

+ 0 - 20
vim/settings/white_space.vim

@@ -1,20 +0,0 @@
-" Highlight trailing whitespace, except where still typing
-autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/
-autocmd InsertLeave * match ExtraWhitespace /\s\+$/
-
-" Remove trailing spaces before save
-autocmd BufWritePre * call StripTrailingWhitespace()
-function! StripTrailingWhitespace()
-  " Save last search, and cursor position.
-  let _s=@/
-  let l = line(".")
-  let c = col(".")
-  " Do it.
-  %s/\s\+$//e
-  " Restore previous search history, and cursor position
-  let @/=_s
-  call cursor(l, c)
-endfunction
-
-" Convert tabs to spaces
-nnoremap <silent> <Leader><Tab> :%s/<Tab>/  /g<CR>

+ 238 - 74
vim/vimrc

@@ -1,106 +1,270 @@
-" Being vi-compatible disables more advanced features
-set nocompatible
+" vim: set sw=2 ts=2 sts=2 et tw=78 foldmarker={{{,}}} foldlevel=0 foldmethod=marker:
+"
+" The Main VIMRC
+"
+" Configures have-anywhere, plugin-independent settings and mappings.
 
-" Clear all existing autocommands first to avoid unwanted side effects
-if has("autocmd")
+" Loads plugins from `~/dotfiles/plugins.vim`.
+" Loads additional settings from `~/dotfiles/vim/settings/*.vim`.
+"
+
+" General Behaviours {{{
+set nocompatible               " Use vim's full features (not vi-compatible)
+set mouse=a                    " Mouse for scrolling and resizing splits
+set modeline                   " Support vim modelines at the top of files
+set splitbelow                 " Normal splits open below current
+set splitright                 " Vertical splits open right of current
+set hidden                     " Change buffers without unsaved-warnings
+set backspace=indent,eol,start " Backspace for dummies - deletes most things
+set virtualedit=block          " Move cursor freely in visual block mode
+if has('autocmd')
+
+  " Clear existing autocommands to avoid side effects
   autocmd!
-  " Automatically detect file types.
+
+  " Detect a file's type and use plugin/indent configs if available
   filetype plugin indent on
-endif
 
-" Syntax highlighting.
-if has("syntax")
-  syntax enable
-endif
+  " Restore cursor position in a file (:help last-position-jump)
+  autocmd BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$")
+                     \|   execute "normal! g`\""
+                     \| endif
 
-set nowrap
-set cursorline     " Highlight current line
-set expandtab      " convert tab characters into spaces
-set tabstop=2      " actual tab press distance
-set softtabstop=2  " let backspace delete by indents
-set shiftround     " indent to nearest tabstops
-set shiftwidth=2   " amount to indent with > and <
-set smarttab       " backspace tabs where appropriate even if spaces
-set textwidth=80   " try to keep text within 80 characters
-set colorcolumn=+1 " mark out the limits of the textwidth
-set hidden         " allow changing buffers without unsaved-warnings e.g. for argdo
-
-set mouse=a                    " Mouse support enabled.
-set splitright                 " Puts new vsplit windows to the right of the current
-set splitbelow                 " Puts new split windows to the bottom of the current
-set backspace=indent,eol,start " Backspace for dummies
-set linespace=0                " No extra spaces between rows
-set relativenumber             " Show line numbers relative to current line, and
-set number                     " Show the actual line number on current line.
-set showmatch                  " Show matching brackets/parenthesis
-set incsearch                  " Find as you type search
-set hlsearch                   " Highlight search terms
-set ignorecase                 " Case insensitive search
-set smartcase                  " Case sensitive when uc present
-set winminheight=0             " Windows can be 0 line high
-set wildmenu                   " Show list instead of just completing
-set modeline                   " Support vim modelines at the top of files
-set whichwrap=b,s,h,l,<,>,[,]  " Backspace and cursor keys wrap too
-set shortmess+=filmnrxoOtT     " Abbrev. of messages (reduces 'hit enter')
-set scrolloff=5                " Minimum lines to keep above and below cursor
-set sidescroll=1
-set sidescrolloff=10
-set linebreak                  " Break on words when wrapping.
-
-set list
-set listchars=tab:>\ ,extends:#,nbsp:#
+  " Git commit exception - keep cursor at start of file
+  autocmd FileType gitcommit call cursor(1, 1)
+endif
+" }}}
 
-" Persistent undo is great!
+" Persistent Undo {{{
 if has('persistent_undo')
-  set undofile
+  set undofile          " Keep undo history even when files are closed
   set undolevels=1000   " Max changes that can be undone
   set undoreload=10000  " Max lines to save for undo on a buffer reload
 endif
+" }}}
+
+" Vim Folders {{{
+
+" Store vim-related files in `~/.vim*` folders (e.g. `~/.vimswap`) instead of
+" at the currently-editted file's location
+let folders = {}
+if &swapfile   | let folders['swap']   = 'directory' | endif
+if &backup     | let folders['backup'] = 'backupdir' | endif
+if has('persistent_undo')
+  if &undofile | let folders['undo']   = 'undodir'   | endif
+endif
+
+for [folder, setting] in items(folders)
+  let path = expand('~/.vim'.folder.'/')
+  " Create the folders
+  if exists('*mkdir') && !isdirectory(path)
+    call mkdir(path, 'p')
+  endif
+  " Use the folders
+  if isdirectory(path)
+    execute 'set' setting.'='.path
+  else
+    echo 'Warning! No folder:' path
+  endif
+endfor
+" }}}
+
+" Tabs and Whitespace {{{
+set expandtab      " Convert tabs to spaces
+set tabstop=2      " Number of spaces to a tab
+set softtabstop=2  " Let backspace delete by indents
+set shiftround     " Indent to nearest tabstops
+set shiftwidth=2   " Amount to indent with > and <
+set smarttab       " Backspace tabs where appropriate even if spaces
+if has('autocmd')
+
+  " Highlight trailing whitespace
+  autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/
+  autocmd InsertLeave * match ExtraWhitespace /\s\+$/
+
+  " Remove trailing whitespace on save
+  autocmd BufWritePre * call RemoveTrailingWhitespace()
+  function! RemoveTrailingWhitespace()
+    let _s=@/ | let l = line(".") | let c = col(".")  " Save search and cursor
+    %s/\s\+$//e                                       " Remove whitespace
+    let @/=_s | call cursor(l, c)                     " Restore settings
+  endfunction
+endif
+" }}}
+
+" Search {{{
+set hlsearch    " Highlight search terms
+set ignorecase  " Case insensitive search
+set incsearch   " Find as you type search
+set smartcase   " Case sensitive when uc present
+" }}}
+
+" Visuals {{{
+set colorcolumn=+1                      " Highlight the textwidth limit
+set cursorline                          " Highlight current line
+set list                                " Display unprintables (like tabs)
+set listchars=tab:>\ ,extends:#,nbsp:#  " Customise unprintables
+set scrolloff=5                         " Lines to keep above/below cursor
+set shortmess+=filmnrxoOtT              " Abbrev. of messages
+set showmatch                           " Show matching brackets/parenthesis
+set matchpairs+=<:>                     " Match <> as a pair, not just ()[]{}
+set sidescroll=1                        " Side-ways scroll speed
+set sidescrolloff=10                    " Columns to keep left/right of cursor
+set wildmenu                            " Ex command tab-completion shows list
+if has('syntax')
+  syntax enable                         " Syntax highlighting
+endif
+set number                              " Show line numbers
+if v:version >= 703
+  set relativenumber                    " Numbers relative to current line
+endif
+" }}}
+
+" Folding {{{
+if has('folding')
+  set foldenable
+  set foldmethod=indent  " Fold lines based on indentation levels
+  set foldlevel=10       " Files start mostly unfolded, start 10 indents deep
+endif
+" }}}}
 
-" Join (J) options
+" Text Wrapping {{{
+set textwidth=80               " Try to keep text within 80 chars
+set nowrap                     " Start without text wrapping
+set whichwrap=b,s,h,l,<,>,[,]  " Backspace and cursor keys wrap too
+set linebreak                  " Break on words when wrapping
+" }}}
+
+" Join (J) Behaviour {{{
 set nojoinspaces        " Prevents inserting two spaces after punctuation
 if v:version > 703 || v:version == 703 && has("patch541")
-  set formatoptions+=j  " Remove comment characters when joining comment lines.
+  set formatoptions+=j  " Remove comment chars when joining comment lines
 endif
+" }}}
 
-""""""""
-"" Mappings
-""""""""""""""""""""""""""""""""""""""""""""""""""""""
+" Status Line {{{
+set laststatus=2  " always show the status line
+set showcmd       " display command keypresses on the last line
+" }}}
 
+" Mappings {{{
+
+" <Space> is a very convenient leader key
 let mapleader = ' '
 
-" Save changes to a file
-nmap <silent> <Leader>w :up<CR>
+" Reload vimrc settings
+map <leader>s :source $MYVIMRC<CR>:echo "vimrc reloaded..."<CR>
+
+  " Buffers {{{
+
+  " Save changes to a buffer
+  map <silent> <Leader>w :up<CR>
+
+  " Close a buffer
+  map <silent> <Leader>q :q<CR>
+
+  " List (:ls) all buffers, <CR> to close, or [number]<CR> to go to one
+  map <Leader>l :buffers<CR>:buffer<Space>
+
+  " Go to a buffer with [number]<CR>
+  nmap <silent> <expr> <CR> (v:count > 0) ? ':<C-U>b'.v:count.'<CR>' : '<CR>'
+  " }}}
+
+  " Movement {{{
+
+  " Jump to start and end of line with shift
+  map H ^
+  map L $
+
+  " Move by screen lines when wrapped (g-movements)
+  for key in ['j', 'k', '0', '^', '$']
+    for mode in ['n', 'o', 'x']
+      execute mode.'map <silent> <expr>' key '&wrap ? "g'.key.'" : "'.key.'"'
+    endfor
+  endfor
+
+  " Move between splits easily
+  map <C-j> <C-w>j
+  map <C-k> <C-w>k
+  map <C-h> <C-w>h
+  map <C-l> <C-w>l
+  " }}}
+
+  " Visuals {{{
 
-" Close a file
-nmap <silent> <Leader>q :q<CR>
+  " Adjust viewports to the same size
+  map <Leader>= <C-w>=
 
-" More convenient escape
-inoremap kj <Esc>
-inoremap jk <Esc>
+  " Half-screen horizontal scrolling instead of full-screen
+  map zl zL
+  map zh zH
 
-" Yank from the cursor to the end of the line, to be consistent with C and D.
-nnoremap Y y$
+  " Backspace to hide search highlight temporarily
+  nmap <silent> <backspace> :nohlsearch<CR>
 
-" Remap vim's 'increment next number' to <C-b> since <C-a> is used by tmux.
-nnoremap <C-b> <C-a>
+  if v:version >= 703
+    " Toggle both types of line numbers together
+    map <Leader>n :set number! relativenumber! number?<CR>
+  endif
+  " }}}
 
-" Allow using the repeat operator with a visual selection (!)
-" http://stackoverflow.com/a/8064607/127816
-vnoremap . :normal .<CR>
+  " Folding {{{
+  if has('folding')
 
-""""""""
-"" Load Plugins
-""""""""""""""""""""""""""""""""""""""""""""""""""""""
+    " Toggle the fold of the current line with double-space
+    nmap <silent> <expr> <Leader><Space> foldlevel('.') ? 'za' : '<Space>'
 
+    " Set fold level 0-9 with zf[number]
+    for lvl in range(10)
+      execute 'nmap <silent> zf'.lvl.' :set foldlevel='.lvl.'<CR>'
+    endfor
+  endif
+  " }}}
+
+  " Editing {{{
+
+  " Yank to end of line. Consistent with `C` and `D`
+  map Y y$
+
+  " More convenient escape
+  imap kj <Esc>
+  imap jk <Esc>
+
+  " Remap number incrementing to `<C-c>`. For when `<C-a>` is used by tmux
+  map <C-c> <C-a>
+
+  " Convert tabs to spaces
+  map <silent> <Leader><Tab> :retab<CR>
+
+  " Toggle paste mode - no autoindenting of pasted material
+  nmap <silent> <F2> :set paste! paste?<CR>
+  set pastetoggle=<F2>
+
+  " Search for version control conflict markers
+  map <Leader>c /\v^[<\|=>]{7}( .*\|$)<CR>
+  " }}}
+" }}}
+
+" Commands {{{
+if has('user_commands')
+
+  " View unsaved changes in a file (:help DiffOrig)
+  command! DiffOrig vert new | set buftype=nofile | read ++edit # | 0d_
+        \| diffthis | wincmd p | diffthis
+
+  " Insert a date/time on the next line
+  command! Date :put = strftime('%d/%m/%Y %I:%M%p')
+endif
+" }}}
+
+" Load Plugins {{{
 if filereadable(expand("~/dotfiles/vim/plugins.vim"))
   source ~/dotfiles/vim/plugins.vim
 endif
+" }}}
 
-""""""""
-"" Load Settings Files
-""""""""""""""""""""""""""""""""""""""""""""""""""""""
-
+" Load Extra Settings {{{
 for filePath in split(globpath('~/dotfiles/vim/settings', '*.vim'), '\n')
   execute 'source' filePath
 endfor
+" }}}