This commit is contained in:
Reed Esau
2013-12-24 22:48:32 -07:00
commit f1d22657fd
6 changed files with 1093 additions and 0 deletions

1
CONTRIBUTING.markdown Normal file
View File

@@ -0,0 +1 @@
Tips on contributing.

0
LICENSE Normal file
View File

355
README.markdown Normal file
View File

@@ -0,0 +1,355 @@
# `themata.vim`
_Manage the look and feel of your Vim text editor_
* Written in pure Vimscript for recent versions of MacVim, gVim, Vim, etc.
* Stays out of your way, except where you want it
* No predefined key mappings that could interfere with your other mappings
* Support for font and fullscreen settings in GUI-based Vim
* Integrates with [airline][https://github.com/bling/vim-airline], another `themeable` plugin
## Why `themata`?
Many Vim users will keep things simple by sticking with a single theme that suits their needs, configuring it in their `.vimrc` by setting colorscheme, `guifont`, number, status line, etc.. Nothing wrong with that approach.
But you may instead want to configure the visual details of Vim to match the task at hand, or even to suit your mood. For example, you might choose a theme that is less fatiguing to your eyes given the ambient lighting conditions, where you'll have a muted theme for a dark room and a high-contrast theme for use in a bright one.
Writing code, you may want a status bar, ruler, transparency and a programming font. But if you're writing an essay or screenplay, you may want the screen stripped of all extraneous detail, with a traditional font and generous left and right margins.
You may want to complement a colorscheme with a particular typeface -- a lightweight anti-aliased typeface like Adobe's _Source Code Pro ExtraLight_ may look great against a black background but be unreadable against a white one. Or for a given typeface you may want a specific [leading][http://en.wikipedia.org/wiki/Leading] as supported with Vim's `linespace`.
Managing such an environment in Vim has traditionally been a hassle. The `themata` plugin is intended to provide the Vim user more flexibility and convenience.
## What theme properties can I set?
For each theme you specify one or more properties.
For console or GUI Vim:
* `laststatus` (0, 1, or 2) - _controls the visibility of the status bar_
* `ruler` - _as alternative to status bar, shows minimal position details in lower right_
* `colorscheme` - _set the colors for all windows_
* `background` (dark or light) - _some colorschemes can be further configured via background_
* `sign-column` - _optional two-character gutter on left-side of window_
* `airline-theme` - _plugin for theming your status bar_
* `sign-column-color-fix` - _temporarily modifies colorscheme to force gutter background_
* `diff-color-fix` - _temporarily modifies colorscheme to force diff character color_
* `fold-column-color-mute` - _temporarily modifies colorscheme to hide indicators in foldcolumn_
* `force-redraw` - _if 1, forces a `redraw!` after `themata` makes changes_
For GUI-based Vim only:
* `typeface`, `font-size`, and `linespace` - _be specific about typography_
* `fullscreen` and `fullscreen-background-color-fix` - _force a switch to fullscreen, with optional change of color of the background (or border)_
* `columns` and `lines` - _manage the width of margins in `fullscreen` mode_
* `transparency` (0-100) - _view details of window and desktop beneath Vim_
* Check `:help themata` for details.
## Basic Usage
* Run `:ThemataFirst` to invoke `themata` and choose the first theme. Your themes will be ordered alphabetically.
```vim
:ThemataFirst " select the first theme
:ThemataNext " select the next theme
:ThemataPrevious " select the previous theme
:ThemataRandom " select a random theme
:ThemataOriginal " revert to the original theme
```
`themata` does not map any keys by default, but you can easily do so in your `.vimrc` file, like this:
```vim
nmap <Leader>t <Plug>ThemataNext
nmap <Leader>T <Plug>ThemataPrevious
```
...where with the default leader key of `\`, `\t` would select the next theme in your list, as ordered alphabetically.
A few of Vim's standard `colorschemes` are configured as default themes, but you'll likely want to override them with your own, like this:
```
let g:themata#themes = {
\ 'bubblegum' : { 'typeface': 'CosmicSansNeueMono',
\ 'sign-column-color-fix': 1,
\ 'transparency': 10,
\ },
\ 'desert' : { 'sign-column': 0,
\ },
\ 'jellybeans' : { 'typeface': 'Droid Sans Mono',
\ 'font-size': 20,
\ 'laststatus': 0,
\ 'ruler': 1,
\ },
\ 'matrix' : { 'colorscheme': 'base16-greenscreen',
\ 'typeface': 'Dot Matrix',
\ 'laststatus': 0,
\ 'linespace': 9,
\ 'transparency': 10,
\ },
\ 'reede_dark' : { 'typeface': 'Source Code Pro ExtraLight',
\ 'airline-theme': 'badwolf',
\ },
\ 'reede_light': { 'typeface': 'Luxi Mono',
\ 'columns': 75,
\ 'font-size': 20,
\ 'fullscreen': 1,
\ 'laststatus': 0,
\ 'linespace': 9,
\ 'sign-column': 1,
\ },
\ 'solar_dark' : { 'colorscheme': 'solarized',
\ 'background': 'dark',
\ 'diff-color-fix': 1,
\ 'sign-column-color-fix': 1,
\ 'signcolumn-color-fix': 1,
\ 'typeface': 'Source Code Pro Light',
\ },
\ 'solar_lite' : { 'colorscheme': 'solarized',
\ 'background': 'light',
\ 'font-size': 20,
\ 'signcolumn-color-fix': 1,
\ },
\ }
```
If you don't specify a `colorscheme`, `themata` will assume it matches your theme name.
You can also specify a dictionary of default values, to be shared by all of your themes.
```
let g:themata#defaults = {
\ 'airline-theme': 'jellybeans',
\ 'fullscreen-background-color-fix': 1,
\ 'laststatus': 2,
\ 'font-size': 20,
\ 'transparency': 0,
\ }
```
Note that an explicit setting in a theme will always override these defaults.
Note also that `themata` stays out of your way, ignoring any settings that you aren't explicitly setting through your `themata` configuration.* For example, you can `set guifont=` in your .gvimrc independent of your `themata` configuration.
* * the one exception is `fuoptions` discussed below
## Installation
Install using Pathogen, Vundle, Neobundle, or your favorite Vim package manager.
## Configuration
```
set nocompatible
filetype off
```
## GUI fullscreen capabilities
`themata` supports fullscreen capabilities in a GUI-based Vim, including typeface, font-size, lines, columns, linespace, transparency and even the fullscreen background.
Note that once invoked, `themata` will override your fullscreen settings, specifically `fuoptions` to get better control over lines and columns and the fullscreen background.
## Column sizing
You may wish to adjust the columns while in full screen. Map to Command-9 and Command-0 in your `.vimrc` with:
```
nmap <silent> <D-9> <Plug>ThemataNarrow
nmap <silent> <D-0> <Plug>ThemataWiden
```
## FAQ
### Q: I want to set `cursorline`, `wrap`, `foldcolumn`, `list`, `number`, `relativenumber`, `textwidth`, etc. in my themes.
`themata` focuses exclusively on global settings. The settings above are not globally-scoped but are instead scoped to individual buffers and windows. These are best set using the existing `FileType` facility in Vim.
In addition, settings like `textwidth` will modify your documents. This plugin strenuously avoids doing anything to change your documents.
To your `.vimrc` add
```
filetype plugin on
" defaults for all buffers/windows
set nocursorline
set foldcolumn=0
set list
set nonumber
set norelativenumber
set nowrap
```
Then for each `filetype` that you wish to support with specific settings, create a file in the `~/.vim/after/ftplugin` directory.
For example, to support custom settings for `python` files, create a file `~/.vim/after/ftplugin/python.vim` containing:
```
" python-specific settings
set cursorline
set number
```
Then a cursor line and line numbering will be present whenever you edit a python file.
### Q: Using MacVim, the fullscreen background color isn't working as expected. How do I change its behavior?
To have the fullscreen background's color set by `themata`, enter the following in OSX Terminal:
```
$ defaults write org.vim.MacVim MMNativeFullScreen 0
```
Or, if you prefer your fullscreen window to float against a standard background:
```
$ defaults write org.vim.MacVim MMNativeFullScreen 1
```
### Q: How can I configure Vim to emulate soft-wrapping markdown editors like IAWriter?
It works best in GUI Vim's fullscreen. Several steps are involved:
(1) Install a `markdown.vim` plugin from [plasticboy][https://github.com/plasticboy/vim-markdown] or [tpope][https://github.com/tpope/vim-markdown].
(2) Configure your `~/.gvimrc` to disable the tool bar, etc.
```
set antialias
set guicursor+=a:blinkon0 " disable cursor blink
set guioptions-=r "kill right scrollbar
set guioptions-=l "kill left scrollbar
set guioptions-=L "kill left scrollbar multiple buffers
set guioptions-=T "kill toolbar
```
(3) Edit `~/.vim/after/ftplugin/markdown.vim` to control editing behavior and buffer-specific settings:
```
" IAWriter-like settings (soft-wrap mode)
setlocal textwidth=0
setlocal wrap
setlocal complete+=k
setlocal complete+=kspell
setlocal complete+=s
setlocal nocursorline
setlocal dictionary+=/usr/share/dict/words
setlocal display+=lastline
setlocal formatoptions+=l " long lines not broken in insert mode
setlocal linebreak " default breakat ' ^I!@*-+;:,./?'
setlocal nojoinspaces " only one space after a .!?
setlocal nolist
setlocal nonumber
setlocal norelativenumber
setlocal spell spelllang=en_us
setlocal spellfile=~/.vim/spell/en.utf-8.add
setlocal thesaurus+=~/.vim/thesaurus/mthesaur.txt
setlocal virtualedit=
setlocal wrapmargin=0
nnoremap <buffer> <silent> $ g$
nnoremap <buffer> <silent> 0 g0
nnoremap <buffer> <silent> j gj
nnoremap <buffer> <silent> k gk
vnoremap <buffer> <silent> $ g$
vnoremap <buffer> <silent> 0 g0
vnoremap <buffer> <silent> j gj
vnoremap <buffer> <silent> k gk
```
(4) Finally, add a theme configured to your tastes. Here's an example:
```
let g:themata#themes = {
\ 'mark_lite' :{ 'colorscheme': 'solarized',
\ 'background': 'light',
\ 'columns': 75,
\ 'font-size': 20,
\ 'fullscreen': 1,
\ 'laststatus': 0,
\ 'linespace': 8,
\ 'typeface': 'Menlo',
\ },
...
\ }
```
Console-based emulation is trickier, as there's no easy way to create generous left and right margins. You can approximate it by switching from soft-wrap to hard line breaks with additional changes to `~/.vim/after/ftplugin/markdown.vim`:
```
setlocal foldcolumn=12 " add a generous left column
setlocal nowrap " replaces 'set wrap'
setlocal textwidth=70 " replaces 'set textwidth=0'
```
Note that this chooses hard line breaks over soft-wrapping and thus may not be desirable. You can also use the following setting in your theme to hide the indicators in the fold column.
```
let g:themata#themes = {
\ 'YOURTHEME' :{ 'fold-column-color-mute': 1,
...
\ },
...
\ }
```
Also, check out:
* [vimroom][https://github.com/mikewest/vimroom/blob/master/plugin/vimroom.vim]
* [vim-writeroom][https://github.com/jamestomasino/vim-writeroom]
* [vim-zenmode][https://github.com/mmai/vim-zenmode]
* [df_moded][https://github.com/nielsadb/df_mode.vim]
### Q: In Mac OSX I switch to fullscreen via Control+Command+F and the screen is blank!
You can refresh via `:redraw!`
(if anybody knows how to fix this, let me know!)
As an alternative to key command you can force fullscreen in a theme with:
```
let g:themata#themes = {
\ 'bubblegum' : { 'fullscreen': 1,
\ ...
\ },
\ ...
\ }
```
## Where to find
TODO GUI Vim
TODO Colorschemes
## Monospaced fonts
Many monospaced fonts are available for free. Note that your computer probably has several installed, such as `Menlo` on OSX.
### Popular monospaced fonts
* [Anonymous Pro](https://www.google.com/fonts/specimen/Anonymous+Pro)
* [CosmicSansNeueMono](https://github.com/belluzj/cosmic-sans-neue)
* [Courier Prime](http://quoteunquoteapps.com/courierprime/)
* [Cousine](http://www.google.com/fonts/specimen/Cousine)
* [Cutive Mono](http://www.google.com/fonts/specimen/Cutive+Mono)
* [DejaVu Sans Mono](http://dejavu-fonts.org/wiki/Download)
* [Droid Sans Mono](http://www.google.com/fonts/specimen/Droid+Sans+Mono)
* [Hermit](https://pcaro.es/p/hermit/)
* [Inconsolata](http://www.google.com/fonts/specimen/Inconsolata)
* [Linux Libertine Mono O](http://sourceforge.net/projects/linuxlibertine/)
* [Liberation](https://fedorahosted.org/liberation-fonts/)
* [Luxi Mono Regular](http://www.fontsquirrel.com/fonts/Luxi-Mono)
* [Meslo](https://github.com/andreberg/Meslo-Font)
* [Oxygen Mono](https://www.google.com/fonts/specimen/Oxygen+Mono)
* [PT Mono](http://www.google.com/fonts/specimen/PT+Mono)
* [Share Tech Mono](http://www.google.com/fonts/specimen/Share+Tech+Mono)
* [Source Code Pro](http://www.google.com/fonts/specimen/Source+Code+Pro)
* [Ubuntu Mono](https://www.google.com/fonts/specimen/Ubuntu+Mono)
## Similar Projects
If this project is not to your liking, you might enjoy:
* [vim-ultimate-colorscheme-utility][https://github.com/biskark/vim-ultimate-colorscheme-utility]
* [stylish][https://github.com/mislav/stylish.vim]
* [vim-session][https://github.com/xolox/vim-session]
* [vim-obsession][https://github.com/tpope/vim-obsession]

458
autoload/thematic.vim Normal file
View File

@@ -0,0 +1,458 @@
" Autoload portion of plugin/themata.vim.
"
" Credit for some font regex/functions: https://github.com/drmikehenry/vim-fontsize
if exists("autoloaded_themata")
finish
endif
let autoloaded_themata = 1
" # FONT REGEXES {{{1
" Regex values for each platform split guifont into three
" sections (\1, \2, and \3 in capturing parentheses):
" - prefix
" - size (possibly fractional)
" - suffix (possibly including extra fonts after commas)
if has("gui_macvim")
" gui_macvim: Courier\ New:h11
let s:regex = '\(.\{-}\):h\(\d\+\)'
elseif has("gui_gtk2")
" gui_gtk2: Courier\ New\ 11
let s:regex = '\(.\{-} \)\(\d\+\)\(.*\)'
elseif has("gui_photon")
" gui_photon: Courier\ New:s11
let s:regex = '\(.\{-}\):s\(\d\+\)\(.*\)'
elseif has("gui_kde")
" gui_kde: Courier\ New/11/-1/5/50/0/0/0/1/0
let s:regex = '\(.\{-}\)\/\(\d\+\)\(.*\)'
"elseif has("x11")
" " gui_x11: -*-courier-medium-r-normal-*-*-180-*-*-m-*-*
" let s:regex = '\(.\{-}-\)\(\d\+\)\(.*\)'
else
" gui_other: Courier_New:h11:cDEFAULT
let s:regex = '\(.\{-}\):h\(\d\+\)\(.*\)'
endif
" }}}1
" # FUNCTIONS {{{1
" # Function: s:encodeFont {{{2
function! s:encodeFont(font)
if has("iconv") && exists("g:themata#encoding")
let encodedFont = iconv(a:font, &enc, g:themata#encoding)
else
let encodedFont = a:font
endif
return encodedFont
endfunction
" }}}2
" # Function: s:decodeFont {{{2
function! s:decodeFont(font)
if has("iconv") && exists("g:themata#encoding")
let decodedFont = iconv(a:font, g:themata#encoding, &enc)
else
let decodedFont = a:font
endif
return decodedFont
endfunction
" }}}2
" # Function: s:getSize {{{2
function! s:getSize(font, fallback)
let l:decodedFont = s:decodeFont(a:font)
if match(l:decodedFont, s:regex) != -1
" Add zero to convert to integer.
let l:size = 0 + substitute(l:decodedFont, s:regex, '\2', '')
else
let l:size = 0 + fallback
endif
return l:size
endfunction
" }}}2
" # Function: s:getTypeface {{{2
function! s:getTypeface(font, fallback)
let decodedFont = s:decodeFont(a:font)
if match(decodedFont, s:regex) != -1
let l:typeface = substitute(decodedFont, s:regex, '\1', '')
else
let l:typeface = a:fallback
endif
return l:typeface
endfunction
" }}}2
" # Function: s:getThemeName {{{2
function! s:getThemeName(mode)
let l:avail_names = sort(keys(g:themata#themes))
let l:avail_count = len(l:avail_names)
let l:new_n = -1
if a:mode == '#first'
let l:new_n = 0
elseif a:mode == '#last'
let l:new_n = l:avail_count - 1
elseif a:mode == '#random'
let l:new_n =
\ str2nr(matchstr(reltimestr(reltime()), '\v\.@<=\d+')[1:])
\ % l:avail_count
elseif a:mode == '#next' || a:mode == '#previous'
let l:current_n = index(l:avail_names, g:themata#theme_name)
if a:mode == '#next'
if l:current_n == -1 || l:current_n == l:avail_count - 1
let l:new_n = 0
else
let l:new_n = l:current_n + 1
endif
elseif a:mode == '#previous'
if l:current_n <= 0
let l:new_n = l:avail_count - 1
else
let l:new_n = l:current_n - 1
endif
endif
endif
if l:new_n == -1
return a:mode
else
return l:avail_names[l:new_n]
endif
endfunction
" }}}2
" # Function: s:getThemeValue {{{2
" Obtain value for theme property, falling back to either user-specified
" defaults or the original value.
function! s:getThemeValue(th, key_name, ultimate_fallback_value)
if has_key(g:themata#defaults, a:key_name)
let l:fallback_value = get(g:themata#defaults, a:key_name)
elseif has_key(g:themata#original, a:key_name)
let l:fallback_value = get(g:themata#original, a:key_name)
else
let l:fallback_value = a:ultimate_fallback_value
endif
return get(a:th, a:key_name, l:fallback_value)
endfunction
" }}}2
" # Function: s:updateFullscreenBackground {{{2
" Note that bgcolor may not be available at initial program load
function! s:updateFullscreenBackground()
" #123456 => #00123456
let l:bgcolor=synIDattr(hlID('Normal'), 'bg#')
if l:bgcolor =~ '#[0-9a-fA-F]\+'
let l:border_color = substitute(l:bgcolor, '#', '#00', '')
" Note that this will blow away existing options, such
" as maxhorz and maxvert, but we removed those earlier.
execute 'set fuoptions=background:' . l:border_color
endif
endfunction
" }}}2
" # Function: s:airline {{{2
function! s:airline(th)
" set the g:airline_theme variable and refresh
"https://github.com/bling/vim-airline/wiki/Screenshots
if exists(':AirlineRefresh')
" attempt to preserve original airline theme if not yet set
if !has_key(g:themata#original, 'airline-theme') && exists('g:airline_theme')
let g:themata#original['airline-theme'] = g:airline_theme
endif
let l:al = s:getThemeValue(a:th, 'airline-theme', '')
if l:al != ''
let g:airline_theme = l:al
else
let l:airline_supported = {
\ '.*solarized.*': 'solarized',
\ '.*zenburn.*': 'zenburn',
\ 'Tomorrow.*': 'tomorrow',
\ 'base16.*': 'base16',
\ 'jellybeans.*': 'jellybeans',
\ 'mo[l|n]okai': 'molokai',
\ 'wombat.*': 'wombat',
\ }
if exists('g:colors_name')
for l:item in items(l:airline_supported) | if g:colors_name =~ l:item[0]
let g:airline_theme = l:item[1]
break
endif | endfo
endif
endif
AirlineRefresh
endif
endfunction
" }}}2
" # Function: s:composeGuifontString {{{2
function! s:composeGuifontString(typeface, fontsize)
" TODO need support for platform-specific suffixes
let l:encoded_typeface = s:encodeFont(a:typeface)
if has('gui_macvim')
"set guifont=Courier\ New\:h11
let l:gf = substitute(l:encoded_typeface, ' ', '\\ ', 'g') . '\:h' . a:fontsize
elseif has('gui_gtk') || has('gui_gtk2') || has('gui_gnome')
"set guifont=Courier\ New\ 11
let l:gf = substitute(l:encoded_typeface, ' ', '\\ ', 'g') . '\ ' . a:fontsize
elseif has('gui_photon')
"set guifont=Courier\ New:s11
let l:gf = substitute(l:encoded_typeface, ' ', '\\ ', 'g') . ':s' . a:fontsize
elseif has('gui_kde') "|| has('gui_qt')
"set guifont=B&H\ LucidaTypewriter/9/-1/5/50/0/0/0/1/0
"set guifont=Courier\ New/11/-1/5/50/0/0/0/1/0
let l:gf = substitute(l:encoded_typeface, ' ', '\\ ', 'g') . '/' . a:fontsize
"elseif has("x11") && !(has("gui_gtk2") || has("gui_kde") || has("gui_photon"))
" "set guifont=-*-courier-medium-r-normal-*-*-180-*-*-m-*-*
" " 18.0pt Courier
" "set gfn=-*-lucidatypewriter-medium-r-normal-*-*-95-*-*-m-*-*
" " 9.5pt LucidaTypewriter
" let l:gf = '-*-' . tolower(l:tf) . '-medium-r-normal-*-*-' . (l:fs*10) . '-*-*-m-*-*'
elseif has('win32') || has('win64') "|| has('gui_win32') || has('gui_win64')
"set guifont=courier_new:h11
"set guifont=Lucida_Console:h8:cANSI
let l:gf = substitute(l:encoded_typeface, ' ', '_', 'g') . ':h' . a:fontsize
else
echoerr 'GUI platform not yet supported'
let l:gf = ''
endif
return l:gf
endfunction
" }}}2
" # Function: s:setGuifont {{{2
function! s:setGuifont(gf)
if strlen(a:gf)
try
execute 'set guifont=' . a:gf
return 1
catch /E596/
echohl ErrorMsg
echo 'Unable to set guifont=' . a:gf
echohl None
endtry
endif
return 0
endfunction
" }}}
" # Function: s:guiFont {{{2
function! s:guiFont(th)
" attempt to preserve original font if not yet set
if !has_key(g:themata#original, 'typeface')
let l:typeface = s:getTypeface(&guifont, '')
if l:typeface != ''
let g:themata#original['typeface'] = l:typeface
endif
endif
if !has_key(g:themata#original, 'font-size')
let l:size = s:getSize(&guifont, 0)
if l:size != 0
let g:themata#original['font-size'] = l:size
endif
endif
let l:tf = s:getThemeValue(a:th, 'typeface', '')
let l:fs = s:getThemeValue(a:th, 'font-size', -1)
" TODO support list of typefaces with most desired as first in list
let l:gf = s:composeGuifontString(l:tf, l:fs)
if l:gf != ''
call s:setGuifont(l:gf)
endif
endfunction
" }}}2
" # Function: s:guiMisc {{{2
function! s:guiMisc(th)
let l:tr = s:getThemeValue(a:th, 'transparency', -1)
if l:tr > 100
let l:tr = 100
endif
if l:tr > 0
try
execute 'set transparency=' . l:tr
catch
echohl ErrorMsg
echo 'Unable to set transparency=' . l:tr
echohl None
endtry
endif
let l:ls = s:getThemeValue(a:th, 'linespace', -1)
if l:ls != -1
try
execute 'set linespace=' . l:ls
catch
echohl ErrorMsg
echo 'Unable to set linespace=' . l:ls
echohl None
endtry
endif
if has('fullscreen')
" Because it can be jarring to see fullscreen disable,
" we'll only enable it.
if !&fullscreen && s:getThemeValue(a:th, 'fullscreen', -1) == 1
try
set fullscreen
catch
echohl ErrorMsg
echo 'Fullscreen not supported'
echohl None
endtry
endif
" Have the fullscreen background match the text background
if s:getThemeValue(a:th, 'fullscreen-background-color-fix', 0)
call s:updateFullscreenBackground()
endif
endif
endfunction
" }}}2
" # Function: s:setColumnsAndLines {{{2
" If no explicit settings on lines and columns in
" either the theme or the defaults, then leave alone.
function! s:setColumnsAndLines(th)
let l:columns = s:getThemeValue(a:th, 'columns', 0)
if l:columns > 0
execute 'set columns=' . l:columns
elseif s:getThemeValue(a:th, 'maxhorz', 0)
set columns=999
endif
let l:lines = s:getThemeValue(a:th, 'lines', 0)
if l:lines > 0
execute 'set lines=' . l:lines
elseif s:getThemeValue(a:th, 'maxvert', 0)
set lines=999
endif
endfunction
" }}}2
" # Function: load {{{2
function! themata#load(mode)
if len(g:themata#themes) == 0
echohl WarningMsg | echo 'No themes found.' | echohl NONE
finish
endif
" attempt to preserve original colorscheme and its background
if !has_key(g:themata#original, 'colorscheme') && exists('g:colors_name')
let g:themata#original.colorscheme = g:colors_name
let g:themata#original.background = &background
endif
" Resolve theme_name from mode, where mode can be #first, #last, #next,
" #previous, #random, a colorscheme, a key in g:themata#themes, or the
" user's original settings.
if a:mode == '#original'
let l:theme_name = ''
let l:th = g:themata#original
else
let l:theme_name = s:getThemeName(a:mode)
let l:th = get(g:themata#themes, l:theme_name, {})
endif
" ------ Set colorscheme and background ------ {{{3
" assume the colorscheme matches the theme name if not explicit
let l:cs = get(l:th, 'colorscheme', l:theme_name)
try
execute 'colorscheme ' . l:cs
catch /E185:/
" no colorscheme matching the theme name, so fall back to original, if any
if has_key(g:themata#original, 'colorscheme')
let l:cs = g:themata#original.colorscheme
execute 'colorscheme ' . l:cs
endif
endtry
" use the original background, if not explicit and no default
let l:bg = s:getThemeValue(l:th, 'background', '')
if (l:bg == 'light' || l:bg == 'dark') && &background != l:bg
execute 'set background=' . l:bg
endif
" }}}3
" ------ Fix/mute colors ------ {{{3
if s:getThemeValue(l:th, 'sign-column-color-fix', 0)
" Ensure the gutter matches the text background
" TODO how about match the number background?
hi! SignColumn guifg=fg guibg=bg
endif
if s:getThemeValue(l:th, 'diff-color-fix', 0)
" Override diff colors
" TODO figure out what to do for cterm
hi! DiffAdd guifg=darkgreen guibg=bg "cterm=bold ctermbg=237 ctermfg=119
hi! DiffDelete guifg=darkorange guibg=bg "cterm=bold ctermbg=237 ctermfg=167
hi! DiffChange guifg=darkyellow guibg=bg "cterm=bold ctermbg=237 ctermfg=227
hi! DiffText guifg=fg guibg=bg
endif
if s:getThemeValue(l:th, 'fold-column-color-mute', 0)
" Ensure the fold column is blank, for non-distracted editing
hi! FoldColumn guifg=bg guibg=bg cterm=none ctermbg=none ctermfg=none
endif
" }}}3
" ------ Set sign column for all buffers ------ {{{3
" Force the display of a two-column gutter for signs, etc.
" The sign configuration is apparently buffer-scoped, so iterate
" over all listed buffers to force the sign column.
let l:sc = s:getThemeValue(l:th, 'sign-column', -1)
if l:sc == 1
" TODO how to auto-refresh/disable Signify, gitgutter, etc.?
sign define dummy
let l:b_all = range(1, bufnr('$'))
for l:b_no in filter(l:b_all, 'buflisted(v:val)')
execute 'sign place 9999 line=1 name=dummy buffer=' . l:b_no
endfor
elseif l:sc == 0
sign unplace *
endif
" }}}3
" ------ Set statusline, ruler, airline_theme ------ {{{3
" These are all globally-scoped settings
let l:ruler = s:getThemeValue(l:th, 'ruler', -1)
if l:ruler == 1
set ruler
elseif l:ruler == 0
set noruler
endif
call s:airline(l:th)
let l:ls = s:getThemeValue(l:th, 'laststatus', -1)
if l:ls > 2
let l:ls = 2
endif
if l:ls >= 0
execute 'set laststatus=' . l:ls
endif
" }}}3
" ------ Set GUI-only settings ------ {{{3
if has('gui_running')
call s:guiFont(l:th)
call s:guiMisc(l:th)
call s:setColumnsAndLines(l:th)
endif
" }}}3
let g:themata#theme_name = l:theme_name
if s:getThemeValue(l:th, 'force-redraw', 0)
redraw!
endif
endfunction
" }}}2
" # Function: adjustColumns {{{2
function! themata#adjustColumns(delta)
let l:nu_cols = &columns + a:delta
silent execute "set columns=" . l:nu_cols
endfunction
" }}}2
" }}}1
" vim:ts=2:sw=2:sts=2

163
doc/thematic.txt Normal file
View File

@@ -0,0 +1,163 @@
*themata.txt* Theme manager for VIM
Author: Reed Esau <http://esau.org/>
License: Same terms as Vim itself (see |license|)
This plugin is only available if 'compatible' is not set.
INTRODUCTION *themata* *:themata*
themata lets you quickly find, substitute, and abbreviate several variations
of a word at once. By default, three case variants (foo, Foo, and FOO) are
operated on by every command.
Two commands are provided. :themata is the most general interface.
:Subvert provides an alternative, more concise syntax for searching and
substituting.
>
:themata [options] {abbreviation} {replacement}
:themata -delete [options] {abbreviation}
:themata -search [options] {pattern}
:Subvert/{pattern}[/flags]
:themata!-search [options] {pattern}
:Subvert?{pattern}[?flags]
:themata -search [options] {pattern} {grep-arguments}
:Subvert /{pattern}/[flags] {grep-options}
:themata!-search [options] {pattern} {grep-arguments}
:Subvert!/{pattern}/[flags] {grep-options}
:[range]themata -substitute [options] {pattern} {replacement}
:[range]Subvert/{pattern}/{replacement}[/flags]
<
*:S*
In addition to the :Subvert command, a :S synonym is provided if not
already defined. This will be used in examples below.
PATTERNS *themata-patterns*
Patterns can include brace pairs that contain comma separated alternatives:
box{,es} => box, boxes, Box, Boxes, BOX, BOXES
For commands with a replacement, corresponding brace pairs are used in both
halves. If the replacement should be identical to the pattern, an empty
brace pair may be used. If fewer replacements are given than were given in
the pattern, they are looped. That is, {a,b} on the replacement side is the
same as {a,b,a,b,a,b,...} repeated indefinitely.
The following replaces several different misspellings of "necessary":
>
:%S/{,un}nec{ce,ces,e}sar{y,ily}/{}nec{es}sar{}/g
<
ABBREVIATING *themata-abbrev*
By default :themata creates abbreviations, which replace words automatically
as you type. This is good for words you frequently misspell, or as
shortcuts for longer words. Since these are just Vim abbreviations, only
whole words will match.
>
:themata anomol{y,ies} anomal{}
:themata {,in}consistant{,ly} {}consistent{}
:themata Tqbf The quick, brown fox jumps over the lazy dog
<
Accepts the following options:
-buffer: buffer local
-cmdline: work in command line in addition to insert mode
A good place to define abbreviations is "after/plugin/themata.vim",
relative to ~\vimfiles on Windows and ~/.vim everywhere else.
With a bang (:themata!) the abbreviation is also appended to the file in
g:themata_save_file. The default is "after/plugin/themata.vim", relative
to the install directory.
Abbreviations can be removed with :themata -delete:
>
themata -delete -buffer -cmdline anomol{y,ies}
<
SEARCHING *themata-search*
The -search command does a search in a manner similar to / key.
search. After searching, you can use |n| and |N| as you would with a normal
search.
The following will search for box, Box, and BOX:
>
:themata -search box
<
When given a single word to operate on, :Subvert defaults to doing a
search as well:
>
:S/box/
<
This one searches for box, boxes, boxed, boxing, Box, Boxes, Boxed, Boxing,
BOX, BOXES, BOXED, and BOXING:
>
:S/box{,es,ed,ing}/
<
The following syntaxes search in reverse.
>
:themata! -search box
:S?box?
<
Flags can be given with the -flags= option to :themata, or by appending them
after the separator to :Subvert. The flags trigger the following behaviors:
I: Disable case variations (box, Box, BOX)
v: Match inside variable names (match my_box, myBox, but not mybox)
w: Match whole words (like surrounding with \< and \>)
A |search-offset| may follow the flags.
>
:themata -search -flags=avs+1 box
:S?box{,es,ed,ing}?we
<
GREPPING *themata-grep*
Grepping works similar to searching, and is invoked when additional options
are given. These options are passed directly to the :grep command.
>
:themata -search box{,es}
:S /box{,es}/ *
:S /box/aw *.txt *.html
<
The slash delimiters must both be present if used with :Subvert. They may
both be omitted if no flags are used.
Both an external grepprg and vimgrep (via grepprg=internal) are supported.
With an external grep, the "v" flag behaves less intelligently, due to the
lack of look ahead and look behind support in grep regexps.
SUBSTITUTING *themata-substitute*
Giving a range switches :Subvert into substitute mode. This command will
change box -> bag, boxes -> bags, Box -> Bag, Boxes -> Bags, BOX -> BAG,
BOXES -> BAGS across the entire document:
>
:%themata -substitute -flags=g box{,es} bag{,s}
:%S/box{,es}/bag{,s}/g
<
The "c", "e", "g", and "n" flags can be used from the substitute command
|:s_flags|, along with the "a", "I", "v", and "w" flags from searching.
COERCION *themata-coercion* *cr*
themata's case mutating algorithms can be applied to the word under the cursor
using the cr mapping (mnemonic: CoeRce) followed by one of the following
characters:
c: camelCase
m: MixedCase
_: snake_case
s: snake_case
u: SNAKE_UPPERCASE
U: SNAKE_UPPERCASE
-: dash-case (not reversible)
For example, cru on a lowercase word is a slightly easier to type equivalent
to gUiw.
vim:tw=78:ts=8:ft=help:norl:

116
plugin/thematic.vim Normal file
View File

@@ -0,0 +1,116 @@
" =============================================================================
" File: plugin/themata.vim
" Description: Theme Manager for the Vim text editor
" Maintainer: Reed Esau <github.com/reedes>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
" =============================================================================
"
" TODO licensing
" TODO guioptions
" TODO screen capture
" TODO help file
" TODO command to support named theme, with custom completion
" TODO test from filetype
"for feature in ['autocmd',]
" if !has(feature)
" call syntastic#log#error("need Vim compiled with feature " . feature)
" finish
" endif
"endfor
if exists('g:loaded_themata') || &cp | finish | endif
let g:loaded_themata = 1
" Save 'cpoptions' and set Vim default to enable line continuations.
let s:save_cpo = &cpo
set cpo&vim
let g:themata#theme_name = ''
" Preserve original settings {{{
let g:themata#original = {
\ 'laststatus': &laststatus,
\ 'ruler': &ruler,
\ }
" }}}
" Overrides {{{
" Take control of fullscreen behavior from Vim, specifically to
" override its default behavior of maximizing columns and lines
" in fullscreen Vim.
if has('fullscreen')
let l_fuopts = split(&fuoptions, ',')
if index(l_fuopts, 'maxvert') != -1
let g:themata#original.maxvert = 1
" NOTE removing maxvert results in a screen redraw problem
" if Ctrl+Command+F hit before switching themes,
" so we'll remove it here.
"set fuoptions-=maxvert
endif
if index(l_fuopts, 'maxhorz') != -1
let g:themata#original.maxhorz = 1
set fuoptions-=maxhorz
endif
unlet l_fuopts
endif
" }}}
" Defaults {{{
if !exists('g:themata#defaults')
let g:themata#defaults = {}
endif
if !exists('g:themata#themes')
let g:themata#themes = {
\ 'blue' : { 'sign-column-color-fix': 1,
\ 'fold-column-color-mute': 1,
\ },
\ 'desert' : { 'sign-column-color-fix': 1,
\ 'fold-column-color-mute': 1,
\ },
\ 'peachpuff' : {
\ },
\ 'slate' : {
\ },
\ }
endif
" }}}
" Commands {{{
command -nargs=0 ThemataNarrow call themata#adjustColumns(-5)
command -nargs=0 ThemataWiden call themata#adjustColumns(5)
command -nargs=0 ThemataFirst call themata#load('#first')
command -nargs=0 ThemataNext call themata#load('#next')
command -nargs=0 ThemataPrevious call themata#load('#previous')
command -nargs=0 ThemataRandom call themata#load('#random')
command -nargs=0 ThemataOriginal call themata#load('#original')
"command! -nargs=1 MyCommand call s:MyFunc(<f-args>)
" }}}
" Plugin mappings {{{
noremap <silent> <Plug>ThemataNarrow :ThemataNarrow<CR>
noremap <silent> <Plug>ThemataWiden :ThemataWiden<CR>
" Create mappings for the `Themata` commands
noremap <silent> <Plug>ThemataFirst :ThemataFirst<CR>
noremap <silent> <Plug>ThemataNext :ThemataNext<CR>
noremap <silent> <Plug>ThemataPrevious :ThemataPrevious<CR>
noremap <silent> <Plug>ThemataRandom :ThemataRandom<CR>
noremap <silent> <Plug>ThemataOriginal :ThemataOriginal<CR>
" }}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:ts=2:sw=2:sts=2