return symbolMap[symkind]
enddef
+# process SymbolInformation[]
+def s:processSymbolInfoTable(symbolInfoTable: list<dict<any>>,
+ symbolTypeTable: dict<list<dict<any>>>,
+ symbolLineTable: list<dict<any>>)
+ var fname: string
+ var symbolType: string
+ var name: string
+ var r: dict<dict<number>>
+ var symInfo: dict<any>
+
+ for symbol in symbolInfoTable
+ fname = LspUriToFile(symbol.location.uri)
+ symbolType = LspSymbolKindToName(symbol.kind)
+ name = symbol.name
+ if symbol->has_key('containerName')
+ if symbol.containerName != ''
+ name ..= ' [' .. symbol.containerName .. ']'
+ endif
+ endif
+ r = symbol.location.range
+
+ if !symbolTypeTable->has_key(symbolType)
+ symbolTypeTable[symbolType] = []
+ endif
+ symInfo = {name: name, range: r}
+ symbolTypeTable[symbolType]->add(symInfo)
+ symbolLineTable->add(symInfo)
+ endfor
+enddef
+
+# process DocumentSymbol[]
+def s:processDocSymbolTable(docSymbolTable: list<dict<any>>,
+ symbolTypeTable: dict<list<dict<any>>>,
+ symbolLineTable: list<dict<any>>)
+ var symbolType: string
+ var name: string
+ var r: dict<dict<number>>
+ var symInfo: dict<any>
+ var symbolDetail: string
+ var childSymbols: dict<list<dict<any>>>
+
+ for symbol in docSymbolTable
+ name = symbol.name
+ symbolType = LspSymbolKindToName(symbol.kind)
+ r = symbol.range
+ if symbol->has_key('detail')
+ symbolDetail = symbol.detail
+ endif
+ if !symbolTypeTable->has_key(symbolType)
+ symbolTypeTable[symbolType] = []
+ endif
+ childSymbols = {}
+ if symbol->has_key('children')
+ s:processDocSymbolTable(symbol.children, childSymbols, symbolLineTable)
+ endif
+ symInfo = {name: name, range: r, detail: symbolDetail,
+ children: childSymbols}
+ symbolTypeTable[symbolType]->add(symInfo)
+ symbolLineTable->add(symInfo)
+ endfor
+enddef
+
# process the 'textDocument/documentSymbol' reply from the LSP server
# Open a symbols window and display the symbols as a tree
def s:processDocSymbolReply(lspserver: dict<any>, req: dict<any>, reply: dict<any>): void
var fname: string
var symbolTypeTable: dict<list<dict<any>>>
var symbolLineTable: list<dict<any>> = []
- var name: string
- var symbolType: string
- var r: dict<dict<number>>
- var symbolDetail: string
- var symInfo: dict<any>
if req.params.textDocument.uri != ''
fname = LspUriToFile(req.params.textDocument.uri)
endif
- for symbol in reply.result
- symbolDetail = ''
- if symbol->has_key('location')
- # interface SymbolInformation
- fname = LspUriToFile(symbol.location.uri)
- symbolType = LspSymbolKindToName(symbol.kind)
- name = symbol.name
- if symbol->has_key('containerName')
- if symbol.containerName != ''
- name ..= ' [' .. symbol.containerName .. ']'
- endif
- endif
- r = symbol.location.range
- else
- # interface DocumentSymbol
- name = symbol.name
- symbolType = LspSymbolKindToName(symbol.kind)
- r = symbol.range
- if symbol->has_key('detail')
- symbolDetail = symbol.detail
- endif
- endif
- if !symbolTypeTable->has_key(symbolType)
- symbolTypeTable[symbolType] = []
- endif
- symInfo = {name: name, range: r, detail: symbolDetail}
- symbolTypeTable[symbolType]->add(symInfo)
- symbolLineTable->add(symInfo)
- endfor
+ if reply.result[0]->has_key('location')
+ # SymbolInformation[]
+ s:processSymbolInfoTable(reply.result, symbolTypeTable, symbolLineTable)
+ else
+ # DocumentSymbol[]
+ s:processDocSymbolTable(reply.result, symbolTypeTable, symbolLineTable)
+ endif
+
# sort the symbols by line number
symbolLineTable->sort({a, b -> a.range.start.line - b.range.start.line})
lsp#updateOutlineWindow(fname, symbolTypeTable, symbolLineTable)
# Highlight the selected symbol
prop_remove({type: 'LspOutlineHighlight'})
- prop_add(line('.'), 3, {type: 'LspOutlineHighlight',
+ var col: number = match(getline('.'), '\S') + 1
+ prop_add(line('.'), col, {type: 'LspOutlineHighlight',
length: w:lspSymbols.lnumTable[lnum].name->len()})
# disable the outline window refresh
var skipOutlineRefresh: bool = false
+def s:addSymbolText(symbolTypeTable: dict<list<dict<any>>>,
+ pfx: string,
+ text: list<string>,
+ lnumMap: list<dict<any>>,
+ children: bool)
+ var prefix: string = pfx .. ' '
+ for [symType, symbols] in items(symbolTypeTable)
+ if !children
+ # Add an empty line for the top level symbol types. For types in the
+ # children symbols, don't add the empty line.
+ text->extend([''])
+ lnumMap->extend([{}])
+ endif
+ if children
+ text->extend([prefix .. symType])
+ prefix ..= ' '
+ else
+ text->extend([symType])
+ endif
+ lnumMap->extend([{}])
+ for s in symbols
+ text->add(prefix .. s.name)
+ # remember the line number for the symbol
+ lnumMap->add({name: s.name, lnum: s.range.start.line + 1,
+ col: s.range.start.character + 1})
+ s.outlineLine = lnumMap->len()
+ if !s.children->empty()
+ s:addSymbolText(s.children, prefix, text, lnumMap, true)
+ endif
+ endfor
+ endfor
+enddef
+
# update the symbols displayed in the outline window
def lsp#updateOutlineWindow(fname: string,
symbolTypeTable: dict<list<dict<any>>>,
# First two lines in the buffer display comment information
var lnumMap: list<dict<any>> = [{}, {}]
var text: list<string> = []
- for [symType, syms] in items(symbolTypeTable)
- text->extend(['', symType])
- lnumMap->extend([{}, {}])
- for s in syms
- text->add(' ' .. s.name)
- # remember the line number for the symbol
- lnumMap->add({name: s.name, lnum: s.range.start.line + 1,
- col: s.range.start.character + 1})
- s.outlineLine = lnumMap->len()
- endfor
- endfor
+ s:addSymbolText(symbolTypeTable, '', text, lnumMap, false)
append('$', text)
w:lspSymbols = {filename: fname, lnumTable: lnumMap,
symbolsByLine: symbolLineTable}
if !saveCursor->empty()
setpos('.', saveCursor)
endif
+
win_gotoid(prevWinID)
# Highlight the current symbol
endif
# Highlight the selected symbol
- prop_add(symbolTable[mid].outlineLine, 3,
+ var col: number =
+ match(getbufline(bnr, symbolTable[mid].outlineLine)[0], '\S') + 1
+ prop_add(symbolTable[mid].outlineLine, col,
{bufnr: bnr, type: 'LspOutlineHighlight',
length: symbolTable[mid].name->len()})
:setlocal bufhidden=delete
:setlocal noswapfile nobuflisted
:setlocal nonumber norelativenumber fdc=0 nowrap winfixheight winfixwidth
+ :setlocal shiftwidth=2
+ :setlocal foldenable
+ :setlocal foldcolumn=4
+ :setlocal foldlevel=4
+ :setlocal foldmethod=indent
setline(1, ['# File Outline'])
:nnoremap <silent> <buffer> q :quit<CR>
:nnoremap <silent> <buffer> <CR> :call <SID>outlineJumpToSymbol()<CR>