Permalink
Browse files

Add vim-powerline plugin. (rev 99277d9)

  • Loading branch information...
bernd committed Apr 11, 2012
1 parent 47eacae commit e5692a7daf1a44cda98d84d3364a0df251dff747
View
@@ -0,0 +1,183 @@
+" Powerline - The ultimate statusline utility
+"
+" Author: Kim Silkebækken <kim.silkebaekken+vim@gmail.com>
+" Source repository: https://github.com/Lokaltog/vim-powerline
+
+" Script variables {{{
+ let g:Pl#OLD_STL = ''
+ let g:Pl#THEME = []
+ let g:Pl#THEME_CALLBACKS = []
+ let g:Pl#HL = []
+
+ " Cache revision, this must be incremented whenever the cache format is changed
+ let s:CACHE_REVISION = 7
+" }}}
+" Script initialization {{{
+ function! Pl#LoadCache() " {{{
+ if filereadable(g:Powerline_cache_file) && g:Powerline_cache_enabled
+ exec 'source' escape(g:Powerline_cache_file, ' \')
+
+ if ! exists('g:Powerline_cache_revision') || g:Powerline_cache_revision != s:CACHE_REVISION
+ " Cache revision differs, cache is invalid
+ unlet! g:Powerline_cache_revision
+
+ return 0
+ endif
+
+ " Create highlighting groups
+ for hi_cmd in g:Pl#HL
+ exec hi_cmd
+ endfor
+
+ " Run theme callbacks
+ for callback in g:Pl#THEME_CALLBACKS
+ " Substitute {{NEWLINE}} with newlines (strings must be
+ " stored without newlines characters to avoid vim errors)
+ exec substitute(callback[0], "{{NEWLINE}}", "\n", 'g')
+ exec substitute(callback[1], "{{NEWLINE}}", "\n", 'g')
+ endfor
+
+ return 1
+ endif
+
+ return 0
+ endfunction " }}}
+ function! Pl#ClearCache() " {{{
+ if filereadable(g:Powerline_cache_file)
+ " Delete the cache file
+ call delete(g:Powerline_cache_file)
+ endif
+
+ echo 'Powerline cache cleared. Please restart vim for the changes to take effect.'
+ endfunction " }}}
+ function! Pl#ReloadColorscheme() " {{{
+ call Pl#ClearCache()
+
+ " The colorscheme and theme files must be manually sourced because
+ " vim won't reload previously autoloaded files
+ "
+ " This is a bit hackish, but it works
+ unlet! g:Powerline#Colorschemes#{g:Powerline_colorscheme}#colorscheme
+ exec "source" split(globpath(&rtp, 'autoload/Powerline/Colorschemes/'. g:Powerline_colorscheme .'.vim', 1), '\n')[0]
+
+ unlet! g:Powerline#Themes#{g:Powerline_theme}#theme
+ exec "source" split(globpath(&rtp, 'autoload/Powerline/Themes/'. g:Powerline_theme .'.vim', 1), '\n')[0]
+
+ let g:Pl#THEME = []
+
+ call Pl#Load()
+ endfunction " }}}
+ function! Pl#Load() " {{{
+ if empty(g:Pl#OLD_STL)
+ " Store old statusline
+ let g:Pl#OLD_STL = &statusline
+ endif
+
+ if ! Pl#LoadCache()
+ try
+ " Autoload the theme dict first
+ let raw_theme = g:Powerline#Themes#{g:Powerline_theme}#theme
+ catch
+ echom 'Invalid Powerline theme! Please check your theme and colorscheme settings.'
+
+ return
+ endtry
+
+ " Create list with parsed statuslines
+ for buffer_statusline in raw_theme
+ unlet! mode_statuslines
+ let mode_statuslines = Pl#Parser#GetStatusline(buffer_statusline.segments)
+
+ if ! empty(buffer_statusline.callback)
+ " The callback function passes its arguments on to
+ " Pl#StatuslineCallback along with the normal/current mode
+ " statusline.
+ let s:cb_func = "function! PowerlineStatuslineCallback_". buffer_statusline.callback[1] ."(...)\n"
+ let s:cb_func .= "return Pl#StatuslineCallback(". string(mode_statuslines['n']) .", a:000)\n"
+ let s:cb_func .= "endfunction"
+
+ " The callback expression should be used to initialize any
+ " variables that will use the callback function. The
+ " expression requires a %s which will be replaced by the
+ " callback function name.
+ let s:cb_expr = printf(buffer_statusline.callback[2], 'PowerlineStatuslineCallback_'. buffer_statusline.callback[1])
+
+ exec s:cb_func
+ exec s:cb_expr
+
+ " Newlines must be substituted with another character
+ " because vim doesn't like newlines in strings
+ call add(g:Pl#THEME_CALLBACKS, [substitute(s:cb_func, "\n", "{{NEWLINE}}", 'g'), substitute(s:cb_expr, "\n", "{{NEWLINE}}", 'g')])
+
+ unlet! s:cb_func s:cb_expr
+
+ continue
+ endif
+
+ " Store the statuslines for matching specific buffers
+ call add(g:Pl#THEME, {
+ \ 'matches': buffer_statusline.matches,
+ \ 'mode_statuslines': mode_statuslines
+ \ })
+ endfor
+
+ if ! g:Powerline_cache_enabled
+ " Don't cache anything if caching is disabled or cache file isn't writeable
+ return
+ endif
+
+ " Prepare commands and statuslines for caching
+ let cache = [
+ \ 'let g:Powerline_cache_revision = '. string(s:CACHE_REVISION),
+ \ 'let g:Pl#HL = '. string(g:Pl#HL),
+ \ 'let g:Pl#THEME = '. string(g:Pl#THEME),
+ \ 'let g:Pl#THEME_CALLBACKS = '. string(g:Pl#THEME_CALLBACKS),
+ \ ]
+
+ call writefile(cache, g:Powerline_cache_file)
+ endif
+ endfunction " }}}
+" }}}
+" Statusline updater {{{
+ function! Pl#Statusline(statusline, current) " {{{
+ let mode = mode()
+
+ if ! a:current
+ let mode = 'N' " Normal (non-current)
+ elseif mode =~# '\v(v|V|)'
+ let mode = 'v' " Visual mode
+ elseif mode =~# '\v(s|S|)'
+ let mode = 's' " Select mode
+ elseif mode =~# '\vi'
+ let mode = 'i' " Insert mode
+ elseif mode =~# '\v(R|Rv)'
+ let mode = 'r' " Replace mode
+ else
+ " Fallback to normal mode
+ let mode = 'n' " Normal (current)
+ endif
+
+ return g:Pl#THEME[a:statusline].mode_statuslines[mode]
+ endfunction " }}}
+ function! Pl#StatuslineCallback(statusline, args) " {{{
+ " Replace %1, %2, etc. in the statusline with the callback args
+ return substitute(
+ \ a:statusline,
+ \ '\v\%(\d+)',
+ \ '\=a:args[submatch(1)]',
+ \ 'g')
+ endfunction " }}}
+ function! Pl#UpdateStatusline(current) " {{{
+ if empty(g:Pl#THEME)
+ " Load statuslines if they aren't loaded yet
+ call Pl#Load()
+ endif
+
+ for i in range(0, len(g:Pl#THEME) - 1)
+ if Pl#Match#Validate(g:Pl#THEME[i])
+ " Update window-local statusline
+ let &l:statusline = '%!Pl#Statusline('. i .','. a:current .')'
+ endif
+ endfor
+ endfunction " }}}
+" }}}
View
@@ -0,0 +1,145 @@
+function! Pl#Colorscheme#Init(hi) " {{{
+ let colorscheme = {}
+
+ for hi in a:hi
+ " Ensure that the segments are a list
+ let segments = type(hi[0]) == type('') ? [ hi[0] ] : hi[0]
+ let mode_hi_dict = hi[1]
+
+ for segment in segments
+ let colorscheme[segment] = mode_hi_dict
+ endfor
+ endfor
+
+ return colorscheme
+endfunction " }}}
+function! Pl#Colorscheme#Apply(colorscheme, buffer_segments) " {{{
+ " Set color parameters for all segments in a:buffer_segments
+
+ " TODO This function should be recursive and work on both segments and groups
+ " TODO We could probably handle the NS stuff here...
+
+ try
+ let colorscheme = g:Powerline#Colorschemes#{a:colorscheme}#colorscheme
+ catch
+ echom 'Color scheme "'. a:colorscheme .'" doesn''t exist!'
+
+ return
+ endtry
+
+ let buffer_segments = a:buffer_segments
+
+ " This is a bit complex, I'll walk you through exactly what happens here...
+ "
+ " First of all we loop through the buffer_segments, which are the segments that
+ " this specific buffer will have.
+ for buffer_segment in buffer_segments
+ " The buffer_segment consists of a 'matches' list and a 'segments' list.
+ " The 'matches' list has conditions to limit this statusline to specific buffers/windows.
+ " The 'segments' list has each segment and segment group for this buffer
+ for segment in buffer_segment.segments
+ let type = get(segment, 'type', '')
+
+ if type == 'segment_group'
+ " We're going to handle segment groups different from single segments. Segment groups
+ " have child segments which may have their own highlighting (e.g. fileinfo.flags),
+ " and these child segments may be grouped (e.g. fileinfo.flags.ro) to provide very
+ " specific highlighting. So here we'll handle all that:
+
+ " Set the default/fallback colors for this group
+ for i in range(len(segment.variants), 0, -1)
+ " Check for available highlighting for the main group segment
+ "
+ " This works like the segment highlighting below
+ " TODO Create a function for this
+ let seg_variants = join(segment.variants[0:i], '.')
+
+ let seg_name = i > 0 ? segment.name .'.'. seg_variants : segment.name
+ let seg_ns_name = len(segment.ns) > 0 ? segment.ns .':'. seg_name : seg_name
+
+ if has_key(colorscheme, seg_ns_name)
+ " We have a namespaced highlight group
+ let segment.colors = colorscheme[seg_ns_name]
+ break
+ elseif has_key(colorscheme, seg_name)
+ " We have a non-namespaced group
+ let segment.colors = colorscheme[seg_name]
+ break
+ endif
+ endfor
+
+ " The reason why we need to deepcopy the group's segments is that the child segments
+ " all point to the same base segments and that screws up highlighting if we highlight
+ " some child segments with different namespaced colors
+ let segment.segments = deepcopy(segment.segments)
+
+ " Apply colors to each child segment
+ for child_segment in segment.segments
+ " Check if this child segment is grouped (e.g. fileinfo.flags.group.subgroup)
+ " We're going to prioritize the most specific grouping and then work back to the
+ " most common group (e.g. fileinfo.flags)
+
+ " FIXME We don't have the variants from before because group children aren't run through Pl#Segment#Get
+ let child_segment.variants = [seg_name] + split(child_segment.name, '\.')
+
+ " Use the parent group's namespace
+ let child_segment.ns = segment.ns
+
+ for i in range(len(child_segment.variants), 0, -1)
+ " Check for available highlighting for the main group segment
+ let child_seg_name = join(child_segment.variants[0:i], '.')
+
+ let child_seg_ns_name = len(child_segment.ns) > 0 ? child_segment.ns .':'. child_seg_name : child_seg_name
+
+ if has_key(colorscheme, child_seg_ns_name)
+ " We have a namespaced highlight group
+ let child_segment.colors = colorscheme[child_seg_ns_name]
+ break
+ elseif has_key(colorscheme, child_seg_name)
+ " We have a non-namespaced group
+ let child_segment.colors = colorscheme[child_seg_name]
+ break
+ endif
+ endfor
+ endfor
+ elseif type == 'segment'
+ for i in range(len(segment.variants), 0, -1)
+ " Check for available highlighting
+ "
+ " This is done in the following manner, using the segment gundo:static_filename.text.buffer as an example:
+ "
+ " * Look for the hl group: gundo:static_filename.text.buffer
+ " * Look for the hl group: static_filename.text.buffer
+ " * Look for the hl group: gundo:static_filename.text
+ " * Look for the hl group: static_filename.text
+ " * Look for the hl group: gundo:static_filename
+ " * Look for the hl group: static_filename
+ " * Return the segment without highlighting, causing an error in the parser
+ let seg_variants = join(segment.variants[0:i], '.')
+
+ let seg_name = i > 0 ? segment.name .'.'. seg_variants : segment.name
+ let seg_ns_name = len(segment.ns) > 0 ? segment.ns .':'. seg_name : seg_name
+
+ if has_key(colorscheme, seg_ns_name)
+ " We have a namespaced highlight group
+ let segment.colors = colorscheme[seg_ns_name]
+ break
+ elseif has_key(colorscheme, seg_name)
+ " We have a non-namespaced group
+ let segment.colors = colorscheme[seg_name]
+ break
+ endif
+ endfor
+ endif
+
+ unlet! segment
+ endfor
+ endfor
+
+ " Good luck parsing this return value
+ "
+ " It's a huge dict with all segments for all buffers with their respective syntax highlighting.
+ " It will be parsed by the main Powerline code, where all the data will be shortened to a simple
+ " array consiting of a statusline for each mode, with generated highlighting groups and dividers.
+ return buffer_segments
+endfunction " }}}
Oops, something went wrong.

0 comments on commit e5692a7

Please sign in to comment.