Improved TOC (fixes #31)
* Syntax works for unnumbered sections * No numbers on frontmatter
This commit is contained in:
parent
1ba745a177
commit
e171ba5a3b
@ -25,6 +25,9 @@ function! latex#toc#open() " {{{1
|
||||
let calling_file = expand('%:p')
|
||||
let calling_line = line('.')
|
||||
|
||||
" Parse tex files for max level
|
||||
let s:max_level = s:set_max_level(g:latex#data[b:latex.id].tex)
|
||||
|
||||
" Parse tex files for TOC data
|
||||
let toc = s:parse_file(g:latex#data[b:latex.id].tex, 1)
|
||||
|
||||
@ -43,7 +46,11 @@ function! latex#toc#open() " {{{1
|
||||
let index = 0
|
||||
let closest_index = 0
|
||||
for entry in toc
|
||||
call append('$', entry.number . "\t" . entry.title)
|
||||
call append('$',
|
||||
\ printf('%-10s%-140s%s',
|
||||
\ entry.number,
|
||||
\ entry.title,
|
||||
\ s:max_level - entry.level))
|
||||
|
||||
let index += 1
|
||||
if entry.file == calling_file && entry.line <= calling_line
|
||||
@ -82,6 +89,9 @@ function! latex#toc#toggle() " {{{1
|
||||
endfunction
|
||||
" }}}1
|
||||
|
||||
" {{{1 TOC number variables
|
||||
let s:max_level = 0
|
||||
|
||||
" Define dictionary to keep track of TOC numbers
|
||||
let s:number = {
|
||||
\ 'part' : 0,
|
||||
@ -89,6 +99,8 @@ let s:number = {
|
||||
\ 'section' : 0,
|
||||
\ 'subsection' : 0,
|
||||
\ 'subsubsection' : 0,
|
||||
\ 'subsubsubsection' : 0,
|
||||
\ 'current_level' : 0,
|
||||
\ 'preamble' : 0,
|
||||
\ 'frontmatter' : 0,
|
||||
\ 'mainmatter' : 0,
|
||||
@ -96,11 +108,23 @@ let s:number = {
|
||||
\ 'backmatter' : 0,
|
||||
\ }
|
||||
|
||||
" Map for section hierarchy
|
||||
let s:sec_to_value = {
|
||||
\ '_' : 0,
|
||||
\ 'subsubsubsection' : 1,
|
||||
\ 'subsubsection' : 2,
|
||||
\ 'subsection' : 3,
|
||||
\ 'section' : 4,
|
||||
\ 'chapter' : 5,
|
||||
\ 'part' : 6,
|
||||
\ }
|
||||
|
||||
" Define regular expressions to match document parts
|
||||
let s:re_input = '\v^\s*\\%(input|include)\s*\{'
|
||||
let s:re_input_file = s:re_input . '\zs[^\}]+\ze}'
|
||||
let s:re_sec = '\v^\s*\\%(part|chapter|%(sub)*section)\*?\s*\{'
|
||||
let s:re_sec_level = '\v^\s*\\\zs%(part|chapter|%(sub)*section)\*?'
|
||||
let s:re_sec_starred = '\v^\s*\\%(part|chapter|%(sub)*section)\*'
|
||||
let s:re_sec_level = '\v^\s*\\\zs%(part|chapter|%(sub)*section)'
|
||||
let s:re_sec_title = s:re_sec . '\zs.{-}\ze\}?$'
|
||||
let s:re_structure = '\v^\s*\\((front|main|back)matter|appendix)>'
|
||||
let s:re_structure_match = '\v((front|main|back)matter|appendix)'
|
||||
@ -122,6 +146,8 @@ let s:re_other = {
|
||||
\ },
|
||||
\ }
|
||||
|
||||
" }}}1
|
||||
|
||||
function! s:parse_file(file, ...) " {{{1
|
||||
" Parses tex file for TOC entries
|
||||
"
|
||||
@ -132,10 +158,10 @@ function! s:parse_file(file, ...) " {{{1
|
||||
" number : "3.1.2",
|
||||
" file : /path/to/file.tex,
|
||||
" line : 142,
|
||||
" level : 2,
|
||||
" }
|
||||
|
||||
" Test if file is readable
|
||||
if ! filereadable(a:file)
|
||||
if !filereadable(a:file)
|
||||
echoerr "Error in latex#toc s:parse_file:"
|
||||
echoerr "File not readable: " . a:file
|
||||
return []
|
||||
@ -166,6 +192,7 @@ function! s:parse_file(file, ...) " {{{1
|
||||
\ 'number' : '',
|
||||
\ 'file' : a:file,
|
||||
\ 'line' : lnum,
|
||||
\ 'level' : s:max_level,
|
||||
\ })
|
||||
continue
|
||||
endif
|
||||
@ -197,6 +224,7 @@ function! s:parse_file(file, ...) " {{{1
|
||||
\ 'number' : '',
|
||||
\ 'file' : a:file,
|
||||
\ 'line' : lnum,
|
||||
\ 'level' : s:max_level,
|
||||
\ })
|
||||
continue
|
||||
endif
|
||||
@ -216,26 +244,38 @@ endfunction
|
||||
|
||||
function! s:parse_line_sec(file, lnum, line) " {{{1
|
||||
let title = matchstr(a:line, s:re_sec_title)
|
||||
let number = s:number_increment(matchstr(a:line, s:re_sec_level))
|
||||
let level = matchstr(a:line, s:re_sec_level)
|
||||
let starred = a:line =~# s:re_sec_starred ? 1 : 0
|
||||
let number = s:number_increment(level, starred)
|
||||
|
||||
return {
|
||||
\ 'title' : title,
|
||||
\ 'number' : number,
|
||||
\ 'file' : a:file,
|
||||
\ 'line' : a:lnum,
|
||||
\ 'level' : s:number.current_level,
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
function! s:number_reset(part) " {{{1
|
||||
for key in keys(s:number)
|
||||
let s:number[key] = 0
|
||||
endfor
|
||||
let s:number[a:part] = 1
|
||||
|
||||
" Initialize for preamble
|
||||
if a:part == 'preamble'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:number_increment(level) " {{{1
|
||||
function! s:number_increment(level, starred) " {{{1
|
||||
" Store current level
|
||||
let s:number.current_level = s:sec_to_value[a:level]
|
||||
|
||||
" Check if level should be incremented
|
||||
if a:level !~# '\v%(part|chapter|(sub)*section)$'
|
||||
if a:starred
|
||||
return ''
|
||||
endif
|
||||
|
||||
@ -246,20 +286,27 @@ function! s:number_increment(level) " {{{1
|
||||
let s:number.section = 0
|
||||
let s:number.subsection = 0
|
||||
let s:number.subsubsection = 0
|
||||
let s:number.subsubsubsection = 0
|
||||
elseif a:level == 'chapter'
|
||||
let s:number.chapter += 1
|
||||
let s:number.section = 0
|
||||
let s:number.subsection = 0
|
||||
let s:number.subsubsection = 0
|
||||
let s:number.subsubsubsection = 0
|
||||
elseif a:level == 'section'
|
||||
let s:number.section += 1
|
||||
let s:number.subsection = 0
|
||||
let s:number.subsubsection = 0
|
||||
let s:number.subsubsubsection = 0
|
||||
elseif a:level == 'subsection'
|
||||
let s:number.subsection += 1
|
||||
let s:number.subsubsection = 0
|
||||
let s:number.subsubsubsection = 0
|
||||
elseif a:level == 'subsubsection'
|
||||
let s:number.subsubsection += 1
|
||||
let s:number.subsubsubsection = 0
|
||||
elseif a:level == 'subsubsubsection'
|
||||
let s:number.subsubsubsection += 1
|
||||
endif
|
||||
|
||||
return s:number_print()
|
||||
@ -272,6 +319,7 @@ function! s:number_print() " {{{1
|
||||
\ s:number.section,
|
||||
\ s:number.subsection,
|
||||
\ s:number.subsubsection,
|
||||
\ s:number.subsubsubsection,
|
||||
\ ]
|
||||
|
||||
" Remove unused parts
|
||||
@ -283,12 +331,10 @@ function! s:number_print() " {{{1
|
||||
endwhile
|
||||
|
||||
" Change numbering in frontmatter, appendix, and backmatter
|
||||
if s:number.frontmatter
|
||||
call map(number, 's:roman_numeral(v:val)')
|
||||
if s:number.frontmatter || s:number.backmatter
|
||||
return ""
|
||||
elseif s:number.appendix
|
||||
let number[0] = nr2char(number[0] + 64)
|
||||
elseif s:number.backmatter
|
||||
return ""
|
||||
endif
|
||||
|
||||
return join(number, '.')
|
||||
@ -296,19 +342,25 @@ endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
function! s:roman_numeral(number) " {{{1
|
||||
let n = a:number
|
||||
let result = ""
|
||||
for [limit, glyph] in s:digits
|
||||
while n >= limit
|
||||
let result .= glyph
|
||||
let n -= limit
|
||||
endwhile
|
||||
endfor
|
||||
return result
|
||||
endfunction
|
||||
function! s:set_max_level(file) " {{{1
|
||||
if !filereadable(a:file)
|
||||
echoerr "Error in latex#toc s:get_depth:"
|
||||
echoerr "File not readable: " . a:file
|
||||
return ''
|
||||
endif
|
||||
|
||||
let s:digits = [[10, "x"], [9, "ix"], [5, "v"], [4, "iv"], [1, "i"]]
|
||||
let n = 0
|
||||
|
||||
for line in readfile(a:file)
|
||||
if line =~# s:re_input
|
||||
let n = max([n, s:set_max_level(s:parse_line_input(line))])
|
||||
elseif line =~# s:re_sec
|
||||
let n = max([n, s:sec_to_value[matchstr(line, s:re_sec_level)]])
|
||||
endif
|
||||
endfor
|
||||
|
||||
return n
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
|
@ -12,6 +12,7 @@ let b:did_ftplugin = 1
|
||||
" Set local buffer settings
|
||||
setlocal buftype=nofile
|
||||
setlocal bufhidden=wipe
|
||||
setlocal listchars=
|
||||
setlocal nobuflisted
|
||||
setlocal noswapfile
|
||||
setlocal nowrap
|
||||
|
@ -1,15 +1,15 @@
|
||||
syntax match TocHelpText /^.*: .*/
|
||||
syntax match TocNum /^\S\+\(\.\S\+\)\?\s*/ contained conceal
|
||||
syntax match TocSec /^\t.\+/
|
||||
syntax match TocSec1 /^[^\.]\+\t.*/ contains=secNum
|
||||
syntax match TocSec2 /^\([^\.]\+\.\)\{1}[^\.]\+\t.*/ contains=secNum
|
||||
syntax match TocSec3 /^\([^\.]\+\.\)\{2}[^\.]\+\t.*/ contains=secNum
|
||||
syntax match TocSec4 /^\([^\.]\+\.\)\{3}[^\.]\+\t.*/ contains=secNum
|
||||
syntax match TocNum /^\(\S\+\(\.\S\+\)*\)\?\s*/ contained conceal
|
||||
syntax match TocSec0 /^.*0$/ contains=TocNum,@Tex
|
||||
syntax match TocSec1 /^.*1$/ contains=TocNum,@Tex
|
||||
syntax match TocSec2 /^.*2$/ contains=TocNum,@Tex
|
||||
syntax match TocSec3 /^.*3$/ contains=TocNum,@Tex
|
||||
syntax match TocSec4 /^.*4$/ contains=TocNum,@Tex
|
||||
|
||||
highlight link TocHelpText helpVim
|
||||
highlight link TocNum Number
|
||||
highlight link TocSec Title
|
||||
highlight link TocSec1 TocSec
|
||||
highlight link TocSec2 Normal
|
||||
highlight link TocSec0 Title
|
||||
highlight link TocSec1 Normal
|
||||
highlight link TocSec2 helpVim
|
||||
highlight link TocSec3 NonText
|
||||
highlight link TocSec4 Comment
|
||||
|
Loading…
Reference in New Issue
Block a user