1 " ScrollColors.vim - Colorsheme Scroller, Chooser, and Browser
3 " Author and maintainer: Yakov Lerner <iler_ml@fastmail.fm>
4 " Last Change: 2006-07-18
7 " This is colorscheme Scroller/Chooser/Browser.
8 " With this plugin, you walk through installed
9 " colorschemes using arrow keys.
11 " SHORT USAGE DESCRIPTION:
12 " Drop ScrollColors.vim into your plugin directory.
14 " Use arrow keys to walk through colorschemes, ? for help, Esc to exit.
16 " DETAILED DESCRIPTION:
17 " 1. source ScrollColors.vim " or drop ScrollColors.vim into
18 " " your ~/.vim/plugins directory
20 " 3. Use arrows to scroll thgough colorschemes.
21 " 4. When done, press Esc to exit. You will be prompted
24 " You can download 140 colorschemes pack from:
25 " http://www.vim.org/scripts/script.php?script_id=625
26 " Having 140 installed colorschemes is in no way prerequisite for
27 " ScrollColors. But with ScrollColors you can preview 140 colorschemes
28 " in couple of minutes.
30 " CUSTOM KEY MAPPINGS:
31 " You can map two keys of your choice to NextColor and PrevColor actions.
32 " Choose pair of shortcut keys (for example <F2> and <f3>, or \n and \p)
33 " and map them as follows:
34 " map <silent><F3> :NEXTCOLOR<cr>
35 " map <silent><F2> :PREVCOLOR<cr>
38 if exists("g:scroll_colors") | finish | endif
39 let g:scroll_colors = 1
41 command! COLORSCROLL :call s:ColorScroller()
42 command! SCROLLCOLOR :call s:ColorScroller()
43 command! NEXTCOLOR :call s:NextColorscheme()
44 command! PREVCOLOR :call s:PrevColorscheme()
46 " Example of convenience mappings:
47 "map <silent><F3> :NEXTCOLOR<cr>
48 "map <silent><F2> :PREVCOLOR<cr>
49 "map <silent><F4> :SCROLLCOLOR<cr>
51 function! s:ScrollerHelp()
54 echo "Color Scroller Help:"
55 echo "--------------------"
57 echo "Arrows - change colorscheme"
58 echo "Esc,q,Enter - exit"
59 echo "h,j,k,l - change colorscheme"
60 echo "0,g - go to first colorscheme"
61 echo "$,G - go to last colorscheme"
62 echo "L - list colorschemes"
63 echo "PgUp,PgDown - jump by 10 colorschemes"
64 echo "# - go to colorscheme by index (1-N)"
65 echo "R - refresh colorscheme list"
66 echo "? - this help text"
68 echo "Press any key to continue"
73 function! s:Align(s, width)
74 if strlen(a:s) >= a:width
79 while strlen(res) < a:width
80 let chunk = (a:width - strlen(res) > strlen(pad) ? strlen(pad) : a:width - strlen(res))
81 let res = res . strpart(pad,0,chunk)
87 function! s:ListColors()
89 let list=s:GetColorschemesList()
93 let str=substitute(list,"\n.*","","")
94 let list=substitute(list,"[^\n]*\n", "", "")
95 let aligned = s:Align(str, width)
96 if( pos+strlen(aligned)+1 >= &columns)
101 let pos = pos + strlen(aligned)
103 echo "Press any key to continue"
107 function! s:CurrentColor()
108 return exists("g:colors_name") ? g:colors_name : ""
111 function! s:SetColor(name)
113 " if we do not assign a:colors_name, then
114 " bad things happen if file colors/name.vim conmtains wrong assignment inside.
115 " Wrong assignment inside happens when file was copied but
116 " assignment inside not fixed.
117 " Such wrong assignment cause up erratic switches unless
118 " we do our own assignment to g:colors_name
119 let g:colors_name=a:name
122 function! s:JumpByIndex(list,total)
123 let ans = input("Enter colorscheme number (1-".a:total.") : ")
124 let index = (ans<=0? 1 : 1+(ans-1)%a:total )
125 let name = s:EntryByIndex(a:list, index )
126 call s:SetColor(name)
129 function! s:JumpByIndex2(list,total, index)
130 let mod = (a:index <= 0? 1 : 1+(a:index-1)%a:total )
131 let name = s:EntryByIndex(a:list, mod )
132 call s:SetColor(name)
135 function! s:ExitDialog(old, action)
138 if a:old == s:CurrentColor()
140 elseif a:action == ''
141 let ans = confirm("Keep this colorscheme ?", "&Yes\n&No\n&Cancel")
142 elseif action == 'keep'
144 elseif action == 'revert'
148 if ans == 1 || ans==0
149 " exit, keep colorscheme
150 let msg = (a:old == s:CurrentColor() ? '' : "(original: '".a:old."')")
151 call s:FinalEcho( msg )
153 " exit, revert colorscheme
154 call s:SetColor(a:old)
155 call s:FinalEcho('original color restored')
157 " do not exit, continue browsing
162 function! s:ColorScroller()
163 let old = s:CurrentColor()
164 let list = s:GetColorschemesList()
165 let total = s:CountEntries(list)
168 if line("$") == 1 && getline(1) == "" && bufnr('$')==1
169 " if buffer is empty, open something
170 echo "We will open sample text with syntax highlighting."
171 echo "Watch for the guiding prompt in the bottom line."
172 echo "When the text will open, use Arrow keys to switch colorschemes, ? for help."
174 echo "Press any key to continue"
176 :e $VIMRUNTIME/syntax/abc.vim
182 if !exists("g:syntax_on")
189 let index = s:FindIndex(list, s:CurrentColor())
192 echon s:CurrentColor()
195 echon "] ColorScroller: "
196 echohl MoreMsg | echon "Arrows" | echohl NONE | echon "-next/prev; "
197 echohl MoreMsg | echon "Esc" | echohl NONE | echon "-exit; "
198 echohl MoreMsg | echon "?" | echohl NONE | echon "-help > "
201 echon " " . index . "/" . total . " "
202 echon s:Align("", 12-strlen(s:CurrentColor()))
203 echon "> ColorScroll > "
204 echon "Arrows,Esc,? > "
209 if key == "\<Left>" || key == "\<Up>" || c ==# 'h' || c ==# 'j'
211 elseif key == "\<Down>" || key == "\<Right>" || c ==# 'l' || c==# 'k' || c==# ' '
213 elseif c==# 'g' || c=='0' || c=='1'
214 call s:SetColor( s:GetFirstColors() )
215 elseif c=='$' || c==# 'G'
216 call s:SetColor( s:GetLastColors() )
218 " command 'L' list colors
220 elseif c=='Z' || c=='z' || key == 13 || c=='q' || c=='Q' || c==':' || key == 27
221 if s:ExitDialog(old, '') != -1
224 elseif key == 12 " c=="\<C-L>"
227 call s:JumpByIndex(list,total)
228 elseif key == "\<PageDown>"
229 call s:JumpByIndex2(list,total, (index-10>=1 ? index-10 : index-10+total))
230 elseif key == "\<PageUp>"
231 call s:JumpByIndex2(list,total, index+10)
233 call s:ScrollerHelp()
235 call s:RefreshColorschemesList()
236 echo "Colorscheme list refreshed. Press any key to continue."
239 call s:ScrollerHelp()
245 " Get 1-based index of 'entry' in \n-separated 'list'
246 function! s:FindIndex(list,entry)
247 " we assume entry has no special chars or we could escape() it
248 let str = substitute("\n" . a:list . "\n", "\n" . a:entry . "\n.*$", "", "")
249 return 1 + s:CountEntries(str)
252 " Get list element by 1-based index
253 function! s:EntryByIndex(list,index)
256 while tail != '' && k < a:index
257 let tail=substitute(tail, "^[^\n]*\n", "", "")
260 let tail = substitute(tail, "\n.*$", "", "")
264 function! s:MakeWellFormedList(list)
266 " make sure last \n is present
268 " make sure leading \n are not present
269 let str=substitute(str, "^\n*", "", "")
270 " make sure entries are separated by exactly one \n
271 let str=substitute(str, "\n\\+", "\n", "g")
276 function! s:CountEntries(list)
277 let str = s:MakeWellFormedList(a:list)
279 let str=substitute(str, "[^\n]\\+\n", ".", "g")
284 function! s:RemoveDuplicates(list)
286 let res = s:MakeWellFormedList(a:list . "\n")
288 while beg < strlen(res)
289 let end = matchend(res, sep, beg)
290 let str1 = strpart( res, beg, end - beg)
291 let res = strpart(res,0,end) . substitute("\n".strpart(res,end), "\n".str1,"\n","g")
292 let res = substitute(res, "\n\\+", "\n", "g")
300 " s:SortVar(): sort components of string @var separated
301 " by delimiter @sep, and returns the sorted string.
302 " For example, s:SortVar("c\nb\na", "\n") returns "a\nb\nc\n"
303 function! s:SortVar(list, sep)
304 let list = split( a:list, a:sep )
305 let sorted = sort(list)
306 let result = join( sorted, "\n" )
313 " s:SortVar(): sort components of string @var separated
314 " by delimiter @sep, and returns the sorted string.
315 " For example, s:SortVar("c\nb\na", "\n") returns "a\nb\nc\n"
316 function! s:SortVar(list, sep)
318 let res=s:MakeWellFormedList(a:list . "\n")
325 let index2=matchend(res, a:sep, index1)
326 if index2 == -1 || index2>=len
329 let index3=matchend(res, a:sep, index2)
333 let str1=strpart(res, index1, index2-index1)
334 let str2=strpart(res, index2, index3-index2)
337 " swap str1 and str2 in res
338 let res=strpart(res,0,index1).str2.str1.strpart(res,index3)
339 let index1=index1 + strlen(str2)
341 let index1=index1 + strlen(str1)
351 endif " v:version < 700
355 function! s:GetColorschemesList()
357 let s:list = s:RefreshColorschemesList()
363 function! s:RefreshColorschemesList()
364 let x=globpath(&rtp, "colors/*.vim")
365 let y=substitute(x."\n","\\(^\\|\n\\)[^\n]*[/\\\\]", "\n", "g")
366 let z=substitute(y,"\\.vim\n", "\n", "g")
367 let sorted = s:SortVar(z, "\n")
368 let s:list = s:RemoveDuplicates(sorted)
372 function! s:GetFirstColors()
373 let list=s:GetColorschemesList()
374 let trim=substitute(list, "^\n\\+", "", "")
375 return substitute(trim, "\n.*", "", "")
378 function! s:GetLastColors()
379 let list=s:GetColorschemesList()
380 let trim=substitute(list, "\n\\+$", "", "")
381 return substitute(trim, "^.*\n", "", "")
384 function! s:FinalEcho(suffix)
385 let list = s:GetColorschemesList()
386 let total = s:CountEntries(list)
387 let index = s:FindIndex(list, s:CurrentColor())
392 echon s:CurrentColor()
394 echon "] colorscheme #".index ." of " . total.". "
398 function! s:GetNextColor(color)
399 let list=s:GetColorschemesList()
400 if ("\n".list) =~ ("\n".s:CurrentColor()."\n")
401 let next=substitute("\n".list."\n", ".*\n".a:color."\n", "", "")
402 let next = substitute(next, "\n.*", "", "")
403 return next=='' ? s:GetFirstColors() : next
405 return s:GetFirstColors()
409 function! s:GetPrevColor(color)
410 let list=s:GetColorschemesList()
411 if ("\n".list) =~ ("\n".a:color."\n")
412 let prev=substitute("\n".list."\n", "\n".a:color."\n.*", "", "")
413 let prev=substitute(prev, "^.*\n", "", "")
414 return prev=='' ? s:GetLastColors() : prev
416 return s:GetLastColors()
420 function! s:NextSilent()
421 let old = s:CurrentColor()
422 let next = s:GetNextColor(s:CurrentColor())
423 call s:SetColor( next )
426 function! s:PrevSilent()
427 let old = s:CurrentColor()
428 let prev = s:GetPrevColor(s:CurrentColor())
429 call s:SetColor( prev )
432 function! s:NextColorscheme()
433 let old = s:CurrentColor()
434 let next = s:GetNextColor(s:CurrentColor())
435 call s:SetColor( next )
437 call s:FinalEcho('previous: '.old)
440 function! s:PrevColorscheme()
441 let old = s:CurrentColor()
442 let prev = s:GetPrevColor(s:CurrentColor())
443 call s:SetColor( prev )
445 call s:FinalEcho('previous: '.old)
448 command! CN :call s:NextColorscheme()
449 command! CP :call s:PrevColorscheme()
452 map \c :echo g:colors_name<cr>
454 " 2006-07-18 fixed bug with Align() -> s:Align() (affected L command)
455 " 2006-07-18 added colorlist cache (s:list)
456 " 2006-07-18 added R key to refresh colorlist
457 " 2006-07-19 for vim7, sort using builtin sort() (bubblesort is slow)