aboutsummaryrefslogtreecommitdiff
path: root/files/.vim/bundle/CSApprox/plugin/CSApprox.vim
diff options
context:
space:
mode:
authorAnton Bobov <abobov@gmail.com>2014-07-09 23:35:18 +0600
committerAnton Bobov <abobov@gmail.com>2014-07-09 23:35:18 +0600
commitd92bc283866947e1347911e19f4ed70a2990e1be (patch)
tree1b1207a6dd2be489d0f226990f3cc7ada734084b /files/.vim/bundle/CSApprox/plugin/CSApprox.vim
parentdef34c32fb20935727a3de9042ea339a16ada542 (diff)
Change vim color scheme.
Diffstat (limited to 'files/.vim/bundle/CSApprox/plugin/CSApprox.vim')
-rw-r--r--files/.vim/bundle/CSApprox/plugin/CSApprox.vim921
1 files changed, 921 insertions, 0 deletions
diff --git a/files/.vim/bundle/CSApprox/plugin/CSApprox.vim b/files/.vim/bundle/CSApprox/plugin/CSApprox.vim
new file mode 100644
index 0000000..68f92d8
--- /dev/null
+++ b/files/.vim/bundle/CSApprox/plugin/CSApprox.vim
@@ -0,0 +1,921 @@
+" CSApprox: Make gvim-only colorschemes Just Work terminal vim
+" Maintainer: Matthew Wozniski (godlygeek@gmail.com)
+" Date: Fri, 14 Sep 2012 01:12:13 -0400
+" Version: 4.00
+" History: :help csapprox-changelog
+"
+" Long Description:
+" It's hard to find colorschemes for terminal Vim. Most colorschemes are
+" written to only support GVim, and don't work at all in terminal Vim.
+"
+" This plugin makes GVim-only colorschemes Just Work in terminal Vim, as long
+" as the terminal supports 88 or 256 colors - and most do these days. This
+" usually requires no user interaction (but see below for what to do if things
+" don't Just Work). After getting this plugin happily installed, any time you
+" use :colorscheme it will do its magic and make the colorscheme Just Work.
+"
+" Whenever you change colorschemes using the :colorscheme command this script
+" will be executed. It will take the colors that the scheme specified for use
+" in the GUI and use an approximation algorithm to try to gracefully degrade
+" them to the closest color available in your terminal. If you are running in
+" a GUI or if your terminal doesn't support 88 or 256 colors, no changes are
+" made. Also, no changes will be made if the colorscheme seems to have been
+" high color already.
+"
+" License:
+" Copyright (c) 2012, Matthew J. Wozniski
+" All rights reserved.
+"
+" Redistribution and use in source and binary forms, with or without
+" modification, are permitted provided that the following conditions are met:
+" * Redistributions of source code must retain the above copyright
+" notice, this list of conditions and the following disclaimer.
+" * Redistributions in binary form must reproduce the above copyright
+" notice, this list of conditions and the following disclaimer in the
+" documentation and/or other materials provided with the distribution.
+" * The names of the contributors may not be used to endorse or promote
+" products derived from this software without specific prior written
+" permission.
+"
+" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY
+" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+" DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+" {>1} Basic plugin setup
+
+" {>2} Check preconditions
+" Quit if the user doesn't want or need us or is missing the gui feature. We
+" need +gui to be able to check the gui color settings; vim doesn't bother to
+" store them if it is not built with +gui.
+if exists('g:CSApprox_loaded')
+ finish
+elseif !has('gui') && v:version < 703
+ " Vim versions less than < 7.3.0 need +gui.
+ " Warn unless the user set g:CSApprox_verbose_level to zero.
+ if get(g:, 'CSApprox_verbose_level', 1)
+ echomsg "CSApprox needs gui support - not loading."
+ echomsg " See :help |csapprox-+gui| for possible workarounds."
+ endif
+
+ finish
+endif
+
+" {1} Mark us as loaded, and disable all compatibility options for now.
+let g:CSApprox_loaded = 1
+
+let s:savecpo = &cpo
+set cpo&vim
+
+" {>1} Collect info for the set highlights
+
+" {>2} Determine if synIDattr is usable
+" synIDattr() couldn't support 'guisp' until 7.2.052. This function returns
+" true if :redir is needed to find the 'guisp' attribute, false if synIDattr()
+" is functional. This test can be overridden by setting the global variable
+" g:CSApprox_redirfallback to 1 (to force use of :redir) or to 0 (to force use
+" of synIDattr()).
+function! s:NeedRedirFallback()
+ if !exists("g:CSApprox_redirfallback")
+ let g:CSApprox_redirfallback = (v:version == 702 && !has('patch52'))
+ \ || v:version < 702
+ endif
+ return g:CSApprox_redirfallback
+endfunction
+
+" {>2} Collect and store the highlights
+" Get a dictionary containing information for every highlight group not merely
+" linked to another group. Return value is a dictionary, with highlight group
+" numbers for keys and values that are dictionaries with four keys each,
+" 'name', 'term', 'cterm', and 'gui'. 'name' holds the group name, and each
+" of the others holds highlight information for that particular mode.
+function! s:Highlights(modes)
+ let rv = {}
+
+ let i = 0
+ while 1
+ let i += 1
+
+ " Only interested in groups that exist and aren't linked
+ if synIDtrans(i) == 0
+ break
+ endif
+
+ " Handle vim bug allowing groups with name == "" to be created
+ if synIDtrans(i) != i || len(synIDattr(i, "name")) == 0
+ continue
+ endif
+
+ let rv[i] = {}
+ let rv[i].name = synIDattr(i, "name")
+
+ for where in a:modes
+ let rv[i][where] = {}
+ for attr in s:PossibleAttributes()
+ let rv[i][where][attr] = synIDattr(i, attr, where)
+ endfor
+
+ for attr in [ "fg", "bg" ]
+ let rv[i][where][attr] = synIDattr(i, attr.'#', where)
+ endfor
+
+ if where == "gui"
+ let rv[i][where]["sp"] = s:SynGuiSp(i, rv[i].name)
+ else
+ let rv[i][where]["sp"] = -1
+ endif
+
+ for attr in [ "fg", "bg", "sp" ]
+ if rv[i][where][attr] == -1
+ let rv[i][where][attr] = ''
+ endif
+ endfor
+ endfor
+ endwhile
+
+ return rv
+endfunction
+
+" {>2} Retrieve guisp
+
+" Get guisp using whichever method is specified by _redir_fallback
+function! s:SynGuiSp(idx, name)
+ if !s:NeedRedirFallback()
+ return s:SynGuiSpAttr(a:idx)
+ else
+ return s:SynGuiSpRedir(a:name)
+ endif
+endfunction
+
+" {>3} Implementation for retrieving guisp with redir hack
+function! s:SynGuiSpRedir(name)
+ redir => temp
+ exe 'sil hi ' . a:name
+ redir END
+ let temp = matchstr(temp, 'guisp=\zs.*')
+ if len(temp) == 0 || temp[0] =~ '\s'
+ let temp = ""
+ else
+ " Make sure we can handle guisp='dark red'
+ let temp = substitute(temp, '[\x00].*', '', '')
+ let temp = substitute(temp, '\s*\(c\=term\|gui\).*', '', '')
+ let temp = substitute(temp, '\s*$', '', '')
+ endif
+ return temp
+endfunction
+
+" {>3} Implementation for retrieving guisp with synIDattr()
+function! s:SynGuiSpAttr(idx)
+ return synIDattr(a:idx, 'sp#', 'gui')
+endfunction
+
+" {>1} Handle color names
+
+" Place to store rgb.txt name to color mappings - lazy loaded if needed
+let s:rgb = {}
+
+" {>2} Builtin gui color names
+" gui_x11.c and gui_gtk_x11.c have some default colors names that are searched
+" if the x server doesn't know about a color. If 'showrgb' is available,
+" we'll default to using these color names and values, and overwrite them with
+" other values if 'showrgb' tells us about those colors.
+let s:rgb_defaults = { "lightred" : "#FFBBBB",
+ \ "lightgreen" : "#88FF88",
+ \ "lightmagenta" : "#FFBBFF",
+ \ "darkcyan" : "#008888",
+ \ "darkblue" : "#0000BB",
+ \ "darkred" : "#BB0000",
+ \ "darkmagenta" : "#BB00BB",
+ \ "darkgrey" : "#BBBBBB",
+ \ "darkyellow" : "#BBBB00",
+ \ "gray10" : "#1A1A1A",
+ \ "grey10" : "#1A1A1A",
+ \ "gray20" : "#333333",
+ \ "grey20" : "#333333",
+ \ "gray30" : "#4D4D4D",
+ \ "grey30" : "#4D4D4D",
+ \ "gray40" : "#666666",
+ \ "grey40" : "#666666",
+ \ "gray50" : "#7F7F7F",
+ \ "grey50" : "#7F7F7F",
+ \ "gray60" : "#999999",
+ \ "grey60" : "#999999",
+ \ "gray70" : "#B3B3B3",
+ \ "grey70" : "#B3B3B3",
+ \ "gray80" : "#CCCCCC",
+ \ "grey80" : "#CCCCCC",
+ \ "gray90" : "#E5E5E5",
+ \ "grey90" : "#E5E5E5" }
+
+" {>2} Colors that vim will use by name in one of the default schemes, either
+" for bg=light or for bg=dark. This lets us avoid loading the entire rgb.txt
+" database when the scheme itself doesn't ask for colors by name.
+let s:rgb_presets = { "black" : "#000000",
+ \ "blue" : "#0000ff",
+ \ "brown" : "#a52a2a",
+ \ "cyan" : "#00ffff",
+ \ "darkblue" : "#00008b",
+ \ "darkcyan" : "#008b8b",
+ \ "darkgrey" : "#a9a9a9",
+ \ "darkmagenta" : "#8b008b",
+ \ "green" : "#00ff00",
+ \ "grey" : "#bebebe",
+ \ "grey40" : "#666666",
+ \ "grey90" : "#e5e5e5",
+ \ "lightblue" : "#add8e6",
+ \ "lightcyan" : "#e0ffff",
+ \ "lightgrey" : "#d3d3d3",
+ \ "lightmagenta" : "#ffbbff",
+ \ "magenta" : "#ff00ff",
+ \ "red" : "#ff0000",
+ \ "seagreen" : "#2e8b57",
+ \ "white" : "#ffffff",
+ \ "yellow" : "#ffff00" }
+
+" {>2} Find available color names
+" Find the valid named colors. By default, use our own rgb list, but try to
+" retrieve the system's list if g:CSApprox_use_showrgb is set to true. Store
+" the color names and color values to the dictionary s:rgb - the keys are
+" color names (in lowercase), the values are strings representing color values
+" (as '#rrggbb').
+function! s:UpdateRgbHash()
+ try
+ if !exists("g:CSApprox_use_showrgb") || !g:CSApprox_use_showrgb
+ throw "Not using showrgb"
+ endif
+
+ " We want to use the 'showrgb' program, if it's around
+ let lines = split(system('showrgb'), '\n')
+
+ if v:shell_error || !exists('lines') || empty(lines)
+ throw "'showrgb' didn't give us an rgb.txt"
+ endif
+
+ let s:rgb = copy(s:rgb_defaults)
+
+ " fmt is (blanks?)(red)(blanks)(green)(blanks)(blue)(blanks)(name)
+ let parsepat = '^\s*\(\d\+\)\s\+\(\d\+\)\s\+\(\d\+\)\s\+\(.*\)$'
+
+ for line in lines
+ let v = matchlist(line, parsepat)
+ if len(v) < 0
+ throw "CSApprox: Bad RGB line: " . string(line)
+ endif
+ let s:rgb[tolower(v[4])] = printf("#%02x%02x%02x", v[1], v[2], v[3])
+ endfor
+ catch
+ try
+ let s:rgb = csapprox#rgb()
+ catch
+ echohl ErrorMsg
+ echomsg "Can't call rgb() from autoload/csapprox.vim"
+ echomsg "Named colors will not be available!"
+ echohl None
+ endtry
+ endtry
+
+ return 0
+endfunction
+
+" {>1} Derive and set cterm attributes
+
+" {>2} List of all possible attributes
+function! s:PossibleAttributes()
+ return [ "bold", "italic", "reverse", "underline", "undercurl" ]
+endfunction
+
+" {>2} Attribute overrides
+" Allow the user to override a specified attribute with another attribute.
+" For example, the default is to map 'italic' to 'underline' (since many
+" terminals cannot display italic text, and gvim itself will replace italics
+" with underlines where italicizing is impossible), and to replace 'sp' with
+" 'fg' (since terminals can't use one color for the underline and another for
+" the foreground, we color the entire word). This default can of course be
+" overridden by the user, by setting g:CSApprox_attr_map. This map must be
+" a dictionary of string keys, representing the same attributes that synIDattr
+" can look up, to string values, representing the attribute mapped to or an
+" empty string to disable the given attribute entirely.
+function! s:attr_map(attr)
+ let rv = get(g:CSApprox_attr_map, a:attr, a:attr)
+
+ return rv
+endfunction
+
+function! s:NormalizeAttrMap(map)
+ let old = copy(a:map)
+ let new = filter(a:map, '0')
+
+ let valid_attrs = [ 'bg', 'fg', 'sp' ] + s:PossibleAttributes()
+
+ let colorattrs = [ 'fg', 'bg', 'sp' ]
+
+ for olhs in keys(old)
+ if olhs ==? 'inverse'
+ let nlhs = 'reverse'
+ endif
+
+ let orhs = old[olhs]
+
+ if orhs ==? 'inverse'
+ let nrhs = 'reverse'
+ endif
+
+ let nlhs = tolower(olhs)
+ let nrhs = tolower(orhs)
+
+ try
+ if index(valid_attrs, nlhs) == -1
+ echomsg "CSApprox: Bad attr map (removing unrecognized attribute " . olhs . ")"
+ elseif nrhs != '' && index(valid_attrs, nrhs) == -1
+ echomsg "CSApprox: Bad attr map (removing unrecognized attribute " . orhs . ")"
+ elseif nrhs != '' && !!(index(colorattrs, nlhs)+1) != !!(index(colorattrs, nrhs)+1)
+ echomsg "CSApprox: Bad attr map (removing " . olhs . "; type mismatch with " . orhs . ")"
+ elseif nrhs == 'sp'
+ echomsg "CSApprox: Bad attr map (removing " . olhs . "; can't map to 'sp')"
+ else
+ let new[nlhs] = nrhs
+ endif
+ catch
+ echo v:exception
+ endtry
+ endfor
+endfunction
+
+" {>2} Normalize the GUI settings of a highlight group
+" If the Normal group is cleared, set it to gvim's default, black on white
+" Though this would be a really weird thing for a scheme to do... *shrug*
+function! s:FixupGuiInfo(highlights)
+ if a:highlights[s:hlid_normal].gui.bg == ''
+ let a:highlights[s:hlid_normal].gui.bg = 'white'
+ endif
+
+ if a:highlights[s:hlid_normal].gui.fg == ''
+ let a:highlights[s:hlid_normal].gui.fg = 'black'
+ endif
+endfunction
+
+" {>2} Map gui settings to cterm settings
+" Given information about a highlight group, replace the cterm settings with
+" the mapped gui settings, applying any attribute overrides along the way. In
+" particular, this gives special treatment to the 'reverse' attribute and the
+" 'guisp' attribute. In particular, if the 'reverse' attribute is set for
+" gvim, we unset it for the terminal and instead set ctermfg to match guibg
+" and vice versa, since terminals can consider a 'reverse' flag to mean using
+" default-bg-on-default-fg instead of current-bg-on-current-fg. We also
+" ensure that the 'sp' attribute is never set for cterm, since no terminal can
+" handle that particular highlight. If the user wants to display the guisp
+" color, he should map it to either 'fg' or 'bg' using g:CSApprox_attr_map.
+function! s:FixupCtermInfo(highlights)
+ for hl in values(a:highlights)
+
+ if !has_key(hl, 'cterm')
+ let hl["cterm"] = {}
+ endif
+
+ " Find attributes to be set in the terminal
+ for attr in s:PossibleAttributes()
+ let hl.cterm[attr] = ''
+ if hl.gui[attr] == 1
+ if s:attr_map(attr) != ''
+ let hl.cterm[ s:attr_map(attr) ] = 1
+ endif
+ endif
+ endfor
+
+ for color in [ "bg", "fg" ]
+ let eff_color = color
+ if hl.cterm['reverse']
+ let eff_color = (color == 'bg' ? 'fg' : 'bg')
+ endif
+
+ let hl.cterm[color] = get(hl.gui, s:attr_map(eff_color), '')
+ endfor
+
+ if hl.gui['sp'] != '' && s:attr_map('sp') != ''
+ let hl.cterm[s:attr_map('sp')] = hl.gui['sp']
+ endif
+
+ if exists("g:CSApprox_fake_reverse") && g:CSApprox_fake_reverse
+ if hl.cterm['reverse'] && hl.cterm.bg == ''
+ let hl.cterm.bg = 'fg'
+ endif
+
+ if hl.cterm['reverse'] && hl.cterm.fg == ''
+ let hl.cterm.fg = 'bg'
+ endif
+
+ if hl.cterm['reverse']
+ let hl.cterm.reverse = ''
+ endif
+ endif
+ endfor
+endfunction
+
+" {>2} Kludge around inability to reference autoload functions
+function! s:DefaultApproximator(...)
+ return call('csapprox#per_component#Approximate', a:000)
+endfunction
+
+" {>2} Set cterm colors for a highlight group
+" Given the information for a single highlight group (ie, the value of
+" one of the items in s:Highlights() already normalized with s:FixupCtermInfo
+" and s:FixupGuiInfo), handle matching the gvim colors to the closest cterm
+" colors by calling the appropriate approximator as specified with the
+" g:CSApprox_approximator_function variable and set the colors and attributes
+" appropriately to match the gui.
+function! s:SetCtermFromGui(hl)
+ let hl = a:hl
+
+ " Set up the default approximator function, if needed
+ if !exists("g:CSApprox_approximator_function")
+ let g:CSApprox_approximator_function = function("s:DefaultApproximator")
+ endif
+
+ " Clear existing highlights
+ exe 'hi ' . hl.name . ' cterm=NONE ctermbg=NONE ctermfg=NONE'
+
+ for which in [ 'bg', 'fg' ]
+ let val = hl.cterm[which]
+
+ " Skip unset colors
+ if val == -1 || val == ""
+ continue
+ endif
+
+ " Try translating anything but 'fg', 'bg', #rrggbb, and rrggbb from an
+ " rgb.txt color to a #rrggbb color
+ if val !~? '^[fb]g$' && val !~ '^#\=\x\{6}$'
+ try
+ " First see if it is in our preset-by-vim rgb list
+ let val = s:rgb_presets[tolower(val)]
+ catch
+ " Then try loading and checking our real rgb list
+ if empty(s:rgb)
+ call s:UpdateRgbHash()
+ endif
+ try
+ let val = s:rgb[tolower(val)]
+ catch
+ " And then barf if we still haven't found it
+ if &verbose
+ echomsg "CSApprox: Colorscheme uses unknown color \"" . val . "\""
+ endif
+ continue
+ endtry
+ endtry
+ endif
+
+ if val =~? '^[fb]g$'
+ exe 'hi ' . hl.name . ' cterm' . which . '=' . val
+ let hl.cterm[which] = val
+ elseif val =~ '^#\=\x\{6}$'
+ let val = substitute(val, '^#', '', '')
+ let r = str2nr(val[0:1], 16)
+ let g = str2nr(val[2:3], 16)
+ let b = str2nr(val[4:5], 16)
+ let hl.cterm[which] = g:CSApprox_approximator_function(r, g, b)
+ exe 'hi ' . hl.name . ' cterm' . which . '=' . hl.cterm[which]
+ else
+ throw "Internal error handling color: " . val
+ endif
+ endfor
+
+ " Finally, set the attributes
+ let attrs = s:PossibleAttributes()
+ call filter(attrs, 'hl.cterm[v:val] == 1')
+
+ if !empty(attrs)
+ exe 'hi ' . hl.name . ' cterm=' . join(attrs, ',')
+ endif
+endfunction
+
+
+" {>1} Top-level control
+
+" Cache the highlight ID of the normal group; it's used often and won't change
+let s:hlid_normal = hlID('Normal')
+
+" {>2} Builtin cterm color names above 15
+" Vim defines some color name to high color mappings internally (see
+" syntax.c:do_highlight). Since we don't want to overwrite a colorscheme that
+" was actually written for a high color terminal with our choices, but have no
+" way to tell if a colorscheme was written for a high color terminal, we fall
+" back on guessing. If any highlight group has a cterm color set to 16 or
+" higher, we assume that the user has used a high color colorscheme - unless
+" that color is one of the below, which vim can set internally when a color is
+" requested by name.
+let s:presets_88 = []
+let s:presets_88 += [32] " Brown
+let s:presets_88 += [72] " DarkYellow
+let s:presets_88 += [84] " Gray
+let s:presets_88 += [84] " Grey
+let s:presets_88 += [82] " DarkGray
+let s:presets_88 += [82] " DarkGrey
+let s:presets_88 += [43] " LightBlue
+let s:presets_88 += [61] " LightGreen
+let s:presets_88 += [63] " LightCyan
+let s:presets_88 += [74] " LightRed
+let s:presets_88 += [75] " LightMagenta
+let s:presets_88 += [78] " LightYellow
+
+let s:presets_256 = []
+let s:presets_256 += [130] " Brown
+let s:presets_256 += [130] " DarkYellow
+let s:presets_256 += [248] " Gray
+let s:presets_256 += [248] " Grey
+let s:presets_256 += [242] " DarkGray
+let s:presets_256 += [242] " DarkGrey
+let s:presets_256 += [ 81] " LightBlue
+let s:presets_256 += [121] " LightGreen
+let s:presets_256 += [159] " LightCyan
+let s:presets_256 += [224] " LightRed
+let s:presets_256 += [225] " LightMagenta
+let s:presets_256 += [229] " LightYellow
+
+" {>2} Wrapper around :exe to allow :executing multiple commands.
+" "cmd" is the command to be :executed.
+" If the variable is a String, it is :executed.
+" If the variable is a List, each element is :executed.
+function! s:exe(cmd)
+ if type(a:cmd) == type('')
+ exe a:cmd
+ else
+ for cmd in a:cmd
+ call s:exe(cmd)
+ endfor
+ endif
+endfunction
+
+" {>2} Function to handle hooks
+" Prototype: HandleHooks(type [, scheme])
+" "type" is the type of hook to be executed, ie. "pre" or "post"
+" "scheme" is the name of the colorscheme that is currently active, if known
+"
+" If the variables g:CSApprox_hook_{type} and g:CSApprox_hook_{scheme}_{type}
+" exist, this will :execute them in that order. If one does not exist, it
+" will silently be ignored.
+"
+" If the scheme name contains characters that are invalid in a variable name,
+" they will simply be removed. Ie, g:colors_name = "123 foo_bar-baz456"
+" becomes "foo_barbaz456"
+"
+" NOTE: Exceptions will be printed out, rather than end processing early. The
+" rationale is that it is worse for the user to fix the hook in an editor with
+" broken colors. :)
+function! s:HandleHooks(type, ...)
+ let type = a:type
+ let scheme = (a:0 == 1 ? a:1 : "")
+ let scheme = substitute(scheme, '[^[:alnum:]_]', '', 'g')
+ let scheme = substitute(scheme, '^\d\+', '', '')
+
+ for cmd in [ 'g:CSApprox_hook_' . type,
+ \ 'g:CSApprox_' . scheme . '_hook_' . type,
+ \ 'g:CSApprox_hook_' . scheme . '_' . type ]
+ if exists(cmd)
+ try
+ call s:exe(eval(cmd))
+ catch
+ echomsg "Error processing " . cmd . ":"
+ echomsg v:exception
+ endtry
+ endif
+ endfor
+endfunction
+
+" {>2} Main function
+" Wrapper around the actual implementation to make it easier to ensure that
+" all temporary settings are restored by the time we return, whether or not
+" something was thrown. Additionally, sets the 'verbose' option to the max of
+" g:CSApprox_verbose_level (default 1) and &verbose for the duration of the
+" main function. This allows us to default to a message whenever any error,
+" even a recoverable one, occurs, meaning the user quickly finds out when
+" something's wrong, but makes it very easy for the user to make us silent.
+function! s:CSApprox(...)
+ try
+ if a:0 == 1 && a:1
+ if !exists('s:inhibit_hicolor_test')
+ let s:inhibit_hicolor_test = 0
+ endif
+ let s:inhibit_hicolor_test += 1
+ endif
+
+ let savelz = &lz
+
+ set lz
+
+ if exists("g:CSApprox_attr_map") && type(g:CSApprox_attr_map) == type({})
+ call s:NormalizeAttrMap(g:CSApprox_attr_map)
+ else
+ let g:CSApprox_attr_map = { 'italic' : 'underline', 'sp' : 'fg' }
+ endif
+
+ " colors_name must be unset and reset, or vim will helpfully reload the
+ " colorscheme when we set the background for the Normal group.
+ " See the help entries ':hi-normal-cterm' and 'g:colors_name'
+ if exists("g:colors_name")
+ let colors_name = g:colors_name
+ unlet g:colors_name
+ endif
+
+ " Similarly, the global variable "syntax_cmd" must be set to something vim
+ " doesn't recognize, lest vim helpfully switch all colors back to the
+ " default whenever the Normal group is changed (in syncolor.vim)...
+ if exists("g:syntax_cmd")
+ let syntax_cmd = g:syntax_cmd
+ endif
+ let g:syntax_cmd = "PLEASE DON'T CHANGE ANY COLORS!!!"
+
+ " Set up our verbosity level, if needed.
+ " Default to 1, so the user can know if something's wrong.
+ if !exists("g:CSApprox_verbose_level")
+ let g:CSApprox_verbose_level = 1
+ endif
+
+ call s:HandleHooks("pre", (exists("colors_name") ? colors_name : ""))
+
+ let old_bg = &bg
+
+ " Set 'verbose' set to the maximum of &verbose and CSApprox_verbose_level
+ exe max([&vbs, g:CSApprox_verbose_level]) 'verbose call s:CSApproxImpl()'
+
+ let &bg = old_bg
+
+ call s:HandleHooks("post", (exists("colors_name") ? colors_name : ""))
+ finally
+ if exists("colors_name")
+ let g:colors_name = colors_name
+ endif
+
+ unlet g:syntax_cmd
+ if exists("syntax_cmd")
+ let g:syntax_cmd = syntax_cmd
+ endif
+
+ let &lz = savelz
+
+ if a:0 == 1 && a:1
+ let s:inhibit_hicolor_test -= 1
+ if s:inhibit_hicolor_test == 0
+ unlet s:inhibit_hicolor_test
+ endif
+ endif
+ endtry
+endfunction
+
+" {>2} CSApprox implementation
+" Verifies that the user has not started the gui, and that vim recognizes his
+" terminal as having enough colors for us to go on, then gathers the existing
+" highlights and sets the cterm colors to match the gui colors for all those
+" highlights (unless the colorscheme was already high-color).
+function! s:CSApproxImpl()
+ " Return if not running in an 88/256 color terminal
+ if &t_Co != 256 && &t_Co != 88
+ if &verbose && &t_Co != ''
+ echomsg "CSApprox skipped; terminal only has" &t_Co "colors, not 88/256"
+ echomsg "Try checking :help csapprox-terminal for workarounds"
+ endif
+
+ return
+ endif
+
+ " Get the current highlight colors
+ let highlights = s:Highlights(["gui"])
+
+ let hinums = keys(highlights)
+
+ " Make sure that the script is not already 256 color by checking to make
+ " sure that no groups are set to a value above 256, unless the color they're
+ " set to can be set internally by vim (gotten by scraping
+ " color_numbers_{88,256} in syntax.c:do_highlight)
+ "
+ " XXX: s:inhibit_hicolor_test allows this test to be skipped for snapshots
+ if !exists("s:inhibit_hicolor_test") || !s:inhibit_hicolor_test
+ for hlid in hinums
+ for type in [ 'bg', 'fg' ]
+ let color = synIDattr(hlid, type, 'cterm')
+
+ if color > 15 && index(s:presets_{&t_Co}, str2nr(color)) < 0
+ " The value is set above 15, and wasn't set by vim.
+ if &verbose >= 2
+ echomsg 'CSApprox: Exiting - high' type 'color found for' highlights[hlid].name
+ endif
+ return
+ endif
+ endfor
+ endfor
+ endif
+
+ call s:FixupGuiInfo(highlights)
+ call s:FixupCtermInfo(highlights)
+
+ " We need to set the Normal group first so 'bg' and 'fg' work as colors
+ call insert(hinums, remove(hinums, index(hinums, string(s:hlid_normal))))
+
+ " then set each color's cterm attributes to match gui
+ for hlid in hinums
+ call s:SetCtermFromGui(highlights[hlid])
+ endfor
+endfunction
+
+" {>2} Write out the current colors to an 88/256 color colorscheme file.
+" "file" - destination filename
+" "overwrite" - overwrite an existing file
+function! s:CSApproxSnapshot(file, overwrite)
+ let force = a:overwrite
+ let file = fnamemodify(a:file, ":p")
+
+ if empty(file)
+ throw "Bad file name: \"" . file . "\""
+ elseif (filewritable(fnamemodify(file, ':h')) != 2)
+ throw "Cannot write to directory \"" . fnamemodify(file, ':h') . "\""
+ elseif (glob(file) || filereadable(file)) && !force
+ " TODO - respect 'confirm' here and prompt if it's set.
+ echohl ErrorMsg
+ echomsg "E13: File exists (add ! to override)"
+ echohl None
+ return
+ endif
+
+ " Sigh... This is basically a bug, but one that I have no chance of fixing.
+ " Vim decides that Pmenu should be highlighted in 'LightMagenta' in terminal
+ " vim and as 'Magenta' in gvim... And I can't ask it what color it actually
+ " *wants*. As far as I can see, there's no way for me to learn that
+ " I should output 'Magenta' when 'LightMagenta' is provided by vim for the
+ " terminal.
+ if !has('gui_running')
+ echohl WarningMsg
+ echomsg "Warning: The written colorscheme may have incorrect colors"
+ echomsg " when CSApproxSnapshot is used in terminal vim!"
+ echohl None
+ endif
+
+ let save_t_Co = &t_Co
+ let s:inhibit_hicolor_test = 1
+ if exists("g:CSApprox_konsole")
+ let save_CSApprox_konsole = g:CSApprox_konsole
+ endif
+ if exists("g:CSApprox_eterm")
+ let save_CSApprox_eterm = g:CSApprox_eterm
+ endif
+
+ " Needed just like in CSApprox()
+ if exists("g:colors_name")
+ let colors_name = g:colors_name
+ unlet g:colors_name
+ endif
+
+ " Needed just like in CSApprox()
+ if exists("g:syntax_cmd")
+ let syntax_cmd = g:syntax_cmd
+ endif
+ let g:syntax_cmd = "PLEASE DON'T CHANGE ANY COLORS!!!"
+
+ try
+ let lines = []
+ let lines += [ '" This scheme was created by CSApproxSnapshot' ]
+ let lines += [ '" on ' . strftime("%a, %d %b %Y") ]
+ let lines += [ '' ]
+ let lines += [ 'hi clear' ]
+ let lines += [ 'if exists("syntax_on")' ]
+ let lines += [ ' syntax reset' ]
+ let lines += [ 'endif' ]
+ let lines += [ '' ]
+ let lines += [ 'if v:version < 700' ]
+ let lines += [ ' let g:colors_name = expand("<sfile>:t:r")' ]
+ let lines += [ ' command! -nargs=+ CSAHi exe "hi" substitute(substitute(<q-args>, "undercurl", "underline", "g"), "guisp\\S\\+", "", "g")' ]
+ let lines += [ 'else' ]
+ let lines += [ ' let g:colors_name = expand("<sfile>:t:r")' ]
+ let lines += [ ' command! -nargs=+ CSAHi exe "hi" <q-args>' ]
+ let lines += [ 'endif' ]
+ let lines += [ '' ]
+ let lines += [ 'function! s:old_kde()' ]
+ let lines += [ ' " Konsole only used its own palette up til KDE 4.2.0' ]
+ let lines += [ " if executable('kde4-config') && system('kde4-config --kde-version') =~ '^4\.[10]\.'" ]
+ let lines += [ ' return 1' ]
+ let lines += [ " elseif executable('kde-config') && system('kde-config --version') =~# 'KDE: 3\.'" ]
+ let lines += [ ' return 1' ]
+ let lines += [ ' else' ]
+ let lines += [ ' return 0' ]
+ let lines += [ ' endif' ]
+ let lines += [ 'endfunction' ]
+ let lines += [ '' ]
+
+
+ let lines += [ 'if 0' ]
+ for round in [ 'konsole', 'eterm', 'xterm', 'urxvt' ]
+ sil! unlet g:CSApprox_eterm
+ sil! unlet g:CSApprox_konsole
+
+ if round == 'konsole'
+ let g:CSApprox_konsole = 1
+ elseif round == 'eterm'
+ let g:CSApprox_eterm = 1
+ endif
+
+ if round == 'urxvt'
+ set t_Co=88
+ else
+ set t_Co=256
+ endif
+
+ call s:CSApprox()
+
+ let highlights = s:Highlights(["term", "cterm", "gui"])
+ call s:FixupGuiInfo(highlights)
+
+ if round == 'konsole' || round == 'eterm'
+ if round == 'konsole'
+ let term_matches_round = '(&term =~? "^konsole" && s:old_kde())'
+ else
+ let term_matches_round = '&term =~? "^' . round . '"'
+ endif
+
+ let lines += [ 'elseif has("gui_running") || (&t_Co == ' . &t_Co
+ \ . ' && (&term ==# "xterm" || &term =~# "^screen")'
+ \ . ' && exists("g:CSApprox_' . round . '")'
+ \ . ' && g:CSApprox_' . round . ')'
+ \ . ' || ' . term_matches_round ]
+ else
+ let lines += [ 'elseif has("gui_running") || &t_Co == ' . &t_Co ]
+ endif
+
+ let hinums = keys(highlights)
+
+ call insert(hinums, remove(hinums, index(hinums, string(s:hlid_normal))))
+
+ for hlnum in hinums
+ let hl = highlights[hlnum]
+ let line = ' CSAHi ' . hl.name
+ for type in [ 'term', 'cterm', 'gui' ]
+ let attrs = s:PossibleAttributes()
+ call filter(attrs, 'hl[type][v:val] == 1')
+ let line .= ' ' . type . '=' . (empty(attrs) ? 'NONE' : join(attrs, ','))
+ if type != 'term'
+ let line .= ' ' . type . 'bg=' . (len(hl[type].bg) ? hl[type].bg : 'bg')
+ let line .= ' ' . type . 'fg=' . (len(hl[type].fg) ? hl[type].fg : 'fg')
+ if type == 'gui' && hl.gui.sp !~ '^\s*$'
+ let line .= ' ' . type . 'sp=' . hl[type].sp
+ endif
+ endif
+ endfor
+ let lines += [ line ]
+ endfor
+ endfor
+ let lines += [ 'endif' ]
+ let lines += [ '' ]
+ let lines += [ 'if 1' ]
+ let lines += [ ' delcommand CSAHi' ]
+ let lines += [ 'endif' ]
+ call writefile(lines, file)
+ finally
+ let &t_Co = save_t_Co
+
+ if exists("save_CSApprox_konsole")
+ let g:CSApprox_konsole = save_CSApprox_konsole
+ endif
+ if exists("save_CSApprox_eterm")
+ let g:CSApprox_eterm = save_CSApprox_eterm
+ endif
+
+ if exists("colors_name")
+ let g:colors_name = colors_name
+ endif
+
+ unlet g:syntax_cmd
+ if exists("syntax_cmd")
+ let g:syntax_cmd = syntax_cmd
+ endif
+
+ call s:CSApprox()
+
+ unlet s:inhibit_hicolor_test
+ endtry
+endfunction
+
+" {>2} Snapshot user command
+command! -bang -nargs=1 -complete=file -bar CSApproxSnapshot
+ \ call s:CSApproxSnapshot(<f-args>, strlen("<bang>"))
+
+" {>2} Manual updates
+command -bang -bar CSApprox call s:CSApprox(strlen("<bang>"))
+
+" {>1} Autocmds
+" Set up an autogroup to hook us on the completion of any :colorscheme command
+augroup CSApprox
+ au!
+ au ColorScheme * call s:CSApprox()
+ "au User CSApproxPost highlight Normal ctermbg=none | highlight NonText ctermbg=None
+augroup END
+
+" {>1} Restore compatibility options
+let &cpo = s:savecpo
+unlet s:savecpo
+
+
+" {0} vim:sw=2:sts=2:et:fdm=expr:fde=substitute(matchstr(getline(v\:lnum),'^\\s*"\\s*{\\zs.\\{-}\\ze}'),'^$','=','')