summaryrefslogtreecommitdiffstats
path: root/autoload/vimtex/qf
diff options
context:
space:
mode:
Diffstat (limited to 'autoload/vimtex/qf')
-rw-r--r--autoload/vimtex/qf/biblatex.vim250
-rw-r--r--autoload/vimtex/qf/bibtex.vim187
-rw-r--r--autoload/vimtex/qf/latexlog.vim209
-rw-r--r--autoload/vimtex/qf/pplatex.vim98
-rw-r--r--autoload/vimtex/qf/pulp.vim67
5 files changed, 811 insertions, 0 deletions
diff --git a/autoload/vimtex/qf/biblatex.vim b/autoload/vimtex/qf/biblatex.vim
new file mode 100644
index 00000000..2e5e08a5
--- /dev/null
+++ b/autoload/vimtex/qf/biblatex.vim
@@ -0,0 +1,250 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" vimtex - LaTeX plugin for Vim
+"
+" Maintainer: Karl Yngve Lervåg
+" Email: karl.yngve@gmail.com
+"
+
+function! vimtex#qf#biblatex#addqflist(blg) abort " {{{1
+ if get(g:vimtex_quickfix_blgparser, 'disable') | return | endif
+
+ try
+ call s:biblatex.addqflist(a:blg)
+ catch /biblatex Aborted/
+ endtry
+endfunction
+
+" }}}1
+
+let s:biblatex = {
+ \ 'file' : '',
+ \ 'types' : [],
+ \ 'db_files' : [],
+ \}
+function! s:biblatex.addqflist(blg) abort " {{{1
+ let self.file = a:blg
+ let self.root = fnamemodify(a:blg, ':h')
+ if empty(self.file) | throw 'biblatex Aborted' | endif
+
+ let self.types = map(
+ \ filter(items(s:), 'v:val[0] =~# ''^type_'''),
+ \ 'v:val[1]')
+ let self.db_files = []
+
+ let self.errorformat_saved = &l:errorformat
+ setlocal errorformat=%+E%.%#\>\ ERROR%m
+ setlocal errorformat+=%+W%.%#\>\ WARN\ -\ Duplicate\ entry%m
+ setlocal errorformat+=%+W%.%#\>\ WARN\ -\ The\ entry%.%#cannot\ be\ encoded%m
+ setlocal errorformat+=%-G%.%#
+ execute 'caddfile' fnameescape(self.file)
+ let &l:errorformat = self.errorformat_saved
+
+ call self.fix_paths()
+endfunction
+
+" }}}1
+function! s:biblatex.fix_paths() abort " {{{1
+ let l:qflist = getqflist()
+ try
+ let l:title = getqflist({'title': 1})
+ catch /E118/
+ let l:title = 'Vimtex errors'
+ endtry
+
+ for l:qf in l:qflist
+ for l:type in self.types
+ if l:type.fix(self, l:qf) | break | endif
+ endfor
+ endfor
+
+ call setqflist(l:qflist, 'r')
+
+ " Set title if supported
+ try
+ call setqflist([], 'r', l:title)
+ catch
+ endtry
+endfunction
+
+" }}}1
+function! s:biblatex.get_db_files() abort " {{{1
+ if empty(self.db_files)
+ let l:preamble = vimtex#parser#preamble(b:vimtex.tex, {
+ \ 'root' : b:vimtex.root,
+ \})
+ let l:files = map(
+ \ filter(l:preamble, 'v:val =~# ''\\addbibresource'''),
+ \ 'matchstr(v:val, ''{\zs.*\ze}'')')
+ let self.db_files = []
+ for l:file in l:files
+ if filereadable(l:file)
+ let self.db_files += [l:file]
+ elseif filereadable(expand(l:file))
+ let self.db_files += [expand(l:file)]
+ else
+ let l:cand = vimtex#kpsewhich#run(l:file)
+ if len(l:cand) == 1
+ let self.db_files += [l:cand[0]]
+ endif
+ endif
+ endfor
+ endif
+
+ return self.db_files
+endfunction
+
+" }}}1
+function! s:biblatex.get_filename(name) abort " {{{1
+ if !filereadable(a:name)
+ for l:root in [self.root, b:vimtex.root]
+ let l:candidate = fnamemodify(simplify(l:root . '/' . a:name), ':.')
+ if filereadable(l:candidate)
+ return l:candidate
+ endif
+ endfor
+ endif
+
+ return a:name
+endfunction
+
+" }}}1
+function! s:biblatex.get_key_pos(key) abort " {{{1
+ for l:file in self.get_db_files()
+ let l:lnum = self.get_key_lnum(a:key, l:file)
+ if l:lnum > 0
+ return [l:file, l:lnum]
+ endif
+ endfor
+
+ return []
+endfunction
+
+" }}}1
+function! s:biblatex.get_key_lnum(key, filename) abort " {{{1
+ if !filereadable(a:filename) | return 0 | endif
+
+ let l:lines = readfile(a:filename)
+ let l:lnums = range(len(l:lines))
+ let l:annotated_lines = map(l:lnums, '[v:val, l:lines[v:val]]')
+ let l:matches = filter(l:annotated_lines, 'v:val[1] =~# ''^\s*@\w*{\s*\V' . a:key . '''')
+
+ return len(l:matches) > 0 ? l:matches[-1][0]+1 : 0
+endfunction
+
+" }}}1
+function! s:biblatex.get_entry_key(filename, lnum) abort " {{{1
+ for l:file in self.get_db_files()
+ if fnamemodify(l:file, ':t') !=# a:filename | continue | endif
+
+ let l:entry = get(filter(readfile(l:file, 0, a:lnum), 'v:val =~# ''^@'''), -1)
+ if empty(l:entry) | continue | endif
+
+ return matchstr(l:entry, '{\v\zs.{-}\ze(,|$)')
+ endfor
+
+ return ''
+endfunction
+
+" }}}1
+
+"
+" Parsers for the various warning types
+"
+
+let s:type_parse_error = {}
+function! s:type_parse_error.fix(ctx, entry) abort " {{{1
+ if a:entry.text =~# 'ERROR - BibTeX subsystem.*expected end of entry'
+ let l:matches = matchlist(a:entry.text, '\v(\S*\.bib).*line (\d+)')
+ let a:entry.filename = a:ctx.get_filename(fnamemodify(l:matches[1], ':t'))
+ let a:entry.lnum = l:matches[2]
+
+ " Use filename and line number to get entry name
+ let l:key = a:ctx.get_entry_key(a:entry.filename, a:entry.lnum)
+ if !empty(l:key)
+ let a:entry.text = 'biblatex: Error parsing entry with key "' . l:key . '"'
+ endif
+ return 1
+ endif
+endfunction
+
+" }}}1
+
+let s:type_duplicate = {}
+function! s:type_duplicate.fix(ctx, entry) abort " {{{1
+ if a:entry.text =~# 'WARN - Duplicate entry'
+ let l:matches = matchlist(a:entry.text, '\v: ''(\S*)'' in file ''(.{-})''')
+ let l:key = l:matches[1]
+ let a:entry.filename = a:ctx.get_filename(l:matches[2])
+ let a:entry.lnum = a:ctx.get_key_lnum(l:key, a:entry.filename)
+ let a:entry.text = 'biblatex: Duplicate entry key "' . l:key . '"'
+ return 1
+ endif
+endfunction
+
+" }}}1
+
+let s:type_no_driver = {}
+function! s:type_no_driver.fix(ctx, entry) abort " {{{1
+ if a:entry.text =~# 'No driver for entry type'
+ let l:key = matchstr(a:entry.text, 'entry type ''\v\zs.{-}\ze''')
+ let a:entry.text = 'biblatex: Using fallback driver for ''' . l:key . ''''
+
+ let l:pos = a:ctx.get_key_pos(l:key)
+ if !empty(l:pos)
+ let a:entry.filename = a:ctx.get_filename(l:pos[0])
+ let a:entry.lnum = l:pos[1]
+ if has_key(a:entry, 'bufnr')
+ unlet a:entry.bufnr
+ endif
+ endif
+
+ return 1
+ endif
+endfunction
+
+" }}}1
+
+let s:type_not_found = {}
+function! s:type_not_found.fix(ctx, entry) abort " {{{1
+ if a:entry.text =~# 'The following entry could not be found'
+ let l:key = split(a:entry.text, ' ')[-1]
+ let a:entry.text = 'biblatex: Entry with key ''' . l:key . ''' not found'
+
+ for [l:file, l:lnum, l:line] in vimtex#parser#tex(b:vimtex.tex)
+ if l:line =~# g:vimtex#re#not_comment . '\\\S*\V' . l:key
+ let a:entry.lnum = l:lnum
+ let a:entry.filename = l:file
+ unlet a:entry.bufnr
+ break
+ endif
+ endfor
+
+ return 1
+ endif
+endfunction
+
+" }}}1
+
+let s:type_encoding = {}
+function! s:type_encoding.fix(ctx, entry) abort " {{{1
+ if a:entry.text =~# 'The entry .* has characters which cannot'
+ let l:key = matchstr(a:entry.text, 'The entry ''\v\zs.{-}\ze''')
+ let a:entry.text = 'biblatex: Entry with key ''' . l:key . ''' has non-ascii characters'
+
+ let l:pos = a:ctx.get_key_pos(l:key)
+ if !empty(l:pos)
+ let a:entry.filename = a:ctx.get_filename(l:pos[0])
+ let a:entry.lnum = l:pos[1]
+ if has_key(a:entry, 'bufnr')
+ unlet a:entry.bufnr
+ endif
+ endif
+
+ return 1
+ endif
+endfunction
+
+" }}}1
+
+endif
diff --git a/autoload/vimtex/qf/bibtex.vim b/autoload/vimtex/qf/bibtex.vim
new file mode 100644
index 00000000..94bdcafa
--- /dev/null
+++ b/autoload/vimtex/qf/bibtex.vim
@@ -0,0 +1,187 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" vimtex - LaTeX plugin for Vim
+"
+" Maintainer: Karl Yngve Lervåg
+" Email: karl.yngve@gmail.com
+"
+
+function! vimtex#qf#bibtex#addqflist(blg) abort " {{{1
+ if get(g:vimtex_quickfix_blgparser, 'disable') | return | endif
+
+ try
+ call s:bibtex.addqflist(a:blg)
+ catch /BibTeX Aborted/
+ endtry
+endfunction
+
+" }}}1
+
+let s:bibtex = {
+ \ 'file' : '',
+ \ 'types' : [],
+ \ 'db_files' : [],
+ \}
+function! s:bibtex.addqflist(blg) abort " {{{1
+ let self.file = a:blg
+ if empty(self.file) || !filereadable(self.file) | throw 'BibTeX Aborted' | endif
+
+ let self.types = map(
+ \ filter(items(s:), 'v:val[0] =~# ''^type_'''),
+ \ 'v:val[1]')
+ let self.db_files = []
+
+ let self.errorformat_saved = &l:errorformat
+ setlocal errorformat=%+E%.%#---line\ %l\ of\ file\ %f
+ setlocal errorformat+=%+EI\ found\ %.%#---while\ reading\ file\ %f
+ setlocal errorformat+=%+WWarning--empty\ %.%#\ in\ %.%m
+ setlocal errorformat+=%+WWarning--entry\ type\ for%m
+ setlocal errorformat+=%-C--line\ %l\ of\ file\ %f
+ setlocal errorformat+=%-G%.%#
+ execute 'caddfile' fnameescape(self.file)
+ let &l:errorformat = self.errorformat_saved
+
+ call self.fix_paths()
+endfunction
+
+" }}}1
+function! s:bibtex.fix_paths() abort " {{{1
+ let l:qflist = getqflist()
+ try
+ let l:title = getqflist({'title': 1})
+ catch /E118/
+ let l:title = 'Vimtex errors'
+ endtry
+
+ for l:qf in l:qflist
+ for l:type in self.types
+ if l:type.fix(self, l:qf) | break | endif
+ endfor
+ endfor
+
+ call setqflist(l:qflist, 'r')
+
+ " Set title if supported
+ try
+ call setqflist([], 'r', l:title)
+ catch
+ endtry
+endfunction
+
+" }}}1
+function! s:bibtex.get_db_files() abort " {{{1
+ if empty(self.db_files)
+ let l:build_dir = fnamemodify(b:vimtex.ext('log'), ':.:h') . '/'
+ for l:file in map(
+ \ filter(readfile(self.file), 'v:val =~# ''Database file #\d:'''),
+ \ 'matchstr(v:val, '': \zs.*'')')
+ if filereadable(l:file)
+ call add(self.db_files, l:file)
+ elseif filereadable(l:build_dir . l:file)
+ call add(self.db_files, l:build_dir . l:file)
+ endif
+ endfor
+ endif
+
+ return self.db_files
+endfunction
+
+" }}}1
+function! s:bibtex.get_key_loc(key) abort " {{{1
+ for l:file in self.get_db_files()
+ let l:lines = readfile(l:file)
+ let l:lnum = 0
+ for l:line in l:lines
+ let l:lnum += 1
+ if l:line =~# '^\s*@\w*{\s*\V' . a:key
+ return [l:file, l:lnum]
+ endif
+ endfor
+ endfor
+
+ return []
+endfunction
+
+" }}}1
+
+"
+" Parsers for the various warning types
+"
+
+let s:type_syn_error = {}
+function! s:type_syn_error.fix(ctx, entry) abort " {{{1
+ if a:entry.text =~# '---line \d\+ of file'
+ let a:entry.text = split(a:entry.text, '---')[0]
+ return 1
+ endif
+endfunction
+
+" }}}1
+
+let s:type_empty = {
+ \ 're' : '\vWarning--empty (.*) in (\S*)',
+ \}
+function! s:type_empty.fix(ctx, entry) abort " {{{1
+ let l:matches = matchlist(a:entry.text, self.re)
+ if empty(l:matches) | return 0 | endif
+
+ let l:type = l:matches[1]
+ let l:key = l:matches[2]
+
+ unlet a:entry.bufnr
+ let a:entry.text = printf('Missing "%s" in "%s"', l:type, l:key)
+
+ let l:loc = a:ctx.get_key_loc(l:key)
+ if !empty(l:loc)
+ let a:entry.filename = l:loc[0]
+ let a:entry.lnum = l:loc[1]
+ endif
+
+ return 1
+endfunction
+
+" }}}1
+
+let s:type_style_file_defined = {
+ \ 're' : '\vWarning--entry type for "(\w+)"',
+ \}
+function! s:type_style_file_defined.fix(ctx, entry) abort " {{{1
+ let l:matches = matchlist(a:entry.text, self.re)
+ if empty(l:matches) | return 0 | endif
+
+ let l:key = l:matches[1]
+
+ unlet a:entry.bufnr
+ let a:entry.text = 'Entry type for "' . l:key . '" isn''t style-file defined'
+
+ let l:loc = a:ctx.get_key_loc(l:key)
+ if !empty(l:loc)
+ let a:entry.filename = l:loc[0]
+ let a:entry.lnum = l:loc[1]
+ endif
+
+ return 1
+endfunction
+
+" }}}1
+
+let s:type_no_bibstyle = {}
+function! s:type_no_bibstyle.fix(ctx, entry) abort " {{{1
+ if a:entry.text =~# 'I found no \\bibstyle'
+ let a:entry.text = 'BibTeX found no \bibstyle command (missing \bibliographystyle?)'
+ let a:entry.filename = b:vimtex.tex
+ unlet a:entry.bufnr
+ for [l:file, l:lnum, l:line] in vimtex#parser#tex(b:vimtex.tex)
+ if l:line =~# g:vimtex#re#not_comment . '\\bibliography'
+ let a:entry.lnum = l:lnum
+ let a:entry.filename = l:file
+ break
+ endif
+ endfor
+ return 1
+ endif
+endfunction
+
+" }}}1
+
+endif
diff --git a/autoload/vimtex/qf/latexlog.vim b/autoload/vimtex/qf/latexlog.vim
new file mode 100644
index 00000000..0046543e
--- /dev/null
+++ b/autoload/vimtex/qf/latexlog.vim
@@ -0,0 +1,209 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" vimtex - LaTeX plugin for Vim
+"
+" Maintainer: Karl Yngve Lervåg
+" Email: karl.yngve@gmail.com
+"
+
+function! vimtex#qf#latexlog#new() abort " {{{1
+ return deepcopy(s:qf)
+endfunction
+
+" }}}1
+
+
+let s:qf = {
+ \ 'name' : 'LaTeX logfile',
+ \}
+
+function! s:qf.init(state) abort dict "{{{1
+ let self.config = get(g:, 'vimtex_quickfix_latexlog', {})
+ let self.config.default = get(self.config, 'default', 1)
+ let self.config.packages = get(self.config, 'packages', {})
+ let self.config.packages.default = get(self.config.packages, 'default',
+ \ self.config.default)
+
+ let self.types = map(
+ \ filter(items(s:), 'v:val[0] =~# ''^type_'''),
+ \ 'v:val[1]')
+endfunction
+
+" }}}1
+function! s:qf.set_errorformat() abort dict "{{{1
+ "
+ " Note: The errorformat assumes we're using the -file-line-error with
+ " [pdf]latex. For more info, see |errorformat-LaTeX|.
+ "
+
+ " Push file to file stack
+ setlocal errorformat=%-P**%f
+ setlocal errorformat+=%-P**\"%f\"
+
+ " Match errors
+ setlocal errorformat+=%E!\ LaTeX\ %trror:\ %m
+ setlocal errorformat+=%E%f:%l:\ %m
+ setlocal errorformat+=%E!\ %m
+
+ " More info for undefined control sequences
+ setlocal errorformat+=%Z<argument>\ %m
+
+ " More info for some errors
+ setlocal errorformat+=%Cl.%l\ %m
+
+ "
+ " Define general warnings
+ "
+ let l:default = self.config.default
+ if get(self.config, 'font', l:default)
+ setlocal errorformat+=%+WLaTeX\ Font\ Warning:\ %.%#line\ %l%.%#
+ setlocal errorformat+=%-CLaTeX\ Font\ Warning:\ %m
+ setlocal errorformat+=%-C(Font)%m
+ else
+ setlocal errorformat+=%-WLaTeX\ Font\ Warning:\ %m
+ endif
+
+ if !get(self.config, 'references', l:default)
+ setlocal errorformat+=%-WLaTeX\ %.%#Warning:\ %.%#eference%.%#undefined%.%#line\ %l%.%#
+ setlocal errorformat+=%-WLaTeX\ %.%#Warning:\ %.%#undefined\ references.
+ endif
+
+ if get(self.config, 'general', l:default)
+ setlocal errorformat+=%+WLaTeX\ %.%#Warning:\ %.%#line\ %l%.%#
+ setlocal errorformat+=%+WLaTeX\ %.%#Warning:\ %m
+ endif
+
+ if get(self.config, 'overfull', l:default)
+ setlocal errorformat+=%+WOverfull\ %\\%\\hbox%.%#\ at\ lines\ %l--%*\\d
+ setlocal errorformat+=%+WOverfull\ %\\%\\hbox%.%#\ at\ line\ %l
+ setlocal errorformat+=%+WOverfull\ %\\%\\vbox%.%#\ at\ line\ %l
+ endif
+
+ if get(self.config, 'underfull', l:default)
+ setlocal errorformat+=%+WUnderfull\ %\\%\\hbox%.%#\ at\ lines\ %l--%*\\d
+ setlocal errorformat+=%+WUnderfull\ %\\%\\vbox%.%#\ at\ line\ %l
+ endif
+
+ "
+ " Define package related warnings
+ "
+ let l:default = self.config.packages.default
+ if get(self.config.packages, 'natbib', l:default)
+ setlocal errorformat+=%+WPackage\ natbib\ Warning:\ %m\ on\ input\ line\ %l.
+ else
+ setlocal errorformat+=%-WPackage\ natbib\ Warning:\ %m\ on\ input\ line\ %l.
+ endif
+
+ if get(self.config.packages, 'biblatex', l:default)
+ setlocal errorformat+=%+WPackage\ biblatex\ Warning:\ %m
+ setlocal errorformat+=%-C(biblatex)%.%#in\ t%.%#
+ setlocal errorformat+=%-C(biblatex)%.%#Please\ v%.%#
+ setlocal errorformat+=%-C(biblatex)%.%#LaTeX\ a%.%#
+ setlocal errorformat+=%-C(biblatex)%m
+ else
+ setlocal errorformat+=%-WPackage\ biblatex\ Warning:\ %m
+ endif
+
+ if get(self.config.packages, 'babel', l:default)
+ setlocal errorformat+=%+WPackage\ babel\ Warning:\ %m
+ setlocal errorformat+=%-Z(babel)%.%#input\ line\ %l.
+ setlocal errorformat+=%-C(babel)%m
+ else
+ setlocal errorformat+=%-WPackage\ babel\ Warning:\ %m
+ endif
+
+ if get(self.config.packages, 'hyperref', l:default)
+ setlocal errorformat+=%+WPackage\ hyperref\ Warning:\ %m
+ setlocal errorformat+=%-C(hyperref)%m\ on\ input\ line\ %l.
+ setlocal errorformat+=%-C(hyperref)%m
+ else
+ setlocal errorformat+=%-WPackage\ hyperref\ Warning:\ %m
+ endif
+
+ if get(self.config.packages, 'scrreprt', l:default)
+ setlocal errorformat+=%+WPackage\ scrreprt\ Warning:\ %m
+ setlocal errorformat+=%-C(scrreprt)%m
+ else
+ setlocal errorformat+=%-WPackage\ scrreprt\ Warning:\ %m
+ endif
+
+ if get(self.config.packages, 'fixltx2e', l:default)
+ setlocal errorformat+=%+WPackage\ fixltx2e\ Warning:\ %m
+ setlocal errorformat+=%-C(fixltx2e)%m
+ else
+ setlocal errorformat+=%-WPackage\ fixltx2e\ Warning:\ %m
+ endif
+
+ if get(self.config.packages, 'titlesec', l:default)
+ setlocal errorformat+=%+WPackage\ titlesec\ Warning:\ %m
+ setlocal errorformat+=%-C(titlesec)%m
+ else
+ setlocal errorformat+=%-WPackage\ titlesec\ Warning:\ %m
+ endif
+
+ if get(self.config.packages, 'general', l:default)
+ setlocal errorformat+=%+WPackage\ %.%#\ Warning:\ %m\ on\ input\ line\ %l.
+ setlocal errorformat+=%+WPackage\ %.%#\ Warning:\ %m
+ setlocal errorformat+=%-Z(%.%#)\ %m\ on\ input\ line\ %l.
+ setlocal errorformat+=%-C(%.%#)\ %m
+ endif
+
+ " Ignore unmatched lines
+ setlocal errorformat+=%-G%.%#
+endfunction
+
+" }}}1
+function! s:qf.addqflist(tex, log) abort dict "{{{1
+ if empty(a:log) || !filereadable(a:log)
+ throw 'Vimtex: No log file found'
+ endif
+
+ let self.errorformat_saved = &l:errorformat
+ call self.set_errorformat()
+ execute 'caddfile' fnameescape(a:log)
+ let &l:errorformat = self.errorformat_saved
+
+ " Apply some post processing of the quickfix list
+ let self.main = a:tex
+ let self.root = b:vimtex.root
+ call self.fix_paths()
+endfunction
+
+" }}}1
+function! s:qf.pprint_items() abort dict " {{{1
+ return [[ 'config', self.config ]]
+endfunction
+
+" }}}1
+function! s:qf.fix_paths() abort dict " {{{1
+ let l:qflist = getqflist()
+
+ for l:qf in l:qflist
+ " For errors and warnings that don't supply a file, the basename of the
+ " main file is used. However, if the working directory is not the root of
+ " the LaTeX project, than this results in bufnr = 0.
+ if l:qf.bufnr == 0
+ let l:qf.bufnr = bufnr(self.main)
+ continue
+ endif
+
+ " The buffer names of all file:line type errors are relative to the root of
+ " the main LaTeX file.
+ let l:file = fnamemodify(
+ \ simplify(self.root . '/' . bufname(l:qf.bufnr)), ':.')
+ if !filereadable(l:file) | continue | endif
+
+ if !bufexists(l:file)
+ execute 'badd' l:file
+ endif
+
+ let l:qf.filename = l:file
+ let l:qf.bufnr = bufnr(l:file)
+ endfor
+
+ call setqflist(l:qflist, 'r')
+endfunction
+
+" }}}1
+
+endif
diff --git a/autoload/vimtex/qf/pplatex.vim b/autoload/vimtex/qf/pplatex.vim
new file mode 100644
index 00000000..39e9a03e
--- /dev/null
+++ b/autoload/vimtex/qf/pplatex.vim
@@ -0,0 +1,98 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" vimtex - LaTeX plugin for Vim
+"
+" CreatedBy: Johannes Wienke (languitar@semipol.de)
+" Maintainer: Karl Yngve Lervåg
+" Email: karl.yngve@gmail.com
+"
+
+function! vimtex#qf#pplatex#new() abort " {{{1
+ return deepcopy(s:qf)
+endfunction
+
+" }}}1
+
+
+let s:qf = {
+ \ 'name' : 'LaTeX logfile using pplatex',
+ \}
+
+function! s:qf.init(state) abort dict "{{{1
+ if !executable('pplatex')
+ call vimtex#log#error('pplatex is not executable!')
+ throw 'vimtex: Requirements not met'
+ endif
+
+ " Automatically remove the -file-line-error option if we use the latexmk
+ " backend (for convenience)
+ if a:state.compiler.name ==# 'latexmk'
+ let l:index = index(a:state.compiler.options, '-file-line-error')
+ if l:index >= 0
+ call remove(a:state.compiler.options, l:index)
+ endif
+ endif
+endfunction
+
+function! s:qf.set_errorformat() abort dict "{{{1
+ " Each new item starts with two asterics followed by the file, potentially
+ " a line number and sometimes even the message itself is on the same line.
+ " Please note that the trailing whitspaces in the error formats are
+ " intentional as pplatex produces these.
+
+ " Start of new items with file and line number, message on next line(s).
+ setlocal errorformat=%E**\ Error\ \ \ in\ %f\\,\ Line\ %l:%m
+ setlocal errorformat+=%W**\ Warning\ in\ %f\\,\ Line\ %l:%m
+ setlocal errorformat+=%I**\ BadBox\ \ in\ %f\\,\ Line\ %l:%m
+
+ " Start of items with with file, line and message on the same line. There are
+ " no BadBoxes reported this way.
+ setlocal errorformat+=%E**\ Error\ \ \ in\ %f\\,\ Line\ %l:%m
+ setlocal errorformat+=%W**\ Warning\ in\ %f\\,\ Line\ %l:%m
+
+ " Start of new items with only a file.
+ setlocal errorformat+=%E**\ Error\ \ \ in\ %f:%m
+ setlocal errorformat+=%W**\ Warning\ in\ %f:%m
+ setlocal errorformat+=%I**\ BadBox\ \ in\ %f:%m
+
+ " Start of items with with file and message on the same line. There are
+ " no BadBoxes reported this way.
+ setlocal errorformat+=%E**\ Error\ in\ %f:%m
+ setlocal errorformat+=%W**\ Warning\ in\ %f:%m
+
+ " Some errors are difficult even for pplatex
+ setlocal errorformat+=%E**\ Error\ \ :%m
+
+ " Anything that starts with three spaces is part of the message from a
+ " previously started multiline error item.
+ setlocal errorformat+=%C\ \ \ %m\ on\ input\ line\ %l.
+ setlocal errorformat+=%C\ \ \ %m
+
+ " Items are terminated with two newlines.
+ setlocal errorformat+=%-Z
+
+ " Skip statistical results at the bottom of the output.
+ setlocal errorformat+=%-GResult%.%#
+ setlocal errorformat+=%-G
+endfunction
+
+" }}}1
+function! s:qf.addqflist(tex, log) abort dict " {{{1
+ if empty(a:log) || !filereadable(a:log)
+ throw 'Vimtex: No log file found'
+ endif
+
+ let l:tmp = fnameescape(fnamemodify(a:log, ':r') . '.pplatex')
+ let l:log = fnameescape(a:log)
+
+ silent call system(printf('pplatex -i %s >%s', l:log, l:tmp))
+ let self.errorformat_saved = &l:errorformat
+ call self.set_errorformat()
+ execute 'caddfile' l:tmp
+ let &l:errorformat = self.errorformat_saved
+ silent call system('rm ' . l:tmp)
+endfunction
+
+" }}}1
+
+endif
diff --git a/autoload/vimtex/qf/pulp.vim b/autoload/vimtex/qf/pulp.vim
new file mode 100644
index 00000000..0f0b73ef
--- /dev/null
+++ b/autoload/vimtex/qf/pulp.vim
@@ -0,0 +1,67 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" vimtex - LaTeX plugin for Vim
+"
+" Maintainer: Karl Yngve Lervåg
+" Email: karl.yngve@gmail.com
+"
+
+function! vimtex#qf#pulp#new() abort " {{{1
+ return deepcopy(s:qf)
+endfunction
+
+" }}}1
+
+
+let s:qf = {
+ \ 'name' : 'LaTeX logfile using pulp',
+ \}
+
+function! s:qf.init(state) abort dict "{{{1
+ if !executable('pulp')
+ call vimtex#log#error('pulp is not executable!')
+ throw 'vimtex: Requirements not met'
+ endif
+
+ " Automatically remove the -file-line-error option if we use the latexmk
+ " backend (for convenience)
+ if a:state.compiler.name ==# 'latexmk'
+ let l:index = index(a:state.compiler.options, '-file-line-error')
+ if l:index >= 0
+ call remove(a:state.compiler.options, l:index)
+ endif
+ endif
+endfunction
+
+function! s:qf.set_errorformat() abort dict "{{{1
+ setlocal errorformat=
+ setlocal errorformat+=%-G%*[^\ ])\ %.%#
+ setlocal errorformat+=%-G%.%#For\ some\ reason%.%#
+ setlocal errorformat+=%W%f:%l-%*[0-9?]:\ %*[^\ ]\ warning:\ %m
+ setlocal errorformat+=%E%f:%l-%*[0-9?]:\ %*[^\ ]\ error:\ %m
+ setlocal errorformat+=%W%f:%l-%*[0-9?]:\ %m
+ setlocal errorformat+=%W%l-%*[0-9?]:\ %m
+ setlocal errorformat+=%-G%.%#
+endfunction
+
+" }}}1
+function! s:qf.addqflist(tex, log) abort dict " {{{1
+ if empty(a:log) || !filereadable(a:log)
+ call setqflist([])
+ throw 'Vimtex: No log file found'
+ endif
+
+ let l:tmp = fnameescape(fnamemodify(a:log, ':r') . '.pulp')
+ let l:log = fnameescape(a:log)
+
+ silent call system(printf('pulp %s >%s', l:log, l:tmp))
+ let self.errorformat_saved = &l:errorformat
+ call self.set_errorformat()
+ execute 'caddfile' l:tmp
+ let &l:errorformat = self.errorformat_saved
+ silent call system('rm ' . l:tmp)
+endfunction
+
+" }}}1
+
+endif