Improved TOC (fixes #31)

* Syntax works for unnumbered sections
* No numbers on frontmatter
This commit is contained in:
Karl Yngve Lervåg 2014-07-20 14:47:41 +02:00
parent 1ba745a177
commit e171ba5a3b
3 changed files with 85 additions and 32 deletions

View File

@ -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

View File

@ -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

View File

@ -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