Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Version 0.9

- Re-arrangements & modularization (this means many function names have
changed, on the other hand only those functions are loaded that are
actually needed)
- tlib#input#List(): Added maps with m-modifiers for <c-q>, <c-z>, <c-a>
- tlib#input#List(): Make sure &fdm is manual
- tlib#input#List(): When exiting the list view, consume the next 5
characters in the queue (if any)
- tlib#input#EditList(): Now has cut, copy, paste functionality.
- Added documentation and examples
  • Loading branch information...
commit 017773ae6e772b311692fe5ada77bd6d697f1b07 1 parent ec6f89e
@tomtom tomtom authored committed
View
1,203 autoload/tlib.vim
@@ -1,1202 +1,15 @@
-" tlib.vim -- Some utility functions
-" @Author: Thomas Link (mailto:samul AT web de?subject=vim-tlib)
+" tlib.vim
+" @Author: Thomas Link (mailto:samul AT web de?subject=[vim])
" @Website: http://www.vim.org/account/profile.php?user_id=4037
" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
-" @Created: 2007-04-10.
-" @Last Change: 2007-06-24.
-" @Revision: 1432
-" vimscript: 1863
-"
-" TODO:
-" - tlib#InputList() shouldn't take a list of handlers but an instance
-" of tlib#World as argument.
-" - tlib#InputList(): Speed up with large lists (n > 1000)
-" - tlib#Args(dictionary)
+" @Created: 2007-07-17.
+" @Last Change: 2007-07-17.
+" @Revision: 0.0.2
-if &cp || exists("loaded_tlib_autoload") "{{{2
+if &cp || exists("loaded_tlib_autoload")
finish
endif
-let loaded_tlib_autoload = loaded_tlib
+let loaded_tlib_autoload = 1
+" Dummy file for backwards compatibility.
-""" Scratch buffer {{{1
-function! tlib#UseScratch(world) "{{{3
- let id = get(a:world, 'scratch', '__InputList__')
- if id =~ '^\d\+$'
- if bufnr('%') != id
- exec 'buffer! '. id
- endif
- else
- let bn = bufnr(id)
- if bn != -1
- " TLogVAR bn
- let wn = bufwinnr(bn)
- if wn != -1
- " TLogVAR wn
- exec wn .'wincmd w'
- else
- let cmd = get(a:world, 'scratch_split', 1) ? 'botright sbuffer! ' : 'buffer! '
- silent exec cmd . bn
- endif
- else
- " TLogVAR id
- let cmd = get(a:world, 'scratch_split', 1) ? 'botright split ' : 'edit '
- silent exec cmd . escape(id, '%#\ ')
- " silent exec 'split '. id
- endif
- setlocal buftype=nofile
- setlocal bufhidden=hide
- setlocal noswapfile
- setlocal nobuflisted
- setlocal modifiable
- set ft=tlibInputList
- endif
- return bufnr('%')
-endf
-
-function! tlib#CloseScratch(world) "{{{3
- let scratch = get(a:world, 'scratch', '')
- " TLogVAR scratch
- if !empty(scratch)
- let wn = bufwinnr(scratch)
- if wn != -1
- " TLogVAR wn
- exec wn .'wincmd w'
- " call tlib#UseScratch(a:world)
- wincmd c
- " redraw
- endif
- unlet a:world.scratch
- endif
-endf
-
-
-""" Input-related, select from a list etc. {{{1
-function! s:SNR() "{{{3
- return matchstr(expand('<sfile>'), '<SNR>\d\+_\zeSNR$')
-endf
-
-function! s:DisplayHelp(type, handlers) "{{{3
- let help = [
- \ 'Help:',
- \ 'Mouse ... Pick an item Letter ... Filter the list',
- \ 'Number ... Pick an item +, |, ! ... AND, OR, (NOT)',
- \ 'Enter ... Pick the current item <bs>, <c-bs> ... Reduce filter',
- \ '<c-r> ... Reset the display Up/Down ... Next/previous item',
- \ '<c-q> ... Edit top filter string Page Up/Down ... Scroll',
- \ '<c-z> ... Suspend/Resume <Esc> ... Abort',
- \ '',
- \ ]
-
- if stridx(a:type, 'm') != -1
- let help += [
- \ '#, <c-space> ... (Un)Select the current item',
- \ '<c-a> ... (Un)Select all currently visible items',
- \ '<s-up/down> ... (Un)Select items',
- \ ]
- " \ '<c-\> ... Show only selected',
- endif
- for handler in a:handlers
- let key = get(handler, 'key_name', '')
- if !empty(key)
- let desc = get(handler, 'help', '')
- call add(help, printf('%-12s ... %s', key, desc))
- endif
- endfor
- let help += [
- \ '',
- \ 'Warning:',
- \ 'Please don''t try to resize the window with the mouse.',
- \ '',
- \ 'Note on filtering:',
- \ 'The filter is prepended with "\V". Basically, filtering is case-insensitive.',
- \ 'Letters at word boundaries or upper-case lettes in camel-case names is given',
- \ 'more weight. If an OR-joined pattern start with "!", matches will be excluded.',
- \ '',
- \ 'Press any key to continue.',
- \ ]
- norm! ggdG
- call append(0, help)
- norm! Gddgg
- exec 'resize '. len(help)
-endf
-
-" s:DisplayList(world, type, handlers, query, ?list)
-function! s:DisplayList(world, type, handlers, query, ...) "{{{3
- " TLogVAR a:query
- " TLogVAR a:world.state
- let list = a:0 >= 1 ? a:1 : []
- call tlib#UseScratch(a:world)
- if a:world.state == 'scroll'
- exec 'norm! '. a:world.offset .'zt'
- elseif a:world.state == 'help'
- call s:DisplayHelp(a:type, a:handlers)
- else
- let ll = len(list)
- let x = len(ll) + 1
- " TLogVAR ll
- if a:world.state =~ '\<display\>'
- norm! ggdG
- let w = &co - &fdc - 1
- call append(0, map(copy(list), 'printf("%-'. w .'.'. w .'s", substitute(v:val, ''[[:cntrl:][:space:]]'', " ", "g"))'))
- " call append(0, a:query)
- norm! Gddgg
- " if a:world.state !~ '\<redisplay\>'
- let resize = get(a:world, 'resize', 0)
- " TLogVAR resize
- exec 'resize '. (resize == 0 ? ll : min([ll, resize]))
- " endif
- endif
- " TLogVAR a:world.prefidx
- let base_pref = a:world.GetBaseIdx(a:world.prefidx)
- " TLogVAR base_pref
- if a:world.state =~ '\<redisplay\>'
- call filter(b:tlibDisplayListMarks, 'index(a:world.sel_idx, v:val) == -1 && v:val != base_pref')
- " TLogVAR b:tlibDisplayListMarks
- call map(b:tlibDisplayListMarks, 's:DisplayListMark(a:world, x, v:val, ":")')
- " let b:tlibDisplayListMarks = map(copy(a:world.sel_idx), 's:DisplayListMark(a:world, x, v:val, "#")')
- " call add(b:tlibDisplayListMarks, a:world.prefidx)
- " call s:DisplayListMark(a:world, x, a:world.GetBaseIdx(a:world.prefidx), '*')
- endif
- let b:tlibDisplayListMarks = map(copy(a:world.sel_idx), 's:DisplayListMark(a:world, x, v:val, "#")')
- call add(b:tlibDisplayListMarks, base_pref)
- call s:DisplayListMark(a:world, x, base_pref, '*')
- exec 'norm! '. a:world.offset .'zt'
- let &statusline = a:query
- endif
- redraw
-endf
-
-function! s:DisplayListMark(world, x, y, mark) "{{{3
- " TLogVAR a:y, a:mark
- if a:x > 0 && a:y >= 0
- " TLogDBG a:x .'x'. a:y .' '. a:mark
- let sy = a:world.GetListIdx(a:y) + 1
- " TLogVAR sy
- if sy >= 1
- call setpos('.', [0, sy, a:x, 0])
- exec 'norm! r'. a:mark
- " exec 'norm! '. a:y .'gg'. a:x .'|r'. a:mark
- endif
- endif
- return a:y
-endf
-
-" tlib#GetChar(?timeout=0)
-function! tlib#GetChar(...) "{{{3
- let timeout = a:0 >= 1 ? a:1 : 0
- if timeout == 0
- return getchar()
- else
- let start = localtime()
- while 1
- let c = getchar(0)
- if c != 0
- return c
- elseif localtime() - start > timeout
- return -1
- endif
- endwh
- endif
- return -1
-endf
-
-function! s:AssessName(name) "{{{3
- let xa = 0
- for fltl in s:world.filter
- let flt = s:world.GetRx(fltl)
- if a:name =~# '\V'. flt
- let xa += 3
- endif
- if a:name =~ '\V\^'. flt .'\|'. flt .'\$'
- let xa += 3
- elseif a:name =~ '\V\<'. flt .'\|'. flt .'\>'
- let xa += 2
- elseif a:name =~ '\V\A'. flt .'\|'. flt .'\A'
- let xa += 1
- endif
- if flt[0] =~# '\u' && matchstr(a:name, '\V\.\ze'. flt) =~# '\U'
- let xa += 1
- endif
- if flt[0] =~# '\U' && matchstr(a:name, '\V\.\ze'. flt) =~# '\u'
- let xa += 1
- endif
- if flt[-1] =~# '\u' && matchstr(a:name, '\V'. flt .'\zs\.') =~# '\U'
- let xa += 1
- endif
- if flt[-1] =~# '\U' && matchstr(a:name, '\V'. flt .'\zs\.') =~# '\u'
- let xa += 1
- endif
- endfor
- return xa
-endf
-
-function! s:SortPrefs(a, b) "{{{3
- let a = s:world.GetItem(a:a)
- let b = s:world.GetItem(a:b)
- let xa = s:AssessName(a)
- let xb = s:AssessName(b)
- if a < b
- let xa += 1
- elseif b < a
- let xb += 1
- endif
- " let la = len(a)
- " let lb = len(b)
- " if la < lb
- " let xa += 1
- " elseif lb < la
- " let xb += 1
- " endif
- return xa == xb ? 0 : xa < xb ? 1 : -1
-endf
-
-function! s:CheckAgentReturnValue(name, value) "{{{3
- if type(a:value) != 4 && !has_key(a:value, 'state')
- echoerr 'Malformed agent: '. a:name
- endif
- return a:value
-endf
-
-function! s:AgentPageUp(world, selected) "{{{3
- let a:world.offset -= (winheight(0) / 2)
- let a:world.state = 'scroll'
- return a:world
-endf
-
-function! s:AgentPageDown(world, selected) "{{{3
- let a:world.offset += (winheight(0) / 2)
- let a:world.state = 'scroll'
- return a:world
-endf
-
-function! s:AgentUp(world, selected) "{{{3
- let a:world.idx = ''
- if a:world.prefidx > 1
- let a:world.prefidx -= 1
- else
- let a:world.prefidx = len(a:world.list)
- endif
- let a:world.state = 'redisplay'
- return a:world
-endf
-
-function! s:AgentDown(world, selected) "{{{3
- let a:world.idx = ''
- if a:world.prefidx < len(a:world.list)
- let a:world.prefidx += 1
- else
- let a:world.prefidx = 1
- endif
- let a:world.state = 'redisplay'
- return a:world
-endf
-
-function! s:AgentReset(world, selected) "{{{3
- let a:world.state = 'reset'
- return a:world
-endf
-
-function! s:AgentInput(world, selected) "{{{3
- let flt0 = a:world.filter[0][0]
- let flt1 = input('Filter: ', flt0)
- echo
- if flt1 != flt0 && !empty(flt1)
- let a:world.filter[0][0] = flt1
- endif
- let a:world.state = 'display'
- return a:world
-endf
-
-function! s:AgentSuspend(world, selected) "{{{3
- let bn = bufnr('.')
- let wn = bufwinnr(bn)
- exec 'noremap <buffer> <c-z> :call <SID>Resume("world", '. bn .', '. wn .')<cr>'
- let s:tlib_world = a:world
- let a:world.state = 'exit suspend'
- return a:world
-endf
-
-function! s:Resume(name, bn, wn) "{{{3
- echo
- let s:tlib_{a:name}.state = 'display'
- call tlib#InputList('resume '. a:name)
-endf
-
-function! s:AgentHelp(world, selected) "{{{3
- let a:world.state = 'help'
- return a:world
-endf
-
-function! s:AgentOR(world, selected) "{{{3
- if !empty(a:world.filter[0])
- call insert(a:world.filter[0], '')
- endif
- let a:world.state = 'display'
- return a:world
-endf
-
-function! s:AgentAND(world, selected) "{{{3
- if !empty(a:world.filter[0])
- call insert(a:world.filter, [''])
- endif
- let a:world.state = 'display'
- return a:world
-endf
-
-function! s:AgentReduceFilter(world, selected) "{{{3
- call a:world.ReduceFilter()
- let a:world.offset = 1
- let a:world.state = 'display'
- return a:world
-endf
-
-function! s:AgentPopFilter(world, selected) "{{{3
- call a:world.PopFilter()
- let a:world.offset = 1
- let a:world.state = 'display'
- return a:world
-endf
-
-function! s:AgentDebug(world, selected) "{{{3
- " echo string(world.state)
- echo string(a:world.filter)
- echo string(a:world.idx)
- echo string(a:world.prefidx)
- echo string(a:world.sel_idx)
- call getchar()
- let a:world.state = 'display'
- return a:world
-endf
-
-function! s:AgentSelect(world, selected) "{{{3
- call a:world.SelectItem('toggle', a:world.prefidx)
- " let a:world.state = 'display keepcursor'
- let a:world.state = 'redisplay'
- return a:world
-endf
-
-function! s:AgentSelectUp(world, selected) "{{{3
- call a:world.SelectItem('toggle', a:world.prefidx)
- if a:world.prefidx > 1
- let a:world.prefidx -= 1
- endif
- let a:world.state = 'redisplay'
- return a:world
-endf
-
-function! s:AgentSelectDown(world, selected) "{{{3
- call a:world.SelectItem('toggle', a:world.prefidx)
- if a:world.prefidx < len(a:world.list)
- let a:world.prefidx += 1
- endif
- let a:world.state = 'redisplay'
- return a:world
-endf
-
-function! s:AgentSelectAll(world, selected) "{{{3
- let listrange = range(1, len(a:world.list))
- let mode = empty(filter(copy(listrange), 'index(a:world.sel_idx, a:world.GetBaseIdx(v:val)) == -1'))
- \ ? 'toggle' : 'set'
- for i in listrange
- call a:world.SelectItem(mode, i)
- endfor
- let a:world.state = 'display keepcursor'
- return a:world
-endf
-
-" function! s:Agent<+TBD+>(world, selected)
-" <+TBD+>
-" endf
-
-function! s:DisplayFormat(file)
- let fname = fnamemodify(a:file, ":p:t")
- " let fname = fnamemodify(a:file, ":t")
- " if isdirectory(a:file)
- " let fname .='/'
- " endif
- let dname = fnamemodify(a:file, ":h")
- let dnmax = &co - max([20, len(fname)]) - 12 - &fdc
- if len(dname) > dnmax
- let dname = '...'. strpart(fnamemodify(a:file, ":h"), len(dname) - dnmax)
- endif
- return printf("%-20s %s", fname, dname)
-endf
-
-" Type
-" Mouse ... Immediatly select an item
-" Number ... (Immediatly) select an item
-" Letter ... Filter the list (if only one item is left, take it)
-" Esc ... Abort
-" Enter ... Select preferred item
-" tlib#InputList(type. query, list, ?handlers=[], ?default="", ?timeout=0)
-" function! tlib#InputList(type, query, list, ...) "{{{3
-function! tlib#InputList(type, ...) "{{{3
- exec tlib#Args([
- \ ['query', ''],
- \ ['list', []],
- \ ['handlers', []],
- \ ['rv', ''],
- \ ['timeout', 0],
- \ ])
- " let handlers = a:0 >= 1 ? a:1 : []
- " let rv = a:0 >= 2 ? a:2 : ''
- " let timeout = a:0 >= 3 ? a:3 : 0
- let backchar = ["\<bs>", "\<del>"]
-
- if a:type =~ '^resume'
- let world = s:tlib_{matchstr(a:type, ' \zs.\+')}
- let [_, query, list, handlers, rv, timeout] = world.arguments
- else
- let world = tlib#World#New({
- \ 'type': a:type,
- \ 'base': list,
- \ 'wnr': winnr(),
- \ 'query': query,
- \ 'arguments': [a:type, query, list, handlers, rv, timeout],
- \ })
- endif
-
- let state_handlers = filter(copy(handlers), 'has_key(v:val, "state")')
- let post_handlers = filter(copy(handlers), 'has_key(v:val, "postprocess")')
- let display_format = tlib#Find(handlers, 'has_key(v:val, "display_format")', '', 'v:val.display_format')
- if display_format == 'filename'
- " let display_format = 'printf("%%-20s %%s", fnamemodify(%s, ":t"), fnamemodify(%s, ":h"))'
- let display_format = 's:DisplayFormat(%s)'
- endif
- let filter_format = tlib#Find(handlers, 'has_key(v:val, "filter_format")', '', 'v:val.filter_format')
- let return_agent = tlib#Find(handlers, 'has_key(v:val, "return_agent")')
- let resize_value = tlib#Find(handlers, 'has_key(v:val, "resize")')
- if !empty(resize_value) && a:type !~ '^resume'
- let world.resize = resize_value.resize
- endif
- let show_empty = tlib#Find(handlers, 'has_key(v:val, "show_empty")', 0, 'v:val.show_empty')
- let pick_last_item = tlib#Find(handlers, 'has_key(v:val, "pick_last_item")',
- \ tlib#GetValue('tlib_pick_last_item', 'bg'), 'v:val.pick_last_item')
- let numeric_chars = tlib#Find(handlers, 'has_key(v:val, "numeric_chars")',
- \ tlib#GetValue('tlib_numeric_chars', 'bg'), 'v:val.numeric_chars')
- let key_handlers = filter(copy(handlers), 'has_key(v:val, "key")')
- let key_agents = {
- \ "\<PageUp>": function('s:AgentPageUp'),
- \ "\<PageDown>": function('s:AgentPageDown'),
- \ "\<Up>": function('s:AgentUp'),
- \ "\<Down>": function('s:AgentDown'),
- \ 18: function('s:AgentReset'),
- \ 17: function('s:AgentInput'),
- \ 27: 'tlib#agent#Exit',
- \ 26: function('s:AgentSuspend'),
- \ 63: function('s:AgentHelp'),
- \ "\<F1>": function('s:AgentHelp'),
- \ 124: function('s:AgentOR'),
- \ 43: function('s:AgentAND'),
- \ "\<bs>": function('s:AgentReduceFilter'),
- \ "\<del>": function('s:AgentReduceFilter'),
- \ "\<c-bs>": function('s:AgentPopFilter'),
- \ "\<m-bs>": function('s:AgentPopFilter'),
- \ "\<c-del>": function('s:AgentPopFilter'),
- \ "\<m-del>": function('s:AgentPopFilter'),
- \ 191: function('s:AgentDebug'),
- \ }
- if stridx(world.type, 'm') != -1
- " let key_agents["\<c-space>"] = function('s:AgentSelect')
- let key_agents[35] = function('s:AgentSelect')
- let key_agents["\<s-up>"] = function('s:AgentSelectUp')
- let key_agents["\<s-down>"] = function('s:AgentSelectDown')
- let key_agents[1] = function('s:AgentSelectAll')
- endif
- for handler in key_handlers
- let k = get(handler, 'key', '')
- if !empty(k)
- let key_agents[k] = handler.agent
- endif
- endfor
- let statusline = &statusline
- let laststatus = &laststatus
- let &laststatus = 2
-
- try
- while !empty(world.state) && world.state !~ '^exit' && (show_empty || !empty(world.base))
- " TLogDBG 'while'
- " TLogVAR world.state
- try
- for handler in state_handlers
- let eh = get(handler, 'state', '')
- if !empty(eh) && eh == world.state
- let ea = get(handler, 'exec', '')
- if !empty(ea)
- exec ea
- else
- let agent = get(handler, 'agent', '')
- let world = call(agent, [world])
- call s:CheckAgentReturnValue(agent, world)
- endif
- endif
- endfor
-
- if world.state == 'reset'
- " TLogDBG 'reset'
- call world.Reset()
- continue
- endif
-
- let llenw = len(world.base) - winheight(0) + 1
- if world.offset > llenw
- let world.offset = llenw
- endif
- if world.offset < 1
- let world.offset = 1
- endif
-
- " TLogDBG 1
- " TLogVAR world.state
- if world.state =~ 'display'
- if world.state =~ '^display'
- let world.table = filter(range(1, len(world.base)), 'world.MatchBaseIdx(filter_format, v:val)')
- " TLogDBG 2
- " TLogVAR world.table
- let world.list = map(copy(world.table), 'world.GetBaseItem(v:val)')
- " TLogDBG 3
- let llen = len(world.list)
- if llen == 0 && !show_empty
- call world.ReduceFilter()
- let world.offset = 1
- continue
- else
- if llen == 1
- let world.last_item = world.list[0]
- if pick_last_item
- echom 'Pick last item: '. world.list[0]
- let world.prefidx = '1'
- throw 'pick'
- endif
- else
- let world.last_item = ''
- endif
- endif
- " TLogDBG 4
- if world.state == 'display'
- if world.idx == '' && llen < g:tlib_sortprefs_threshold && !world.FilterIsEmpty()
- let s:world = world
- let pref = sort(range(1, llen), 's:SortPrefs')
- let world.prefidx = get(pref, 0, 1)
- else
- let world.prefidx = world.idx == '' ? 1 : world.idx
- endif
- endif
- " TLogDBG 5
- let dlist = copy(world.list)
- if !empty(display_format)
- call map(dlist, 'eval(call(function("printf"), world.FormatArgs(display_format, v:val)))')
- endif
- " TLogVAR world.prefidx
- " TLogDBG 6
- let dlist = map(range(1, llen), 'printf("%0'. len(llen) .'d", v:val) .": ". dlist[v:val - 1]')
- endif
- " TLogDBG 7
- if world.prefidx > world.offset + winheight(0) - 1
- let world.offset = world.prefidx - winheight(0) + 1
- elseif world.prefidx < world.offset
- let world.offset = world.prefidx
- endif
- " TLogDBG 8
- call s:DisplayList(world, world.type, handlers, world.query .' (filter: '. world.DisplayFilter() .'; press "?" for help)', dlist)
- " TLogDBG 9
- let world.state = ''
-
- else
- if world.state == 'scroll'
- let world.prefidx = world.offset
- endif
- call s:DisplayList(world, world.type, handlers, '')
- if world.state == 'help'
- let world.state = 'display'
- else
- let world.state = ''
- endif
- endif
-
- " TLogVAR timeout
- let c = tlib#GetChar(timeout)
- if world.state != ''
- " continue
- elseif has_key(key_agents, c)
- let world = call(key_agents[c], [world, world.GetSelectedItems(world.GetCurrentItem())])
- call s:CheckAgentReturnValue(c, world)
- " continue
- elseif c == 13
- throw 'pick'
- elseif c == "\<LeftMouse>"
- let world.prefidx = matchstr(getline(v:mouse_lnum), '^\d\+\ze:')
- if empty(world.prefidx)
- " call feedkeys(c, 't')
- let c = tlib#GetChar(timeout)
- let world.state = 'help'
- continue
- endif
- throw 'pick'
- elseif c >= 32
- let world.state = 'display'
- if has_key(numeric_chars, c)
- let world.idx .= (c - numeric_chars[c])
- if len(world.idx) == len(llen)
- let world.prefidx = world.idx
- throw 'pick'
- endif
- else
- let world.idx = ''
- " TLogVAR world.filter
- let world.filter[0][0] .= nr2char(c)
- " continue
- endif
- else
- let world.state = 'redisplay'
- endif
-
- catch /^pick$/
- let world.state = ''
- " echom 'Pick item #'. world.prefidx
-
- finally
- " TLogDBG 'finally 1'
- if world.state =~ '\<suspend\>'
- elseif !empty(world.list) && !empty(world.base)
- " TLogVAR world.list
- if empty(world.state)
- " TLogVAR world.state
- if stridx(world.type, 'i') != -1
- let rv = llen == 1 ? 1 : world.prefidx
- else
- if llen == 1
- " TLogVAR llen
- let rv = world.list[0]
- elseif world.prefidx > 0
- " TLogVAR world.prefidx
- let rv = world.GetCurrentItem()
- endif
- endif
- endif
- for handler in post_handlers
- let state = get(handler, 'postprocess', '')
- " TLogVAR handler
- " TLogVAR state
- " TLogVAR world.state
- if state == world.state
- let agent = handler.agent
- let [world, rv] = call(agent, [world, rv])
- call s:CheckAgentReturnValue(agent, world)
- endif
- endfor
- endif
- " TLogDBG 'state0='. world.state
- endtry
- " TLogDBG 'state1='. world.state
- endwh
-
- " TLogDBG 'exit while loop'
- " TLogVAR world.list
- " TLogVAR world.sel_idx
- " TLogVAR world.idx
- " TLogVAR world.prefidx
- " TLogVAR rv
- if world.state =~ '\<suspend\>'
- elseif !empty(return_agent)
- return call(return_agent.return_agent, [world, rv])
- elseif stridx(world.type, 'm') != -1
- return world.GetSelectedItems(rv)
- else
- return rv
- endif
-
- finally
- let &statusline = statusline
- let &laststatus = laststatus
- " TLogDBG 'finally 2'
- if world.state !~ '\<suspend\>'
- call tlib#CloseScratch(world)
- exec world.wnr .'wincmd w'
- endif
- echo
- redraw
- endtry
-endf
-
-function! s:AgentEditItem(world, selected) "{{{3
- let lidx = a:world.prefidx
- " TLogVAR lidx
- " TLogVAR a:world.table
- let bidx = a:world.GetBaseIdx(lidx)
- " TLogVAR bidx
- let item = a:world.GetBaseItem(bidx)
- let item = input(lidx .'@'. bidx .': ', item)
- if item != ''
- call a:world.SetBaseItem(bidx, item)
- endif
- let a:world.state = 'display'
- return a:world
-endf
-
-function! s:AgentNewItem(world, selected) "{{{3
- let basepi = a:world.GetBaseIdx(a:world.prefidx)
- let item = input('New item: ')
- call insert(a:world.base, item, basepi)
- let a:world.state = 'reset'
- return a:world
-endf
-
-function! s:AgentDeleteItems(world, selected) "{{{3
- let remove = copy(a:world.sel_idx)
- let basepi = a:world.GetBaseIdx(a:world.prefidx)
- if index(remove, basepi) == -1
- call add(remove, basepi)
- endif
- " call map(remove, 'a:world.GetBaseIdx(v:val)')
- for idx in reverse(sort(remove))
- call remove(a:world.base, idx - 1)
- endfor
- let a:world.state = 'display'
- call a:world.ResetSelected()
- " let a:world.state = 'reset'
- return a:world
-endf
-
-function! s:AgentEditReturnValue(world, rv) "{{{3
- return [a:world.state !~ '\<exit\>', a:world.base]
-endf
-
-function! tlib#EditListHandlers() "{{{3
- return [
- \ {'key': 5, 'agent': s:SNR() .'AgentEditItem', 'key_name': '<c-e>', 'help': 'Edit item'},
- \ {'key': 4, 'agent': s:SNR() .'AgentDeleteItems', 'key_name': '<c-d>', 'help': 'Delete item(s)'},
- \ {'key': 14, 'agent': s:SNR() .'AgentNewItem', 'key_name': '<c-n>', 'help': 'New item'},
- \ {'pick_last_item': 0},
- \ {'return_agent': s:SNR() .'AgentEditReturnValue'},
- \ ]
-endf
-
-function! tlib#EditList(query, list, ...) "{{{3
- let handlers = a:0 >= 1 ? a:1 : tlib#EditListHandlers()
- let rv = a:0 >= 2 ? a:2 : ''
- let timeout = a:0 >= 3 ? a:3 : 0
- " TLogVAR handlers
- let [success, list] = tlib#InputList('m', a:query, copy(a:list), handlers, rv, timeout)
- return success ? list : a:list
-endf
-
-
-""" List related functions {{{1
-function! tlib#Inject(list, value, Function) "{{{3
- if empty(a:list)
- return a:value
- else
- let item = a:list[0]
- let rest = a:list[1:-1]
- let value = call(a:Function, [a:value, item])
- return tlib#Inject(rest, value, a:Function)
- endif
-endf
-
-function! tlib#Compact(list) "{{{3
- return filter(copy(a:list), '!empty(v:val)')
-endf
-
-function! tlib#Flatten(list) "{{{3
- let acc = []
- for e in a:list
- if type(e) == 3
- let acc += tlib#Flatten(e)
- else
- call add(acc, e)
- endif
- unlet e
- endfor
- return acc
-endf
-
-" tlib#FindAll(list, filter, ?process_expr="")
-function! tlib#FindAll(list, filter, ...) "{{{3
- let rv = filter(copy(a:list), a:filter)
- if a:0 >= 1 && a:1 != ''
- let rv = map(rv, a:1)
- endif
- return rv
-endf
-
-" tlib#Find(list, filter, ?default="", ?process_expr="")
-function! tlib#Find(list, filter, ...) "{{{3
- let default = a:0 >= 1 ? a:1 : ''
- let expr = a:0 >= 2 ? a:2 : ''
- return get(tlib#FindAll(a:list, a:filter, expr), 0, default)
-endf
-
-function! tlib#Any(list, expr) "{{{3
- return !empty(tlib#FindAll(a:list, a:expr))
-endf
-
-function! tlib#All(list, expr) "{{{3
- return len(tlib#FindAll(a:list, a:expr)) == len(a:list)
-endf
-
-function! tlib#Remove(list, element) "{{{3
- let idx = index(a:list, a:element)
- if idx == -1
- call remove(a:list, idx)
- endif
- return a:list
-endf
-
-function! tlib#RemoveAll(list, element) "{{{3
- call filter(a:list, 'v:val != a:element')
- return a:list
-endf
-
-
-""" Variables {{{1
-function! tlib#Let(name, val)
- if !exists(a:name)
- " exec "let ". a:name ."='". a:val ."'"
- " exec 'let '. a:name .'="'. escape(a:val, '"\') .'"'
- let {a:name} = a:val
- endif
-endf
-
-" tlib#GetArg(n, var, ?default="", ?test='')
-function! tlib#GetArg(n, var, ...) "{{{3
- let default = a:0 >= 1 ? a:1 : ''
- let atest = a:0 >= 2 ? a:2 : ''
- if !empty(atest)
- let atest = ' && (a:'. a:n .' '. atest .')'
- endif
- let test = printf('a:0 >= %d', a:n) . atest
- return printf('let %s = %s ? a:%d : %s', a:var, test, a:n, string(default))
-endf
-
-" tlib#Args(list, ?default='')
-function! tlib#Args(list, ...) "{{{3
- let default = a:0 >= 1 ? a:1 : ''
- let list = map(copy(a:list), 'type(v:val) == 3 ? v:val : [v:val, default]')
- let args = map(range(1, len(list)), 'call("tlib#GetArg", [v:val] + list[v:val - 1])')
- return join(args, ' | ')
-endf
-
-function! tlib#GetValue(var, namespace, ...) "{{{3
- for namespace in split(a:namespace, '\zs')
- let var = namespace .':'. a:var
- if exists(var)
- return eval(var)
- endif
- endfor
- return a:0 >= 1 ? a:1 : ''
-endf
-
-function! tlib#GetVar(var, namespace, ...) "{{{3
- let pre = []
- let post = []
- for namespace in split(a:namespace, '\zs')
- let var = namespace .':'. a:var
- call add(pre, printf('exists("%s") ? %s : (', var, var))
- call add(post, ')')
- endfor
- let default = a:0 >= 1 ? a:1 : ''
- return join(pre) . string(default) . join(post)
-endf
-
-function! tlib#EvalInBuffer(buffer, code) "{{{3
- let cb = bufnr('%')
- let wb = bufwinnr('%')
- " TLogVAR cb
- let sn = bufnr(a:buffer)
- let sb = sn != cb
- let lazyredraw = &lazyredraw
- set lazyredraw
- if sb
- let ws = bufwinnr(sn)
- if ws != -1
- try
- exec ws.'wincmd w'
- exec a:code
- finally
- exec wb.'wincmd w'
- endtry
- else
- try
- silent exec 'sbuffer! '. sn
- exec a:code
- finally
- wincmd c
- endtry
- endif
- else
- exec a:code
- endif
- let &lazyredraw = lazyredraw
-endf
-
-
-
-""" Command line {{{1
-function! tlib#ExArg(arg, ...) "{{{3
- let chars = '%# \'
- if a:0 >= 1
- let chars .= a:1
- endif
- return escape(a:arg, chars)
-endf
-
-
-""" File related {{{1
-let g:tlibFileNameSeparator = '/'
-" let g:tlibFileNameSeparator = exists('+shellslash') && !&shellslash ? '\' : '/'
-
-function! tlib#FileSplit(filename) "{{{3
- let prefix = matchstr(a:filename, '^\(\w\+:\)\?/\+')
- " TLogVAR prefix
- if !empty(prefix)
- let filename = a:filename[len(prefix) : -1]
- else
- let filename = a:filename
- endif
- let rv = split(filename, '[\/]')
- " let rv = split(filename, '[\/]', 1)
- if !empty(prefix)
- call insert(rv, prefix[0:-2])
- endif
- return rv
-endf
-
-function! tlib#FileJoin(filename_parts) "{{{3
- return join(a:filename_parts, g:tlibFileNameSeparator)
-endf
-
-function! tlib#DirName(dirname) "{{{3
- if a:dirname !~ '[/\\]$'
- return a:dirname . g:tlibFileNameSeparator
- endif
- return a:dirname
-endf
-
-function! tlib#RelativeFilename(filename, basedir) "{{{3
- let f0 = fnamemodify(a:filename, ':p')
- let fn = fnamemodify(f0, ':t')
- let fd = fnamemodify(f0, ':h')
- let f = tlib#FileSplit(fd)
- " TLogVAR f
- let b0 = fnamemodify(a:basedir, ':p')
- let b = tlib#FileSplit(b0)
- " TLogVAR b
- if f[0] != b[0]
- return f0
- else
- while !empty(f) && !empty(b)
- if f[0] != b[0]
- break
- endif
- call remove(f, 0)
- call remove(b, 0)
- endwh
- return tlib#FileJoin(repeat(['..'], len(b)) + f + [fn])
- endif
-endf
-
-function! tlib#EnsureDirectoryExists(dir) "{{{3
- if !isdirectory(a:dir)
- return mkdir(a:dir, 'p')
- endif
- return 1
-endf
-
-function! tlib#MyRuntimeDir() "{{{3
- return get(split(&rtp, ','), 0)
-endf
-
-" tlib#GetCacheName(type, ?file=%, ?mkdir=0)
-function! tlib#GetCacheName(type, ...) "{{{3
- " TLogDBG 'bufname='. bufname('.')
- if empty(expand('%:t'))
- return ''
- endif
- let file = a:0 >= 1 && !empty(a:1) ? a:1 : expand('%:p')
- let mkdir = a:0 >= 2 ? a:2 : 0
- let dir = tlib#MyRuntimeDir()
- let file = tlib#RelativeFilename(file, dir)
- let file = substitute(file, '\.\.\|[:&<>]\|//\+\|\\\\\+', '_', 'g')
- let dir = tlib#FileJoin([dir, 'cache', a:type, fnamemodify(file, ':h')])
- let file = fnamemodify(file, ':t')
- " TLogVAR dir
- " TLogVAR file
- if mkdir && !isdirectory(dir)
- call mkdir(dir, 'p')
- endif
- retur tlib#FileJoin([dir, file])
-endf
-
-function! tlib#CacheSave(cfile, dictionary) "{{{3
- if !empty(a:cfile)
- call writefile([string(a:dictionary)], a:cfile, 'b')
- endif
-endf
-
-function! tlib#CacheGet(cfile) "{{{3
- if !empty(a:cfile) && filereadable(a:cfile)
- let val = readfile(a:cfile, 'b')
- return eval(join(val, "\n"))
- else
- return {}
- endif
-endf
-
-function! s:SetScrollBind(world) "{{{3
- let sb = get(a:world, 'scrollbind', &scrollbind)
- if sb != &scrollbind
- let &scrollbind = sb
- endif
-endf
-
-function! tlib#ExWithFiles(world, fcmd, bcmd, files) "{{{3
- for f in a:files
- let bn = bufnr(f)
- if bn != -1
- if !empty(a:bcmd)
- exec a:bcmd .' '. bn
- call s:SetScrollBind(a:world)
- endif
- elseif filereadable(f)
- if !empty(a:fcmd)
- exec a:fcmd .' '. escape(f, '%#\ ')
- call s:SetScrollBind(a:world)
- endif
- endif
- endfor
-endf
-
-
-""" Strings {{{1
-function! tlib#RemoveBackslashes(text, ...) "{{{3
- exec tlib#GetArg(1, 'chars', ' ')
- " TLogVAR chars
- let rv = substitute(a:text, '\\\(['. chars .']\)', '\1', 'g')
- return rv
-endf
-
-
-
-""" URLs {{{1
-" These functions could use printf() now.
-function! tlib#DecodeURL(url)
- let rv = ''
- let n = 0
- let m = strlen(a:url)
- while n < m
- let c = a:url[n]
- if c == '+'
- let c = ' '
- elseif c == '%'
- if a:url[n + 1] == '%'
- let n = n + 1
- else
- " let c = escape(nr2char('0x'. strpart(a:url, n + 1, 2)), '\')
- let c = nr2char('0x'. strpart(a:url, n + 1, 2))
- let n = n + 2
- endif
- endif
- let rv = rv.c
- let n = n + 1
- endwh
- return rv
-endf
-
-function! tlib#EncodeChar(char)
- if a:char == '%'
- return '%%'
- elseif a:char == ' '
- return '+'
- else
- " Taken from eval.txt
- let n = char2nr(a:char)
- let r = ''
- while n
- let r = '0123456789ABCDEF'[n % 16] . r
- let n = n / 16
- endwhile
- return '%'. r
- endif
-endf
-
-function! tlib#EncodeURL(url)
- return substitute(a:url, '\([^a-zA-Z0-9_.-]\)', '\=EncodeChar(submatch(1))', 'g')
-endf
-
-
-
-finish
------------------------------------------------------------------------
-This library provides some utility functions. There isn't much need to
-install it unless another plugin requires you to do so.
-
-tlib#InputList(type, query, list)
- Select items from a list that can be filtered using a regexp and
- does some other tricks. The goal of the function is to let you
- select items from a list with only a few keystrokes. The function
- can be used to select a single item or multiple items.
-
-tlib#EditList(query, list)
- Edit items in a list. Return the modified list.
-
-
-CHANGES:
-0.1
-Initial release
-
-0.2
-- More list convenience functions
-- tlib#EditList()
-- tlib#InputList(): properly handle duplicate items; it type contains
-'i', the list index + 1 is returned, not the element
-
-0.3
-- tlib#InputList(): Show feedback in statusline instead of the echo area
-- tlib#GetVar(), tlib#GetValue()
-
-0.4
-- tlib#InputList(): Up/Down keys wrap around list
-- tlib#InputList(): FIX: Problem when reducing the filter & using AND
-- tlib#InputList(): Made <a-numeric> work (can be configured via
-- tlib#InputList(): special display_format: "filename"
-- tlib#Object: experimental support for some kind of OOP
-- tlib#World: Extracted some functions from tlib.vim to tlib/World.vim
-- tlib#FileJoin(), tlib#FileSplit(), tlib#RelativeFilename()
-- tlib#Let()
-- tlib#EnsureDirectoryExists(dir)
-- tlib#DirName(dir)
-- tlib#DecodeURL(url), tlib#EncodeChar(char), tlib#EncodeURL(url)
-- FIX: Problem when using shift-up/down with filtered lists
-
-0.5
-- tlib#InputList(): FIX: Selecting items in filtered view
-- tlib#InputList(): <c-bs>: Remove last AND pattern from filter
-
-0.6
-- tlib#InputList(): Disabled <c-space> map
-- tlib#InputList(): try to be smart about user itentions only if a
-list's length is < g:tlib_sortprefs_threshold (default: 200)
-- tlib#Object: Super() method
-- tlib#MyRuntimeDir()
-- tlib#GetCacheName(), tlib#CacheSave(), tlib#CacheGet()
-- tlib#Args(), tlib#GetArg()
-- FIX: tlib#InputList(): Display problem with first item
-
-0.7
-- tlib#InputList(): <c-z> ... Suspend/Resume input
-- tlib#InputList(): <c-q> ... Input text on the command line (useful on
-slow systems when working with very large lists)
-- tlib#InputList(): AND-pattern starting with '!' will work as 'exclude
-matches'
-- tlib#InputList(): FIX <c-bs> pop OR-patterns properly
-- tlib#InputList(): display_format == filename: don't add '/' to
-directory names (avoid filesystem access)
-
-0.8
-- FIX: Return empty cache name for buffers that have no files attached to it
-- Some re-arranging
-
-
-" vi: fdm=marker
View
23 autoload/tlib/TestChild.vim
@@ -0,0 +1,23 @@
+" TestChild.vim
+" @Author: Thomas Link (mailto:samul AT web de?subject=[vim])
+" @Website: http://members.a1.net/t.link/
+" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
+" @Created: 2007-05-18.
+" @Last Change: 2007-05-18.
+" @Revision: 0.1.7
+
+if &cp || exists("loaded_tlib_TestChild_autoload")
+ finish
+endif
+let loaded_tlib_TestChild_autoload = 1
+
+let s:prototype = tlib#Test#New({'_class': ['TestChild']}) "{{{2
+function! tlib#TestChild#New(...) "{{{3
+ let object = s:prototype.New(a:0 >= 1 ? a:1 : {})
+ return object
+endf
+
+function! s:prototype.Dummy() dict "{{{3
+ return 'TestChild.vim'
+endf
+
View
174 autoload/tlib/World.vim
@@ -1,10 +1,10 @@
-" World.vim -- The World prototype for tlib#InputList()
+" World.vim -- The World prototype for tlib#input#List()
" @Author: Thomas Link (mailto:samul AT web de?subject=[vim])
" @Website: http://members.a1.net/t.link/
" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
" @Created: 2007-05-01.
-" @Last Change: 2007-06-20.
-" @Revision: 0.1.54
+" @Last Change: 2007-07-10.
+" @Revision: 0.1.80
if &cp || exists("loaded_tlib_world_autoload")
finish
@@ -161,8 +161,59 @@ function! s:prototype.DisplayFilter() dict "{{{3
return join(reverse(filter1), ' AND ')
endf
-function! s:UseInputListScratch(world) "{{{3
- let scratch = tlib#UseScratch(a:world)
+function! s:prototype.UseScratch() "{{{3
+ let id = get(self, 'scratch', '__InputList__')
+ if id =~ '^\d\+$'
+ if bufnr('%') != id
+ exec 'buffer! '. id
+ endif
+ else
+ let bn = bufnr(id)
+ if bn != -1
+ " TLogVAR bn
+ let wn = bufwinnr(bn)
+ if wn != -1
+ " TLogVAR wn
+ exec wn .'wincmd w'
+ else
+ let cmd = get(self, 'scratch_split', 1) ? 'botright sbuffer! ' : 'buffer! '
+ silent exec cmd . bn
+ endif
+ else
+ " TLogVAR id
+ let cmd = get(self, 'scratch_split', 1) ? 'botright split ' : 'edit '
+ silent exec cmd . escape(id, '%#\ ')
+ " silent exec 'split '. id
+ endif
+ setlocal buftype=nofile
+ setlocal bufhidden=hide
+ setlocal noswapfile
+ setlocal nobuflisted
+ setlocal modifiable
+ setlocal foldmethod=manual
+ set ft=tlibInputList
+ endif
+ let self.scratch = bufnr('%')
+ return self.scratch
+endf
+
+function! s:prototype.CloseScratch() "{{{3
+ let scratch = get(self, 'scratch', '')
+ " TLogVAR scratch
+ if !empty(scratch)
+ let wn = bufwinnr(scratch)
+ if wn != -1
+ " TLogVAR wn
+ exec wn .'wincmd w'
+ wincmd c
+ " redraw
+ endif
+ unlet self.scratch
+ endif
+endf
+
+function! s:prototype.UseInputListScratch() "{{{3
+ let scratch = self.UseScratch()
syntax match InputlListCursor /^\d\+\* .*$/
syntax match InputlListSelected /^\d\+# .*$/
hi def link InputlListCursor Search
@@ -179,7 +230,7 @@ function! s:prototype.Reset() dict "{{{3
let self.filter = [['']]
let self.idx = ''
let self.prefidx = 0
- let self.scratch = s:UseInputListScratch(self)
+ call self.UseInputListScratch()
call self.ResetSelected()
endf
@@ -187,3 +238,114 @@ function! s:prototype.ResetSelected() dict "{{{3
let self.sel_idx = []
endf
+
+
+function! s:DisplayHelp(type, handlers) "{{{3
+ let help = [
+ \ 'Help:',
+ \ 'Mouse ... Pick an item Letter ... Filter the list',
+ \ 'Number ... Pick an item +, |, ! ... AND, OR, (NOT)',
+ \ 'Enter ... Pick the current item <bs>, <c-bs> ... Reduce filter',
+ \ '<c|m-r> ... Reset the display Up/Down ... Next/previous item',
+ \ '<c|m-q> ... Edit top filter string Page Up/Down ... Scroll',
+ \ '<c|m-z> ... Suspend/Resume <Esc> ... Abort',
+ \ '',
+ \ ]
+
+ if stridx(a:type, 'm') != -1
+ let help += [
+ \ '#, <c-space> ... (Un)Select the current item',
+ \ '<c|m-a> ... (Un)Select all currently visible items',
+ \ '<s-up/down> ... (Un)Select items',
+ \ ]
+ " \ '<c-\> ... Show only selected',
+ endif
+ for handler in a:handlers
+ let key = get(handler, 'key_name', '')
+ if !empty(key)
+ let desc = get(handler, 'help', '')
+ call add(help, printf('%-12s ... %s', key, desc))
+ endif
+ endfor
+ let help += [
+ \ '',
+ \ 'Warning:',
+ \ 'Please don''t try to resize the window with the mouse.',
+ \ '',
+ \ 'Note on filtering:',
+ \ 'The filter is prepended with "\V". Basically, filtering is case-insensitive.',
+ \ 'Letters at word boundaries or upper-case lettes in camel-case names is given',
+ \ 'more weight. If an OR-joined pattern start with "!", matches will be excluded.',
+ \ '',
+ \ 'Press any key to continue.',
+ \ ]
+ norm! ggdG
+ call append(0, help)
+ norm! Gddgg
+ exec 'resize '. len(help)
+endf
+
+" DisplayList(type, handlers, query, ?list)
+function! s:prototype.DisplayList(type, handlers, query, ...) "{{{3
+ " TLogVAR a:query
+ " TLogVAR self.state
+ let list = a:0 >= 1 ? a:1 : []
+ call self.UseScratch()
+ if self.state == 'scroll'
+ exec 'norm! '. self.offset .'zt'
+ elseif self.state == 'help'
+ call s:DisplayHelp(a:type, a:handlers)
+ else
+ let ll = len(list)
+ let x = len(ll) + 1
+ " TLogVAR ll
+ if self.state =~ '\<display\>'
+ norm! ggdG
+ let w = &co - &fdc - 1
+ call append(0, map(copy(list), 'printf("%-'. w .'.'. w .'s", substitute(v:val, ''[[:cntrl:][:space:]]'', " ", "g"))'))
+ " call append(0, a:query)
+ norm! Gddgg
+ " if self.state !~ '\<redisplay\>'
+ let resize = get(self, 'resize', 0)
+ " TLogVAR resize
+ let resize = resize == 0 ? ll : min([ll, resize])
+ let resize = min([resize, (&lines * 3 / 4)])
+ " TLogVAR resize, ll, &lines
+ exec 'resize '. resize
+ " endif
+ endif
+ " TLogVAR self.prefidx
+ let base_pref = self.GetBaseIdx(self.prefidx)
+ " TLogVAR base_pref
+ if self.state =~ '\<redisplay\>'
+ call filter(b:tlibDisplayListMarks, 'index(self.sel_idx, v:val) == -1 && v:val != base_pref')
+ " TLogVAR b:tlibDisplayListMarks
+ call map(b:tlibDisplayListMarks, 'self.DisplayListMark(x, v:val, ":")')
+ " let b:tlibDisplayListMarks = map(copy(self.sel_idx), 'self.DisplayListMark(x, v:val, "#")')
+ " call add(b:tlibDisplayListMarks, self.prefidx)
+ " call self.DisplayListMark(x, self.GetBaseIdx(self.prefidx), '*')
+ endif
+ let b:tlibDisplayListMarks = map(copy(self.sel_idx), 'self.DisplayListMark(x, v:val, "#")')
+ call add(b:tlibDisplayListMarks, base_pref)
+ call self.DisplayListMark(x, base_pref, '*')
+ exec 'norm! '. self.offset .'zt'
+ let &statusline = a:query
+ endif
+ redraw
+endf
+
+function! s:prototype.DisplayListMark(x, y, mark) "{{{3
+ " TLogVAR a:y, a:mark
+ if a:x > 0 && a:y >= 0
+ " TLogDBG a:x .'x'. a:y .' '. a:mark
+ let sy = self.GetListIdx(a:y) + 1
+ " TLogVAR sy
+ if sy >= 1
+ call setpos('.', [0, sy, a:x, 0])
+ exec 'norm! r'. a:mark
+ " exec 'norm! '. a:y .'gg'. a:x .'|r'. a:mark
+ endif
+ endif
+ return a:y
+endf
+
View
249 autoload/tlib/agent.vim
@@ -3,8 +3,8 @@
" @Website: http://www.vim.org/account/profile.php?user_id=4037
" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
" @Created: 2007-06-24.
-" @Last Change: 2007-06-24.
-" @Revision: 0.1.21
+" @Last Change: 2007-07-09.
+" @Revision: 0.1.41
if &cp || exists("loaded_tlib_agent_autoload")
finish
@@ -14,7 +14,7 @@ let loaded_tlib_agent_autoload = 1
" General {{{1
function! tlib#agent#Exit(world, selected) "{{{3
- call tlib#CloseScratch(a:world)
+ call a:world.CloseScratch()
let a:world.state = 'exit escape'
let a:world.list = []
" let a:world.base = []
@@ -29,30 +29,253 @@ function! tlib#agent#CopyItems(world, selected)
endf
+" InputList related {{{1
+function! tlib#agent#PageUp(world, selected) "{{{3
+ let a:world.offset -= (winheight(0) / 2)
+ let a:world.state = 'scroll'
+ return a:world
+endf
+
+function! tlib#agent#PageDown(world, selected) "{{{3
+ let a:world.offset += (winheight(0) / 2)
+ let a:world.state = 'scroll'
+ return a:world
+endf
+
+function! tlib#agent#Up(world, selected) "{{{3
+ let a:world.idx = ''
+ if a:world.prefidx > 1
+ let a:world.prefidx -= 1
+ else
+ let a:world.prefidx = len(a:world.list)
+ endif
+ let a:world.state = 'redisplay'
+ return a:world
+endf
+
+function! tlib#agent#Down(world, selected) "{{{3
+ let a:world.idx = ''
+ if a:world.prefidx < len(a:world.list)
+ let a:world.prefidx += 1
+ else
+ let a:world.prefidx = 1
+ endif
+ let a:world.state = 'redisplay'
+ return a:world
+endf
+
+function! tlib#agent#Reset(world, selected) "{{{3
+ let a:world.state = 'reset'
+ return a:world
+endf
+
+function! tlib#agent#Input(world, selected) "{{{3
+ let flt0 = a:world.filter[0][0]
+ let flt1 = input('Filter: ', flt0)
+ echo
+ if flt1 != flt0 && !empty(flt1)
+ let a:world.filter[0][0] = flt1
+ endif
+ let a:world.state = 'display'
+ return a:world
+endf
+
+function! tlib#agent#Suspend(world, selected) "{{{3
+ let bn = bufnr('.')
+ let wn = bufwinnr(bn)
+ exec 'noremap <buffer> <c-z> :call <SID>Resume("world", '. bn .', '. wn .')<cr>'
+ let b:tlib_world = a:world
+ let a:world.state = 'exit suspend'
+ return a:world
+endf
+
+function! s:Resume(name, bn, wn) "{{{3
+ echo
+ let b:tlib_{a:name}.state = 'display'
+ call tlib#input#List('resume '. a:name)
+endf
+
+function! tlib#agent#Help(world, selected) "{{{3
+ let a:world.state = 'help'
+ return a:world
+endf
+
+function! tlib#agent#OR(world, selected) "{{{3
+ if !empty(a:world.filter[0])
+ call insert(a:world.filter[0], '')
+ endif
+ let a:world.state = 'display'
+ return a:world
+endf
+
+function! tlib#agent#AND(world, selected) "{{{3
+ if !empty(a:world.filter[0])
+ call insert(a:world.filter, [''])
+ endif
+ let a:world.state = 'display'
+ return a:world
+endf
+
+function! tlib#agent#ReduceFilter(world, selected) "{{{3
+ call a:world.ReduceFilter()
+ let a:world.offset = 1
+ let a:world.state = 'display'
+ return a:world
+endf
+
+function! tlib#agent#PopFilter(world, selected) "{{{3
+ call a:world.PopFilter()
+ let a:world.offset = 1
+ let a:world.state = 'display'
+ return a:world
+endf
+
+function! tlib#agent#Debug(world, selected) "{{{3
+ " echo string(world.state)
+ echo string(a:world.filter)
+ echo string(a:world.idx)
+ echo string(a:world.prefidx)
+ echo string(a:world.sel_idx)
+ call getchar()
+ let a:world.state = 'display'
+ return a:world
+endf
+
+function! tlib#agent#Select(world, selected) "{{{3
+ call a:world.SelectItem('toggle', a:world.prefidx)
+ " let a:world.state = 'display keepcursor'
+ let a:world.state = 'redisplay'
+ return a:world
+endf
+
+function! tlib#agent#SelectUp(world, selected) "{{{3
+ call a:world.SelectItem('toggle', a:world.prefidx)
+ if a:world.prefidx > 1
+ let a:world.prefidx -= 1
+ endif
+ let a:world.state = 'redisplay'
+ return a:world
+endf
+
+function! tlib#agent#SelectDown(world, selected) "{{{3
+ call a:world.SelectItem('toggle', a:world.prefidx)
+ if a:world.prefidx < len(a:world.list)
+ let a:world.prefidx += 1
+ endif
+ let a:world.state = 'redisplay'
+ return a:world
+endf
+
+function! tlib#agent#SelectAll(world, selected) "{{{3
+ let listrange = range(1, len(a:world.list))
+ let mode = empty(filter(copy(listrange), 'index(a:world.sel_idx, a:world.GetBaseIdx(v:val)) == -1'))
+ \ ? 'toggle' : 'set'
+ for i in listrange
+ call a:world.SelectItem(mode, i)
+ endfor
+ let a:world.state = 'display keepcursor'
+ return a:world
+endf
+
+
+" EditList related {{{1
+function! tlib#agent#EditItem(world, selected) "{{{3
+ let lidx = a:world.prefidx
+ " TLogVAR lidx
+ " TLogVAR a:world.table
+ let bidx = a:world.GetBaseIdx(lidx)
+ " TLogVAR bidx
+ let item = a:world.GetBaseItem(bidx)
+ let item = input(lidx .'@'. bidx .': ', item)
+ if item != ''
+ call a:world.SetBaseItem(bidx, item)
+ endif
+ let a:world.state = 'display'
+ return a:world
+endf
+
+function! tlib#agent#NewItem(world, selected) "{{{3
+ let basepi = a:world.GetBaseIdx(a:world.prefidx)
+ let item = input('New item: ')
+ call insert(a:world.base, item, basepi)
+ let a:world.state = 'reset'
+ return a:world
+endf
+
+function! tlib#agent#DeleteItems(world, selected) "{{{3
+ let remove = copy(a:world.sel_idx)
+ let basepi = a:world.GetBaseIdx(a:world.prefidx)
+ if index(remove, basepi) == -1
+ call add(remove, basepi)
+ endif
+ " call map(remove, 'a:world.GetBaseIdx(v:val)')
+ for idx in reverse(sort(remove))
+ call remove(a:world.base, idx - 1)
+ endfor
+ let a:world.state = 'display'
+ call a:world.ResetSelected()
+ " let a:world.state = 'reset'
+ return a:world
+endf
+
+
+function! tlib#agent#Cut(world, selected) "{{{3
+ let world = tlib#agent#Copy(a:world, a:selected)
+ return tlib#agent#DeleteItems(world, a:selected)
+endf
+
+function! tlib#agent#Copy(world, selected) "{{{3
+ let a:world.clipboard = []
+ let bidxs = copy(a:world.sel_idx)
+ call add(bidxs, a:world.GetBaseIdx(a:world.prefidx))
+ for bidx in sort(bidxs)
+ call add(a:world.clipboard, a:world.GetBaseItem(bidx))
+ endfor
+ let a:world.state = 'redisplay'
+ return a:world
+endf
+
+function! tlib#agent#Paste(world, selected) "{{{3
+ if has_key(a:world, 'clipboard')
+ for e in reverse(copy(a:world.clipboard))
+ call insert(a:world.base, e, a:world.prefidx)
+ endfor
+ endif
+ let a:world.state = 'display'
+ call a:world.ResetSelected()
+ return a:world
+endf
+
+function! tlib#agent#EditReturnValue(world, rv) "{{{3
+ return [a:world.state !~ '\<exit\>', a:world.base]
+endf
+
+
+
" Files related {{{1
function! tlib#agent#EditFile(world, selected)
- call tlib#CloseScratch(a:world)
- call tlib#ExWithFiles(a:world, 'edit', 'buffer', a:selected)
+ call a:world.CloseScratch()
+ call tlib#file#With('edit', 'buffer', a:selected, a:world)
return tlib#agent#Exit(a:world, a:selected)
endf
function! tlib#agent#EditFileInSplit(world, selected)
- call tlib#CloseScratch(a:world)
- call tlib#ExWithFiles(a:world, 'edit', 'buffer', a:selected[0:0])
- call tlib#ExWithFiles(a:world, 'split', 'sbuffer', a:selected[1:-1])
+ call a:world.CloseScratch()
+ call tlib#file#With('edit', 'buffer', a:selected[0:0], a:world)
+ call tlib#file#With('split', 'sbuffer', a:selected[1:-1], a:world)
return tlib#agent#Exit(a:world, a:selected)
endf
function! tlib#agent#EditFileInVSplit(world, selected)
- call tlib#CloseScratch(a:world)
- call tlib#ExWithFiles(a:world, 'edit', 'buffer', a:selected[0:0])
- call tlib#ExWithFiles(a:world, 'vertical split', 'vertical sbuffer', a:selected[1:-1])
+ call a:world.CloseScratch()
+ call tlib#file#With('edit', 'buffer', a:selected[0:0], a:world)
+ call tlib#file#With('vertical split', 'vertical sbuffer', a:selected[1:-1], a:world)
return tlib#agent#Exit(a:world, a:selected)
endf
function! tlib#agent#EditFileInTab(world, selected)
- call tlib#CloseScratch(a:world)
- call tlib#ExWithFiles(a:world, 'tabe', 'tab buffer', a:selected)
+ call a:world.CloseScratch()
+ call tlib#file#With('tabe', 'tab buffer', a:selected, a:world)
return tlib#agent#Exit(a:world, a:selected)
endf
View
52 autoload/tlib/arg.vim
@@ -0,0 +1,52 @@
+" arg.vim
+" @Author: Thomas Link (mailto:samul AT web de?subject=[vim])
+" @Website: http://www.vim.org/account/profile.php?user_id=4037
+" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
+" @Created: 2007-06-30.
+" @Last Change: 2007-06-30.
+" @Revision: 0.0.6
+
+if &cp || exists("loaded_tlib_arg_autoload")
+ finish
+endif
+let loaded_tlib_arg_autoload = 1
+
+" tlib#arg#Get(n, var, ?default="", ?test='')
+" Set a positional argument from a variable argument list.
+" See tlib#string#RemoveBackslashes() for an example.
+function! tlib#arg#Get(n, var, ...) "{{{3
+ let default = a:0 >= 1 ? a:1 : ''
+ let atest = a:0 >= 2 ? a:2 : ''
+ if !empty(atest)
+ let atest = ' && (a:'. a:n .' '. atest .')'
+ endif
+ let test = printf('a:0 >= %d', a:n) . atest
+ return printf('let %s = %s ? a:%d : %s', a:var, test, a:n, string(default))
+endf
+
+" tlib#arg#Let(list, ?default='')
+" Set a positional arguments from a variable argument list.
+" See tlib#InputList() for an example.
+function! tlib#arg#Let(list, ...) "{{{3
+ let default = a:0 >= 1 ? a:1 : ''
+ let list = map(copy(a:list), 'type(v:val) == 3 ? v:val : [v:val, default]')
+ let args = map(range(1, len(list)), 'call("tlib#arg#Get", [v:val] + list[v:val - 1])')
+ return join(args, ' | ')
+endf
+
+
+""" Command line {{{1
+" tlib#arg#Ex(arg, ?chars='%# \')
+" Escape some characters in a string.
+"
+" EXAMPLES:
+" exec 'edit '. tlib#arg#Ex('foo%#bar.txt')
+function! tlib#arg#Ex(arg, ...) "{{{3
+ let chars = '%# \'
+ if a:0 >= 1
+ let chars .= a:1
+ endif
+ return escape(a:arg, chars)
+endf
+
+
View
53 autoload/tlib/buffer.vim
@@ -0,0 +1,53 @@
+" buffer.vim
+" @Author: Thomas Link (mailto:samul AT web de?subject=[vim])
+" @Website: http://www.vim.org/account/profile.php?user_id=4037
+" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
+" @Created: 2007-06-30.
+" @Last Change: 2007-06-30.
+" @Revision: 0.0.2
+
+if &cp || exists("loaded_tlib_buffer_autoload")
+ finish
+endif
+let loaded_tlib_buffer_autoload = 1
+
+" tlib#buffer#Eval(buffer, code)
+" Evaluate CODE in BUFFER.
+"
+" EXAMPLES:
+" call tlib#buffer#Eval('foo.txt', 'echo b:bar')
+function! tlib#buffer#Eval(buffer, code) "{{{3
+ let cb = bufnr('%')
+ let wb = bufwinnr('%')
+ " TLogVAR cb
+ let sn = bufnr(a:buffer)
+ let sb = sn != cb
+ let lazyredraw = &lazyredraw
+ set lazyredraw
+ try
+ if sb
+ let ws = bufwinnr(sn)
+ if ws != -1
+ try
+ exec ws.'wincmd w'
+ exec a:code
+ finally
+ exec wb.'wincmd w'
+ endtry
+ else
+ try
+ silent exec 'sbuffer! '. sn
+ exec a:code
+ finally
+ wincmd c
+ endtry
+ endif
+ else
+ exec a:code
+ endif
+ finally
+ let &lazyredraw = lazyredraw
+ endtry
+endf
+
+
View
50 autoload/tlib/cache.vim
@@ -0,0 +1,50 @@
+" cache.vim
+" @Author: Thomas Link (mailto:samul AT web de?subject=[vim])
+" @Website: http://www.vim.org/account/profile.php?user_id=4037
+" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
+" @Created: 2007-06-30.
+" @Last Change: 2007-06-30.
+" @Revision: 0.1.6
+
+if &cp || exists("loaded_tlib_cache_autoload")
+ finish
+endif
+let loaded_tlib_cache_autoload = 1
+
+" tlib#cache#Filename(type, ?file=%, ?mkdir=0)
+function! tlib#cache#Filename(type, ...) "{{{3
+ " TLogDBG 'bufname='. bufname('.')
+ if empty(expand('%:t'))
+ return ''
+ endif
+ let file = a:0 >= 1 && !empty(a:1) ? a:1 : expand('%:p')
+ let mkdir = a:0 >= 2 ? a:2 : 0
+ let dir = tlib#dir#MyRuntime()
+ let file = tlib#file#Relative(file, dir)
+ let file = substitute(file, '\.\.\|[:&<>]\|//\+\|\\\\\+', '_', 'g')
+ let dir = tlib#file#Join([dir, 'cache', a:type, fnamemodify(file, ':h')])
+ let file = fnamemodify(file, ':t')
+ " TLogVAR dir
+ " TLogVAR file
+ if mkdir && !isdirectory(dir)
+ call mkdir(dir, 'p')
+ endif
+ retur tlib#file#Join([dir, file])
+endf
+
+function! tlib#cache#Save(cfile, dictionary) "{{{3
+ if !empty(a:cfile)
+ call writefile([string(a:dictionary)], a:cfile, 'b')
+ endif
+endf
+
+function! tlib#cache#Get(cfile) "{{{3
+ if !empty(a:cfile) && filereadable(a:cfile)
+ let val = readfile(a:cfile, 'b')
+ return eval(join(val, "\n"))
+ else
+ return {}
+ endif
+endf
+
+
View
39 autoload/tlib/char.vim
@@ -0,0 +1,39 @@
+" char.vim
+" @Author: Thomas Link (mailto:samul AT web de?subject=[vim])
+" @Website: http://www.vim.org/account/profile.php?user_id=4037
+" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
+" @Created: 2007-06-30.
+" @Last Change: 2007-06-30.
+" @Revision: 0.0.2
+
+if &cp || exists("loaded_tlib_char_autoload")
+ finish
+endif
+let loaded_tlib_char_autoload = 1
+
+" tlib#char#Get(?timeout=0)
+" Get a character.
+"
+" EXAMPLES:
+" echo tlib#char#Get()
+" echo tlib#char#Get(5)
+function! tlib#char#Get(...) "{{{3
+ let timeout = a:0 >= 1 ? a:1 : 0
+ if timeout == 0
+ return getchar()
+ else
+ let start = localtime()
+ while 1
+ let c = getchar(0)
+ if c != 0
+ return c
+ elseif localtime() - start > timeout
+ return -1
+ endif
+ endwh
+ endif
+ return -1
+endf
+
+
+
View
36 autoload/tlib/dir.vim
@@ -0,0 +1,36 @@
+" dir.vim
+" @Author: Thomas Link (mailto:samul AT web de?subject=[vim])
+" @Website: http://www.vim.org/account/profile.php?user_id=4037
+" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
+" @Created: 2007-06-30.
+" @Last Change: 2007-06-30.
+" @Revision: 0.0.4
+
+if &cp || exists("loaded_tlib_dir_autoload")
+ finish
+endif
+let loaded_tlib_dir_autoload = 1
+
+" EXAMPLES:
+" tlib#dir#CanonicName('foo/bar')
+" => 'foo/bar/'
+function! tlib#dir#CanonicName(dirname) "{{{3
+ if a:dirname !~ '[/\\]$'
+ return a:dirname . g:tlib_filename_sep
+ endif
+ return a:dirname
+endf
+
+" Create a directory if it doesn't already exist.
+function! tlib#dir#Ensure(dir) "{{{3
+ if !isdirectory(a:dir)
+ return mkdir(a:dir, 'p')
+ endif
+ return 1
+endf
+
+" Return the first directory in &rtp.
+function! tlib#dir#MyRuntime() "{{{3
+ return get(split(&rtp, ','), 0)
+endf
+
View
95 autoload/tlib/file.vim
@@ -0,0 +1,95 @@
+" file.vim
+" @Author: Thomas Link (mailto:samul AT web de?subject=[vim])
+" @Website: http://www.vim.org/account/profile.php?user_id=4037
+" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
+" @Created: 2007-06-30.
+" @Last Change: 2007-06-30.
+" @Revision: 0.0.11
+
+if &cp || exists("loaded_tlib_file_autoload")
+ finish
+endif
+let loaded_tlib_file_autoload = 1
+
+""" File related {{{1
+" For the following functions please see ../../test/tlib.vim for examples.
+
+" EXAMPLES:
+" tlib#file#Split('foo/bar/filename.txt')
+" => ['foo', 'bar', 'filename.txt']
+function! tlib#file#Split(filename) "{{{3
+ let prefix = matchstr(a:filename, '^\(\w\+:\)\?/\+')
+ " TLogVAR prefix
+ if !empty(prefix)
+ let filename = a:filename[len(prefix) : -1]
+ else
+ let filename = a:filename
+ endif
+ let rv = split(filename, '[\/]')
+ " let rv = split(filename, '[\/]', 1)
+ if !empty(prefix)
+ call insert(rv, prefix[0:-2])
+ endif
+ return rv
+endf
+
+" EXAMPLES:
+" tlib#file#Join(['foo', 'bar', 'filename.txt'])
+" => 'foo/bar/filename.txt'
+function! tlib#file#Join(filename_parts) "{{{3
+ return join(a:filename_parts, g:tlib_filename_sep)
+endf
+
+" EXAMPLES:
+" tlib#file#Relative('foo/bar/filename.txt', 'foo')
+" => 'bar/filename.txt'
+function! tlib#file#Relative(filename, basedir) "{{{3
+ let f0 = fnamemodify(a:filename, ':p')
+ let fn = fnamemodify(f0, ':t')
+ let fd = fnamemodify(f0, ':h')
+ let f = tlib#file#Split(fd)
+ " TLogVAR f
+ let b0 = fnamemodify(a:basedir, ':p')
+ let b = tlib#file#Split(b0)
+ " TLogVAR b
+ if f[0] != b[0]
+ return f0
+ else
+ while !empty(f) && !empty(b)
+ if f[0] != b[0]
+ break
+ endif
+ call remove(f, 0)
+ call remove(b, 0)
+ endwh
+ return tlib#file#Join(repeat(['..'], len(b)) + f + [fn])
+ endif
+endf
+
+
+function! s:SetScrollBind(world) "{{{3
+ let sb = get(a:world, 'scrollbind', &scrollbind)
+ if sb != &scrollbind
+ let &scrollbind = sb
+ endif
+endf
+
+function! tlib#file#With(fcmd, bcmd, files, ...) "{{{3
+ exec tlib#arg#Let([['world', {}]])
+ for f in a:files
+ let bn = bufnr(f)
+ if bn != -1
+ if !empty(a:bcmd)
+ exec a:bcmd .' '. bn
+ call s:SetScrollBind(world)
+ endif
+ elseif filereadable(f)
+ if !empty(a:fcmd)
+ exec a:fcmd .' '. escape(f, '%#\ ')
+ call s:SetScrollBind(world)
+ endif
+ endif
+ endfor
+endf
+
+
View
392 autoload/tlib/input.vim
@@ -0,0 +1,392 @@
+" input.vim
+" @Author: Thomas Link (mailto:samul AT web de?subject=[vim])
+" @Website: http://www.vim.org/account/profile.php?user_id=4037
+" @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
+" @Created: 2007-06-30.
+" @Last Change: 2007-07-09.
+" @Revision: 0.0.9
+
+if &cp || exists("loaded_tlib_input_autoload")
+ finish
+endif
+let loaded_tlib_input_autoload = 1
+
+
+""" Input-related, select from a list etc. {{{1
+
+" Functions related to tlib#input#List(type, ...) "{{{2
+
+" tlib#input#List(type. ?query='', ?list=[], ?handlers=[], ?default="", ?timeout=0)
+"
+" Select a single or multiple items from a list. Return either the list
+" of selected elements or its indexes.
+"
+" type can be:
+" s ... Return one selected element
+" si ... Return the index of the selected element
+" m ... Return a list of selcted elements
+" mi ... Return a list of indexes
+"
+" EXAMPLES:
+" echo tlib#input#List('s', 'Select one item', [100,200,300])
+" echo tlib#input#List('si', 'Select one item', [100,200,300])
+" echo tlib#input#List('m', 'Select one or more item(s)', [100,200,300])
+" echo tlib#input#List('mi', 'Select one or more item(s)', [100,200,300])
+function! tlib#input#List(type, ...) "{{{3
+ exec tlib#arg#Let([
+ \ ['query', ''],
+ \ ['list', []],
+ \ ['handlers', []],
+ \ ['rv', ''],
+ \ ['timeout', 0],
+ \ ])
+ " let handlers = a:0 >= 1 ? a:1 : []
+ " let rv = a:0 >= 2 ? a:2 : ''
+ " let timeout = a:0 >= 3 ? a:3 : 0
+ let backchar = ["\<bs>", "\<del>"]
+
+ if a:type =~ '^resume'
+ let world = b:tlib_{matchstr(a:type, ' \zs.\+')}
+ " unlet b:tlib_{matchstr(a:type, ' \zs.\+')}
+ let [_, query, list, handlers, rv, timeout] = world.arguments
+ else
+ let world = tlib#World#New({
+ \ 'type': a:type,
+ \ 'base': list,
+ \ 'wnr': winnr(),
+ \ 'query': query,
+ \ 'arguments': [a:type, query, list, handlers, rv, timeout],
+ \ })
+ endif
+
+ let state_handlers = filter(copy(handlers), 'has_key(v:val, "state")')
+ let post_handlers = filter(copy(handlers), 'has_key(v:val, "postprocess")')
+ let display_format = tlib#list#Find(handlers, 'has_key(v:val, "display_format")', '', 'v:val.display_format')
+ if display_format == 'filename'
+ " let display_format = 'printf("%%-20s %%s", fnamemodify(%s, ":t"), fnamemodify(%s, ":h"))'
+ let display_format = 's:DisplayFormat(%s)'
+ endif
+ let filter_format = tlib#list#Find(handlers, 'has_key(v:val, "filter_format")', '', 'v:val.filter_format')
+ let return_agent = tlib#list#Find(handlers, 'has_key(v:val, "return_agent")')
+ let resize_value = tlib#list#Find(handlers, 'has_key(v:val, "resize")')
+ if !empty(resize_value) && a:type !~ '^resume'
+ let world.resize = resize_value.resize
+ endif
+ let show_empty = tlib#list#Find(handlers, 'has_key(v:val, "show_empty")', 0, 'v:val.show_empty')
+ let pick_last_item = tlib#list#Find(handlers, 'has_key(v:val, "pick_last_item")',
+ \ tlib#var#Get('tlib_pick_last_item', 'bg'), 'v:val.pick_last_item')
+ let numeric_chars = tlib#list#Find(handlers, 'has_key(v:val, "numeric_chars")',
+ \ tlib#var#Get('tlib_numeric_chars', 'bg'), 'v:val.numeric_chars')
+ let key_handlers = filter(copy(handlers), 'has_key(v:val, "key")')
+ let key_agents = copy(g:tlib_keyagents_InputList_s)
+ if stridx(world.type, 'm') != -1
+ call extend(key_agents, g:tlib_keyagents_InputList_m, 'force')
+ endif
+ for handler in key_handlers
+ let k = get(handler, 'key', '')
+ if !empty(k)
+ let key_agents[k] = handler.agent
+ endif
+ endfor
+ let statusline = &statusline
+ let laststatus = &laststatus
+ let &laststatus = 2
+
+ try
+ while !empty(world.state) && world.state !~ '^exit' && (show_empty || !empty(world.base))
+ " TLogDBG 'while'
+ " TLogVAR world.state
+ try
+ for handler in state_handlers
+ let eh = get(handler, 'state', '')
+ if !empty(eh) && eh == world.state
+ let ea = get(handler, 'exec', '')
+ if !empty(ea)
+ exec ea
+ else
+ let agent = get(handler, 'agent', '')
+ let world = call(agent, [world])
+ call s:CheckAgentReturnValue(agent, world)
+ endif
+ endif
+ endfor
+
+ if world.state == 'reset'
+ " TLogDBG 'reset'
+ call world.Reset()
+ continue
+ endif
+
+ let llenw = len(world.base) - winheight(0) + 1
+ if world.offset > llenw
+ let world.offset = llenw
+ endif
+ if world.offset < 1
+ let world.offset = 1
+ endif
+
+ " TLogDBG 1
+ " TLogVAR world.state
+ if world.state =~ 'display'
+ if world.state =~ '^display'
+ let world.table = filter(range(1, len(world.base)), 'world.MatchBaseIdx(filter_format, v:val)')
+ " TLogDBG 2
+ " TLogVAR world.table
+ let world.list = map(copy(world.table), 'world.GetBaseItem(v:val)')
+ " TLogDBG 3
+ let llen = len(world.list)
+ if llen == 0 && !show_empty
+ call world.ReduceFilter()
+ let world.offset = 1
+ continue
+ else
+ if llen == 1
+ let world.last_item = world.list[0]
+ if pick_last_item
+ echom 'Pick last item: '. world.list[0]
+ let world.prefidx = '1'
+ throw 'pick'
+ endif
+ else
+ let world.last_item = ''
+ endif
+ endif
+ " TLogDBG 4
+ if world.state == 'display'
+ if world.idx == '' && llen < g:tlib_sortprefs_threshold && !world.FilterIsEmpty()
+ let s:world = world
+ let pref = sort(range(1, llen), 's:SortPrefs')
+ let world.prefidx = get(pref, 0, 1)
+ else
+ let world.prefidx = world.idx == '' ? 1 : world.idx
+ endif
+ endif
+ " TLogDBG 5
+ let dlist = copy(world.list)
+ if !empty(display_format)
+ call map(dlist, 'eval(call(function("printf"), world.FormatArgs(display_format, v:val)))')
+ endif
+ " TLogVAR world.prefidx
+ " TLogDBG 6
+ let dlist = map(range(1, llen), 'printf("%0'. len(llen) .'d", v:val) .": ". dlist[v:val - 1]')
+ endif
+ " TLogDBG 7
+ if world.prefidx > world.offset + winheight(0) - 1
+ let world.offset = world.prefidx - winheight(0) + 1
+ elseif world.prefidx < world.offset
+ let world.offset = world.prefidx
+ endif
+ " TLogDBG 8
+ call world.DisplayList(world.type, handlers, world.query .' (filter: '. world.DisplayFilter() .'; press "?" for help)', dlist)
+ " TLogDBG 9
+ let world.state = ''
+
+ else
+ if world.state == 'scroll'
+ let world.prefidx = world.offset
+ endif
+ call world.DisplayList(world.type, handlers, '')
+ if world.state == 'help'
+ let world.state = 'display'
+ else
+ let world.state = ''
+ endif
+ endif
+
+ " TLogVAR timeout
+ let c = tlib#char#Get(timeout)
+ if world.state != ''
+ " continue
+ elseif has_key(key_agents, c)
+ let world = call(key_agents[c], [world, world.GetSelectedItems(world.GetCurrentItem())])
+ call s:CheckAgentReturnValue(c, world)
+ " continue
+ elseif c == 13
+ throw 'pick'
+ elseif c == "\<LeftMouse>"
+ let world.prefidx = matchstr(getline(v:mouse_lnum), '^\d\+\ze:')
+ if empty(world.prefidx)
+ " call feedkeys(c, 't')
+ let c = tlib#char#Get(timeout)
+ let world.state = 'help'
+ continue
+ endif
+ throw 'pick'
+ elseif c >= 32
+ let world.state = 'display'
+ if has_key(numeric_chars, c)
+ let world.idx .= (c - numeric_chars[c])
+ if len(world.idx) == len(llen)
+ let world.prefidx = world.idx
+ throw 'pick'
+ endif
+ else
+ let world.idx = ''
+ " TLogVAR world.filter
+ let world.filter[0][0] .= nr2char(c)
+ " continue
+ endif
+ else
+ let world.state = 'redisplay'
+ endif
+
+ catch /^pick$/
+ let world.state = ''
+ " echom 'Pick item #'. world.prefidx
+
+ finally
+ " TLogDBG 'finally 1'
+ if world.state =~ '\<suspend\>'
+ elseif !empty(world.list) && !empty(world.base)
+ " TLogVAR world.list
+ if empty(world.state)
+ " TLogVAR world.state
+ if stridx(world.type, 'i') != -1
+ let rv = llen == 1 ? 1 : world.prefidx
+ else
+ if llen == 1
+ " TLogVAR llen
+ let rv = world.list[0]
+ elseif world.prefidx > 0
+ " TLogVAR world.prefidx
+ let rv = world.GetCurrentItem()
+ endif
+ endif
+ endif
+ for handler in post_handlers
+ let state = get(handler, 'postprocess', '')
+ " TLogVAR handler
+ " TLogVAR state
+ " TLogVAR world.state
+ if state == world.state
+ let agent = handler.agent
+ let [world, rv] = call(agent, [world, rv])
+ call s:CheckAgentReturnValue(agent, world)
+ endif
+ endfor
+ endif
+ " TLogDBG 'state0='. world.state
+ endtry
+ " TLogDBG 'state1='. world.state
+ endwh
+
+ " TLogDBG 'exit while loop'
+ " TLogVAR world.list
+ " TLogVAR world.sel_idx
+ " TLogVAR world.idx
+ " TLogVAR world.prefidx
+ " TLogVAR rv
+ if world.state =~ '\<suspend\>'
+ elseif !empty(return_ag