aboutsummaryrefslogtreecommitdiff
path: root/vim/autoload/Pl.vim
blob: 432f84f8aeb60011e6cab5551b5eb495ee436e32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
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 = 5
" }}}
" 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 " }}}
" }}}