diff options
Diffstat (limited to 'vim/bundle/tlib_vim/autoload/tlib/World.vim')
-rwxr-xr-x | vim/bundle/tlib_vim/autoload/tlib/World.vim | 1404 |
1 files changed, 1404 insertions, 0 deletions
diff --git a/vim/bundle/tlib_vim/autoload/tlib/World.vim b/vim/bundle/tlib_vim/autoload/tlib/World.vim new file mode 100755 index 0000000..aa1bc9e --- /dev/null +++ b/vim/bundle/tlib_vim/autoload/tlib/World.vim @@ -0,0 +1,1404 @@ +" @Author: Tom Link (micathom AT gmail com?subject=[vim]) +" @Website: http://www.vim.org/account/profile.php?user_id=4037 +" @License: GPL (see http://www.gnu.org/licenses/gpl.txt) +" @Revision: 1434 + +" :filedoc: +" A prototype used by |tlib#input#List|. +" Inherits from |tlib#Object#New|. + + +" Size of the input list window (in percent) from the main size (of &lines). +" See |tlib#input#List()|. +TLet g:tlib_inputlist_pct = 50 + +" Size of filename columns when listing filenames. +" See |tlib#input#List()|. +TLet g:tlib_inputlist_width_filename = '&co / 3' +" TLet g:tlib_inputlist_width_filename = 25 + +" If true, |tlib#input#List()| will show some indicators about the +" status of a filename (e.g. buflisted(), bufloaded() etc.). +" This is disabled by default because vim checks also for the file on +" disk when doing this. +TLet g:tlib_inputlist_filename_indicators = 0 + +" If not null, display only a short info about the filter. +TLet g:tlib_inputlist_shortmessage = 0 + + + +" Known keys & values: +" scratch_split ... See |tlib#scratch#UseScratch()| +let s:prototype = tlib#Object#New({ + \ '_class': 'World', + \ 'name': 'world', + \ 'allow_suspend': 1, + \ 'base': [], + \ 'bufnr': -1, + \ 'buffer_local': 1, + \ 'cache_var': '', + \ 'display_format': '', + \ 'fileencoding': &fileencoding, + \ 'fmt_display': {}, + \ 'fmt_filter': {}, + \ 'fmt_options': {}, + \ 'filetype': '', + \ 'filter': [['']], + \ 'filter_format': '', + \ 'filter_options': '', + \ 'follow_cursor': '', + \ 'has_menu': 0, + \ 'help_extra': [], + \ 'index_table': [], + \ 'initial_filter': [['']], + \ 'initial_index': 1, + \ 'initial_display': 1, + \ 'initialized': 0, + \ 'key_handlers': [], + \ 'list': [], + \ 'matcher': {}, + \ 'next_agent': '', + \ 'next_eval': '', + \ 'next_state': '', + \ 'numeric_chars': g:tlib#input#numeric_chars, + \ 'offset': 1, + \ 'offset_horizontal': 0, + \ 'on_leave': [], + \ 'pick_last_item': tlib#var#Get('tlib#input#pick_last_item', 'bg'), + \ 'post_handlers': [], + \ 'query': '', + \ 'resize': 0, + \ 'resize_vertical': 0, + \ 'restore_from_cache': [], + \ 'filtered_items': [], + \ 'resume_state': '', + \ 'retrieve_eval': '', + \ 'return_agent': '', + \ 'rv': '', + \ 'scratch': '__InputList__', + \ 'scratch_filetype': 'tlibInputList', + \ 'scratch_hidden': g:tlib#scratch#hidden, + \ 'scratch_vertical': 0, + \ 'scratch_split': 1, + \ 'sel_idx': [], + \ 'show_empty': 0, + \ 'state': 'display', + \ 'state_handlers': [], + \ 'sticky': 0, + \ 'temp_lines': [], + \ 'temp_prompt': [], + \ 'timeout': 0, + \ 'timeout_resolution': 2, + \ 'tabpagenr': -1, + \ 'type': '', + \ 'win_wnr': -1, + \ 'win_height': -1, + \ 'win_width': -1, + \ 'win_pct': 25, + \ }) + " \ 'handlers': [], + " \ 'filter_options': '\c', + +function! tlib#World#New(...) + let object = s:prototype.New(a:0 >= 1 ? a:1 : {}) + call object.SetMatchMode(tlib#var#Get('tlib#input#filter_mode', 'g', 'cnf')) + return object +endf + + +" :nodoc: +function! s:prototype.Set_display_format(value) dict "{{{3 + if a:value == 'filename' + call self.Set_highlight_filename() + let self.display_format = 'world.FormatFilename(%s)' + else + let self.display_format = a:value + endif +endf + + +" :nodoc: +function! s:prototype.DisplayFormat(list) dict "{{{3 + let display_format = self.display_format + if !empty(display_format) + if has_key(self, 'InitFormatName') + call self.InitFormatName() + endif + let cache = self.fmt_display + " TLogVAR display_format, fmt_entries + return map(copy(a:list), 'self.FormatName(cache, display_format, v:val)') + else + return a:list + endif +endf + + +" :nodoc: +function! s:prototype.Set_highlight_filename() dict "{{{3 + let self.tlib_UseInputListScratch = 'call world.Highlight_filename()' +endf + + +if g:tlib#input#format_filename == 'r' + + " :nodoc: + function! s:prototype.Highlight_filename() dict "{{{3 + syntax match TLibDir /\s\+\zs.\{-}[\/]\ze[^\/]\+$/ + hi def link TLibDir Directory + syntax match TLibFilename /[^\/]\+$/ + hi def link TLibFilename Normal + endf + + " :nodoc: + function! s:prototype.FormatFilename(file) dict "{{{3 + if !has_key(self.fmt_options, 'maxlen') + let maxco = &co - len(len(self.base)) - eval(g:tlib#input#filename_padding_r) + let maxfi = max(map(copy(self.base), 'strwidth(v:val)')) + let self.fmt_options.maxlen = min([maxco, maxfi]) + " TLogVAR maxco, maxfi, self.fmt_options.maxlen + endif + let max = self.fmt_options.maxlen + if len(a:file) > max + let filename = '...' . strpart(a:file, len(a:file) - max + 3) + else + let filename = printf('% '. max .'s', a:file) + endif + return filename + endf + +else + + " :nodoc: + function! s:prototype.Highlight_filename() dict "{{{3 + " let self.width_filename = 1 + eval(g:tlib_inputlist_width_filename) + " TLogVAR self.base + let self.width_filename = min([ + \ get(self, 'width_filename', &co), + \ empty(g:tlib#input#filename_max_width) ? &co : eval(g:tlib#input#filename_max_width), + \ max(map(copy(self.base), 'strwidth(matchstr(v:val, "[^\\/]*$"))')) + \ ]) + " TLogVAR self.width_filename + exec 'syntax match TLibDir /\%>'. (1 + self.width_filename) .'c \(|\|\[[^]]*\]\) \zs\(\(\a:\|\.\.\|\.\.\..\{-}\)\?[\/][^&<>*|]\{-}\)\?[^\/]\+$/ contained containedin=TLibMarker contains=TLibFilename' + exec 'syntax match TLibMarker /\%>'. (1 + self.width_filename) .'c \(|\|\[[^]]*\]\) \S.*$/ contains=TLibDir' + " exec 'syntax match TLibDir /\(|\|\[.\{-}\]\) \zs\(\(\a:\|\.\.\|\.\.\..\{-}\)\?[\/][^&<>*|]\{-}\)\?[^\/]\+$/ contained containedin=TLibMarker contains=TLibFilename' + " exec 'syntax match TLibMarker /\(|\|\[.\{-}\]\) \S.*$/ contains=TLibDir' + exec 'syntax match TLibFilename /[^\/]\+$/ contained containedin=TLibDir' + hi def link TLibMarker Special + hi def link TLibDir Directory + hi def link TLibFilename NonText + " :nodoc: + function! self.Highlighter(rx) dict + let rx = '/\c\%>'. (1 + self.width_filename) .'c \(|\|\[[^]]*\]\) .\{-}\zs'. escape(a:rx, '/') .'/' + exec 'match' self.matcher.highlight rx + endf + endf + + + " :nodoc: + function! s:prototype.UseFilenameIndicators() dict "{{{3 + return g:tlib_inputlist_filename_indicators || has_key(self, 'filename_indicators') + endf + + + " :nodoc: + function! s:prototype.InitFormatName() dict "{{{3 + if self.UseFilenameIndicators() + let self._buffers = {} + for bufnr in range(1, bufnr('$')) + let filename = fnamemodify(bufname(bufnr), ':p') + " TLogVAR filename + let bufdef = { + \ 'bufnr': bufnr, + \ } + " '&buflisted' + for opt in ['&modified', '&bufhidden'] + let bufdef[opt] = getbufvar(bufnr, opt) + endfor + let self._buffers[filename] = bufdef + endfor + endif + endf + + + " :nodoc: + function! s:prototype.FormatFilename(file) dict "{{{3 + " TLogVAR a:file + let width = self.width_filename + let split = match(a:file, '[/\\]\zs[^/\\]\+$') + if split == -1 + let fname = a:file + let dname = a:file + else + let fname = strpart(a:file, split) + " let dname = strpart(a:file, 0, split - 1) + let dname = a:file + endif + if strwidth(fname) > width + let fname = strpart(fname, 0, width - 3) .'...' + endif + let dnmax = &co - max([width, strwidth(fname)]) - 8 - self.index_width - &fdc + let use_indicators = self.UseFilenameIndicators() + " TLogVAR use_indicators + let marker = [] + if use_indicators + call insert(marker, '[') + if g:tlib_inputlist_filename_indicators + let bufdef = get(self._buffers, a:file, {}) + " let bnr = bufnr(a:file) + let bnr = get(bufdef, 'bufnr', -1) + " TLogVAR a:file, bnr, self.bufnr + if bnr != -1 + if bnr == self.bufnr + call add(marker, '%') + else + call add(marker, bnr) + endif + if get(bufdef, '&modified', 0) + call add(marker, '+') + endif + if get(bufdef, '&bufhidden', '') == 'hide' + call add(marker, 'h') + endif + " if !get(bufdef, '&buflisted', 1) + " call add(marker, 'u') + " endif + " echom "DBG" a:file string(get(self,'filename_indicators')) + endif + endif + if has_key(self, 'filename_indicators') && has_key(self.filename_indicators, a:file) + if len(marker) > 1 + call add(marker, '|') + endif + call add(marker, self.filename_indicators[a:file]) + endif + if len(marker) <= 1 + call add(marker, ' ') + endif + call add(marker, ']') + else + call add(marker, '|') + endif + let markers = join(marker, '') + if !empty(markers) + let dnmax -= len(markers) + endif + if strwidth(dname) > dnmax + let dname = '...'. strpart(dname, len(dname) - dnmax) + endif + return printf("%-*s %s %s", + \ self.width_filename + len(fname) - strwidth(fname), + \ fname, markers, dname) + endf + +endif + + +" :nodoc: +function! s:prototype.GetSelectedItems(current) dict "{{{3 + " TLogVAR a:current + if stridx(self.type, 'i') != -1 + let rv = copy(self.sel_idx) + else + let rv = map(copy(self.sel_idx), 'self.GetBaseItem(v:val)') + endif + if !empty(a:current) + " TLogVAR a:current, rv, type(a:current) + if tlib#type#IsNumber(a:current) || tlib#type#IsString(a:current) + call s:InsertSelectedItems(rv, a:current) + elseif tlib#type#IsList(a:current) + for item in a:current + call s:InsertSelectedItems(rv, item) + endfor + elseif tlib#type#IsDictionary(a:current) + for [inum, item] in items(a:current) + call s:InsertSelectedItems(rv, item) + endfor + endif + endif + " TAssert empty(rv) || rv[0] == a:current + if stridx(self.type, 'i') != -1 + if !empty(self.index_table) + " TLogVAR rv, self.index_table + call map(rv, 'self.index_table[v:val - 1]') + " TLogVAR rv + endif + endif + return rv +endf + + +function! s:InsertSelectedItems(rv, current) "{{{3 + let ci = index(a:rv, a:current) + if ci != -1 + call remove(a:rv, ci) + endif + call insert(a:rv, a:current) +endf + + +" :nodoc: +function! s:prototype.SelectItemsByNames(mode, items) dict "{{{3 + for item in a:items + let bi = index(self.base, item) + 1 + " TLogVAR item, bi + if bi > 0 + let si = index(self.sel_idx, bi) + " TLogVAR self.sel_idx + " TLogVAR si + if si == -1 + call add(self.sel_idx, bi) + elseif a:mode == 'toggle' + call remove(self.sel_idx, si) + endif + endif + endfor + return 1 +endf + + +" :nodoc: +function! s:prototype.SelectItem(mode, index) dict "{{{3 + " TLogVAR a:mode, a:index + let bi = self.GetBaseIdx(a:index) + " if self.RespondTo('MaySelectItem') + " if !self.MaySelectItem(bi) + " return 0 + " endif + " endif + " TLogVAR bi + let si = index(self.sel_idx, bi) + " TLogVAR self.sel_idx + " TLogVAR si + if si == -1 + call add(self.sel_idx, bi) + elseif a:mode == 'toggle' + call remove(self.sel_idx, si) + endif + return 1 +endf + + +" :nodoc: +function! s:prototype.FormatBaseFromData() abort dict "{{{3 + if has_key(self, 'format_data') && has_key(self, 'data') + let self.base = map(copy(self.data), 'call(self.format_data, [v:val], self)') + endif +endf + + +" :nodoc: +function! s:prototype.FormatArgs(format_string, arg) dict "{{{3 + let nargs = len(substitute(a:format_string, '%%\|[^%]', '', 'g')) + return [a:format_string] + repeat([string(a:arg)], nargs) +endf + + +" :nodoc: +function! s:prototype.GetRx(filter) dict "{{{3 + return '\('. join(filter(copy(a:filter), 'v:val[0] != "!"'), '\|') .'\)' +endf + + +" :nodoc: +function! s:prototype.GetRx0(...) dict "{{{3 + exec tlib#arg#Let(['negative']) + let rx0 = [] + for filter in self.filter + " TLogVAR filter + let rx = join(reverse(filter(copy(filter), '!empty(v:val)')), '\|') + " TLogVAR rx + if !empty(rx) && (negative ? rx[0] == g:tlib#input#not : rx[0] != g:tlib#input#not) + call add(rx0, rx) + endif + endfor + let rx0s = join(rx0, '\|') + if empty(rx0s) + return '' + else + return self.FilterRxPrefix() .'\('. rx0s .'\)' + endif +endf + + +" :nodoc: +function! s:prototype.FormatName(cache, format, value) dict "{{{3 + " TLogVAR a:format, a:value + " TLogDBG has_key(self.fmt_display, a:value) + if has_key(a:cache, a:value) + " TLogDBG "cached" + return a:cache[a:value] + else + let world = self + let ftpl = self.FormatArgs(a:format, a:value) + let fn = call(function("printf"), ftpl) + let fmt = eval(fn) + " TLogVAR ftpl, fn, fmt + let a:cache[a:value] = fmt + return fmt + endif +endf + + +" :nodoc: +function! s:prototype.GetItem(idx) dict "{{{3 + return self.list[a:idx - 1] +endf + + +" :nodoc: +function! s:prototype.GetListIdx(baseidx) dict "{{{3 + " if empty(self.index_table) + let baseidx = a:baseidx + " else + " let baseidx = 0 + self.index_table[a:baseidx - 1] + " " TLogVAR a:baseidx, baseidx, self.index_table + " endif + let rv = index(self.table, baseidx) + " TLogVAR rv, self.table + return rv +endf + + +" :nodoc: +" The first index is 1. +function! s:prototype.GetBaseIdx(idx) dict "{{{3 + " TLogVAR a:idx, self.table, self.index_table + if !empty(self.table) && a:idx > 0 && a:idx <= len(self.table) + return self.table[a:idx - 1] + else + return 0 + endif +endf + + +" :nodoc: +function! s:prototype.GetBaseIdx0(idx) dict "{{{3 + let idx0 = self.GetBaseIdx(a:idx) - 1 + if idx0 < 0 + call tlib#notify#Echo('TLIB: Internal Error: GetBaseIdx0: idx0 < 0', 'WarningMsg') + endif + return idx0 +endf + + +" :nodoc: +function! s:prototype.GetBaseItem(idx) dict "{{{3 + return self.base[a:idx - 1] +endf + + +" :nodoc: +function! s:prototype.SetBaseItem(idx, item) dict "{{{3 + let self.base[a:idx - 1] = a:item +endf + + +" :nodoc: +function! s:prototype.GetLineIdx(lnum) dict "{{{3 + let line = getline(a:lnum) + let prefidx = substitute(matchstr(line, '^\d\+\ze[*:]'), '^0\+', '', '') + return prefidx +endf + + +" :nodoc: +function! s:prototype.SetPrefIdx() dict "{{{3 + " let pref = sort(range(1, self.llen), 'self.SortPrefs') + " let self.prefidx = get(pref, 0, self.initial_index) + let pref_idx = -1 + let pref_weight = -1 + " TLogVAR self.filter_pos, self.filter_neg + " let t0 = localtime() " DBG + for idx in range(1, self.llen) + let item = self.GetItem(idx) + let weight = self.matcher.AssessName(self, item) + " TLogVAR item, weight + if weight > pref_weight + let pref_idx = idx + let pref_weight = weight + endif + endfor + " TLogVAR localtime() - t0 + " TLogVAR pref_idx + " TLogDBG self.GetItem(pref_idx) + if pref_idx == -1 + let self.prefidx = self.initial_index + else + let self.prefidx = pref_idx + endif +endf + + +" " :nodoc: +" function! s:prototype.GetCurrentItem() dict "{{{3 +" let idx = self.prefidx +" " TLogVAR idx +" if stridx(self.type, 'i') != -1 +" return idx +" elseif !empty(self.list) +" if len(self.list) >= idx +" let idx1 = idx - 1 +" let rv = self.list[idx - 1] +" " TLogVAR idx, idx1, rv, self.list +" return rv +" endif +" else +" return '' +" endif +" endf + + +" :nodoc: +function! s:prototype.CurrentItem() dict "{{{3 + if stridx(self.type, 'i') != -1 + return self.GetBaseIdx(self.llen == 1 ? 1 : self.prefidx) + else + if self.llen == 1 + " TLogVAR self.llen + return self.list[0] + elseif self.prefidx > 0 + " TLogVAR self.prefidx + " return self.GetCurrentItem() + if len(self.list) >= self.prefidx + let rv = self.list[self.prefidx - 1] + " TLogVAR idx, rv, self.list + return rv + endif + else + return '' + endif + endif +endf + + +" :nodoc: +function! s:prototype.FilterRxPrefix() dict "{{{3 + return self.matcher.FilterRxPrefix() +endf + + +" :nodoc: +function! s:prototype.SetFilter() dict "{{{3 + " let mrx = '\V'. (a:0 >= 1 && a:1 ? '\C' : '') + let mrx = self.FilterRxPrefix() . self.filter_options + let self.filter_pos = [] + let self.filter_neg = [] + " TLogVAR mrx, self.filter + for filter in self.filter + " TLogVAR filter + let rx = join(reverse(filter(copy(filter), '!empty(v:val)')), '\|') + " TLogVAR rx + if !empty(rx) + if rx =~ '\u' + let mrx1 = mrx .'\C' + else + let mrx1 = mrx + endif + " TLogVAR rx + if rx[0] == g:tlib#input#not + if len(rx) > 1 + call add(self.filter_neg, mrx1 .'\('. rx[1:-1] .'\)') + endif + else + call add(self.filter_pos, mrx1 .'\('. rx .'\)') + endif + endif + endfor + " TLogVAR self.filter_pos, self.filter_neg +endf + + +" :nodoc: +function! s:prototype.IsValidFilter() dict "{{{3 + let last = self.FilterRxPrefix() .'\('. self.filter[0][0] .'\)' + Tlibtrace 'tlib', last + " TLogVAR last + try + let a = match("", last) + return 1 + catch + Tlibtrace 'tlib', v:exception + return 0 + endtry +endf + + +" :nodoc: +function! s:prototype.SetMatchMode(match_mode) dict "{{{3 + " TLogVAR a:match_mode + if !empty(a:match_mode) + unlet self.matcher + try + let self.matcher = tlib#Filter_{a:match_mode}#New() + call self.matcher.Init(self) + catch /^Vim\%((\a\+)\)\=:E117/ + throw 'tlib: Unknown mode for tlib#input#filter_mode: '. a:match_mode + endtry + endif +endf + + +" function! s:prototype.Match(text) dict "{{{3 +" return self.matcher.Match(self, text) +" endf + + +" :nodoc: +function! s:prototype.MatchBaseIdx(idx) dict "{{{3 + let text = self.GetBaseItem(a:idx) + if !empty(self.filter_format) + let text = self.FormatName(self.fmt_filter, self.filter_format, text) + endif + " TLogVAR text + " return self.Match(text) + return self.matcher.Match(self, text) +endf + + +" :nodoc: +function! s:prototype.BuildTableList() dict "{{{3 + " let time0 = str2float(reltimestr(reltime())) " DBG + " TLogVAR time0 + call self.SetFilter() + " TLogVAR self.filter_neg, self.filter_pos + let self.table = range(1, len(self.base)) + " TLogVAR self.filtered_items + let copy_base = 1 + if !empty(self.filtered_items) + let self.table = filter(self.table, 'index(self.filtered_items, v:val) != -1') + let copy_base = 0 + endif + if !empty(self.filter_pos) || !empty(self.filter_neg) + let self.table = filter(self.table, 'self.MatchBaseIdx(v:val)') + let copy_base = 0 + endif + if copy_base + let self.list = copy(self.base) + else + let self.list = map(copy(self.table), 'self.GetBaseItem(v:val)') + endif +endf + + +" :nodoc: +function! s:prototype.ReduceFilter() dict "{{{3 + " TLogVAR self.filter + let reduced = 0 + while !reduced + if self.filter[0] == [''] && len(self.filter) > 1 + call remove(self.filter, 0) + elseif empty(self.filter[0][0]) && len(self.filter[0]) > 1 + call remove(self.filter[0], 0) + else + call self.matcher.ReduceFrontFilter(self) + endif + if self.IsValidFilter() + let reduced = 1 + endif + endwh +endf + + +" :nodoc: +" filter is either a string or a list of list of strings. +function! s:prototype.SetInitialFilter(filter) dict "{{{3 + " let self.initial_filter = [[''], [a:filter]] + Tlibtrace 'tlib', a:filter + if type(a:filter) == 3 + let self.initial_filter = deepcopy(a:filter) + else + let self.initial_filter = [[a:filter]] + endif +endf + + +" :nodoc: +function! s:prototype.PopFilter() dict "{{{3 + " TLogVAR self.filter + if len(self.filter[0]) > 1 + call remove(self.filter[0], 0) + elseif len(self.filter) > 1 + call remove(self.filter, 0) + else + let self.filter[0] = [''] + endif +endf + + +" :nodoc: +function! s:prototype.FilterIsEmpty() dict "{{{3 + " TLogVAR self.filter + return self.filter == copy(self.initial_filter) +endf + + +" :nodoc: +function! s:prototype.DisplayFilter() dict "{{{3 + let filter1 = copy(self.filter) + call filter(filter1, 'v:val != [""]') + " TLogVAR self.matcher['_class'] + let rv = self.matcher.DisplayFilter(filter1) + let rv = self.CleanFilter(rv) + return rv +endf + + +" :nodoc: +function! s:prototype.SetFrontFilter(pattern) dict "{{{3 + call self.matcher.SetFrontFilter(self, a:pattern) +endf + + +" :nodoc: +function! s:prototype.PushFrontFilter(char) dict "{{{3 + call self.matcher.PushFrontFilter(self, a:char) +endf + + +" :nodoc: +function! s:prototype.CleanFilter(filter) dict "{{{3 + return self.matcher.CleanFilter(a:filter) +endf + + +" :nodoc: +function! s:prototype.UseScratch() dict "{{{3 + " if type(self.scratch) != 0 && get(self, 'buffer_local', 1) + " if self.scratch != fnamemodify(self.scratch, ':p') + " let self.scratch = tlib#file#Join([expand('%:p:h'), self.scratch]) + " " TLogVAR self.scratch + " endif + " " let self.scratch_hidden = 'wipe' + " endif + keepjumps keepalt let rv = tlib#scratch#UseScratch(self) + " if expand('%:t') == self.scratch + let b:tlib_world = self + " endif + return rv +endf + + +" :nodoc: +function! s:prototype.CloseScratch(...) dict "{{{3 + TVarArg ['reset_scratch', 0] + " TVarArg ['reset_scratch', 1] + " TLogVAR reset_scratch + if self.sticky + return 0 + else + let rv = tlib#scratch#CloseScratch(self, reset_scratch) + " TLogVAR rv + if rv + call self.SwitchWindow('win') + endif + return rv + endif +endf + + +" :nodoc: +function! s:prototype.Initialize() dict "{{{3 + let self.initialized = 1 + call self.SetOrigin(1) + call self.Reset(1) + if !empty(self.cache_var) && exists(self.cache_var) + for prop in self.restore_from_cache + exec 'let self[prop] = get('. self.cache_var .', prop, self[prop])' + endfor + exec 'unlet '. self.cache_var + endif +endf + + +" :nodoc: +function! s:prototype.Leave() dict "{{{3 + if !empty(self.cache_var) + exec 'let '. self.cache_var .' = self' + endif + for handler in self.on_leave + call call(handler, [self]) + endfor +endf + + +" :nodoc: +function! s:prototype.UseInputListScratch() dict "{{{3 + let scratch = self.UseScratch() + if !exists('b:tlib_list_init') + call tlib#autocmdgroup#Init() + autocmd TLib VimResized <buffer> call feedkeys("\<c-j>", 't') + " autocmd TLib WinLeave <buffer> let b:tlib_world_event = 'WinLeave' | call feedkeys("\<c-j>", 't') + let b:tlib_list_init = 1 + endif + if !exists('w:tlib_list_init') + " TLogVAR scratch + if has_key(self, 'index_next_syntax') + if type(self.index_next_syntax) == 1 + exec 'syntax match InputlListIndex /^\d\+:\s/ nextgroup='. self.index_next_syntax + elseif type(self.index_next_syntax) == 4 + for [n, nsyn] in items(self.index_next_syntax) + let fn = printf('%0'. world.index_width .'d', n) + exec 'syntax match InputlListIndex /^'. fn .':\s/ nextgroup='. nsyn + endfor + endif + else + syntax match InputlListIndex /^\d\+:\s/ + endif + call tlib#hook#Run('tlib_UseInputListScratch', self) + syntax match InputlListCursor /^\d\+\* .*$/ contains=InputlListIndex + syntax match InputlListSelected /^\d\+# .*$/ contains=InputlListIndex + hi def link InputlListIndex Constant + hi def link InputlListCursor Search + hi def link InputlListSelected IncSearch + setlocal nowrap + " hi def link InputlListIndex Special + " let b:tlibDisplayListMarks = {} + let b:tlibDisplayListMarks = [] + let b:tlibDisplayListWorld = self + let w:tlib_list_init = 1 + endif + return scratch +endf + + +" s:prototype.Reset(?initial=0) +" :nodoc: +function! s:prototype.Reset(...) dict "{{{3 + TVarArg ['initial', 0] + " TLogVAR initial + Tlibtrace 'tlib', initial, self.initial_filter + let self.state = 'display' + let self.offset = 1 + let self.filter = deepcopy(self.initial_filter) + let self.idx = '' + let self.prefidx = 0 + let self.initial_display = 1 + let self.fmt_display = {} + let self.fmt_filter = {} + call self.UseInputListScratch() + call self.ResetSelected() + call self.Retrieve(!initial) + call self.FormatBaseFromData() + return self +endf + + +" :nodoc: +function! s:prototype.ResetSelected() dict "{{{3 + let self.sel_idx = [] +endf + + +" :nodoc: +function! s:prototype.Retrieve(anyway) dict "{{{3 + " TLogVAR a:anyway, self.base + " TLogDBG (a:anyway || empty(self.base)) + if (a:anyway || empty(self.base)) + let ra = self.retrieve_eval + " TLogVAR ra + if !empty(ra) + let back = self.SwitchWindow('win') + let world = self + let self.base = eval(ra) + " TLogVAR self.base + exec back + return 1 + endif + endif + return 0 +endf + + +function! s:FormatHelp(help) "{{{3 + " TLogVAR a:help + let max = [0, 0] + for item in a:help + " TLogVAR item + if type(item) == 3 + let itemlen = map(copy(item), 'strwidth(v:val)') + " TLogVAR itemlen + let max = map(range(2), 'max[v:val] >= itemlen[v:val] ? max[v:val] : itemlen[v:val]') + endif + unlet item + endfor + " TLogVAR max + let cols = float2nr((winwidth(0) - &foldcolumn - 1) / (max[0] + max[1] + 2)) + if cols < 1 + let cols = 1 + endif + let fmt = printf('%%%ds: %%-%ds', max[0], max[1]) + " TLogVAR cols, fmt + let help = [] + let idx = -1 + let maxidx = len(a:help) + while idx < maxidx + let push_item = 0 + let accum = [] + for i in range(cols) + let idx += 1 + if idx >= maxidx + break + endif + let item = a:help[idx] + if type(item) == 3 + call add(accum, item) + else + let push_item = 1 + break + endif + unlet item + endfor + if !empty(accum) + call add(help, s:FormatHelpItem(accum, fmt)) + endif + if push_item + call add(help, a:help[idx]) + endif + endwh + " TLogVAR help + return help +endf + + +function! s:FormatHelpItem(item, fmt) "{{{3 + let args = [join(repeat([a:fmt], len(a:item)), ' ')] + for item in a:item + " TLogVAR item + let args += item + endfor + " TLogVAR args + return call('printf', args) +endf + + +" :nodoc: +function! s:prototype.InitHelp() dict "{{{3 + return [] +endf + + +" :nodoc: +function! s:prototype.PushHelp(...) dict "{{{3 + " TLogVAR a:000 + if a:0 == 1 + if type(a:1) == 3 + let self.temp_lines += a:1 + else + call add(self.temp_lines, a:1) + endif + elseif a:0 == 2 + call add(self.temp_lines, a:000) + else + throw "TLIB: PushHelp: Wrong number of arguments: ". string(a:000) + endif + " TLogVAR helpstring +endf + + +" :nodoc: +function! s:prototype.DisplayHelp() dict "{{{3 + let self.temp_lines = self.InitHelp() + call self.PushHelp('<Esc>', self.key_mode == 'default' ? 'Abort' : 'Reset keymap') + call self.PushHelp('Enter, <cr>', 'Pick the current item') + call self.PushHelp('Mouse', 'L: Pick item, R: Show menu') + call self.PushHelp('<M-Number>', 'Select an item') + call self.PushHelp('<BS>, <C-BS>', 'Reduce filter') + call self.PushHelp('<Tab>', 'Complete word') + call self.PushHelp('<S-Esc>, <F10>', 'Enter command') + + if self.key_mode == 'default' + call self.PushHelp('<C|M-r>', 'Reset the display') + call self.PushHelp('Up/Down', 'Next/previous item') + call self.PushHelp('<C|M-q>', 'Edit top filter string') + call self.PushHelp('Page Up/Down', 'Scroll') + call self.PushHelp('<S-Space>', 'Enter * Wildcard') + if self.allow_suspend + call self.PushHelp('<C|M-z>', 'Suspend/Resume') + call self.PushHelp('<C-o>', 'Switch to origin') + endif + if stridx(self.type, 'm') != -1 + call self.PushHelp('<S-Up/Down>', '(Un)Select items') + call self.PushHelp('#', '(Un)Select the current item') + call self.PushHelp('<C|M-a>', '(Un)Select all items') + call self.PushHelp('<F9>', '(Un)Restrict view to selection') + " \ '<c-\> ... Show only selected', + endif + endif + + " TLogVAR len(self.temp_lines) + call self.matcher.Help(self) + + " TLogVAR self.key_mode + for handler in values(self.key_map[self.key_mode]) + " TLogVAR handler + let key = get(handler, 'key_name', '') + " TLogVAR key + if !empty(key) + let desc = get(handler, 'help', '') + if empty(desc) + let desc = get(handler, 'agent', '') + endif + call self.PushHelp(key, desc) + endif + endfor + + if !has_key(self.key_map[self.key_mode], 'unknown_key') + call self.PushHelp('Letter', 'Filter the list') + endif + + if self.key_mode == 'default' && !empty(self.help_extra) + call self.PushHelp(self.help_extra) + endif + + " TLogVAR len(self.temp_lines) + call self.PushHelp([ + \ '', + \ 'Matches at word boundaries are prioritized.', + \ ]) + let self.temp_lines = s:FormatHelp(self.temp_lines) + call self.PrintLines() +endf + + +function! s:prototype.PrintLines() dict "{{{3 + let self.temp_prompt = ['Press any key to continue.', 'Question'] + call tlib#buffer#DeleteRange('1', '$') + call append(0, self.temp_lines) + call tlib#buffer#DeleteRange('$', '$') + 1 + call self.Resize(len(self.temp_lines), 0) + let self.temp_lines = [] +endf + + +" :nodoc: +function! s:prototype.Resize(hsize, vsize) dict "{{{3 + " TLogVAR self.scratch_vertical, a:hsize, a:vsize + let world_resize = '' + let winpos = '' + let scratch_split = get(self, 'scratch_split', 1) + " TLogVAR scratch_split + if scratch_split > 0 + if self.scratch_vertical + if a:vsize + let world_resize = 'vert resize '. a:vsize + let winpos = tlib#fixes#Winpos() + " let w:winresize = {'v': a:vsize} + setlocal winfixwidth + endif + else + if a:hsize + let world_resize = 'resize '. a:hsize + " let w:winresize = {'h': a:hsize} + setlocal winfixheight + endif + endif + endif + if !empty(world_resize) + " TLogVAR world_resize, winpos + exec world_resize + if !empty(winpos) + exec winpos + endif + " redraw! + endif +endf + + +" :nodoc: +function! s:prototype.GetResize(size) dict "{{{3 + let resize0 = get(self, 'resize', 0) + let resize = empty(resize0) ? 0 : eval(resize0) + " TLogVAR resize0, resize + let resize = resize == 0 ? a:size : min([a:size, resize]) + " let min = self.scratch_vertical ? &cols : &lines + let min1 = (self.scratch_vertical ? self.win_width : self.win_height) * g:tlib_inputlist_pct + let min2 = (self.scratch_vertical ? &columns : &lines) * self.win_pct + let min = max([min1, min2]) + let resize = min([resize, (min / 100)]) + " TLogVAR resize, a:size, min, min1, min2 + return resize +endf + + +" function! s:prototype.DisplayList(?query=self.Query(), ?list=[]) +" :nodoc: +function! s:prototype.DisplayList(...) dict "{{{3 + " TLogVAR self.state + let query = a:0 >= 1 ? a:1 : self.Query() + let list = a:0 >= 2 ? a:2 : [] + " TLogVAR query, len(list) + " TLogDBG 'len(list) = '. len(list) + call self.UseScratch() + " TLogVAR self.scratch + " TAssert IsNotEmpty(self.scratch) + if self.state == 'scroll' + call self.ScrollToOffset() + elseif self.state == 'help' + call self.DisplayHelp() + call self.SetStatusline(query) + elseif self.state == 'printlines' + call self.PrintLines() + call self.SetStatusline(query) + else + " TLogVAR query + " let ll = len(list) + let ll = self.llen + " let x = len(ll) + 1 + let x = self.index_width + 1 + " TLogVAR ll + if self.state =~ '\<display\>' + call self.Resize(self.GetResize(ll), eval(get(self, 'resize_vertical', 0))) + call tlib#normal#WithRegister('gg"tdG', 't') + let lines = copy(list) + let lines = map(lines, 'substitute(v:val, ''[[:cntrl:][:space:]]'', " ", "g")') + let w = winwidth(0) - &fdc + " let w = winwidth(0) - &fdc - 1 + let lines = map(lines, 'printf("%-'. w .'.'. w .'s", v:val)') + " TLogVAR lines + call append(0, lines) + call tlib#normal#WithRegister('G"tddgg', 't') + 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, '*') + call self.SetOffset() + call self.SetStatusline(query) + " TLogVAR self.offset + call self.ScrollToOffset() + let rx0 = self.GetRx0() + " TLogVAR rx0 + if !empty(self.matcher.highlight) + if empty(rx0) + match none + elseif self.IsValidFilter() + if has_key(self, 'Highlighter') + call self.Highlighter(rx0) + else + exec 'match '. self.matcher.highlight .' /\c'. escape(rx0, '/') .'/' + endif + endif + endif + endif + redraw +endf + + +" :nodoc: +function! s:prototype.SetStatusline(query) dict "{{{3 + " TLogVAR a:query + if !empty(self.temp_prompt) + let echo = get(self.temp_prompt, 0, '') + let hl = get(self.temp_prompt, 1, 'Normal') + let self.temp_prompt = [] + else + let hl = 'Normal' + let query = a:query + let options = [self.matcher.name] + if self.sticky + call add(options, '#') + endif + if self.key_mode != 'default' + call add(options, 'map:'. self.key_mode) + endif + if !empty(self.filtered_items) + if g:tlib_inputlist_shortmessage + call add(options, 'R') + else + call add(options, 'restricted') + endif + endif + if !empty(options) + let sopts = printf('[%s]', join(options, ', ')) + " let echo = query . repeat(' ', &columns - len(sopts) - len(query) - 20) . sopts + let echo = query . ' ' . sopts + " let query .= '%%='. sopts .' ' + endif + " TLogVAR &l:statusline, query + " let &l:statusline = query + endif + echo + if hl != 'Normal' + exec 'echohl' hl + echo echo + echohl None + else + echo echo + endif +endf + + +" :nodoc: +function! s:prototype.Query() dict "{{{3 + let flt = self.DisplayFilter() + if g:tlib_inputlist_shortmessage + let query = 'Filter: '. flt + else + let query = self.query .' (filter: '. flt .'; press <F1> for help)' + endif + return query +endf + + +" :nodoc: +function! s:prototype.ScrollToOffset() dict "{{{3 + " TLogVAR self.scratch_vertical, self.llen, winheight(0) + exec 'norm! '. self.offset .'zt' +endf + + +" :nodoc: +function! s:prototype.SetOffset() dict "{{{3 + " TLogVAR self.prefidx, self.offset + " TLogDBG winheight(0) + " TLogDBG self.prefidx > self.offset + winheight(0) - 1 + let listtop = len(self.list) - winheight(0) + 1 + if listtop < 1 + let listtop = 1 + endif + if self.prefidx > listtop + let self.offset = listtop + elseif self.prefidx > self.offset + winheight(0) - 1 + let listoff = self.prefidx - winheight(0) + 1 + let self.offset = min([listtop, listoff]) + " TLogVAR self.prefidx + " TLogDBG len(self.list) + " TLogDBG winheight(0) + " TLogVAR listtop, listoff, self.offset + elseif self.prefidx < self.offset + let self.offset = self.prefidx + endif + " TLogVAR self.offset +endf + + +" :nodoc: +function! s:prototype.ClearAllMarks() dict "{{{3 + let x = self.index_width + 1 + call map(range(1, line('$')), 'self.DisplayListMark(x, v:val, ":")') +endf + + +" :nodoc: +function! s:prototype.MarkCurrent(y) dict "{{{3 + let x = self.index_width + 1 + call self.DisplayListMark(x, a:y, '*') +endf + + +" :nodoc: +function! s:prototype.DisplayListMark(x, y, mark) dict "{{{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 + + +" :nodoc: +function! s:prototype.SwitchWindow(where) dict "{{{3 + " TLogDBG string(tlib#win#List()) + if self.tabpagenr != tabpagenr() + call tlib#tab#Set(self.tabpagenr) + endif + let wnr = get(self, a:where.'_wnr') + " TLogVAR self, wnr + return tlib#win#Set(wnr) +endf + + +" :nodoc: +function! s:prototype.FollowCursor() dict "{{{3 + if !empty(self.follow_cursor) + let back = self.SwitchWindow('win') + " TLogVAR back + " TLogDBG winnr() + try + call call(self.follow_cursor, [self, [self.CurrentItem()]]) + finally + exec back + endtry + endif +endf + + +" :nodoc: +function! s:prototype.SetOrigin(...) dict "{{{3 + TVarArg ['winview', 0] + " TLogVAR self.win_wnr, self.bufnr + " TLogDBG bufname('%') + " TLogDBG winnr() + " TLogDBG winnr('$') + let self.win_wnr = winnr() + let self.win_height = winheight(self.win_wnr) + let self.win_width = winwidth(self.win_wnr) + " TLogVAR self.win_wnr, self.win_height, self.win_width + let self.bufnr = bufnr('%') + let self.tabpagenr = tabpagenr() + let self.cursor = getpos('.') + if winview + let self.winview = tlib#win#GetLayout() + endif + " TLogVAR self.win_wnr, self.bufnr, self.winview + return self +endf + + +" :nodoc: +function! s:prototype.RestoreOrigin(...) dict "{{{3 + TVarArg ['winview', 0] + if winview + " TLogVAR winview + call tlib#win#SetLayout(self.winview) + endif + " TLogVAR self.win_wnr, self.bufnr, self.cursor, &splitbelow + " TLogDBG "RestoreOrigin0 ". string(tlib#win#List()) + " If &splitbelow or &splitright is false, we cannot rely on + " self.win_wnr to be our source buffer since, e.g, opening a buffer + " in a split window changes the whole layout. + " Possible solutions: + " - Restrict buffer switching to cases when the number of windows + " hasn't changed. + " - Guess the right window, which we try to do here. + if &splitbelow == 0 || &splitright == 0 + let wn = bufwinnr(self.bufnr) + " TLogVAR wn + if wn == -1 + let wn = 1 + end + else + let wn = self.win_wnr + endif + if wn != winnr() + exec wn .'wincmd w' + endif + exec 'buffer! '. self.bufnr + call setpos('.', self.cursor) + " TLogDBG "RestoreOrigin1 ". string(tlib#win#List()) +endf + + +function! s:prototype.Suspend() dict "{{{3 + call tlib#agent#Suspend(self, self.rv) +endf + |