Extract prototypes to separate autoload files

This commit is contained in:
Jan Larres
2017-08-13 18:55:28 +12:00
parent d880bcc333
commit 2abcbf33f0
9 changed files with 775 additions and 731 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,214 @@
let s:visibility_symbols = {
\ 'public' : '+',
\ 'protected' : '#',
\ 'private' : '-'
\ }
let s:BaseTag = {}
let g:tagbar#prototypes#basetag#BaseTag = s:BaseTag
function! tagbar#prototypes#basetag#new(name) abort
let newobj = copy(s:BaseTag)
call newobj._init(a:name)
return newobj
endfunction
" s:BaseTag._init() {{{1
function! s:BaseTag._init(name) abort dict
let self.name = a:name
let self.fields = {}
let self.fields.line = 0
let self.fields.column = 0
let self.prototype = ''
let self.path = ''
let self.fullpath = a:name
let self.depth = 0
let self.parent = {}
let self.tline = -1
let self.fileinfo = {}
let self.typeinfo = {}
let self._childlist = []
let self._childdict = {}
endfunction
" s:BaseTag.isNormalTag() {{{1
function! s:BaseTag.isNormalTag() abort dict
return 0
endfunction
" s:BaseTag.isPseudoTag() {{{1
function! s:BaseTag.isPseudoTag() abort dict
return 0
endfunction
" s:BaseTag.isKindheader() {{{1
function! s:BaseTag.isKindheader() abort dict
return 0
endfunction
" s:BaseTag.getPrototype() {{{1
function! s:BaseTag.getPrototype(short) abort dict
return self.prototype
endfunction
" s:BaseTag._getPrefix() {{{1
function! s:BaseTag._getPrefix() abort dict
let fileinfo = self.fileinfo
if !empty(self._childlist)
if fileinfo.tagfolds[self.fields.kind][self.fullpath]
let prefix = g:tagbar#icon_closed
else
let prefix = g:tagbar#icon_open
endif
else
let prefix = ' '
endif
" Visibility is called 'access' in the ctags output
if g:tagbar_show_visibility
if has_key(self.fields, 'access')
let prefix .= get(s:visibility_symbols, self.fields.access, ' ')
elseif has_key(self.fields, 'file')
let prefix .= s:visibility_symbols.private
else
let prefix .= ' '
endif
endif
return prefix
endfunction
" s:BaseTag.initFoldState() {{{1
function! s:BaseTag.initFoldState(known_files) abort dict
let fileinfo = self.fileinfo
if a:known_files.has(fileinfo.fpath) &&
\ has_key(fileinfo, '_tagfolds_old') &&
\ has_key(fileinfo._tagfolds_old[self.fields.kind], self.fullpath)
" The file has been updated and the tag was there before, so copy its
" old fold state
let fileinfo.tagfolds[self.fields.kind][self.fullpath] =
\ fileinfo._tagfolds_old[self.fields.kind][self.fullpath]
elseif self.depth >= fileinfo.foldlevel
let fileinfo.tagfolds[self.fields.kind][self.fullpath] = 1
else
let fileinfo.tagfolds[self.fields.kind][self.fullpath] =
\ fileinfo.kindfolds[self.fields.kind]
endif
endfunction
" s:BaseTag.getClosedParentTline() {{{1
function! s:BaseTag.getClosedParentTline() abort dict
let tagline = self.tline
" Find the first closed parent, starting from the top of the hierarchy.
let parents = []
let curparent = self.parent
while !empty(curparent)
call add(parents, curparent)
let curparent = curparent.parent
endwhile
for parent in reverse(parents)
if parent.isFolded()
let tagline = parent.tline
break
endif
endfor
return tagline
endfunction
" s:BaseTag.isFoldable() {{{1
function! s:BaseTag.isFoldable() abort dict
return !empty(self._childlist)
endfunction
" s:BaseTag.isFolded() {{{1
function! s:BaseTag.isFolded() abort dict
return self.fileinfo.tagfolds[self.fields.kind][self.fullpath]
endfunction
" s:BaseTag.openFold() {{{1
function! s:BaseTag.openFold() abort dict
if self.isFoldable()
let self.fileinfo.tagfolds[self.fields.kind][self.fullpath] = 0
endif
endfunction
" s:BaseTag.closeFold() {{{1
function! s:BaseTag.closeFold() abort dict
let newline = line('.')
if !empty(self.parent) && self.parent.isKindheader()
" Tag is child of generic 'kind'
call self.parent.closeFold()
let newline = self.parent.tline
elseif self.isFoldable() && !self.isFolded()
" Tag is parent of a scope and is not folded
let self.fileinfo.tagfolds[self.fields.kind][self.fullpath] = 1
let newline = self.tline
elseif !empty(self.parent)
" Tag is normal child, so close parent
let parent = self.parent
let self.fileinfo.tagfolds[parent.fields.kind][parent.fullpath] = 1
let newline = parent.tline
endif
return newline
endfunction
" s:BaseTag.setFolded() {{{1
function! s:BaseTag.setFolded(folded) abort dict
let self.fileinfo.tagfolds[self.fields.kind][self.fullpath] = a:folded
endfunction
" s:BaseTag.openParents() {{{1
function! s:BaseTag.openParents() abort dict
let parent = self.parent
while !empty(parent)
call parent.openFold()
let parent = parent.parent
endwhile
endfunction
" s:BaseTag.addChild() {{{1
function! s:BaseTag.addChild(tag) abort dict
call add(self._childlist, a:tag)
if has_key(self._childdict, a:tag.name)
call add(self._childdict[a:tag.name], a:tag)
else
let self._childdict[a:tag.name] = [a:tag]
endif
endfunction
" s:BaseTag.getChildren() {{{1
function! s:BaseTag.getChildren() dict abort
return self._childlist
endfunction
" s:BaseTag.getChildrenByName() {{{1
function! s:BaseTag.getChildrenByName(tagname) dict abort
return get(self._childdict, a:tagname, [])
endfunction
" s:BaseTag.removeChild() {{{1
function! s:BaseTag.removeChild(tag) dict abort
let idx = index(self._childlist, a:tag)
if idx >= 0
call remove(self._childlist, idx)
endif
let namelist = get(self._childdict, a:tag.name, [])
let idx = index(namelist, a:tag)
if idx >= 0
call remove(namelist, idx)
endif
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,130 @@
let s:FileInfo = {}
function! tagbar#prototypes#fileinfo#new(fname, ftype, typeinfo) abort
let newobj = copy(s:FileInfo)
" The complete file path
let newobj.fpath = a:fname
let newobj.bufnr = bufnr(a:fname)
" File modification time
let newobj.mtime = getftime(a:fname)
" The vim file type
let newobj.ftype = a:ftype
" List of the tags that are present in the file, sorted according to the
" value of 'g:tagbar_sort'
let newobj._taglist = []
let newobj._tagdict = {}
" Dictionary of the tags, indexed by line number in the file
let newobj.fline = {}
" Dictionary of the tags, indexed by line number in the tagbar
let newobj.tline = {}
" Dictionary of the folding state of 'kind's, indexed by short name
let newobj.kindfolds = {}
let newobj.typeinfo = a:typeinfo
" copy the default fold state from the type info
for kind in a:typeinfo.kinds
let newobj.kindfolds[kind.short] =
\ g:tagbar_foldlevel == 0 ? 1 : kind.fold
endfor
" Dictionary of dictionaries of the folding state of individual tags,
" indexed by kind and full path
let newobj.tagfolds = {}
for kind in a:typeinfo.kinds
let newobj.tagfolds[kind.short] = {}
endfor
" The current foldlevel of the file
let newobj.foldlevel = g:tagbar_foldlevel
return newobj
endfunction
" s:FileInfo.addTag() {{{1
function! s:FileInfo.addTag(tag) abort dict
call add(self._taglist, a:tag)
if has_key(self._tagdict, a:tag.name)
call add(self._tagdict[a:tag.name], a:tag)
else
let self._tagdict[a:tag.name] = [a:tag]
endif
endfunction
" s:FileInfo.getTags() {{{1
function! s:FileInfo.getTags() dict abort
return self._taglist
endfunction
" s:FileInfo.getTagsByName() {{{1
function! s:FileInfo.getTagsByName(tagname) dict abort
return get(self._tagdict, a:tagname, [])
endfunction
" s:FileInfo.removeTag() {{{1
function! s:FileInfo.removeTag(tag) dict abort
let idx = index(self._taglist, a:tag)
if idx >= 0
call remove(self._taglist, idx)
endif
let namelist = get(self._tagdict, a:tag.name, [])
let idx = index(namelist, a:tag)
if idx >= 0
call remove(namelist, idx)
endif
endfunction
" s:FileInfo.reset() {{{1
" Reset stuff that gets regenerated while processing a file and save the old
" tag folds
function! s:FileInfo.reset() abort dict
let self.mtime = getftime(self.fpath)
let self._taglist = []
let self._tagdict = {}
let self.fline = {}
let self.tline = {}
let self._tagfolds_old = self.tagfolds
let self.tagfolds = {}
for kind in self.typeinfo.kinds
let self.tagfolds[kind.short] = {}
endfor
endfunction
" s:FileInfo.clearOldFolds() {{{1
function! s:FileInfo.clearOldFolds() abort dict
if exists('self._tagfolds_old')
unlet self._tagfolds_old
endif
endfunction
" s:FileInfo.sortTags() {{{1
function! s:FileInfo.sortTags(compare_typeinfo) abort dict
if get(a:compare_typeinfo, 'sort', g:tagbar_sort)
call tagbar#sorting#sort(self._taglist, 'kind', a:compare_typeinfo)
else
call tagbar#sorting#sort(self._taglist, 'line', a:compare_typeinfo)
endif
endfunction
" s:FileInfo.openKindFold() {{{1
function! s:FileInfo.openKindFold(kind) abort dict
let self.kindfolds[a:kind.short] = 0
endfunction
" s:FileInfo.closeKindFold() {{{1
function! s:FileInfo.closeKindFold(kind) abort dict
let self.kindfolds[a:kind.short] = 1
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,49 @@
let s:KindheaderTag = copy(g:tagbar#prototypes#basetag#BaseTag)
function! tagbar#prototypes#kindheadertag#new(name) abort
let newobj = copy(s:KindheaderTag)
call newobj._init(a:name)
return newobj
endfunction
" s:KindheaderTag.isKindheader() {{{1
function! s:KindheaderTag.isKindheader() abort dict
return 1
endfunction
" s:KindheaderTag.getPrototype() {{{1
function! s:KindheaderTag.getPrototype(short) abort dict
return self.name . ': ' .
\ self.numtags . ' ' . (self.numtags > 1 ? 'tags' : 'tag')
endfunction
" s:KindheaderTag.isFoldable() {{{1
function! s:KindheaderTag.isFoldable() abort dict
return 1
endfunction
" s:KindheaderTag.isFolded() {{{1
function! s:KindheaderTag.isFolded() abort dict
return self.fileinfo.kindfolds[self.short]
endfunction
" s:KindheaderTag.openFold() {{{1
function! s:KindheaderTag.openFold() abort dict
let self.fileinfo.kindfolds[self.short] = 0
endfunction
" s:KindheaderTag.closeFold() {{{1
function! s:KindheaderTag.closeFold() abort dict
let self.fileinfo.kindfolds[self.short] = 1
return line('.')
endfunction
" s:KindheaderTag.toggleFold() {{{1
function! s:KindheaderTag.toggleFold(fileinfo) abort dict
let a:fileinfo.kindfolds[self.short] = !a:fileinfo.kindfolds[self.short]
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,110 @@
let s:NormalTag = copy(g:tagbar#prototypes#basetag#BaseTag)
function! tagbar#prototypes#normaltag#new(name) abort
let newobj = copy(s:NormalTag)
call newobj._init(a:name)
return newobj
endfunction
" s:NormalTag.isNormalTag() {{{1
function! s:NormalTag.isNormalTag() abort dict
return 1
endfunction
" s:NormalTag.strfmt() {{{1
function! s:NormalTag.strfmt() abort dict
let typeinfo = self.typeinfo
let suffix = get(self.fields, 'signature', '')
if has_key(self.fields, 'type')
let suffix .= ' : ' . self.fields.type
elseif has_key(get(typeinfo, 'kind2scope', {}), self.fields.kind)
let suffix .= ' : ' . typeinfo.kind2scope[self.fields.kind]
endif
return self._getPrefix() . self.name . suffix
endfunction
" s:NormalTag.str() {{{1
function! s:NormalTag.str(longsig, full) abort dict
if a:full && self.path != ''
let str = self.path . self.typeinfo.sro . self.name
else
let str = self.name
endif
if has_key(self.fields, 'signature')
if a:longsig
let str .= self.fields.signature
else
let str .= '()'
endif
endif
return str
endfunction
" s:NormalTag.getPrototype() {{{1
function! s:NormalTag.getPrototype(short) abort dict
if self.prototype != ''
let prototype = self.prototype
else
let bufnr = self.fileinfo.bufnr
if self.fields.line == 0 || !bufloaded(bufnr)
" No linenumber available or buffer not loaded (probably due to
" 'nohidden'), try the pattern instead
return substitute(self.pattern, '^\\M\\^\\C\s*\(.*\)\\$$', '\1', '')
endif
let line = getbufline(bufnr, self.fields.line)[0]
let list = split(line, '\zs')
let start = index(list, '(')
if start == -1
return substitute(line, '^\s\+', '', '')
endif
let opening = count(list, '(', 0, start)
let closing = count(list, ')', 0, start)
if closing >= opening
return substitute(line, '^\s\+', '', '')
endif
let balance = opening - closing
let prototype = line
let curlinenr = self.fields.line + 1
while balance > 0
let curline = getbufline(bufnr, curlinenr)[0]
let curlist = split(curline, '\zs')
let balance += count(curlist, '(')
let balance -= count(curlist, ')')
let prototype .= "\n" . curline
let curlinenr += 1
endwhile
let self.prototype = prototype
endif
if a:short
" join all lines and remove superfluous spaces
let prototype = substitute(prototype, '^\s\+', '', '')
let prototype = substitute(prototype, '\_s\+', ' ', 'g')
let prototype = substitute(prototype, '(\s\+', '(', 'g')
let prototype = substitute(prototype, '\s\+)', ')', 'g')
" Avoid hit-enter prompts
let maxlen = &columns - 12
if len(prototype) > maxlen
let prototype = prototype[:maxlen - 1 - 3]
let prototype .= '...'
endif
endif
return prototype
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,29 @@
let s:PseudoTag = copy(g:tagbar#prototypes#basetag#BaseTag)
function! tagbar#prototypes#pseudotag#new(name) abort
let newobj = copy(s:PseudoTag)
call newobj._init(a:name)
return newobj
endfunction
" s:PseudoTag.isPseudoTag() {{{1
function! s:PseudoTag.isPseudoTag() abort dict
return 1
endfunction
" s:PseudoTag.strfmt() {{{1
function! s:PseudoTag.strfmt() abort dict
let typeinfo = self.typeinfo
let suffix = get(self.fields, 'signature', '')
if has_key(typeinfo.kind2scope, self.fields.kind)
let suffix .= ' : ' . typeinfo.kind2scope[self.fields.kind]
endif
return self._getPrefix() . self.name . '*' . suffix
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,33 @@
let s:TypeInfo = {}
function! tagbar#prototypes#typeinfo#new(...) abort
let newobj = copy(s:TypeInfo)
let newobj.kinddict = {}
if a:0 > 0
call extend(newobj, a:1)
endif
return newobj
endfunction
" s:TypeInfo.getKind() {{{1
function! s:TypeInfo.getKind(kind) abort dict
let idx = self.kinddict[a:kind]
return self.kinds[idx]
endfunction
" s:TypeInfo.createKinddict() {{{1
" Create a dictionary of the kind order for fast access in sorting functions
function! s:TypeInfo.createKinddict() abort dict
let i = 0
for kind in self.kinds
let self.kinddict[kind.short] = i
let i += 1
endfor
let self.kinddict['?'] = i
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,57 @@
" Script-local variable needed since compare functions can't
" take additional arguments
let s:compare_typeinfo = {}
function! tagbar#sorting#sort(tags, compareby, compare_typeinfo) abort
let s:compare_typeinfo = a:compare_typeinfo
let comparemethod =
\ a:compareby == 'kind' ? 's:compare_by_kind' : 's:compare_by_line'
call sort(a:tags, comparemethod)
for tag in a:tags
if !empty(tag.getChildren())
call tagbar#sorting#sort(tag.getChildren(), a:compareby,
\ a:compare_typeinfo)
endif
endfor
endfunction
function! s:compare_by_kind(tag1, tag2) abort
let typeinfo = s:compare_typeinfo
if typeinfo.kinddict[a:tag1.fields.kind] <#
\ typeinfo.kinddict[a:tag2.fields.kind]
return -1
elseif typeinfo.kinddict[a:tag1.fields.kind] >#
\ typeinfo.kinddict[a:tag2.fields.kind]
return 1
else
" Ignore '~' prefix for C++ destructors to sort them directly under
" the constructors
if a:tag1.name[0] ==# '~'
let name1 = a:tag1.name[1:]
else
let name1 = a:tag1.name
endif
if a:tag2.name[0] ==# '~'
let name2 = a:tag2.name[1:]
else
let name2 = a:tag2.name
endif
let ci = g:tagbar_case_insensitive
if (((!ci) && (name1 <=# name2)) || (ci && (name1 <=? name2)))
return -1
else
return 1
endif
endif
endfunction
function! s:compare_by_line(tag1, tag2) abort
return a:tag1.fields.line - a:tag2.fields.line
endfunction
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

51
autoload/tagbar/state.vim Normal file
View File

@ -0,0 +1,51 @@
function! tagbar#state#get_current_file(force_current) abort
return s:get().getCurrent(a:force_current)
endfunction
function! tagbar#state#set_current_file(fileinfo) abort
call s:get().setCurrentFile(a:fileinfo)
endfunction
function! tagbar#state#set_paused() abort
call s:get().setPaused()
endfunction
function! s:get() abort
if !exists('t:tagbar_state')
let t:tagbar_state = s:State.New()
endif
return t:tagbar_state
endfunction
let s:State = {
\ '_current' : {},
\ '_paused' : {},
\ }
" s:state.New() {{{1
function! s:State.New() abort dict
return deepcopy(self)
endfunction
" s:state.getCurrent() {{{1
function! s:State.getCurrent(force_current) abort dict
if !tagbar#is_paused() || a:force_current
return self._current
else
return self._paused
endif
endfunction
" s:state.setCurrentFile() {{{1
function! s:State.setCurrentFile(fileinfo) abort dict
let self._current = a:fileinfo
endfunction
" s:state.setPaused() {{{1
function! s:State.setPaused() abort dict
let self._paused = self._current
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1