1"
2" cream-statusline.vim
3"
4" Cream -- An easy-to-use configuration of the famous Vim text  editor
5" [ http://cream.sourceforge.net ] Copyright (C) 2001-2011 Steve Hall
6"
7" License:
8" This program is free software; you can redistribute it and/or modify
9" it under the terms of the GNU General Public License as published by
10" the Free Software Foundation; either version 2 of  the  License,  or
11" (at your option) any later version.
12" [ http://www.gnu.org/licenses/gpl.html ]
13"
14" This program is distributed in the hope that it will be useful,  but
15" WITHOUT  ANY  WARRANTY;  without  even  the  implied   warranty   of
16" MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE.  See  the  GNU
17" General Public License for more details.
18"
19" You should have received a copy of the GNU  General  Public  License
20" along with  this  program;  if  not,  write  to  the  Free  Software
21" Foundation,  Inc.,  59  Temple  Place  -  Suite  330,   Boston,   MA
22" 02111-1307, USA.
23"
24" Description:
25" o WARNING!! Statuslines prior to version 6.2.071 are unable to
26"   handle more than 50 items. (An items is an "%" object, defined by
27"   begin group, enclosee [, close group]). In fact, prior to some
28"   version of 6.0.? this limit was even lower.
29" o Close of a highlighting group (%*) is not necessary--Vim always
30"   assumes the beginning of the next ends the previous.
31" o Cream's statusline colors are dependent on colors definitions
32"   elsewhere for User highlight groups 1-4, represented as "%N*" ...
33"   "%*" corresponding to the highlight group "UserN"
34" o Changing highlighting groups dynamically in the status bar has far
35"   too much overhead and is too slow. So we:
36"   * Preset all the highlight groups (elsewhere)
37"   * Pair two calls to two corresponding ON/OFF functions for *each*
38"     evaluation
39"   * Return a value for the actual condition (displayed)
40"   * Return empty for reverse (isn't displayed)
41" o :set statusline= requires a very specific syntax and can not
42"   accept a function since it is specially evaluated by Vim, probably
43"   because it happens so often. Examples of illegal/non-functioning:
44"
45"     set statusline=Cream_statusline()
46"     execute "set statusline=" . Cream_statusline()
47"
48"   It's the internal components of the statusline that continually
49"   get re-evaluated, not the entire statusline. (&stl is not
50"   continually executed, only the components *within*.)
51
52" initialize statusline on load (autocmd will handle state by retained
53" preference)
54set laststatus=2
55
56" evaluation functions
57" path/file {{{1
58function! Cream_statusline_path()
59	call Cream_buffer_pathfile()
60	" ignore path in gui (it's in titlebar)
61	if has("gui_running")
62		return " "
63	endif
64	" strip filename
65	let path = fnamemodify(b:cream_pathfilename, ":h")
66	" ensure trailing slash
67	let path = Cream_path_addtrailingslash(path)
68	return path
69endfunction
70
71" file state conditions
72function! Cream_statusline_filestate()
73	let state = ""
74
75	" test read-only state once
76	if !exists("b:cream_pathfilename") || b:cream_pathfilename == "(Untitled)"
77		let b:cream_readonly = 0
78	else
79		let b:cream_readonly = filewritable(b:cream_pathfilename)
80	endif
81
82	" help file
83	if &buftype == "help"
84		return 'H'
85	" writable
86	elseif b:cream_readonly == 0
87		\ || &readonly || &buftype == "nowrite"
88		return '-'
89	" modified
90	elseif &modified != 0
91		return '*'
92	" unmodified
93	else
94		return ' '
95	endif
96endfunction
97
98function! Cream_statusline_filename()
99	if !exists("b:cream_pathfilename")
100		return "(Untitled)"
101	elseif b:cream_pathfilename == ""
102		return "(Untitled)"
103	endif
104	return fnamemodify(b:cream_pathfilename, ":t")
105endfunction
106
107" file properties {{{1
108" grouped to preserve group count
109
110" fileformat (three characters only)
111function! Cream_statusline_fileformat()
112	if &fileformat == ""
113		return "--"
114	else
115		return &fileformat
116	endif
117
118endfunction
119
120" fileencoding (three characters only)
121function! Cream_statusline_fileencoding()
122	if &fileencoding == ""
123		if &encoding != ""
124			return &encoding
125		else
126			return "--"
127		endif
128	else
129		return &fileencoding
130	endif
131endfunction
132
133" file type
134function! Cream_statusline_filetype()
135	if &filetype == ""
136		return "--"
137	else
138		return &filetype
139	endif
140endfunction
141
142function! Cream_statusline_fileinfo()
143
144	return Cream_statusline_fileformat() . ":" .
145		\  Cream_statusline_fileencoding() . ":" .
146		\  Cream_statusline_filetype()
147
148endfunction
149
150
151" specials {{{1
152
153" indicate expert mode
154function! Cream_statusline_expert()
155	if exists("g:CREAM_EXPERTMODE") && g:CREAM_EXPERTMODE == 1
156		return "expert "
157	endif
158	return ""
159endfunction
160
161" diff mode
162function! Cream_statusline_diffmode()
163	if exists("b:cream_diffmode")
164		return "diff "
165	endif
166	return ""
167endfunction
168
169function! Cream_statusline_specials()
170" this function collects multiple special states together so that we
171" are able to minimize the number of items in the final statusline
172
173	let myspecials = ""
174	let myspecials = myspecials . Cream_statusline_expert()
175	let myspecials = myspecials . Cream_statusline_diffmode()
176	return myspecials
177
178endfunction
179
180" right side {{{1
181
182" show invisibles
183function! Cream_statusline_showON()
184	"if exists("g:LIST") && g:LIST == 1
185	if &list
186		if     &encoding == "latin1"
187			"return "�"
188			return nr2char(182)
189		elseif &encoding == "utf-8"
190		\ && v:version >= 602
191		\ || v:version == 601
192		\ && has("patch469")
193			" decimal 182
194			return nr2char(182)
195		else
196			return "$"
197		endif
198	else
199		return ""
200	endif
201endfunction
202function! Cream_statusline_showOFF()
203	"if exists("g:LIST") && g:LIST == 1
204	if &list
205		return ""
206	else
207		if &encoding == "latin1"
208			"return "�"
209			return nr2char(182)
210		elseif &encoding == "utf-8"
211		\ && v:version >= 602
212		\ || v:version == 601
213		\ && has("patch469")
214			" decimal 182
215			return nr2char(182)
216		else
217			return "$"
218		endif
219	endif
220endfunction
221
222" Word wrap
223function! Cream_statusline_wrapON()
224	if &wrap
225		return "wrap"
226	else
227		return ""
228	endif
229endfunction
230function! Cream_statusline_wrapOFF()
231	if &wrap
232		return ""
233	else
234		return "wrap"
235	endif
236endfunction
237
238" Auto Wrap
239function! Cream_statusline_autowrapON()
240	if &textwidth
241		return "auto " . &textwidth
242	else
243		return ""
244	endif
245endfunction
246function! Cream_statusline_autowrapOFF()
247	if &textwidth
248		return ""
249	else
250		if exists("g:CREAM_AUTOWRAP_WIDTH")
251			" use global, actual width is 0
252			return "auto " . g:CREAM_AUTOWRAP_WIDTH
253		else
254			return "auto " . &textwidth
255		endif
256	endif
257endfunction
258
259" wrap width
260function! Cream_statusline_wrap_width()
261" return wrap width setting
262	" (don't check existance of g:CREAM_AUTOWRAP)
263	"if exists("g:CREAM_AUTOWRAP_WIDTH")
264	"    return g:CREAM_AUTOWRAP_WIDTH
265	"endif
266	" respect Vim actual settings (modelines)
267	return &textwidth
268endfunction
269
270" justification
271function! Cream_statusline_wrap_justifyON()
272" return justification mode if not "left"
273	if !exists("g:cream_justify")
274		return ""
275	endif
276	if     g:cream_justify == "center"
277		return "cntr"
278	elseif g:cream_justify == "right"
279		return "rght"
280	elseif g:cream_justify == "full"
281		return "full"
282	else
283		return ""
284	endif
285endfunction
286function! Cream_statusline_wrap_justifyOFF()
287" return justification mode if not "left"
288	if !exists("g:cream_justify")
289		return "left"
290	endif
291	if     g:cream_justify == "left"
292		return "left"
293	else
294		return ""
295	endif
296endfunction
297
298" tabs
299" &expandtab
300function! Cream_statusline_expandtabON()
301	if &expandtab == 0
302		return "tabs"
303	else
304		return ""
305	endif
306endfunction
307function! Cream_statusline_expandtabOFF()
308	if &expandtab == 0
309		return ""
310	else
311		return "tabs"
312	endif
313endfunction
314
315" tabstop and softtabstop
316function! Cream_statusline_tabstop()
317
318	" show by Vim option, not Cream global (modelines)
319	let str = "" . &tabstop
320	" show softtabstop or shiftwidth if not equal tabstop
321	if   (&softtabstop && (&softtabstop != &tabstop))
322	\ || (&shiftwidth  && (&shiftwidth  != &tabstop))
323		if &softtabstop
324			let str = str . ":sts" . &softtabstop
325		endif
326		if &shiftwidth != &tabstop
327			let str = str . ":sw" . &shiftwidth
328		endif
329	endif
330	return str
331
332endfunction
333
334" autoindent
335"function! Cream_statusline_autoindentON()
336"    if exists("g:CREAM_AUTOINDENT")
337"        if g:CREAM_AUTOINDENT == "1"
338"            return "indt"
339"        else
340"            return ""
341"        endif
342"    else
343"        " wrap is on if never initialized
344"        return "wrap"
345"    endif
346"endfunction
347"function! Cream_statusline_autoindentOFF()
348"    if exists("g:CREAM_AUTOINDENT")
349"        if g:CREAM_AUTOINDENT == "1"
350"            return ""
351"        else
352"            return "indt"
353"        endif
354"    else
355"        " autoindent is on if never initialized
356"        return ""
357"    endif
358"endfunction
359function! Cream_statusline_autoindentON()
360	if &autoindent
361		return "indt"
362	else
363		return ""
364	endif
365endfunction
366function! Cream_statusline_autoindentOFF()
367	if &autoindent
368		return ""
369	else
370		return "indt"
371	endif
372endfunction
373
374" mode (Insert/Visual/Select/Replace v. Normal)
375" ( see :help mode() for return strings)
376function! Cream_statusline_modeNO()
377	let mymode = mode()
378	if mymode ==? "i"
379		return ""
380	elseif mymode ==? "v"
381		return ""
382	elseif mymode ==? "s"
383		return ""
384	elseif mymode ==? "R"
385		return ""
386	elseif mymode == ""
387		return "C"
388	elseif mymode ==? "n"
389		return "N"
390	else
391		return "  " . mymode . "  "
392	endif
393endfunction
394"function! Cream_statusline_modeCOL()
395"    let mymode = mode()
396"    else
397"        return ""
398"    endif
399"endfunction
400function! Cream_statusline_modeOK()
401	let mymode = mode()
402	if     mymode ==? "i"
403		return "I"
404	elseif mymode ==? "v"
405		return "V"
406	elseif mymode ==? "s"
407		return "S"
408	elseif mymode ==? "R"
409		return "R"
410	elseif mymode == ""
411		return ""
412	else
413		return ""
414	endif
415endfunction
416
417function! Cream_statusline_bufsize()
418	let bufsize = line2byte(line("$") + 1) - 1
419	" prevent negative numbers (non-existant buffers)
420	if bufsize < 0
421		let bufsize = 0
422	endif
423	" add commas
424	let remain = bufsize
425	let bufsize = ""
426	while strlen(remain) > 3
427		let bufsize = "," . strpart(remain, strlen(remain) - 3) . bufsize
428		let remain = strpart(remain, 0, strlen(remain) - 3)
429	endwhile
430	let bufsize = remain . bufsize
431	" too bad we can't use "�" (nr2char(1068)) :)
432	let char = "b"
433	return bufsize . char
434endfunction
435
436" 1}}}
437
438" utility function ("real time") {{{1
439
440function! Cream_cursor_pos(mode, cursor)
441" NOTE: Function must be global.
442
443	if     a:mode == "\<C-V>"
444		let mode = "V"
445	elseif a:mode == "\<C-S>"
446		let mode = "S"
447	else
448		let mode = a:mode
449	endif
450	let b:cursor_{mode} = a:cursor
451	return ""
452endfunction
453
454" 1}}}
455
456" set statusline {{{1
457
458if v:version < 603
459" limited number of fields
460
461	set statusline=
462		\%{Cream_cursor_pos(mode(),virtcol(\".\"))}
463		\%2*%{Cream_statusline_filename()}
464		\\ %3*%{Cream_statusline_filestate()}
465		\%1*\|%{Cream_statusline_fileinfo()}\|
466		\%{Cream_statusline_bufsize()}\ %=
467		\%3*%{Cream_statusline_specials()}
468		\%1*\|
469		\%2*%{Cream_statusline_showON()}
470		\%1*%{Cream_statusline_showOFF()}\|
471		\%2*%{Cream_statusline_wrapON()}
472		\%1*%{Cream_statusline_wrapOFF()}:
473		\%2*%{Cream_statusline_autowrapON()}
474		\%1*%{Cream_statusline_autowrapOFF()}:
475		\%{Cream_statusline_wrap_width()}\|
476		\%2*%{Cream_statusline_expandtabON()}
477		\%1*%{Cream_statusline_expandtabOFF()}:
478		\%{Cream_statusline_tabstop()}\|
479		\%05(%l%),%03(%v%)
480		\%2*\ %P
481
482else
483
484	set statusline=
485		\%{Cream_cursor_pos(mode(),virtcol(\".\"))}
486		\%1*%{Cream_statusline_path()}
487		\%2*%{Cream_statusline_filename()}
488		\\ %3*%{Cream_statusline_filestate()}
489		\%1*\|%{Cream_statusline_fileinfo()}\|
490		\%{Cream_statusline_bufsize()}\ %=
491		\%3*%{Cream_statusline_specials()}
492		\%1*\|
493		\%2*%{Cream_statusline_showON()}
494		\%1*%{Cream_statusline_showOFF()}\|
495		\%2*%{Cream_statusline_wrapON()}
496		\%1*%{Cream_statusline_wrapOFF()}:
497		\%2*%{Cream_statusline_autowrapON()}
498		\%1*%{Cream_statusline_autowrapOFF()}:
499		\%3*%{Cream_statusline_wrap_justifyON()}
500		\%1*%{Cream_statusline_wrap_justifyOFF()}\|
501		\%2*%{Cream_statusline_expandtabON()}
502		\%1*%{Cream_statusline_expandtabOFF()}:
503		\%{Cream_statusline_tabstop()}:
504		\%2*%{Cream_statusline_autoindentON()}
505		\%1*%{Cream_statusline_autoindentOFF()}\|
506		\%4*%{Cream_statusline_modeNO()}
507		\%1*%{Cream_statusline_modeOK()}\|
508		\%05(%l%),%03(%v%)
509		\%2*\ %P
510
511endif
512
513" 1}}}
514" vim:foldmethod=marker
515