@@ -34,9 +34,15 @@ function! vimtex#state#class#new(opts) abort " {{{1
3434 \ ? vimtex#parser#preamble (l: new .tex, {' root' : l: new .root})
3535 \ : []
3636
37- let l: new .documentclass = s: parse_documentclass (l: preamble )
38- let l: new .packages = s: parse_packages (l: preamble )
39- let l: new .graphicspath = s: parse_graphicspath (l: preamble , l: new .root)
37+ " Create single-line preamble-string without comments
38+ let l: preamble_joined = join (
39+ \ map (copy (l: preamble ), {_, x - > substitute (x , ' \\\@<!%.*' , ' ' , ' ' )}),
40+ \ ' ' )
41+
42+ let [l: new .documentclass, l: new .documentclass_options] =
43+ \ s: parse_documentclass (l: preamble_joined )
44+ let l: new .packages = s: parse_packages (l: preamble_joined )
45+ let l: new .graphicspath = s: parse_graphicspath (l: preamble_joined , l: new .root)
4046 let l: new .glossaries = s: parse_glossaries (
4147 \ l: preamble ,
4248 \ l: new .root,
@@ -74,6 +80,17 @@ function! s:vimtex.__pprint() abort dict " {{{1
7480 call add (l: items , [' document class' , self .documentclass])
7581 endif
7682
83+ if exists (' self.documentclass_options' )
84+ let l: string = join (map (sort (keys (self .documentclass_options)),
85+ \ {_, key - > key .. " =" .. (
86+ \ self .documentclass_options[key ] == v: true ? ' true'
87+ \ : self .documentclass_options[key ] == v: false ? ' false'
88+ \ : self .documentclass_options[key ]
89+ \ )}
90+ \) )
91+ call add (l: items , [' document class options' , l: string ])
92+ endif
93+
7794 if ! empty (self .packages)
7895 call add (l: items , [' packages' , join (sort (keys (self .packages)))])
7996 endif
@@ -193,38 +210,43 @@ endfunction
193210" }}}1
194211
195212
196- function ! s: parse_documentclass (preamble ) abort " {{{1
197- let l: preamble_lines = filter ( copy ( a: preamble ), {_, x - > x !~# ' ^\s*% ' })
198- return matchstr ( join ( l: preamble_lines , ' ' ) ,
213+ function ! s: parse_documentclass (preamble_joined ) abort " {{{1
214+ let l: documentclass = matchstr (
215+ \ a: preamble_joined ,
199216 \ ' \\documentclass[^{]*{\zs[^}]\+\ze}' )
217+
218+ let l: option_string = matchstr (
219+ \ a: preamble_joined ,
220+ \ ' \\documentclass[^\[]*\[\zs[^\]]\+\ze\]' )
221+ let l: options = s: parse_optionlist (l: option_string )
222+
223+ return [l: documentclass , l: options ]
200224endfunction
201225
202226" }}}1
203- function ! s: parse_packages (preamble) abort " {{{1
204- let l: usepackages = filter (copy (a: preamble ),
205- \ ' v:val =~# '' \v%(usep|RequireP)ackage'' ' )
206- let l: pat = g: vimtex #re #not_comment . g: vimtex #re #not_bslash
207- \ . ' \v\\%(usep|RequireP)ackage\s*%(\[[^[\]]*\])?\s*\{\s*\zs%([^{}]+)\ze\s*\}'
208- call map (l: usepackages , {_, x - > split (matchstr (x , l: pat ), ' \s*,\s*' )})
209-
210- let l: parsed = {}
211- for l: packages in l: usepackages
212- for l: package in l: packages
213- let l: parsed [l: package ] = {}
227+ function ! s: parse_packages (preamble_joined) abort " {{{1
228+ " Regex pattern:
229+ " - Match contains package name(s)
230+ " - First submatch contains package options
231+ let l: pat = g: vimtex #re #not_comment .. g: vimtex #re #not_bslash
232+ \ .. ' \v\\%(usep|RequireP)ackage\s*%(\[([^[\]]*)\])?\s*\{\s*\zs%([^{}]+\S)\ze\s*\}'
233+
234+ let l: packages = {}
235+ for l: match in matchstrlist ([a: preamble_joined ], pat, #{submatches: v: true })
236+ let l: new_packages = map (split (l: match .text, ' ,' ), {_, x - > trim (x )})
237+ let l: options = s: parse_optionlist (l: match .submatches[0 ])
238+ for l: pkg in l: new_packages
239+ let l: packages [l: pkg ] = l: options
214240 endfor
215241 endfor
216242
217- return l: parsed
243+ return l: packages
218244endfunction
219245
220246" }}}1
221- function ! s: parse_graphicspath (preamble, root) abort " {{{1
222- " Combine the preamble as one long string of commands
223- let l: preamble = join (map (copy (a: preamble ),
224- \ {_, x - > substitute (x , ' \\\@<!%.*' , ' ' , ' ' )}))
225-
247+ function ! s: parse_graphicspath (preamble_joined, root) abort " {{{1
226248 " Extract the graphicspath command from this string
227- let l: graphicspath = matchstr (l: preamble ,
249+ let l: graphicspath = matchstr (a: preamble_joined ,
228250 \ g: vimtex #re #not_bslash
229251 \ . ' \\graphicspath\s*\{\s*\{\s*\zs.{-}\ze\s*\}\s*\}'
230252 \)
@@ -297,3 +319,33 @@ function! s:gather_sources(texfile, root) abort " {{{1
297319endfunction
298320
299321" }}}1
322+
323+ function ! s: parse_optionlist (string ) abort " {{{1
324+ let l: options = {}
325+ for l: element in map (split (a: string , ' ,' , v: true ), {_, x - > trim (x )})
326+ if l: element == ' '
327+ " Empty option
328+ continue
329+ elseif l: element = ~# ' ='
330+ " Key-value option
331+ let [l: key , l: value ] = map (split (l: element , ' =' ), {_, x - > trim (x )})
332+
333+ if l: value == ? ' true'
334+ let l: options [l: key ] = v: true
335+ elseif l: value == ? ' false'
336+ let l: options [l: key ] = v: false
337+ else
338+ let l: options [l: key ] = l: value
339+ endif
340+ else
341+ " Key-only option
342+ let l: options [l: element ] = v: true
343+ endif
344+ endfor
345+
346+ return l: options
347+ endfunction
348+
349+ " }}}1
350+
351+ " vim: fdm = marker
0 commit comments