Compare commits

..

44 Commits

Author SHA1 Message Date
Adam Stankiewicz
0df1bfa0c5 Add requirements.txt support, closes #507 2020-08-18 23:31:31 +02:00
Adam Stankiewicz
f7302d9262 Add jq syntax, closes #502 2020-08-18 23:25:22 +02:00
Adam Stankiewicz
7e38f4288a Add improved sql syntax, closes #505 2020-08-18 23:22:09 +02:00
Adam Stankiewicz
e521ba3ae2 Add fennel support, closes #514 2020-08-18 23:09:35 +02:00
Adam Stankiewicz
ee4f51587d Add ftdetect for jsonnet 2020-08-18 23:06:10 +02:00
Adam Stankiewicz
20a388cbc8 Add jsonnet support, closes #515 2020-08-18 23:04:38 +02:00
Adam Stankiewicz
81e61a3c5d Ignore auto-generated tags file 2020-08-18 23:00:07 +02:00
Adam Stankiewicz
5670985b3a Add docs, fixes #501 2020-08-18 22:45:46 +02:00
Adam Stankiewicz
69eae22ea6 Let fsharp have priority over fs files, fixes #523 2020-08-18 21:30:22 +02:00
Adam Stankiewicz
f8cee0172b Allow to set let g:python_highlight_all = 0, closes #474 2020-08-18 20:52:00 +02:00
Adam Stankiewicz
c6936aeeb1 Fix dhall plugin, closes #519 2020-08-18 20:08:26 +02:00
Adam Stankiewicz
6bb111eaba Embed plugin guards 2020-08-18 20:01:12 +02:00
Adam Stankiewicz
dfecb63078 Report download errors 2020-08-18 18:49:24 +02:00
Adam Stankiewicz
00015bd105 Migrate all ftdetect to linguist 2020-08-18 15:53:18 +02:00
Adam Stankiewicz
d821de3142 Migrate more filetypes 2020-08-18 11:54:28 +02:00
Adam Stankiewicz
a3bdbcdb3c Fix svelte branch name, closes #522 2020-08-14 19:15:07 +02:00
Adam Stankiewicz
34e01b8b62 Start github-linguist rewrite 2020-08-06 13:42:56 +02:00
Adam Stankiewicz
1e533e5982 Update 2020-08-06 13:22:17 +02:00
Adam Stankiewicz
56121b4e27 Update 2020-07-26 10:20:08 +02:00
Adam Stankiewicz
9c3c0bc082 Fix rspect ftdetect, #503 2020-07-06 19:14:22 +02:00
Adam Stankiewicz
8500ae8bb9 Update 2020-07-06 19:13:39 +02:00
Adam Stankiewicz
d09a56a494 Add unison language support 2020-06-25 13:40:40 +02:00
Adam Stankiewicz
abca7c2014 Update 2020-06-25 13:38:15 +02:00
TravonteD
8b6c06e723 Add detection for rspec files (#503)
Standard convention for rspec files is "*_spec.rb". This is also what
rspec.vim (the syntax plugin that is pulled in) uses.
2020-06-19 14:47:03 +02:00
Adam Stankiewicz
a86c0179eb Update 2020-06-13 11:36:03 +02:00
Adam Stankiewicz
22095febb7 Update 2020-06-10 11:46:12 +02:00
Adam Stankiewicz
ff066ee9f0 Update 2020-06-07 17:37:15 +02:00
Adam Stankiewicz
5b38663027 Update README.md 2020-06-01 22:01:48 +02:00
Adam Stankiewicz
f0b38f2c1d Install vim 8 for tests 2020-05-31 23:53:41 +02:00
Adam Stankiewicz
6676d61f61 Fix 2020-05-31 23:51:46 +02:00
Adam Stankiewicz
f0da1a9f4d Update vim version 2020-05-31 23:48:07 +02:00
Adam Stankiewicz
298d6b6356 Fix tests 2020-05-31 23:44:10 +02:00
Adam Stankiewicz
62f004c3da Update travis script 2020-05-31 23:42:04 +02:00
Adam Stankiewicz
c73ea49ecb Improve bash and zsh highlighting 2020-05-31 20:57:37 +02:00
Adam Stankiewicz
b2be47befc Update 2020-05-31 20:52:04 +02:00
Adam Kwiatek
de38ccabbd Enable TypeScript in ftdetect (#496) 2020-05-29 21:10:18 +02:00
Adam Stankiewicz
f0f49cf0fa Add support for ics, closes #492 2020-05-28 11:12:25 +02:00
Adam Stankiewicz
224a6348f9 Update 2020-05-28 11:09:19 +02:00
Emerson MX
00c3f02945 Remove gdscript ftplugin (#494) 2020-05-28 11:05:53 +02:00
Adam Stankiewicz
df34b4b4fa Update 2020-05-21 22:45:59 +02:00
Adam Stankiewicz
f3804b0892 Restore support for polyglot_disabled for ftdetect, closes #491 2020-05-21 22:45:04 +02:00
Adam Stankiewicz
685aeaaeb1 Add ledger support, closes #488 2020-05-20 20:24:48 +02:00
Adam Stankiewicz
a9cc6fd218 Remove latex, fixes #484 2020-05-20 20:19:03 +02:00
Adam Stankiewicz
3c47f192b5 Fix jinja.html detection 2020-05-20 19:44:40 +02:00
224 changed files with 6329 additions and 26136 deletions

7
.gitattributes vendored
View File

@@ -1,7 +0,0 @@
.gitignore export-ignore
.gitattributes export-ignore
README.md export-ignore
/spec export-ignore
Gemfile export-ignore
Gemfile.lock export-ignore
.travis.yml export-ignore

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
/tmp
!*ctags*
tags

View File

@@ -1,11 +1,7 @@
language: ruby
rvm:
- 2.6
sudo: false
addons:
apt:
packages:
- vim-gtk
language: vim
before_script:
- "./build"
script: xvfb-run bundle exec rspec --format=documentation
- sudo add-apt-repository ppa:jonathonf/vim -y
- sudo apt-get update -q
- sudo apt-get install -y vim
- vim --version
script: ./test

View File

@@ -1,4 +0,0 @@
source 'https://rubygems.org'
gem 'vimrunner'
gem 'rspec'

View File

@@ -1,28 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.3)
rspec (3.8.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-core (3.8.0)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.0)
vimrunner (0.3.4)
PLATFORMS
ruby
DEPENDENCIES
rspec
vimrunner
BUNDLED WITH
1.16.2

View File

@@ -10,13 +10,13 @@ A collection of language packs for Vim.
> One to rule them all, one to find them, one to bring them all and in the darkness bind them.
- It **won't affect your startup time**, as scripts are loaded only on demand\*.
- It **installs and updates 120+ times faster** than the <!--Package Count-->149<!--/Package Count--> packages it consists of.
- It **installs and updates 120+ times faster** than the <!--Package Count-->157<!--/Package Count--> packages it consists of.
- Solid syntax and indentation support (other features skipped). Only the best language packs.
- All unnecessary files are ignored (like enormous documentation from php support).
- No support for esoteric languages, only most popular ones (modern too, like `slim`).
- Each build is tested by automated vimrunner script on CI. See `spec` directory.
\*To be completely honest, concatenated `ftdetect` script takes up to `17ms` to load.
\*To be completely honest, optimized `ftdetect` script takes up to `19ms` to load.
## Installation
@@ -77,11 +77,12 @@ If you need full functionality of any plugin, please use it directly with your p
- [emberscript](https://github.com/yalesov/vim-ember-script) (syntax, indent, ftplugin)
- [emblem](https://github.com/yalesov/vim-emblem) (syntax, indent, ftplugin)
- [erlang](https://github.com/vim-erlang/vim-erlang-runtime) (syntax, indent)
- [fennel](https://github.com/bakpakin/fennel.vim) (syntax, indent, ftplugin)
- [ferm](https://github.com/vim-scripts/ferm.vim) (syntax)
- [fish](https://github.com/georgewitteman/vim-fish) (syntax, indent, compiler, autoload, ftplugin)
- [flatbuffers](https://github.com/dcharbon/vim-flatbuffers) (syntax)
- [fsharp](https://github.com/ionide/Ionide-vim) (syntax, indent)
- [gdscript](https://github.com/calviken/vim-gdscript3) (syntax, indent, ftplugin)
- [gdscript](https://github.com/calviken/vim-gdscript3) (syntax, indent)
- [git](https://github.com/tpope/vim-git) (syntax, indent, ftplugin)
- [glsl](https://github.com/tikhomirov/vim-glsl) (syntax, indent)
- [gmpl](https://github.com/maelvalais/gmpl.vim) (syntax)
@@ -90,7 +91,7 @@ If you need full functionality of any plugin, please use it directly with your p
- [gradle](https://github.com/tfnico/vim-gradle) (compiler)
- [graphql](https://github.com/jparise/vim-graphql) (syntax, indent, autoload, ftplugin, after)
- [haml](https://github.com/sheerun/vim-haml) (syntax, indent, compiler, ftplugin)
- [handlebars](https://github.com/mustache/vim-mustache-handlebars) (syntax, indent, ftplugin)
- [handlebars](https://github.com/sheerun/vim-mustache-handlebars) (syntax, indent, ftplugin)
- [haproxy](https://github.com/CH-DanReif/haproxy.vim) (syntax)
- [haskell](https://github.com/neovimhaskell/haskell-vim) (syntax, indent, ftplugin)
- [haxe](https://github.com/yaymukund/vim-haxe) (syntax)
@@ -99,18 +100,21 @@ If you need full functionality of any plugin, please use it directly with your p
- [hive](https://github.com/zebradil/hive.vim) (syntax, ftplugin)
- [html5](https://github.com/othree/html5.vim) (syntax, indent, autoload, ftplugin)
- [i3](https://github.com/mboughaba/i3config.vim) (syntax, ftplugin)
- [icalenadr](https://github.com/chutzpah/icalendar.vim) (syntax)
- [idris](https://github.com/idris-hackers/idris-vim) (syntax, indent, ftplugin)
- [ion](https://github.com/vmchale/ion-vim) (syntax, ftplugin)
- [javascript](https://github.com/pangloss/vim-javascript) (syntax, indent, compiler, ftplugin, extras)
- [jenkins](https://github.com/martinda/Jenkinsfile-vim-syntax) (syntax, indent)
- [jinja](https://github.com/lepture/vim-jinja) (syntax, indent)
- [jq](https://github.com/vito-c/jq.vim) (syntax, ftplugin)
- [json5](https://github.com/GutenYe/json5.vim) (syntax)
- [json](https://github.com/elzr/vim-json) (syntax, indent, ftplugin)
- [jsonnet](https://github.com/google/vim-jsonnet) (syntax, autoload, ftplugin)
- [jst](https://github.com/briancollins/vim-jst) (syntax, indent)
- [jsx](https://github.com/MaxMEllon/vim-jsx-pretty) (autoload, after)
- [julia](https://github.com/JuliaEditorSupport/julia-vim) (syntax, indent, autoload, ftplugin)
- [kotlin](https://github.com/udalov/kotlin-vim) (syntax, indent, ftplugin)
- [latex](https://github.com/lervag/vimtex) (indent, compiler, autoload, ftplugin, syntax)
- [ledger](https://github.com/ledger/vim-ledger) (syntax, compiler, indent)
- [less](https://github.com/groenewege/vim-less) (syntax, indent, ftplugin)
- [lilypond](https://github.com/anowlcalledjosh/vim-lilypond) (syntax, indent, compiler, ftplugin)
- [livescript](https://github.com/gkz/vim-ls) (syntax, indent, compiler, ftplugin)
@@ -152,6 +156,7 @@ If you need full functionality of any plugin, please use it directly with your p
- [raml](https://github.com/IN3D/vim-raml) (syntax, ftplugin)
- [razor](https://github.com/adamclerk/vim-razor) (syntax, indent, ftplugin)
- [reason](https://github.com/reasonml-editor/vim-reason-plus) (syntax, indent)
- [requirements](https://github.com/raimon49/requirements.txt.vim) (syntax, autoload)
- [rspec](https://github.com/keith/rspec.vim) (syntax)
- [rst](https://github.com/marshallward/vim-restructuredtext) (syntax, indent, autoload, ftplugin)
- [ruby](https://github.com/vim-ruby/vim-ruby) (syntax, indent, compiler, autoload, ftplugin)
@@ -159,12 +164,14 @@ If you need full functionality of any plugin, please use it directly with your p
- [sbt](https://github.com/derekwyatt/vim-sbt) (syntax)
- [scala](https://github.com/derekwyatt/vim-scala) (syntax, indent, compiler, ftplugin, ctags)
- [scss](https://github.com/cakebaker/scss-syntax.vim) (syntax, indent, ftplugin)
- [sh](https://github.com/arzg/vim-sh) (syntax)
- [slim](https://github.com/slim-template/vim-slim) (syntax, indent, ftplugin)
- [slime](https://github.com/slime-lang/vim-slime-syntax) (syntax, indent)
- [smt2](https://github.com/bohlender/vim-smt2) (syntax, autoload, ftplugin)
- [solidity](https://github.com/tomlion/vim-solidity) (syntax, indent, ftplugin)
- [sql](https://github.com/shmup/vim-sql-syntax) (syntax)
- [stylus](https://github.com/wavded/vim-stylus) (syntax, indent, ftplugin)
- [svelte](https://github.com/evanleck/vim-svelte) (syntax, indent, ftplugin)
- [svelte](https://github.com/evanleck/vim-svelte#main) (syntax, indent, ftplugin)
- [svg-indent](https://github.com/jasonshell/vim-svg-indent) (indent)
- [svg](https://github.com/vim-scripts/svg.vim) (syntax)
- [swift](https://github.com/keith/swift.vim) (syntax, indent, compiler, ftplugin, ctags)
@@ -179,6 +186,7 @@ If you need full functionality of any plugin, please use it directly with your p
- [tptp](https://github.com/c-cube/vim-tptp) (syntax)
- [twig](https://github.com/lumiliet/vim-twig) (syntax, indent, ftplugin)
- [typescript](https://github.com/HerringtonDarkholme/yats.vim) (syntax, indent, compiler, ftplugin, ctags)
- [unison](https://github.com/unisonweb/unison#trunk) (syntax)
- [v](https://github.com/ollykel/v-vim) (syntax, indent, ftplugin)
- [vala](https://github.com/arrufat/vala.vim) (syntax, indent, ftplugin)
- [vbnet](https://github.com/vim-scripts/vbnet.vim) (syntax)
@@ -192,7 +200,7 @@ If you need full functionality of any plugin, please use it directly with your p
- [yaml](https://github.com/stephpy/vim-yaml) (syntax, ftplugin)
- [yard](https://github.com/sheerun/vim-yardoc) (syntax)
- [zephir](https://github.com/xwsoul/vim-zephir) (syntax)
- [zig](https://github.com/ziglang/zig.vim) (syntax, autoload, ftplugin)
- [zig](https://github.com/ziglang/zig.vim) (syntax, indent, autoload, ftplugin)
- [zinit](https://github.com/zinit-zsh/zplugin-vim-syntax) (syntax)
<!--/Language Packs-->

View File

@@ -1,20 +0,0 @@
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
"
if !get(g:, 'vimtex_enabled', 1)
finish
endif
if exists('b:did_ftplugin_vimtex')
finish
endif
let b:did_ftplugin_vimtex = 1
call vimtex#check_plugin_clash()
endif

View File

@@ -4,7 +4,7 @@ let s:highlight_close_tag = get(g:, 'vim_jsx_pretty_highlight_close_tag', 0)
" detect jsx region
syntax region jsxRegion
\ start=+\%(\%(\_[([,?:=+\-*/>{}]\|<\s\+\|&&\|||\|=>\|\<return\|\<default\|\<await\|\<yield\)\_s*\)\@<=<\_s*\%(>\|\z(\%(script\|T\s*>\s*(\)\@!\<[_$A-Za-z][-:._$A-Za-z0-9]*\>\)\%(\_s*\%([-+*)\]}&|?,]\|/\%([/*]\|\_s*>\)\@!\)\)\@!\)+
\ start=+\%(\%(\_[([,?:=+\-*/>{}]\|<\s\+\|&&\|||\|=>\|\<return\|\<default\|\<await\|\<yield\)\_s*\)\@<=<\_s*\%(>\|\z(\%(script\|\s*\<T\>\)\@!\<[_$A-Za-z][-:._$A-Za-z0-9]*\>\)\%(\_s*\%([-+*)\]}&|?,]\|/\%([/*]\|\_s*>\)\@!\)\)\@!\)+
\ end=++
\ contains=jsxElement

View File

@@ -0,0 +1,37 @@
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'graphql') == -1
" Copyright (c) 2016-2020 Jon Parise <jon@indelible.org>
"
" Permission is hereby granted, free of charge, to any person obtaining a copy
" of this software and associated documentation files (the "Software"), to
" deal in the Software without restriction, including without limitation the
" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
" sell copies of the Software, and to permit persons to whom the Software is
" furnished to do so, subject to the following conditions:
"
" The above copyright notice and this permission notice shall be included in
" all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
" IN THE SOFTWARE.
"
" Language: GraphQL
" Maintainer: Jon Parise <jon@indelible.org>
if exists('b:current_syntax')
let s:current_syntax = b:current_syntax
unlet b:current_syntax
endif
syn include @GraphQLSyntax syntax/graphql.vim
if exists('s:current_syntax')
let b:current_syntax = s:current_syntax
endif
syntax region graphqlMultilineString matchgroup=reasonMultilineString start=+graphql\_s*\zs{|+ end=+|}+ contains=@GraphQLSyntax,reasonEscape,reasonEscapeUnicode,reasonEscapeError,reasonStringContinuation keepend
endif

View File

@@ -1,11 +0,0 @@
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
"
call vimtex#syntax#init()
endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,5 @@
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'crystal') == -1
let s:save_cpo = &cpo
set cpo&vim
let s:V = vital#crystal#new()
let s:P = s:V.import('Process')
let s:C = s:V.import('ColorEcho')
@@ -365,9 +362,6 @@ function! crystal_lang#expand(file, pos, ...) abort
return crystal_lang#tool('expand', a:file, a:pos, get(a:, 1, ''))
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: sw=2 sts=2 et:
endif

View File

@@ -267,7 +267,7 @@ fu! csv#GetPat(colnr, maxcolnr, pat, allowmore) "{{{3
" Allow space in front of the pattern, so that it works correctly
" even if :Arrange Col has been used #100
return '^' . csv#GetColPat(a:colnr - 1,0) .
\ '\s*\zs' . a:pat . '\ze' . (a:allowmore ? '' : '$')
\ '.*\zs' . a:pat . '\ze' . (a:allowmore ? '' : '$')
else
return '\%' . b:csv_fixed_width_cols[-1] .
\ 'c\zs' . a:pat . '\ze' . (a:allowmore ? '' : '$')
@@ -504,7 +504,7 @@ fu! csv#WColumn(...) "{{{3
" Return on which column the cursor is
let _cur = getpos('.')
if !exists("b:csv_fixed_width_cols")
if line('.') > 1 && mode('') != 'n'
if line('.') > 1 && mode('') != 'n' && empty(getline('.')[0:col('.')-1])
" in insert mode, get line from above, just in case the current
" line is empty
let line = getline(line('.')-1)
@@ -1507,10 +1507,10 @@ fu! csv#AvgColumn(list) "{{{3
endfor
if has("float")
let b:csv_result = printf("%.2f", sum/cnt)
return b:csv_result
return str2float(b:csv_result)
else
let b:csv_result = printf("%s", sum/cnt)
return sum/cnt
return b:csv_result + 0
endif
endif
endfu
@@ -1543,7 +1543,7 @@ fu! csv#VarianceColumn(list, is_population) "{{{3
let cnt = cnt-1
endif
if has("float")
let b:csv_result = printf("%.2f", sum/cnt)
let b:csv_result = printf("%." . get(b:, 'csv_accuracy', get(g:, 'csv_accuracy', 2)) . "f", sum/cnt)
return b:csv_result
else
let b:csv_result = printf("%s", sum/cnt)
@@ -1956,8 +1956,12 @@ fu! csv#CheckHeaderLine() "{{{3
endfu
fu! csv#AnalyzeColumn(...) "{{{3
let maxcolnr = csv#MaxColumns()
if len(a:000) == 1
let topn = 5
if len(a:000) > 0
let colnr = a:1
if len(a:000) == 2
let topn = a:2
endif
else
let colnr = csv#WColumn()
endif
@@ -1985,8 +1989,8 @@ fu! csv#AnalyzeColumn(...) "{{{3
let max_items = reverse(sort(values(res), s:csv_numeric_sort ? 'n' : 'csv#CSVSortValues'))
" What about the minimum 5 items?
let count_items = keys(res)
if len(max_items) > 5
call remove(max_items, 5, -1)
if len(max_items) > topn
call remove(max_items, topn, -1)
call map(max_items, 'printf(''\V%s\m'', escape(v:val, ''\\''))')
call filter(res, 'v:val =~ ''^''.join(max_items, ''\|'').''$''')
endif
@@ -2263,7 +2267,7 @@ fu! csv#CommandDefinitions() "{{{3
\ ':echo csv#EvalColumn(<q-args>, "csv#SmplStdDevColumn", <line1>,<line2>)',
\ '-nargs=? -range=% -complete=custom,csv#SortComplete')
call csv#LocalCmd("PopStdCol",
\ ':echo csv#EvalColumn(<q-args>, "csv#SmplStdDevColumn", <line1>,<line2>)',
\ ':echo csv#EvalColumn(<q-args>, "csv#PopStdDevColumn", <line1>,<line2>)',
\ '-nargs=? -range=% -complete=custom,csv#SortComplete')
call csv#LocalCmd("UnArrangeColumn",
\':call csv#PrepUnArrangeCol(<line1>, <line2>)',
@@ -2311,8 +2315,8 @@ fu! csv#CommandDefinitions() "{{{3
\ '-bang -nargs=? -range=%')
call csv#LocalCmd("Filters", ':call csv#OutputFilters(<bang>0)',
\ '-nargs=0 -bang')
call csv#LocalCmd("Analyze", ':call csv#AnalyzeColumn(<args>)',
\ '-nargs=?')
call csv#LocalCmd("Analyze", ':call csv#AnalyzeColumn(<f-args>)',
\ '-nargs=*' )
call csv#LocalCmd("VertFold", ':call csv#Vertfold(<bang>0,<q-args>)',
\ '-bang -nargs=? -range=% -complete=custom,csv#SortComplete')
call csv#LocalCmd("CSVFixed", ':call csv#InitCSVFixedWidth()', '')

View File

@@ -27,12 +27,16 @@ function! s:clearQfList(reason) abort
endif
endfunction
function! dart#fmt(q_args) abort
let cmd = s:FindDartFmt()
if type(cmd) != type('') | return | endif
function! dart#fmt(...) abort
let l:dartfmt = s:FindDartFmt()
if type(l:dartfmt) != type('') | return | endif
let buffer_content = getline(1, '$')
let args = '--stdin-name '.expand('%').' '.a:q_args
let lines = systemlist(printf('%s %s', cmd, args), join(buffer_content, "\n"))
let l:cmd = [l:dartfmt, '--stdin-name', shellescape(expand('%'))]
if exists('g:dartfmt_options')
call extend(l:cmd, g:dartfmt_options)
endif
call extend(l:cmd, a:000)
let lines = systemlist(join(l:cmd), join(buffer_content, "\n"))
" TODO(https://github.com/dart-lang/sdk/issues/38507) - Remove once the
" tool no longer emits this line on SDK upgrades.
if lines[-1] ==# 'Isolate creation failed'

View File

@@ -1,25 +1,43 @@
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'fish') == -1
function! fish#Indent()
let l:shiftwidth = shiftwidth()
let l:prevlnum = prevnonblank(v:lnum - 1)
if l:prevlnum ==# 0
return 0
endif
let l:indent = 0
let l:prevline = getline(l:prevlnum)
if l:prevline =~# '\v^\s*switch>'
return indent(l:prevlnum) + l:shiftwidth
elseif l:prevline =~# '\v^\s*%(begin|if|else|while|for|function|case)>'
let l:indent = l:shiftwidth
endif
let l:line = getline(v:lnum)
if l:line =~# '\v^\s*end>'
return indent(l:prevlnum) - (l:indent ==# 0 ? l:shiftwidth : l:indent)
elseif l:line =~# '\v^\s*%(case|else)>'
return indent(l:prevlnum) - l:shiftwidth
let l:shiftwidth = shiftwidth()
let l:previndent = indent(l:prevlnum)
let l:indent = l:previndent
if l:prevline =~# '\v^\s*%(begin|if|else|while|for|function|switch|case)>'
let l:indent += l:shiftwidth
endif
return indent(l:prevlnum) + l:indent
if l:line =~# '\v^\s*end>'
let l:indent -= l:shiftwidth
" If we're inside a case, dedent twice because it ends the switch.
if l:prevline =~# '\v^\s*case>'
" Previous line starts the case.
let l:indent -= l:shiftwidth
else
" Scan back to a dedented line to find whether we're in a case.
let l:i = l:prevlnum
while l:i >= 1 && indent(l:i) >= l:previndent
let l:i = prevnonblank(l:i - 1)
endwhile
if indent(l:i) < l:previndent && getline(l:i) =~# '\v^\s*case>'
let l:indent -= l:shiftwidth
endif
endif
elseif l:line =~# '\v^\s*else>'
let l:indent -= l:shiftwidth
elseif l:prevline !~# '\v^\s*switch>' && l:line =~# '\v^\s*case>'
let l:indent -= l:shiftwidth
endif
if l:indent < 0
return 0
endif
return l:indent
endfunction
function! fish#Format()

View File

@@ -170,8 +170,8 @@ function! go#config#EchoCommandInfo() abort
endfunction
function! go#config#DocUrl() abort
let godoc_url = get(g:, 'go_doc_url', 'https://godoc.org')
if godoc_url isnot 'https://godoc.org'
let godoc_url = get(g:, 'go_doc_url', 'https://pkg.go.dev')
if godoc_url isnot 'https://pkg.go.dev'
" strip last '/' character if available
let last_char = strlen(godoc_url) - 1
if godoc_url[last_char] == '/'
@@ -266,23 +266,11 @@ function! go#config#MetalinterCommand() abort
endfunction
function! go#config#MetalinterAutosaveEnabled() abort
let l:default_enabled = ["vet", "golint"]
if go#config#MetalinterCommand() == "golangci-lint"
let l:default_enabled = ["govet", "golint"]
endif
return get(g:, "go_metalinter_autosave_enabled", default_enabled)
return get(g:, "go_metalinter_autosave_enabled", ["govet", "golint"])
endfunction
function! go#config#MetalinterEnabled() abort
let l:default_enabled = ["vet", "golint", "errcheck"]
if go#config#MetalinterCommand() == "golangci-lint"
let l:default_enabled = ["govet", "golint"]
endif
return get(g:, "go_metalinter_enabled", default_enabled)
return get(g:, "go_metalinter_enabled", ["vet", "golint", "errcheck"])
endfunction
function! go#config#GolintBin() abort
@@ -383,7 +371,7 @@ function! go#config#RenameCommand() abort
endfunction
function! go#config#GorenameBin() abort
return get(g:, "go_gorename_bin", "gorename")
return get(g:, "go_gorename_bin", "gopls")
endfunction
function! go#config#GorenamePrefill() abort
@@ -508,6 +496,10 @@ function! go#config#CodeCompletionEnabled() abort
return get(g:, "go_code_completion_enabled", 1)
endfunction
function! go#config#CodeCompletionIcase() abort
return get(g:, "go_code_completion_icase", 0)
endfunction
function! go#config#Updatetime() abort
let go_updatetime = get(g:, 'go_updatetime', 800)
return go_updatetime == 0 ? &updatetime : go_updatetime
@@ -565,7 +557,7 @@ function! go#config#DiagnosticsEnabled() abort
endfunction
function! go#config#GoplsOptions() abort
return get(g:, 'go_gopls_options', [])
return get(g:, 'go_gopls_options', ['-remote=auto'])
endfunction
" Set the default value. A value of "1" is a shortcut for this, for

View File

@@ -1,158 +0,0 @@
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
function! health#vimtex#check() abort
call vimtex#init_options()
call health#report_start('vimtex')
call s:check_general()
call s:check_plugin_clash()
call s:check_view()
call s:check_compiler()
endfunction
function! s:check_general() abort " {{{1
if !has('nvim') || v:version < 800
call health#report_warn('vimtex works best with Vim 8 or neovim')
else
call health#report_ok('Vim version should have full support!')
endif
if !executable('bibtex')
call health#report_warn('bibtex is not executable, so bibtex completions are disabled.')
endif
endfunction
" }}}1
function! s:check_compiler() abort " {{{1
if !g:vimtex_compiler_enabled | return | endif
if !executable(g:vimtex_compiler_method)
let l:ind = ' '
call health#report_error(printf(
\ '|g:vimtex_compiler_method| (`%s`) is not executable!',
\ g:vimtex_compiler_method))
return
endif
let l:ok = 1
if !executable(g:vimtex_compiler_progname)
call health#report_warn(printf(
\ '|g:vimtex_compiler_progname| (`%s`) is not executable!',
\ g:vimtex_compiler_progname))
let l:ok = 0
endif
if has('nvim')
\ && fnamemodify(g:vimtex_compiler_progname, ':t') !=# 'nvr'
call health#report_warn('Compiler callbacks will not work!', [
\ '`neovim-remote` / `nvr` is required for callbacks to work with neovim',
\ "Please also set |g:vimtex_compiler_progname| = 'nvr'",
\ 'For more info, see :help |vimtex-faq-neovim|',
\])
let l:ok = 0
endif
if l:ok
call health#report_ok('Compiler should work!')
endif
endfunction
" }}}1
function! s:check_plugin_clash() abort " {{{1
let l:scriptnames = split(execute('scriptnames'), "\n")
let l:latexbox = !empty(filter(copy(l:scriptnames), "v:val =~# 'latex-box'"))
if l:latexbox
call health#report_warn('Conflicting plugin detected: LaTeX-Box')
call health#report_info('vimtex does not work as expected when LaTeX-Box is installed!')
call health#report_info('Please disable or remove it to use vimtex!')
endif
endfunction
" }}}1
function! s:check_view() abort " {{{1
call s:check_view_{g:vimtex_view_method}()
if executable('xdotool') && !executable('pstree')
call health#report_warn('pstree is not available',
\ 'vimtex#view#reverse_goto is better if pstree is available.')
endif
endfunction
" }}}1
function! s:check_view_general() abort " {{{1
if executable(g:vimtex_view_general_viewer)
call health#report_ok('General viewer should work properly!')
else
call health#report_error(
\ 'Selected viewer is not executable!',
\ '- Selection: ' . g:vimtex_view_general_viewer,
\ '- Please see :h g:vimtex_view_general_viewer')
endif
endfunction
" }}}1
function! s:check_view_zathura() abort " {{{1
let l:ok = 1
if !executable('zathura')
call health#report_error('Zathura is not executable!')
let l:ok = 0
endif
if !executable('xdotool')
call health#report_warn('Zathura requires xdotool for forward search!')
let l:ok = 0
endif
if l:ok
call health#report_ok('Zathura should work properly!')
endif
endfunction
" }}}1
function! s:check_view_mupdf() abort " {{{1
let l:ok = 1
if !executable('mupdf')
call health#report_error('MuPDF is not executable!')
let l:ok = 0
endif
if !executable('xdotool')
call health#report_warn('MuPDF requires xdotool for forward search!')
let l:ok = 0
endif
if !executable('synctex')
call health#report_warn('MuPDF requires synctex for forward search!')
let l:ok = 0
endif
if l:ok
call health#report_ok('MuPDF should work properly!')
endif
endfunction
" }}}1
function! s:check_view_skim() abort " {{{1
let l:cmd = join([
\ 'osascript -e ',
\ '''tell application "Finder" to POSIX path of ',
\ '(get application file id (id of application "Skim") as alias)''',
\])
if system(l:cmd)
call health#report_error('Skim is not installed!')
else
call health#report_ok('Skim viewer should work!')
endif
endfunction
" }}}1
endif

129
autoload/jsonnet.vim Normal file
View File

@@ -0,0 +1,129 @@
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'jsonnet') == -1
" Options.
if !exists("g:jsonnet_command")
let g:jsonnet_command = "jsonnet"
endif
if !exists("g:jsonnet_fmt_command")
let g:jsonnet_fmt_command = "jsonnetfmt"
endif
if !exists('g:jsonnet_fmt_options')
let g:jsonnet_fmt_options = ''
endif
if !exists('g:jsonnet_fmt_fail_silently')
let g:jsonnet_fmt_fail_silently = 1
endif
" System runs a shell command. It will reset the shell to /bin/sh for Unix-like
" systems if it is executable.
function! jsonnet#System(str, ...)
let l:shell = &shell
if executable('/bin/sh')
let &shell = '/bin/sh'
endif
try
let l:output = call("system", [a:str] + a:000)
return l:output
finally
let &shell = l:shell
endtry
endfunction
" CheckBinPath checks whether the given binary exists or not and returns the
" path of the binary. It returns an empty string if it doesn't exists.
function! jsonnet#CheckBinPath(binName)
if executable(a:binName)
if exists('*exepath')
let binPath = exepath(a:binName)
return binPath
else
return a:binName
endif
else
echo "vim-jsonnet: could not find '" . a:binName . "'."
return ""
endif
endfunction
" Format calls `jsonnetfmt ... ` on the file and replaces the file with the
" auto formatted version. Does some primitive error checking of the
" jsonnetfmt command too.
function! jsonnet#Format()
" Save cursor position and many other things.
let l:curw = winsaveview()
" Write current unsaved buffer to a temp file
let l:tmpname = tempname()
call writefile(getline(1, '$'), l:tmpname)
" get the command first so we can test it
let l:binName = g:jsonnet_fmt_command
" check if the user has installed command binary.
let l:binPath = jsonnet#CheckBinPath(l:binName)
if empty(l:binPath)
return
endif
" Populate the final command.
let l:command = l:binPath
" The inplace modification is default. Makes file management easier
let l:command = l:command . ' -i '
let l:command = l:command . g:jsonnet_fmt_options
" Execute the compiled jsonnetfmt command and save the return value
let l:out = jsonnet#System(l:command . " " . l:tmpname)
let l:errorCode = v:shell_error
if l:errorCode == 0
" The format command succeeded Move the formatted temp file over the
" current file and restore other settings
" stop undo recording
try | silent undojoin | catch | endtry
let l:originalFileFormat = &fileformat
if exists("*getfperm")
" save old file permissions
let l:originalFPerm = getfperm(expand('%'))
endif
" Overwrite current file with the formatted temp file
call rename(l:tmpname, expand('%'))
if exists("*setfperm") && l:originalFPerm != ''
call setfperm(expand('%'), l:originalFPerm)
endif
" the file has been changed outside of vim, enable reedit
silent edit!
let &fileformat = l:originalFileFormat
let &syntax = &syntax
elseif g:jsonnet_fmt_fail_silently == 0
" FixMe: We could leverage the errors coming from the `jsonnetfmt` and
" give immediate feedback to the user at every save time.
" Our inspiration, vim-go, opens a new list below the current edit
" window and shows the errors (the output of the fmt command).
" We are not sure whether this is desired in the vim-jsonnet community
" or not. Nevertheless, this else block is a suitable place to benefit
" from the `jsonnetfmt` errors.
endif
" Restore our cursor/windows positions.
call winrestview(l:curw)
endfunction
endif

36
autoload/requirements.vim Normal file
View File

@@ -0,0 +1,36 @@
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'requirements') == -1
" the Requirements File Format syntax support for Vim
" Version: 1.5.3
" Author: raimon <raimon49@hotmail.com>
" License: MIT LICENSE
" The MIT License (MIT)
"
" Copyright (c) 2015 raimon
"
" Permission is hereby granted, free of charge, to any person obtaining a copy
" of this software and associated documentation files (the "Software"), to deal
" in the Software without restriction, including without limitation the rights
" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
" copies of the Software, and to permit persons to whom the Software is
" furnished to do so, subject to the following conditions:
"
" The above copyright notice and this permission notice shall be included in all
" copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
" SOFTWARE.
let s:save_cpo = &cpo
set cpo&vim
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: et sw=4 ts=4 sts=4:
endif

View File

@@ -55,6 +55,8 @@ function! terraform#commands(ArgLead, CmdLine, CursorPos) abort
\ 'graph',
\ 'import',
\ 'init',
\ 'login',
\ 'logout',
\ 'output',
\ 'plan',
\ 'providers',

View File

@@ -1,87 +0,0 @@
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
"
let s:save_cpo = &cpo
set cpo&vim
let s:source = {
\ 'name' : 'vimtex',
\ 'sorters' : 'sorter_nothing',
\ 'default_kind' : 'jump_list',
\ 'syntax' : 'uniteSource__vimtex',
\ 'entries' : [],
\ 'maxlevel' : 1,
\ 'hooks' : {},
\}
function! s:source.gather_candidates(args, context) abort " {{{1
if exists('b:vimtex')
let s:source.entries = vimtex#parser#toc()
let s:source.maxlevel = max(map(copy(s:source.entries), 'v:val.level'))
endif
return map(copy(s:source.entries),
\ 's:create_candidate(v:val, s:source.maxlevel)')
endfunction
" }}}1
function! s:source.hooks.on_syntax(args, context) abort " {{{1
syntax match VimtexTocSecs /.* @\d$/
\ contains=VimtexTocNum,VimtexTocTag,@Tex
\ contained containedin=uniteSource__vimtex
syntax match VimtexTocSec0 /.* @0$/
\ contains=VimtexTocNum,VimtexTocTag,@Tex
\ contained containedin=uniteSource__vimtex
syntax match VimtexTocSec1 /.* @1$/
\ contains=VimtexTocNum,VimtexTocTag,@Tex
\ contained containedin=uniteSource__vimtex
syntax match VimtexTocSec2 /.* @2$/
\ contains=VimtexTocNum,VimtexTocTag,@Tex
\ contained containedin=uniteSource__vimtex
syntax match VimtexTocSec3 /.* @3$/
\ contains=VimtexTocNum,VimtexTocTag,@Tex
\ contained containedin=uniteSource__vimtex
syntax match VimtexTocSec4 /.* @4$/
\ contains=VimtexTocNum,VimtexTocTag,@Tex
\ contained containedin=uniteSource__vimtex
syntax match VimtexTocNum
\ /\%69v\%(\%([A-Z]\+\>\|\d\+\)\%(\.\d\+\)*\)\?\s*@\d$/
\ contains=VimtexTocLevel
\ contained containedin=VimtexTocSec[0-9*]
syntax match VimtexTocTag
\ /\[.\]\s*@\d$/
\ contains=VimtexTocLevel
\ contained containedin=VimtexTocSec[0-9*]
syntax match VimtexTocLevel
\ /@\d$/ conceal
\ contained containedin=VimtexTocNum,VimtexTocTag
endfunction
" }}}1
function! s:create_candidate(entry, maxlevel) abort " {{{1
let level = a:maxlevel - a:entry.level
let title = printf('%-65S%-10s',
\ strpart(repeat(' ', 2*level) . a:entry.title, 0, 60),
\ b:vimtex.toc.print_number(a:entry.number))
return {
\ 'word' : title,
\ 'abbr' : title . ' @' . level,
\ 'action__path' : a:entry.file,
\ 'action__line' : get(a:entry, 'line', 0),
\ }
endfunction
" }}}1
function! unite#sources#vimtex#define() abort
return s:source
endfunction
let &cpo = s:save_cpo
endif

View File

@@ -1,705 +0,0 @@
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#init() abort " {{{1
call vimtex#init_options()
call s:init_highlights()
call s:init_state()
call s:init_buffer()
call s:init_default_mappings()
if exists('#User#VimtexEventInitPost')
doautocmd <nomodeline> User VimtexEventInitPost
endif
augroup vimtex_main
autocmd!
autocmd VimLeave * call s:quit()
augroup END
endfunction
" }}}1
function! vimtex#init_options() abort " {{{1
call s:init_option('vimtex_compiler_enabled', 1)
call s:init_option('vimtex_compiler_method', 'latexmk')
call s:init_option('vimtex_compiler_progname',
\ has('nvim') && executable('nvr')
\ ? 'nvr'
\ : get(v:, 'progpath', get(v:, 'progname', '')))
call s:init_option('vimtex_compiler_callback_hooks', [])
call s:init_option('vimtex_compiler_latexmk_engines', {})
call s:init_option('vimtex_compiler_latexrun_engines', {})
call s:init_option('vimtex_complete_enabled', 1)
call s:init_option('vimtex_complete_close_braces', 0)
call s:init_option('vimtex_complete_ignore_case', &ignorecase)
call s:init_option('vimtex_complete_smart_case', &smartcase)
call s:init_option('vimtex_complete_bib', {
\ 'simple': 0,
\ 'menu_fmt': '[@type] @author_short (@year), "@title"',
\ 'abbr_fmt': '',
\ 'custom_patterns': [],
\})
call s:init_option('vimtex_complete_ref', {
\ 'custom_patterns': [],
\})
call s:init_option('vimtex_delim_timeout', 300)
call s:init_option('vimtex_delim_insert_timeout', 60)
call s:init_option('vimtex_delim_stopline', 500)
call s:init_option('vimtex_include_search_enabled', 1)
call s:init_option('vimtex_doc_enabled', 1)
call s:init_option('vimtex_doc_handlers', [])
call s:init_option('vimtex_echo_verbose_input', 1)
call s:init_option('vimtex_env_change_autofill', 0)
if &diff
let g:vimtex_fold_enabled = 0
else
call s:init_option('vimtex_fold_enabled', 0)
endif
call s:init_option('vimtex_fold_manual', 0)
call s:init_option('vimtex_fold_levelmarker', '*')
call s:init_option('vimtex_fold_types', {})
call s:init_option('vimtex_fold_types_defaults', {
\ 'preamble' : {},
\ 'comments' : { 'enabled' : 0 },
\ 'envs' : {
\ 'blacklist' : [],
\ 'whitelist' : [],
\ },
\ 'env_options' : {},
\ 'markers' : {},
\ 'sections' : {
\ 'parse_levels' : 0,
\ 'sections' : [
\ 'part',
\ 'chapter',
\ 'section',
\ 'subsection',
\ 'subsubsection',
\ ],
\ 'parts' : [
\ 'appendix',
\ 'frontmatter',
\ 'mainmatter',
\ 'backmatter',
\ ],
\ },
\ 'cmd_single' : {
\ 'cmds' : [
\ 'hypersetup',
\ 'tikzset',
\ 'pgfplotstableread',
\ 'lstset',
\ ],
\ },
\ 'cmd_single_opt' : {
\ 'cmds' : [
\ 'usepackage',
\ 'includepdf',
\ ],
\ },
\ 'cmd_multi' : {
\ 'cmds' : [
\ '%(re)?new%(command|environment)',
\ 'providecommand',
\ 'presetkeys',
\ 'Declare%(Multi|Auto)?CiteCommand',
\ 'Declare%(Index)?%(Field|List|Name)%(Format|Alias)',
\ ],
\ },
\ 'cmd_addplot' : {
\ 'cmds' : [
\ 'addplot[+3]?',
\ ],
\ },
\})
call s:init_option('vimtex_format_enabled', 0)
call s:init_option('vimtex_imaps_enabled', 1)
call s:init_option('vimtex_imaps_disabled', [])
call s:init_option('vimtex_imaps_list', [
\ { 'lhs' : '0', 'rhs' : '\emptyset' },
\ { 'lhs' : '6', 'rhs' : '\partial' },
\ { 'lhs' : '8', 'rhs' : '\infty' },
\ { 'lhs' : '=', 'rhs' : '\equiv' },
\ { 'lhs' : '\', 'rhs' : '\setminus' },
\ { 'lhs' : '.', 'rhs' : '\cdot' },
\ { 'lhs' : '*', 'rhs' : '\times' },
\ { 'lhs' : '<', 'rhs' : '\langle' },
\ { 'lhs' : '>', 'rhs' : '\rangle' },
\ { 'lhs' : 'H', 'rhs' : '\hbar' },
\ { 'lhs' : '+', 'rhs' : '\dagger' },
\ { 'lhs' : '[', 'rhs' : '\subseteq' },
\ { 'lhs' : ']', 'rhs' : '\supseteq' },
\ { 'lhs' : '(', 'rhs' : '\subset' },
\ { 'lhs' : ')', 'rhs' : '\supset' },
\ { 'lhs' : 'A', 'rhs' : '\forall' },
\ { 'lhs' : 'E', 'rhs' : '\exists' },
\ { 'lhs' : 'jj', 'rhs' : '\downarrow' },
\ { 'lhs' : 'jJ', 'rhs' : '\Downarrow' },
\ { 'lhs' : 'jk', 'rhs' : '\uparrow' },
\ { 'lhs' : 'jK', 'rhs' : '\Uparrow' },
\ { 'lhs' : 'jh', 'rhs' : '\leftarrow' },
\ { 'lhs' : 'jH', 'rhs' : '\Leftarrow' },
\ { 'lhs' : 'jl', 'rhs' : '\rightarrow' },
\ { 'lhs' : 'jL', 'rhs' : '\Rightarrow' },
\ { 'lhs' : 'a', 'rhs' : '\alpha' },
\ { 'lhs' : 'b', 'rhs' : '\beta' },
\ { 'lhs' : 'c', 'rhs' : '\chi' },
\ { 'lhs' : 'd', 'rhs' : '\delta' },
\ { 'lhs' : 'e', 'rhs' : '\epsilon' },
\ { 'lhs' : 'f', 'rhs' : '\phi' },
\ { 'lhs' : 'g', 'rhs' : '\gamma' },
\ { 'lhs' : 'h', 'rhs' : '\eta' },
\ { 'lhs' : 'i', 'rhs' : '\iota' },
\ { 'lhs' : 'k', 'rhs' : '\kappa' },
\ { 'lhs' : 'l', 'rhs' : '\lambda' },
\ { 'lhs' : 'm', 'rhs' : '\mu' },
\ { 'lhs' : 'n', 'rhs' : '\nu' },
\ { 'lhs' : 'p', 'rhs' : '\pi' },
\ { 'lhs' : 'q', 'rhs' : '\theta' },
\ { 'lhs' : 'r', 'rhs' : '\rho' },
\ { 'lhs' : 's', 'rhs' : '\sigma' },
\ { 'lhs' : 't', 'rhs' : '\tau' },
\ { 'lhs' : 'y', 'rhs' : '\psi' },
\ { 'lhs' : 'u', 'rhs' : '\upsilon' },
\ { 'lhs' : 'w', 'rhs' : '\omega' },
\ { 'lhs' : 'z', 'rhs' : '\zeta' },
\ { 'lhs' : 'x', 'rhs' : '\xi' },
\ { 'lhs' : 'G', 'rhs' : '\Gamma' },
\ { 'lhs' : 'D', 'rhs' : '\Delta' },
\ { 'lhs' : 'F', 'rhs' : '\Phi' },
\ { 'lhs' : 'G', 'rhs' : '\Gamma' },
\ { 'lhs' : 'L', 'rhs' : '\Lambda' },
\ { 'lhs' : 'P', 'rhs' : '\Pi' },
\ { 'lhs' : 'Q', 'rhs' : '\Theta' },
\ { 'lhs' : 'S', 'rhs' : '\Sigma' },
\ { 'lhs' : 'U', 'rhs' : '\Upsilon' },
\ { 'lhs' : 'W', 'rhs' : '\Omega' },
\ { 'lhs' : 'X', 'rhs' : '\Xi' },
\ { 'lhs' : 'Y', 'rhs' : '\Psi' },
\ { 'lhs' : 've', 'rhs' : '\varepsilon' },
\ { 'lhs' : 'vf', 'rhs' : '\varphi' },
\ { 'lhs' : 'vk', 'rhs' : '\varkappa' },
\ { 'lhs' : 'vq', 'rhs' : '\vartheta' },
\ { 'lhs' : 'vr', 'rhs' : '\varrho' },
\ { 'lhs' : '/', 'rhs' : 'vimtex#imaps#style_math("slashed")', 'expr' : 1, 'leader' : '#'},
\ { 'lhs' : 'b', 'rhs' : 'vimtex#imaps#style_math("mathbf")', 'expr' : 1, 'leader' : '#'},
\ { 'lhs' : 'f', 'rhs' : 'vimtex#imaps#style_math("mathfrak")', 'expr' : 1, 'leader' : '#'},
\ { 'lhs' : 'c', 'rhs' : 'vimtex#imaps#style_math("mathcal")', 'expr' : 1, 'leader' : '#'},
\ { 'lhs' : '-', 'rhs' : 'vimtex#imaps#style_math("overline")', 'expr' : 1, 'leader' : '#'},
\ { 'lhs' : 'B', 'rhs' : 'vimtex#imaps#style_math("mathbb")', 'expr' : 1, 'leader' : '#'},
\])
call s:init_option('vimtex_mappings_enabled', 1)
call s:init_option('vimtex_mappings_disable', {})
call s:init_option('vimtex_matchparen_enabled', 1)
call s:init_option('vimtex_motion_enabled', 1)
call s:init_option('vimtex_labels_enabled', 1)
call s:init_option('vimtex_labels_refresh_always', 1)
call s:init_option('vimtex_parser_bib_backend', 'bibtex')
call s:init_option('vimtex_quickfix_enabled', 1)
call s:init_option('vimtex_quickfix_method', 'latexlog')
call s:init_option('vimtex_quickfix_autojump', '0')
call s:init_option('vimtex_quickfix_ignore_filters', [])
call s:init_option('vimtex_quickfix_mode', '2')
call s:init_option('vimtex_quickfix_open_on_warning', '1')
call s:init_option('vimtex_quickfix_blgparser', {})
call s:init_option('vimtex_quickfix_autoclose_after_keystrokes', '0')
call s:init_option('vimtex_syntax_enabled', 1)
call s:init_option('vimtex_syntax_nested', {
\ 'aliases' : {
\ 'C' : 'c',
\ 'csharp' : 'cs',
\ },
\ 'ignored' : {
\ 'cs' : [
\ 'csBraces',
\ ],
\ 'python' : [
\ 'pythonEscape',
\ 'pythonBEscape',
\ 'pythonBytesEscape',
\ ],
\ 'java' : [
\ 'javaError',
\ ],
\ 'haskell' : [
\ 'hsVarSym',
\ ],
\ }
\})
call s:init_option('vimtex_syntax_autoload_packages', ['amsmath'])
call s:init_option('vimtex_texcount_custom_arg', '')
call s:init_option('vimtex_text_obj_enabled', 1)
call s:init_option('vimtex_text_obj_variant', 'auto')
call s:init_option('vimtex_text_obj_linewise_operators', ['d', 'y'])
call s:init_option('vimtex_toc_enabled', 1)
call s:init_option('vimtex_toc_custom_matchers', [])
call s:init_option('vimtex_toc_show_preamble', 1)
call s:init_option('vimtex_toc_todo_labels', {
\ 'TODO': 'TODO: ',
\ 'FIXME': 'FIXME: '
\})
call s:init_option('vimtex_toc_config', {
\ 'name' : 'Table of contents (vimtex)',
\ 'mode' : 1,
\ 'fold_enable' : 0,
\ 'fold_level_start' : -1,
\ 'hide_line_numbers' : 1,
\ 'hotkeys_enabled' : 0,
\ 'hotkeys' : 'abcdeilmnopuvxyz',
\ 'hotkeys_leader' : ';',
\ 'layer_status' : {
\ 'content': 1,
\ 'label': 1,
\ 'todo': 1,
\ 'include': 1,
\ },
\ 'layer_keys' : {
\ 'content': 'C',
\ 'label': 'L',
\ 'todo': 'T',
\ 'include': 'I',
\ },
\ 'resize' : 0,
\ 'refresh_always' : 1,
\ 'show_help' : 1,
\ 'show_numbers' : 1,
\ 'split_pos' : 'vert leftabove',
\ 'split_width' : 30,
\ 'tocdepth' : 3,
\ 'todo_sorted' : 1,
\})
call s:init_option('vimtex_view_enabled', 1)
call s:init_option('vimtex_view_automatic', 1)
call s:init_option('vimtex_view_method', 'general')
call s:init_option('vimtex_view_use_temp_files', 0)
call s:init_option('vimtex_view_forward_search_on_start', 1)
" OS dependent defaults
let l:os = vimtex#util#get_os()
if l:os ==# 'win'
if executable('SumatraPDF')
call s:init_option('vimtex_view_general_viewer', 'SumatraPDF')
call s:init_option('vimtex_view_general_options',
\ '-reuse-instance -forward-search @tex @line @pdf')
call s:init_option('vimtex_view_general_options_latexmk',
\ 'reuse-instance')
elseif executable('mupdf')
call s:init_option('vimtex_view_general_viewer', 'mupdf')
else
call s:init_option('vimtex_view_general_viewer', '')
endif
else
call s:init_option('vimtex_view_general_viewer', get({
\ 'linux' : 'xdg-open',
\ 'mac' : 'open',
\ 'win' : 'start',
\}, l:os, ''))
call s:init_option('vimtex_view_general_options', '@pdf')
call s:init_option('vimtex_view_general_options_latexmk', '')
endif
call s:init_option('vimtex_view_mupdf_options', '')
call s:init_option('vimtex_view_mupdf_send_keys', '')
call s:init_option('vimtex_view_skim_activate', 0)
call s:init_option('vimtex_view_skim_reading_bar', 1)
call s:init_option('vimtex_view_zathura_options', '')
call s:init_option('vimtex_view_zathura_check_libsynctex', 1)
endfunction
" }}}1
function! vimtex#check_plugin_clash() abort " {{{1
let l:scriptnames = vimtex#util#command('scriptnames')
let l:latexbox = !empty(filter(copy(l:scriptnames), "v:val =~# 'latex-box'"))
if l:latexbox
call vimtex#log#warning([
\ 'Conflicting plugin detected: LaTeX-Box',
\ 'vimtex does not work as expected when LaTeX-Box is installed!',
\ 'Please disable or remove it to use vimtex!',
\])
endif
endfunction
" }}}1
function! s:init_option(option, default) abort " {{{1
let l:option = 'g:' . a:option
if !exists(l:option)
let {l:option} = a:default
elseif type(a:default) == type({})
call vimtex#util#extend_recursive({l:option}, a:default, 'keep')
endif
endfunction
" }}}1
function! s:init_highlights() abort " {{{1
for [l:name, l:target] in [
\ ['VimtexImapsArrow', 'Comment'],
\ ['VimtexImapsLhs', 'ModeMsg'],
\ ['VimtexImapsRhs', 'ModeMsg'],
\ ['VimtexImapsWrapper', 'Type'],
\ ['VimtexInfo', 'Question'],
\ ['VimtexInfoTitle', 'PreProc'],
\ ['VimtexInfoKey', 'PreProc'],
\ ['VimtexInfoValue', 'Statement'],
\ ['VimtexInfoOther', 'Normal'],
\ ['VimtexMsg', 'ModeMsg'],
\ ['VimtexSuccess', 'Statement'],
\ ['VimtexTocHelp', 'helpVim'],
\ ['VimtexTocHelpKey', 'ModeMsg'],
\ ['VimtexTocHelpLayerOn', 'Statement'],
\ ['VimtexTocHelpLayerOff', 'Comment'],
\ ['VimtexTocTodo', 'Todo'],
\ ['VimtexTocNum', 'Number'],
\ ['VimtexTocSec0', 'Title'],
\ ['VimtexTocSec1', 'Normal'],
\ ['VimtexTocSec2', 'helpVim'],
\ ['VimtexTocSec3', 'NonText'],
\ ['VimtexTocSec4', 'Comment'],
\ ['VimtexTocHotkey', 'Comment'],
\ ['VimtexTocLabelsSecs', 'Statement'],
\ ['VimtexTocLabelsEq', 'PreProc'],
\ ['VimtexTocLabelsFig', 'Identifier'],
\ ['VimtexTocLabelsTab', 'String'],
\ ['VimtexTocIncl', 'Number'],
\ ['VimtexTocInclPath', 'Normal'],
\ ['VimtexWarning', 'WarningMsg'],
\ ['VimtexError', 'ErrorMsg'],
\]
if !hlexists(l:name)
silent execute 'highlight default link' l:name l:target
endif
endfor
endfunction
" }}}1
function! s:init_state() abort " {{{1
call vimtex#state#init()
call vimtex#state#init_local()
endfunction
" }}}1
function! s:init_buffer() abort " {{{1
" Set Vim options
for l:suf in [
\ '.sty',
\ '.cls',
\ '.log',
\ '.aux',
\ '.bbl',
\ '.out',
\ '.blg',
\ '.brf',
\ '.cb',
\ '.dvi',
\ '.fdb_latexmk',
\ '.fls',
\ '.idx',
\ '.ilg',
\ '.ind',
\ '.inx',
\ '.pdf',
\ '.synctex.gz',
\ '.toc',
\ ]
execute 'set suffixes+=' . l:suf
endfor
setlocal suffixesadd=.sty,.tex,.cls
setlocal comments=sO:%\ -,mO:%\ \ ,eO:%%,:%
setlocal commentstring=%%s
setlocal iskeyword+=:
setlocal includeexpr=vimtex#include#expr()
let &l:include = g:vimtex#re#tex_include
let &l:define = '\\\([egx]\|char\|mathchar\|count\|dimen\|muskip\|skip'
let &l:define .= '\|toks\)\=def\|\\font\|\\\(future\)\=let'
let &l:define .= '\|\\new\(count\|dimen\|skip'
let &l:define .= '\|muskip\|box\|toks\|read\|write\|fam\|insert\)'
let &l:define .= '\|\\\(re\)\=new\(boolean\|command\|counter\|environment'
let &l:define .= '\|font\|if\|length\|savebox'
let &l:define .= '\|theorem\(style\)\=\)\s*\*\=\s*{\='
let &l:define .= '\|DeclareMathOperator\s*{\=\s*'
" Define autocommands
augroup vimtex_buffers
autocmd! * <buffer>
autocmd BufFilePre <buffer> call s:filename_changed_pre()
autocmd BufFilePost <buffer> call s:filename_changed_post()
autocmd BufUnload <buffer> call s:buffer_deleted('unload')
autocmd BufWipeout <buffer> call s:buffer_deleted('wipe')
augroup END
" Initialize buffer settings for sub modules
for l:mod in s:modules
if index(get(b:vimtex, 'disabled_modules', []), l:mod) >= 0 | continue | endif
try
call vimtex#{l:mod}#init_buffer()
catch /E117.*#init_/
catch /E127.*vimtex#profile#/
endtry
endfor
endfunction
" }}}1
function! s:init_default_mappings() abort " {{{1
if !g:vimtex_mappings_enabled | return | endif
function! s:map(mode, lhs, rhs, ...) abort
if !hasmapto(a:rhs, a:mode)
\ && index(get(g:vimtex_mappings_disable, a:mode, []), a:lhs) < 0
\ && (empty(maparg(a:lhs, a:mode)) || a:0 > 0)
silent execute a:mode . 'map <silent><nowait><buffer>' a:lhs a:rhs
endif
endfunction
call s:map('n', '<localleader>li', '<plug>(vimtex-info)')
call s:map('n', '<localleader>lI', '<plug>(vimtex-info-full)')
call s:map('n', '<localleader>lx', '<plug>(vimtex-reload)')
call s:map('n', '<localleader>lX', '<plug>(vimtex-reload-state)')
call s:map('n', '<localleader>ls', '<plug>(vimtex-toggle-main)')
call s:map('n', '<localleader>lq', '<plug>(vimtex-log)')
call s:map('n', 'ds$', '<plug>(vimtex-env-delete-math)')
call s:map('n', 'cs$', '<plug>(vimtex-env-change-math)')
call s:map('n', 'dse', '<plug>(vimtex-env-delete)')
call s:map('n', 'cse', '<plug>(vimtex-env-change)')
call s:map('n', 'tse', '<plug>(vimtex-env-toggle-star)')
call s:map('n', 'dsc', '<plug>(vimtex-cmd-delete)')
call s:map('n', 'csc', '<plug>(vimtex-cmd-change)')
call s:map('n', 'tsc', '<plug>(vimtex-cmd-toggle-star)')
call s:map('n', 'tsf', '<plug>(vimtex-cmd-toggle-frac)')
call s:map('x', 'tsf', '<plug>(vimtex-cmd-toggle-frac)')
call s:map('i', '<F7>', '<plug>(vimtex-cmd-create)')
call s:map('n', '<F7>', '<plug>(vimtex-cmd-create)')
call s:map('x', '<F7>', '<plug>(vimtex-cmd-create)')
call s:map('n', 'dsd', '<plug>(vimtex-delim-delete)')
call s:map('n', 'csd', '<plug>(vimtex-delim-change-math)')
call s:map('n', 'tsd', '<plug>(vimtex-delim-toggle-modifier)')
call s:map('x', 'tsd', '<plug>(vimtex-delim-toggle-modifier)')
call s:map('n', 'tsD', '<plug>(vimtex-delim-toggle-modifier-reverse)')
call s:map('x', 'tsD', '<plug>(vimtex-delim-toggle-modifier-reverse)')
call s:map('i', ']]', '<plug>(vimtex-delim-close)')
if g:vimtex_compiler_enabled
call s:map('n', '<localleader>ll', '<plug>(vimtex-compile)')
call s:map('n', '<localleader>lo', '<plug>(vimtex-compile-output)')
call s:map('n', '<localleader>lL', '<plug>(vimtex-compile-selected)')
call s:map('x', '<localleader>lL', '<plug>(vimtex-compile-selected)')
call s:map('n', '<localleader>lk', '<plug>(vimtex-stop)')
call s:map('n', '<localleader>lK', '<plug>(vimtex-stop-all)')
call s:map('n', '<localleader>le', '<plug>(vimtex-errors)')
call s:map('n', '<localleader>lc', '<plug>(vimtex-clean)')
call s:map('n', '<localleader>lC', '<plug>(vimtex-clean-full)')
call s:map('n', '<localleader>lg', '<plug>(vimtex-status)')
call s:map('n', '<localleader>lG', '<plug>(vimtex-status-all)')
endif
if g:vimtex_motion_enabled
" These are forced in order to overwrite matchit mappings
call s:map('n', '%', '<plug>(vimtex-%)', 1)
call s:map('x', '%', '<plug>(vimtex-%)', 1)
call s:map('o', '%', '<plug>(vimtex-%)', 1)
call s:map('n', ']]', '<plug>(vimtex-]])')
call s:map('n', '][', '<plug>(vimtex-][)')
call s:map('n', '[]', '<plug>(vimtex-[])')
call s:map('n', '[[', '<plug>(vimtex-[[)')
call s:map('x', ']]', '<plug>(vimtex-]])')
call s:map('x', '][', '<plug>(vimtex-][)')
call s:map('x', '[]', '<plug>(vimtex-[])')
call s:map('x', '[[', '<plug>(vimtex-[[)')
call s:map('o', ']]', '<plug>(vimtex-]])')
call s:map('o', '][', '<plug>(vimtex-][)')
call s:map('o', '[]', '<plug>(vimtex-[])')
call s:map('o', '[[', '<plug>(vimtex-[[)')
call s:map('n', ']M', '<plug>(vimtex-]M)')
call s:map('n', ']m', '<plug>(vimtex-]m)')
call s:map('n', '[M', '<plug>(vimtex-[M)')
call s:map('n', '[m', '<plug>(vimtex-[m)')
call s:map('x', ']M', '<plug>(vimtex-]M)')
call s:map('x', ']m', '<plug>(vimtex-]m)')
call s:map('x', '[M', '<plug>(vimtex-[M)')
call s:map('x', '[m', '<plug>(vimtex-[m)')
call s:map('o', ']M', '<plug>(vimtex-]M)')
call s:map('o', ']m', '<plug>(vimtex-]m)')
call s:map('o', '[M', '<plug>(vimtex-[M)')
call s:map('o', '[m', '<plug>(vimtex-[m)')
call s:map('n', ']/', '<plug>(vimtex-]/)')
call s:map('n', ']*', '<plug>(vimtex-]*)')
call s:map('n', '[/', '<plug>(vimtex-[/)')
call s:map('n', '[*', '<plug>(vimtex-[*)')
call s:map('x', ']/', '<plug>(vimtex-]/)')
call s:map('x', ']*', '<plug>(vimtex-]*)')
call s:map('x', '[/', '<plug>(vimtex-[/)')
call s:map('x', '[*', '<plug>(vimtex-[*)')
call s:map('o', ']/', '<plug>(vimtex-]/)')
call s:map('o', ']*', '<plug>(vimtex-]*)')
call s:map('o', '[/', '<plug>(vimtex-[/)')
call s:map('o', '[*', '<plug>(vimtex-[*)')
endif
if g:vimtex_text_obj_enabled
call s:map('x', 'id', '<plug>(vimtex-id)')
call s:map('x', 'ad', '<plug>(vimtex-ad)')
call s:map('o', 'id', '<plug>(vimtex-id)')
call s:map('o', 'ad', '<plug>(vimtex-ad)')
call s:map('x', 'i$', '<plug>(vimtex-i$)')
call s:map('x', 'a$', '<plug>(vimtex-a$)')
call s:map('o', 'i$', '<plug>(vimtex-i$)')
call s:map('o', 'a$', '<plug>(vimtex-a$)')
call s:map('x', 'iP', '<plug>(vimtex-iP)')
call s:map('x', 'aP', '<plug>(vimtex-aP)')
call s:map('o', 'iP', '<plug>(vimtex-iP)')
call s:map('o', 'aP', '<plug>(vimtex-aP)')
call s:map('x', 'im', '<plug>(vimtex-im)')
call s:map('x', 'am', '<plug>(vimtex-am)')
call s:map('o', 'im', '<plug>(vimtex-im)')
call s:map('o', 'am', '<plug>(vimtex-am)')
if vimtex#text_obj#targets#enabled()
call vimtex#text_obj#targets#init()
" These are handled explicitly to avoid conflict with gitgutter
call s:map('x', 'ic', '<plug>(vimtex-targets-i)c')
call s:map('x', 'ac', '<plug>(vimtex-targets-a)c')
call s:map('o', 'ic', '<plug>(vimtex-targets-i)c')
call s:map('o', 'ac', '<plug>(vimtex-targets-a)c')
else
if g:vimtex_text_obj_variant ==# 'targets'
call vimtex#log#warning(
\ "Ignoring g:vimtex_text_obj_variant = 'targets'"
\ . " because 'g:loaded_targets' does not exist or is 0.")
endif
let g:vimtex_text_obj_variant = 'vimtex'
call s:map('x', 'ie', '<plug>(vimtex-ie)')
call s:map('x', 'ae', '<plug>(vimtex-ae)')
call s:map('o', 'ie', '<plug>(vimtex-ie)')
call s:map('o', 'ae', '<plug>(vimtex-ae)')
call s:map('x', 'ic', '<plug>(vimtex-ic)')
call s:map('x', 'ac', '<plug>(vimtex-ac)')
call s:map('o', 'ic', '<plug>(vimtex-ic)')
call s:map('o', 'ac', '<plug>(vimtex-ac)')
endif
endif
if g:vimtex_toc_enabled
call s:map('n', '<localleader>lt', '<plug>(vimtex-toc-open)')
call s:map('n', '<localleader>lT', '<plug>(vimtex-toc-toggle)')
endif
if has_key(b:vimtex, 'viewer')
call s:map('n', '<localleader>lv', '<plug>(vimtex-view)')
if has_key(b:vimtex.viewer, 'reverse_search')
call s:map('n', '<localleader>lr', '<plug>(vimtex-reverse-search)')
endif
endif
if g:vimtex_imaps_enabled
call s:map('n', '<localleader>lm', '<plug>(vimtex-imaps-list)')
endif
if g:vimtex_doc_enabled
call s:map('n', 'K', '<plug>(vimtex-doc-package)')
endif
endfunction
" }}}1
function! s:filename_changed_pre() abort " {{{1
let s:filename_changed = expand('%:p') ==# b:vimtex.tex
endfunction
" }}}1
function! s:filename_changed_post() abort " {{{1
if s:filename_changed
let l:base_old = b:vimtex.base
let b:vimtex.tex = fnamemodify(expand('%'), ':p')
let b:vimtex.base = fnamemodify(b:vimtex.tex, ':t')
let b:vimtex.name = fnamemodify(b:vimtex.tex, ':t:r')
call vimtex#log#warning('Filename change detected')
call vimtex#log#info('Old filename: ' . l:base_old)
call vimtex#log#info('New filename: ' . b:vimtex.base)
if has_key(b:vimtex, 'compiler')
if b:vimtex.compiler.is_running()
call vimtex#log#warning('Compilation stopped!')
call vimtex#compiler#stop()
endif
let b:vimtex.compiler.target = b:vimtex.base
let b:vimtex.compiler.target_path = b:vimtex.tex
endif
endif
endfunction
" }}}1
function! s:buffer_deleted(reason) abort " {{{1
"
" We need a simple cache of buffer ids because a buffer unload might clear
" buffer variables, so that a subsequent buffer wipe will not trigger a full
" cleanup. By caching the buffer id, we should avoid this issue.
"
let s:buffer_cache = get(s:, 'buffer_cache', {})
let l:file = expand('<afile>')
if !has_key(s:buffer_cache, l:file)
let s:buffer_cache[l:file] = getbufvar(l:file, 'vimtex_id', -1)
endif
if a:reason ==# 'wipe'
call vimtex#state#cleanup(s:buffer_cache[l:file])
call remove(s:buffer_cache, l:file)
endif
endfunction
" }}}1
function! s:quit() abort " {{{1
for l:state in vimtex#state#list_all()
call l:state.cleanup()
endfor
call vimtex#cache#write_all()
endfunction
" }}}1
" {{{1 Initialize module
let s:modules = map(
\ glob(fnamemodify(expand('<sfile>'), ':r') . '/*.vim', 0, 1),
\ 'fnamemodify(v:val, '':t:r'')')
" }}}1
endif

View File

@@ -1,179 +0,0 @@
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#cache#open(name, ...) abort " {{{1
let l:opts = a:0 > 0 ? a:1 : {}
let l:name = get(l:opts, 'local') ? s:local_name(a:name) : a:name
let s:caches = get(s:, 'caches', {})
if has_key(s:caches, l:name)
return s:caches[l:name]
endif
let s:caches[l:name] = s:cache.init(l:name, l:opts)
return s:caches[l:name]
endfunction
" }}}1
function! vimtex#cache#close(name) abort " {{{1
let s:caches = get(s:, 'caches', {})
" Try global name first, then local name
let l:name = a:name
if !has_key(s:caches, l:name)
let l:name = s:local_name(l:name)
endif
if !has_key(s:caches, l:name) | return | endif
let l:cache = s:caches[l:name]
call l:cache.write()
unlet s:caches[l:name]
endfunction
" }}}1
function! vimtex#cache#wrap(Func, name, ...) abort " {{{1
if !has('lambda')
throw 'error: vimtex#cache#wrap requires +lambda'
endif
let l:opts = a:0 > 0 ? a:1 : {}
let l:cache = vimtex#cache#open(a:name, l:opts)
function! CachedFunc(key) closure
if l:cache.has(a:key)
return l:cache.get(a:key)
else
return l:cache.set(a:key, a:Func(a:key))
endif
endfunction
return function('CachedFunc')
endfunction
" }}}1
function! vimtex#cache#clear(name, local) abort " {{{1
let l:cache = vimtex#cache#open(a:name, {'local': a:local})
call l:cache.read()
if !empty(l:cache.data)
let l:cache.data = {}
call l:cache.write()
endif
endfunction
" }}}1
function! vimtex#cache#write_all() abort " {{{1
for l:cache in values(get(s:, 'caches', {}))
call l:cache.write()
endfor
endfunction
" }}}1
let s:cache = {}
function! s:cache.init(name, opts) dict abort " {{{1
let new = deepcopy(self)
unlet new.init
let l:root = get(g:, 'vimtex_cache_root', $HOME . '/.cache/vimtex')
if !isdirectory(l:root)
call mkdir(l:root, 'p')
endif
let new.name = a:name
let new.path = l:root . '/' . a:name . '.json'
let new.local = get(a:opts, 'local')
let new.persistent = get(a:opts, 'persistent',
\ get(g:, 'vimtex_cache_persistent', 1))
if has_key(a:opts, 'default')
let new.default = a:opts.default
endif
let new.data = {}
let new.ftime = -1
let new.modified = 0
return new
endfunction
" }}}1
function! s:cache.get(key) dict abort " {{{1
call self.read()
if has_key(self, 'default') && !has_key(self.data, a:key)
let self.data[a:key] = deepcopy(self.default)
endif
return get(self.data, a:key)
endfunction
" }}}1
function! s:cache.has(key) dict abort " {{{1
call self.read()
return has_key(self.data, a:key)
endfunction
" }}}1
function! s:cache.set(key, value) dict abort " {{{1
call self.read()
let self.data[a:key] = a:value
let self.modified = 1
call self.write()
return a:value
endfunction
" }}}1
function! s:cache.write() dict abort " {{{1
if !self.persistent
let self.modified = 0
return
endif
if !self.modified | return | endif
call self.read()
call writefile([json_encode(self.data)], self.path)
let self.ftime = getftime(self.path)
let self.modified = 0
endfunction
" }}}1
function! s:cache.read() dict abort " {{{1
if !self.persistent | return | endif
if getftime(self.path) > self.ftime
let self.ftime = getftime(self.path)
call extend(self.data,
\ json_decode(join(readfile(self.path))), 'keep')
endif
endfunction
" }}}1
"
" Utility functions
"
function! s:local_name(name) abort " {{{1
let l:filename = exists('b:vimtex.tex')
\ ? fnamemodify(b:vimtex.tex, ':r')
\ : expand('%:p:r')
let l:filename = substitute(l:filename, '\s\+', '_', 'g')
let l:filename = substitute(l:filename, '\/', '%', 'g')
let l:filename = substitute(l:filename, '\\', '%', 'g')
let l:filename = substitute(l:filename, ':', '%', 'g')
return a:name . l:filename
endfunction
" }}}1
endif

View File

@@ -1,718 +0,0 @@
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#cmd#init_buffer() abort " {{{1
nnoremap <silent><buffer> <plug>(vimtex-cmd-delete)
\ :<c-u>call <sid>operator_setup('delete')<bar>normal! g@l<cr>
nnoremap <silent><buffer> <plug>(vimtex-cmd-change)
\ :<c-u>call <sid>operator_setup('change')<bar>normal! g@l<cr>
inoremap <silent><buffer> <plug>(vimtex-cmd-create)
\ <c-r>=vimtex#cmd#create_insert()<cr>
nnoremap <silent><buffer> <plug>(vimtex-cmd-create)
\ :<c-u>call <sid>operator_setup('create')<bar>normal! g@l<cr>
xnoremap <silent><buffer> <plug>(vimtex-cmd-create)
\ :<c-u>call vimtex#cmd#create_visual()<cr>
nnoremap <silent><buffer> <plug>(vimtex-cmd-toggle-star)
\ :<c-u>call <sid>operator_setup('toggle_star')<bar>normal! g@l<cr>
nnoremap <silent><buffer> <plug>(vimtex-cmd-toggle-frac)
\ :<c-u>call <sid>operator_setup('toggle_frac')<bar>normal! g@l<cr>
xnoremap <silent><buffer> <plug>(vimtex-cmd-toggle-frac)
\ :<c-u>call vimtex#cmd#toggle_frac_visual()<cr>
endfunction
" }}}1
function! vimtex#cmd#change(new_name) abort " {{{1
let l:cmd = vimtex#cmd#get_current()
if empty(l:cmd) | return | endif
let l:old_name = l:cmd.name
let l:lnum = l:cmd.pos_start.lnum
let l:cnum = l:cmd.pos_start.cnum
" Get new command name
let l:new_name = substitute(a:new_name, '^\\', '', '')
if empty(l:new_name) | return | endif
" Update current position
let l:save_pos = vimtex#pos#get_cursor()
if strlen(l:new_name) < strlen(l:old_name)
let l:col = searchpos('\\\k', 'bcnW')[1] + strlen(l:new_name)
if l:col < l:save_pos[2]
let l:save_pos[2] = l:col
endif
endif
" Perform the change
let l:line = getline(l:lnum)
call setline(l:lnum,
\ strpart(l:line, 0, l:cnum)
\ . l:new_name
\ . strpart(l:line, l:cnum + strlen(l:old_name) - 1))
" Restore cursor position
cal vimtex#pos#set_cursor(l:save_pos)
endfunction
function! vimtex#cmd#delete(...) abort " {{{1
if a:0 > 0
let l:cmd = call('vimtex#cmd#get_at', a:000)
else
let l:cmd = vimtex#cmd#get_current()
endif
if empty(l:cmd) | return | endif
" Save current position
let l:save_pos = vimtex#pos#get_cursor()
let l:lnum_cur = l:save_pos[1]
let l:cnum_cur = l:save_pos[2]
" Remove closing bracket (if exactly one argument)
if len(l:cmd.args) == 1
let l:lnum = l:cmd.args[0].close.lnum
let l:cnum = l:cmd.args[0].close.cnum
let l:line = getline(l:lnum)
call setline(l:lnum,
\ strpart(l:line, 0, l:cnum - 1)
\ . strpart(l:line, l:cnum))
let l:cnum2 = l:cmd.args[0].open.cnum
endif
" Remove command (and possibly the opening bracket)
let l:lnum = l:cmd.pos_start.lnum
let l:cnum = l:cmd.pos_start.cnum
let l:cnum2 = get(l:, 'cnum2', l:cnum + strlen(l:cmd.name) - 1)
let l:line = getline(l:lnum)
call setline(l:lnum,
\ strpart(l:line, 0, l:cnum - 1)
\ . strpart(l:line, l:cnum2))
" Restore appropriate cursor position
if l:lnum_cur == l:lnum
if l:cnum_cur > l:cnum2
let l:save_pos[2] -= l:cnum2 - l:cnum + 1
else
let l:save_pos[2] -= l:cnum_cur - l:cnum
endif
endif
cal vimtex#pos#set_cursor(l:save_pos)
endfunction
function! vimtex#cmd#delete_all(...) abort " {{{1
if a:0 > 0
let l:cmd = call('vimtex#cmd#get_at', a:000)
else
let l:cmd = vimtex#cmd#get_current()
endif
if empty(l:cmd) | return | endif
call vimtex#pos#set_cursor(l:cmd.pos_start)
normal! v
call vimtex#pos#set_cursor(l:cmd.pos_end)
normal! d
endfunction
function! vimtex#cmd#create_insert() abort " {{{1
if mode() !=# 'i' | return | endif
let l:re = '\v%(^|\A)\zs\a+\ze%(\A|$)'
let l:c0 = col('.') - 1
let [l:l1, l:c1] = searchpos(l:re, 'bcn', line('.'))
let l:c1 -= 1
let l:line = getline(l:l1)
let l:match = matchstr(l:line, l:re, l:c1)
let l:c2 = l:c1 + strlen(l:match)
if l:c0 > l:c2
call vimtex#log#warning('Could not create command')
return ''
endif
let l:strpart1 = strpart(l:line, 0, l:c1)
let l:strpart2 = '\' . strpart(l:match, 0, l:c0 - l:c1) . '{'
let l:strpart3 = strpart(l:line, l:c0)
call setline(l:l1, l:strpart1 . l:strpart2 . l:strpart3)
call vimtex#pos#set_cursor(l:l1, l:c2+3)
return ''
endfunction
" }}}1
function! vimtex#cmd#create(cmd, visualmode) abort " {{{1
if empty(a:cmd) | return | endif
" Avoid autoindent (disable indentkeys)
let l:save_indentkeys = &l:indentkeys
setlocal indentkeys=
if a:visualmode
let l:pos_start = getpos("'<")
let l:pos_end = getpos("'>")
if visualmode() ==# ''
normal! gvA}
execute 'normal! gvI\' . a:cmd . '{'
let l:pos_end[2] += strlen(a:cmd) + 3
else
normal! `>a}
normal! `<
execute 'normal! i\' . a:cmd . '{'
let l:pos_end[2] +=
\ l:pos_end[1] == l:pos_start[1] ? strlen(a:cmd) + 3 : 1
endif
call vimtex#pos#set_cursor(l:pos_end)
else
let l:pos = vimtex#pos#get_cursor()
let l:save_reg = getreg('"')
let l:pos[2] += strlen(a:cmd) + 2
execute 'normal! ciw\' . a:cmd . '{"}'
call setreg('"', l:save_reg)
call vimtex#pos#set_cursor(l:pos)
endif
" Restore indentkeys setting
let &l:indentkeys = l:save_indentkeys
endfunction
" }}}1
function! vimtex#cmd#create_visual() abort " {{{1
let l:cmd = vimtex#echo#input({
\ 'info' :
\ ['Create command: ', ['VimtexWarning', '(empty to cancel)']],
\})
let l:cmd = substitute(l:cmd, '^\\', '', '')
call vimtex#cmd#create(l:cmd, 1)
endfunction
" }}}1
function! vimtex#cmd#toggle_star() abort " {{{1
let l:cmd = vimtex#cmd#get_current()
if empty(l:cmd) | return | endif
let l:old_name = l:cmd.name
let l:lnum = l:cmd.pos_start.lnum
let l:cnum = l:cmd.pos_start.cnum
" Set new command name
if match(l:old_name, '\*$') == -1
let l:new_name = l:old_name.'*'
else
let l:new_name = strpart(l:old_name, 0, strlen(l:old_name)-1)
endif
let l:new_name = substitute(l:new_name, '^\\', '', '')
if empty(l:new_name) | return | endif
" Update current position
let l:save_pos = vimtex#pos#get_cursor()
let l:save_pos[2] += strlen(l:new_name) - strlen(l:old_name) + 1
" Perform the change
let l:line = getline(l:lnum)
call setline(l:lnum,
\ strpart(l:line, 0, l:cnum)
\ . l:new_name
\ . strpart(l:line, l:cnum + strlen(l:old_name) - 1))
" Restore cursor position
cal vimtex#pos#set_cursor(l:save_pos)
endfunction
" }}}1
function! vimtex#cmd#toggle_frac() abort " {{{1
let l:frac = s:get_frac_cmd()
if empty(l:frac)
let l:frac = s:get_frac_inline()
endif
if empty(l:frac) | return | endif
let l:lnum = line('.')
let l:line = getline(l:lnum)
call setline(l:lnum,
\ strpart(l:line, 0, l:frac.col_start)
\ . l:frac.text_toggled
\ . strpart(l:line, l:frac.col_end+1))
endfunction
" }}}1
function! vimtex#cmd#toggle_frac_visual() abort " {{{1
let l:save_reg = getreg('a')
normal! gv"ay
let l:selected = substitute(getreg('a'), '\n\s*', ' ', '')
call setreg('a', l:save_reg)
let l:frac = s:get_frac_inline_visual(l:selected)
if empty(l:frac)
let l:frac = s:get_frac_cmd_visual(l:selected)
endif
if empty(l:frac) | return | endif
let l:save_reg = getreg('a')
call setreg('a', l:frac.text_toggled)
normal! gv"ap
call setreg('a', l:save_reg)
endfunction
" }}}1
function! s:get_frac_cmd() abort " {{{1
let l:save_pos = vimtex#pos#get_cursor()
while 1
let l:cmd = s:get_cmd('prev')
if empty(l:cmd) || l:cmd.pos_start.lnum < line('.')
call vimtex#pos#set_cursor(l:save_pos)
return {}
endif
if l:cmd.name ==# '\frac'
break
endif
call vimtex#pos#set_cursor(vimtex#pos#prev(l:cmd.pos_start))
endwhile
call vimtex#pos#set_cursor(l:save_pos)
let l:frac = {
\ 'type': 'cmd',
\ 'col_start': l:cmd.pos_start.cnum - 1,
\ 'col_end': l:cmd.pos_end.cnum - 1,
\}
if len(l:cmd.args) >= 2
let l:consume = []
let l:frac.denominator = l:cmd.args[0].text
let l:frac.numerator = l:cmd.args[1].text
elseif len(l:cmd.args) == 1
let l:consume = ['numerator']
let l:frac.denominator = l:cmd.args[0].text
let l:frac.numerator = ''
else
let l:consume = ['denominator', 'numerator']
let l:frac.denominator = ''
let l:frac.numerator = ''
endif
" Handle unfinished cases
let l:line = getline('.')
let l:pos = l:frac.col_end + 1
for l:key in l:consume
let l:part = strpart(l:line, l:frac.col_end + 1)
let l:blurp = matchstr(l:part, '^\s*{[^}]*}')
if !empty(l:blurp)
let l:frac[l:key] = vimtex#util#trim(l:blurp)[1:-2]
let l:frac.col_end += len(l:blurp)
continue
endif
let l:blurp = matchstr(l:part, '^\s*\w')
if !empty(l:blurp)
let l:frac[l:key] = vimtex#util#trim(l:blurp)
let l:frac.col_end += len(l:blurp)
endif
endfor
" Abort if \frac region does not cover cursor
if l:frac.col_end < col('.') | return {} | endif
let l:frac.text = strpart(getline('.'),
\ l:frac.col_start, l:frac.col_end - l:frac.col_start + 1)
return s:get_frac_cmd_aux(l:frac)
endfunction
" }}}1
function! s:get_frac_cmd_visual(selected) abort " {{{1
let l:matches = matchlist(a:selected, '^\s*\\frac\s*{\(.*\)}\s*{\(.*\)}\s*$')
if empty(l:matches) | return {} | endif
let l:frac = {
\ 'type': 'cmd',
\ 'text': a:selected,
\ 'denominator': l:matches[1],
\ 'numerator': l:matches[2],
\}
return s:get_frac_cmd_aux(l:frac)
endfunction
" }}}1
function! s:get_frac_cmd_aux(frac) abort " {{{1
let l:denominator = (a:frac.denominator =~# '^\\\?\w*$')
\ ? a:frac.denominator
\ : '(' . a:frac.denominator . ')'
let l:numerator = (a:frac.numerator =~# '^\\\?\w*$')
\ ? a:frac.numerator
\ : '(' . a:frac.numerator . ')'
let a:frac.text_toggled = l:denominator . '/' . l:numerator
return a:frac
endfunction
" }}}1
function! s:get_frac_inline() abort " {{{1
let l:line = getline('.')
let l:col = col('.') - 1
let l:pos_after = -1
let l:pos_before = -1
while 1
let l:pos_before = l:pos_after
let l:pos_after = match(l:line, '\/', l:pos_after+1)
if l:pos_after < 0 || l:pos_after >= l:col | break | endif
endwhile
if l:pos_after == -1 && l:pos_before == -1
return {}
endif
let l:positions = []
if l:pos_before > 0
let l:positions += [l:pos_before]
endif
if l:pos_after > 0
let l:positions += [l:pos_after]
endif
for l:pos in l:positions
let l:frac = {'type': 'inline'}
"
" Parse numerator
"
let l:before = strpart(l:line, 0, l:pos)
if l:before =~# ')\s*$'
let l:pos_before = s:get_inline_limit(l:before, -1) - 1
let l:parens = strpart(l:before, l:pos_before)
else
let l:pos_before = match(l:before, '\s*$')
let l:parens = ''
endif
let l:before = strpart(l:line, 0, l:pos_before)
let l:atoms = matchstr(l:before, '\(\\(\)\?\zs[^-$(){} ]*$')
let l:pos_before = l:pos_before - strlen(l:atoms)
let l:frac.numerator = s:get_inline_trim(l:atoms . l:parens)
let l:frac.col_start = l:pos_before
"
" Parse denominator
"
let l:after = strpart(l:line, l:pos+1)
let l:atoms = l:after =~# '^\s*[^$()} ]*\\)'
\ ? matchstr(l:after, '^\s*[^$()} ]*\ze\\)')
\ : matchstr(l:after, '^\s*[^$()} ]*')
let l:pos_after = l:pos + strlen(l:atoms)
let l:after = strpart(l:line, l:pos_after+1)
if l:after =~# '^('
let l:index = s:get_inline_limit(l:after, 1)
let l:pos_after = l:pos_after + l:index + 1
let l:parens = strpart(l:after, 0, l:index+1)
else
let l:parens = ''
endif
let l:frac.denominator = s:get_inline_trim(l:atoms . l:parens)
let l:frac.col_end = l:pos_after
"
" Combine/Parse inline and frac expressions
"
let l:frac.text = strpart(l:line,
\ l:frac.col_start,
\ l:frac.col_end - l:frac.col_start + 1)
let l:frac.text_toggled = printf('\frac{%s}{%s}',
\ l:frac.numerator, l:frac.denominator)
"
" Accept result if the range contains the cursor column
"
if l:col >= l:frac.col_start && l:col <= l:frac.col_end
return l:frac
endif
endfor
return {}
endfunction
" }}}1
function! s:get_frac_inline_visual(selected) abort " {{{1
let l:parts = split(a:selected, '/')
if len(l:parts) != 2 | return {} | endif
let l:frac = {
\ 'type': 'inline',
\ 'text': a:selected,
\ 'numerator': s:get_inline_trim(l:parts[0]),
\ 'denominator': s:get_inline_trim(l:parts[1]),
\}
let l:frac.text_toggled = printf('\frac{%s}{%s}',
\ l:frac.numerator, l:frac.denominator)
return l:frac
endfunction
" }}}1
function! s:get_inline_limit(str, dir) abort " {{{1
if a:dir > 0
let l:open = '('
let l:string = a:str
else
let l:open = ')'
let l:string = join(reverse(split(a:str, '\zs')), '')
endif
let idx = -1
let depth = 0
while idx < len(l:string)
let idx = match(l:string, '[()]', idx + 1)
if idx < 0
let idx = len(l:string)
endif
if idx >= len(l:string) || l:string[idx] ==# l:open
let depth += 1
else
let depth -= 1
if depth == 0
return a:dir < 0 ? len(a:str) - idx : idx
endif
endif
endwhile
return -1
endfunction
" }}}1
function! s:get_inline_trim(str) abort " {{{1
let l:str = vimtex#util#trim(a:str)
return substitute(l:str, '^(\(.*\))$', '\1', '')
endfunction
" }}}1
function! vimtex#cmd#get_next() abort " {{{1
return s:get_cmd('next')
endfunction
" }}}1
function! vimtex#cmd#get_prev() abort " {{{1
return s:get_cmd('prev')
endfunction
" }}}1
function! vimtex#cmd#get_current() abort " {{{1
let l:save_pos = vimtex#pos#get_cursor()
let l:pos_val_cursor = vimtex#pos#val(l:save_pos)
let l:depth = 3
while l:depth > 0
let l:depth -= 1
let l:cmd = s:get_cmd('prev')
if empty(l:cmd) | break | endif
let l:pos_val = vimtex#pos#val(l:cmd.pos_end)
if l:pos_val >= l:pos_val_cursor
call vimtex#pos#set_cursor(l:save_pos)
return l:cmd
else
call vimtex#pos#set_cursor(vimtex#pos#prev(l:cmd.pos_start))
endif
endwhile
call vimtex#pos#set_cursor(l:save_pos)
return {}
endfunction
" }}}1
function! vimtex#cmd#get_at(...) abort " {{{1
let l:pos_saved = vimtex#pos#get_cursor()
call call('vimtex#pos#set_cursor', a:000)
let l:cmd = vimtex#cmd#get_current()
call vimtex#pos#set_cursor(l:pos_saved)
return l:cmd
endfunction
" }}}1
function! s:operator_setup(operator) abort " {{{1
let s:operator = a:operator
let &opfunc = s:snr() . 'operator_function'
" Ask for user input if necessary/relevant
if s:operator ==# 'change'
let l:current = vimtex#cmd#get_current()
if empty(l:current) | return | endif
let s:operator_cmd_name = substitute(vimtex#echo#input({
\ 'info' : ['Change command: ', ['VimtexWarning', l:current.name]],
\}), '^\\', '', '')
elseif s:operator ==# 'create'
let s:operator_cmd_name = substitute(vimtex#echo#input({
\ 'info' : ['Create command: ', ['VimtexWarning', '(empty to cancel)']],
\}), '^\\', '', '')
endif
endfunction
" }}}1
function! s:operator_function(_) abort " {{{1
let l:name = get(s:, 'operator_cmd_name', '')
execute 'call vimtex#cmd#' . {
\ 'change': 'change(l:name)',
\ 'create': 'create(l:name, 0)',
\ 'delete': 'delete()',
\ 'toggle_star': 'toggle_star()',
\ 'toggle_frac': 'toggle_frac()',
\ }[s:operator]
endfunction
" }}}1
function! s:snr() abort " {{{1
return matchstr(expand('<sfile>'), '<SNR>\d\+_')
endfunction
" }}}1
function! s:get_cmd(direction) abort " {{{1
let [lnum, cnum, match] = s:get_cmd_name(a:direction ==# 'next')
if lnum == 0 | return {} | endif
let res = {
\ 'name' : match,
\ 'text' : '',
\ 'pos_start' : { 'lnum' : lnum, 'cnum' : cnum },
\ 'pos_end' : { 'lnum' : lnum, 'cnum' : cnum + strlen(match) - 1 },
\ 'args' : [],
\}
" Environments always start with environment name and allows option
" afterwords
if res.name ==# '\begin'
let arg = s:get_cmd_part('{', res.pos_end)
if empty(arg) | return res | endif
call add(res.args, arg)
let res.pos_end.lnum = arg.close.lnum
let res.pos_end.cnum = arg.close.cnum
endif
" Get overlay specification
let res.overlay = s:get_cmd_overlay(res.pos_end.lnum, res.pos_end.cnum)
if !empty(res.overlay)
let res.pos_end.lnum = res.overlay.close.lnum
let res.pos_end.cnum = res.overlay.close.cnum
endif
" Get options
let res.opt = s:get_cmd_part('[', res.pos_end)
if !empty(res.opt)
let res.pos_end.lnum = res.opt.close.lnum
let res.pos_end.cnum = res.opt.close.cnum
endif
" Get arguments
let arg = s:get_cmd_part('{', res.pos_end)
while !empty(arg)
call add(res.args, arg)
let res.pos_end.lnum = arg.close.lnum
let res.pos_end.cnum = arg.close.cnum
let arg = s:get_cmd_part('{', res.pos_end)
endwhile
" Include entire cmd text
let res.text = s:text_between(res.pos_start, res.pos_end, 1)
return res
endfunction
" }}}1
function! s:get_cmd_name(next) abort " {{{1
let [l:lnum, l:cnum] = searchpos('\v\\\a+\*?', a:next ? 'nW' : 'cbnW')
let l:match = matchstr(getline(l:lnum), '^\v\\\a*\*?', l:cnum-1)
return [l:lnum, l:cnum, l:match]
endfunction
" }}}1
function! s:get_cmd_part(part, start_pos) abort " {{{1
let l:save_pos = vimtex#pos#get_cursor()
call vimtex#pos#set_cursor(a:start_pos)
let l:open = vimtex#delim#get_next('delim_tex', 'open')
call vimtex#pos#set_cursor(l:save_pos)
"
" Ensure that the delimiter
" 1) exists,
" 2) is of the right type,
" 3) and is the next non-whitespace character.
"
if empty(l:open)
\ || l:open.match !=# a:part
\ || strlen(substitute(
\ s:text_between(a:start_pos, l:open), '\_s', '', 'g')) != 0
return {}
endif
let l:close = vimtex#delim#get_matching(l:open)
if empty(l:close)
return {}
endif
return {
\ 'open' : l:open,
\ 'close' : l:close,
\ 'text' : s:text_between(l:open, l:close),
\}
endfunction
" }}}1
function! s:get_cmd_overlay(lnum, cnum) abort " {{{1
let l:match = matchstr(getline(a:lnum), '^\s*[^>]*>', a:cnum)
return empty(l:match)
\ ? {}
\ : {
\ 'open' : {'lnum' : a:lnum, 'cnum' : a:cnum + 1},
\ 'close' : {'lnum' : a:lnum, 'cnum' : a:cnum + strlen(l:match)},
\ 'text' : l:match
\ }
endfunction
" }}}1
function! s:text_between(p1, p2, ...) abort " {{{1
let [l1, c1] = [a:p1.lnum, a:p1.cnum - (a:0 > 0)]
let [l2, c2] = [a:p2.lnum, a:p2.cnum - (a:0 <= 0)]
let lines = getline(l1, l2)
if !empty(lines)
let lines[0] = strpart(lines[0], c1)
let lines[-1] = strpart(lines[-1], 0,
\ l1 == l2 ? c2 - c1 : c2)
endif
return join(lines, "\n")
endfunction
" }}}1
endif

View File

@@ -1,334 +0,0 @@
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#compiler#init_buffer() abort " {{{1
if !g:vimtex_compiler_enabled | return | endif
" Define commands
command! -buffer VimtexCompile call vimtex#compiler#compile()
command! -buffer -bang VimtexCompileSS call vimtex#compiler#compile_ss()
command! -buffer -range VimtexCompileSelected <line1>,<line2>call vimtex#compiler#compile_selected('cmd')
command! -buffer VimtexCompileOutput call vimtex#compiler#output()
command! -buffer VimtexStop call vimtex#compiler#stop()
command! -buffer VimtexStopAll call vimtex#compiler#stop_all()
command! -buffer -bang VimtexClean call vimtex#compiler#clean(<q-bang> == "!")
command! -buffer -bang VimtexStatus call vimtex#compiler#status(<q-bang> == "!")
" Define mappings
nnoremap <buffer> <plug>(vimtex-compile) :call vimtex#compiler#compile()<cr>
nnoremap <buffer> <plug>(vimtex-compile-ss) :call vimtex#compiler#compile_ss()<cr>
nnoremap <buffer> <plug>(vimtex-compile-selected) :set opfunc=vimtex#compiler#compile_selected<cr>g@
xnoremap <buffer> <plug>(vimtex-compile-selected) :<c-u>call vimtex#compiler#compile_selected('visual')<cr>
nnoremap <buffer> <plug>(vimtex-compile-output) :call vimtex#compiler#output()<cr>
nnoremap <buffer> <plug>(vimtex-stop) :call vimtex#compiler#stop()<cr>
nnoremap <buffer> <plug>(vimtex-stop-all) :call vimtex#compiler#stop_all()<cr>
nnoremap <buffer> <plug>(vimtex-clean) :call vimtex#compiler#clean(0)<cr>
nnoremap <buffer> <plug>(vimtex-clean-full) :call vimtex#compiler#clean(1)<cr>
nnoremap <buffer> <plug>(vimtex-status) :call vimtex#compiler#status(0)<cr>
nnoremap <buffer> <plug>(vimtex-status-all) :call vimtex#compiler#status(1)<cr>
endfunction
" }}}1
function! vimtex#compiler#init_state(state) abort " {{{1
if !g:vimtex_compiler_enabled | return | endif
try
let l:options = {
\ 'root': a:state.root,
\ 'target' : a:state.base,
\ 'target_path' : a:state.tex,
\ 'tex_program' : a:state.tex_program,
\}
let a:state.compiler
\ = vimtex#compiler#{g:vimtex_compiler_method}#init(l:options)
catch /vimtex: Requirements not met/
call vimtex#log#error('Compiler was not initialized!')
catch /E117/
call vimtex#log#error(
\ 'Invalid compiler: ' . g:vimtex_compiler_method,
\ 'Please see :h g:vimtex_compiler_method')
endtry
endfunction
" }}}1
function! vimtex#compiler#callback(status) abort " {{{1
if exists('b:vimtex') && get(b:vimtex.compiler, 'silence_next_callback')
let b:vimtex.compiler.silence_next_callback = 0
return
endif
call vimtex#qf#open(0)
redraw
if exists('s:output')
call s:output.update()
endif
if a:status
call vimtex#log#info('Compilation completed')
else
call vimtex#log#warning('Compilation failed!')
endif
if a:status && exists('b:vimtex')
call b:vimtex.parse_packages()
call vimtex#syntax#load#packages()
endif
for l:hook in g:vimtex_compiler_callback_hooks
if exists('*' . l:hook)
execute 'call' l:hook . '(' . a:status . ')'
endif
endfor
return ''
endfunction
" }}}1
function! vimtex#compiler#compile() abort " {{{1
if get(b:vimtex.compiler, 'continuous')
if b:vimtex.compiler.is_running()
call vimtex#compiler#stop()
else
call b:vimtex.compiler.start()
let b:vimtex.compiler.check_timer = s:check_if_running_start()
endif
else
call b:vimtex.compiler.start_single()
endif
endfunction
" }}}1
function! vimtex#compiler#compile_ss() abort " {{{1
call b:vimtex.compiler.start_single()
endfunction
" }}}1
function! vimtex#compiler#compile_selected(type) abort range " {{{1
let l:file = vimtex#parser#selection_to_texfile(a:type)
if empty(l:file) | return | endif
" Create and initialize temporary compiler
let l:options = {
\ 'root' : l:file.root,
\ 'target' : l:file.base,
\ 'target_path' : l:file.tex,
\ 'backend' : 'process',
\ 'tex_program' : b:vimtex.tex_program,
\ 'background' : 1,
\ 'continuous' : 0,
\ 'callback' : 0,
\}
let l:compiler = vimtex#compiler#{g:vimtex_compiler_method}#init(l:options)
call vimtex#log#toggle_verbose()
call l:compiler.start()
" Check if successful
if vimtex#qf#inquire(l:file.base)
call vimtex#log#toggle_verbose()
call vimtex#log#warning('Compiling selected lines ... failed!')
botright cwindow
return
else
call l:compiler.clean(0)
call b:vimtex.viewer.view(l:file.pdf)
call vimtex#log#toggle_verbose()
call vimtex#log#info('Compiling selected lines ... done')
endif
endfunction
" }}}1
function! vimtex#compiler#output() abort " {{{1
let l:file = get(b:vimtex.compiler, 'output', '')
if empty(l:file)
call vimtex#log#warning('No output exists!')
return
endif
" If window already open, then go there
if exists('s:output')
if bufwinnr(l:file) == s:output.winnr
execute s:output.winnr . 'wincmd w'
return
else
call s:output.destroy()
endif
endif
" Create new output window
silent execute 'split' l:file
" Create the output object
let s:output = {}
let s:output.name = l:file
let s:output.bufnr = bufnr('%')
let s:output.winnr = bufwinnr('%')
function! s:output.update() dict abort
if bufwinnr(self.name) != self.winnr
return
endif
if mode() ==? 'v' || mode() ==# "\<c-v>"
return
endif
" Go to last line of file if it is not the current window
if bufwinnr('%') != self.winnr
let l:return = bufwinnr('%')
execute 'keepalt' self.winnr . 'wincmd w'
edit
normal! Gzb
execute 'keepalt' l:return . 'wincmd w'
redraw
endif
endfunction
function! s:output.destroy() dict abort
autocmd! vimtex_output_window
augroup! vimtex_output_window
unlet s:output
endfunction
" Better automatic update
augroup vimtex_output_window
autocmd!
autocmd BufDelete <buffer> call s:output.destroy()
autocmd BufEnter * call s:output.update()
autocmd FocusGained * call s:output.update()
autocmd CursorHold * call s:output.update()
autocmd CursorHoldI * call s:output.update()
autocmd CursorMoved * call s:output.update()
autocmd CursorMovedI * call s:output.update()
augroup END
" Set some mappings
nnoremap <silent><nowait><buffer> q :bwipeout<cr>
if has('nvim') || has('gui_running')
nnoremap <silent><nowait><buffer> <esc> :bwipeout<cr>
endif
" Set some buffer options
setlocal autoread
setlocal nomodifiable
setlocal bufhidden=wipe
endfunction
" }}}1
function! vimtex#compiler#stop() abort " {{{1
call b:vimtex.compiler.stop()
silent! call timer_stop(b:vimtex.compiler.check_timer)
endfunction
" }}}1
function! vimtex#compiler#stop_all() abort " {{{1
for l:state in vimtex#state#list_all()
if exists('l:state.compiler.is_running')
\ && l:state.compiler.is_running()
call l:state.compiler.stop()
endif
endfor
endfunction
" }}}1
function! vimtex#compiler#clean(full) abort " {{{1
call b:vimtex.compiler.clean(a:full)
if empty(b:vimtex.compiler.build_dir) | return | endif
sleep 100m
" Remove auxilliary output directories if they are empty
let l:build_dir = (vimtex#paths#is_abs(b:vimtex.compiler.build_dir)
\ ? '' : b:vimtex.root . '/')
\ . b:vimtex.compiler.build_dir
let l:tree = glob(l:build_dir . '/**/*', 0, 1)
let l:files = filter(copy(l:tree), 'filereadable(v:val)')
if !empty(l:files) | return | endif
for l:dir in sort(l:tree) + [l:build_dir]
call delete(l:dir, 'd')
endfor
endfunction
" }}}1
function! vimtex#compiler#status(detailed) abort " {{{1
if a:detailed
let l:running = []
for l:data in vimtex#state#list_all()
if l:data.compiler.is_running()
let l:name = l:data.tex
if len(l:name) >= winwidth('.') - 20
let l:name = '...' . l:name[-winwidth('.')+23:]
endif
call add(l:running, printf('%-6s %s',
\ string(l:data.compiler.get_pid()) . ':', l:name))
endif
endfor
if empty(l:running)
call vimtex#log#warning('Compiler is not running!')
else
call vimtex#log#info('Compiler is running', l:running)
endif
else
if b:vimtex.compiler.is_running()
call vimtex#log#info('Compiler is running')
else
call vimtex#log#warning('Compiler is not running!')
endif
endif
endfunction
" }}}1
let s:check_timers = {}
function! s:check_if_running_start() abort " {{{1
if !exists('*timer_start') | return -1 | endif
let l:timer = timer_start(50, function('s:check_if_running'), {'repeat': 20})
let s:check_timers[l:timer] = {
\ 'compiler' : b:vimtex.compiler,
\ 'vimtex_id' : b:vimtex_id,
\}
return l:timer
endfunction
" }}}1
function! s:check_if_running(timer) abort " {{{1
if s:check_timers[a:timer].compiler.is_running() | return | endif
call timer_stop(a:timer)
if get(b:, 'vimtex_id', -1) == s:check_timers[a:timer].vimtex_id
call vimtex#compiler#output()
endif
call vimtex#log#error('Compiler did not start successfully!')
unlet s:check_timers[a:timer].compiler.check_timer
unlet s:check_timers[a:timer]
endfunction
" }}}1
" {{{1 Initialize module
if !g:vimtex_compiler_enabled | finish | endif
augroup vimtex_compiler
autocmd!
autocmd VimLeave * call vimtex#compiler#stop_all()
augroup END
" }}}1
endif

View File

@@ -1,218 +0,0 @@
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#compiler#arara#init(options) abort " {{{1
let l:compiler = deepcopy(s:compiler)
call l:compiler.init(extend(a:options,
\ get(g:, 'vimtex_compiler_arara', {}), 'keep'))
return l:compiler
endfunction
" }}}1
let s:compiler = {
\ 'name' : 'arara',
\ 'backend' : has('nvim') ? 'nvim'
\ : v:version >= 800 ? 'jobs' : 'process',
\ 'root' : '',
\ 'target' : '',
\ 'target_path' : '',
\ 'background' : 1,
\ 'output' : tempname(),
\ 'options' : ['--log'],
\}
function! s:compiler.init(options) abort dict " {{{1
call extend(self, a:options)
if !executable('arara')
call vimtex#log#warning('arara is not executable!')
throw 'vimtex: Requirements not met'
endif
call extend(self, deepcopy(s:compiler_{self.backend}))
" Processes run with the new jobs api will not run in the foreground
if self.backend !=# 'process'
let self.background = 1
endif
endfunction
" }}}1
function! s:compiler.build_cmd() abort dict " {{{1
let l:cmd = 'arara'
for l:opt in self.options
let l:cmd .= ' ' . l:opt
endfor
return l:cmd . ' ' . vimtex#util#shellescape(self.target)
endfunction
" }}}1
function! s:compiler.cleanup() abort dict " {{{1
" Pass
endfunction
" }}}1
function! s:compiler.pprint_items() abort dict " {{{1
let l:configuration = []
if self.backend ==# 'process'
call add(l:configuration, ['background', self.background])
endif
call add(l:configuration, ['arara options', self.options])
let l:list = []
call add(l:list, ['backend', self.backend])
if self.background
call add(l:list, ['output', self.output])
endif
if self.target_path !=# b:vimtex.tex
call add(l:list, ['root', self.root])
call add(l:list, ['target', self.target_path])
endif
call add(l:list, ['configuration', l:configuration])
if has_key(self, 'process')
call add(l:list, ['process', self.process])
endif
if has_key(self, 'job')
call add(l:list, ['cmd', self.cmd])
endif
return l:list
endfunction
" }}}1
function! s:compiler.clean(...) abort dict " {{{1
call vimtex#log#warning('Clean not implemented for arara')
endfunction
" }}}1
function! s:compiler.start(...) abort dict " {{{1
call self.exec()
if self.background
call vimtex#log#info('Compiler started in background')
else
call vimtex#compiler#callback(!vimtex#qf#inquire(self.target))
endif
endfunction
" }}}1
function! s:compiler.start_single() abort dict " {{{1
call self.start()
endfunction
" }}}1
function! s:compiler.stop() abort dict " {{{1
" Pass
endfunction
" }}}1
function! s:compiler.is_running() abort dict " {{{1
return 0
endfunction
" }}}1
function! s:compiler.kill() abort dict " {{{1
" Pass
endfunction
" }}}1
function! s:compiler.get_pid() abort dict " {{{1
return 0
endfunction
" }}}1
let s:compiler_process = {}
function! s:compiler_process.exec() abort dict " {{{1
let self.process = vimtex#process#new()
let self.process.name = 'arara'
let self.process.background = self.background
let self.process.workdir = self.root
let self.process.output = self.output
let self.process.cmd = self.build_cmd()
call self.process.run()
endfunction
" }}}1
let s:compiler_jobs = {}
function! s:compiler_jobs.exec() abort dict " {{{1
let self.cmd = self.build_cmd()
let l:cmd = has('win32')
\ ? 'cmd /s /c "' . self.cmd . '"'
\ : ['sh', '-c', self.cmd]
let l:options = {
\ 'out_io' : 'file',
\ 'err_io' : 'file',
\ 'out_name' : self.output,
\ 'err_name' : self.output,
\}
let s:cb_target = self.target_path !=# b:vimtex.tex ? self.target_path : ''
let l:options.exit_cb = function('s:callback')
call vimtex#paths#pushd(self.root)
let self.job = job_start(l:cmd, l:options)
call vimtex#paths#popd()
endfunction
" }}}1
function! s:callback(ch, msg) abort " {{{1
call vimtex#compiler#callback(!vimtex#qf#inquire(s:cb_target))
endfunction
" }}}1
let s:compiler_nvim = {}
function! s:compiler_nvim.exec() abort dict " {{{1
let self.cmd = self.build_cmd()
let l:cmd = has('win32')
\ ? 'cmd /s /c "' . self.cmd . '"'
\ : ['sh', '-c', self.cmd]
let l:shell = {
\ 'on_stdout' : function('s:callback_nvim_output'),
\ 'on_stderr' : function('s:callback_nvim_output'),
\ 'on_exit' : function('s:callback_nvim_exit'),
\ 'cwd' : self.root,
\ 'target' : self.target_path,
\ 'output' : self.output,
\}
let self.job = jobstart(l:cmd, l:shell)
endfunction
" }}}1
function! s:callback_nvim_output(id, data, event) abort dict " {{{1
if !empty(a:data)
call writefile(filter(a:data, '!empty(v:val)'), self.output, 'a')
endif
endfunction
" }}}1
function! s:callback_nvim_exit(id, data, event) abort dict " {{{1
let l:target = self.target !=# b:vimtex.tex ? self.target : ''
call vimtex#compiler#callback(!vimtex#qf#inquire(l:target))
endfunction
" }}}1
endif

View File

@@ -1,700 +0,0 @@
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#compiler#latexmk#init(options) abort " {{{1
let l:compiler = deepcopy(s:compiler)
call l:compiler.init(extend(a:options,
\ get(g:, 'vimtex_compiler_latexmk', {}), 'keep'))
return l:compiler
endfunction
" }}}1
function! vimtex#compiler#latexmk#wrap_option(name, value) abort " {{{1
return has('win32')
\ ? ' -e "$' . a:name . ' = ''' . a:value . '''"'
\ : ' -e ''$' . a:name . ' = "' . a:value . '"'''
endfunction
"}}}1
function! vimtex#compiler#latexmk#get_rc_opt(root, opt, type, default) abort " {{{1
"
" Parse option from .latexmkrc.
"
" Arguments:
" root Root of LaTeX project
" opt Name of options
" type 0 if string, 1 if integer, 2 if list
" default Value to return if option not found in latexmkrc file
"
" Output:
" [value, location]
"
" value Option value (integer or string)
" location An integer that indicates where option was found
" -1: not found (default value returned)
" 0: global latexmkrc file
" 1: local latexmkrc file
"
if a:type == 0
let l:pattern = '^\s*\$' . a:opt . '\s*=\s*[''"]\(.\+\)[''"]'
elseif a:type == 1
let l:pattern = '^\s*\$' . a:opt . '\s*=\s*\(\d\+\)'
elseif a:type == 2
let l:pattern = '^\s*@' . a:opt . '\s*=\s*(\(.*\))'
else
throw 'vimtex: argument error'
endif
" Candidate files
" - each element is a pair [path_to_file, is_local_rc_file].
let l:files = [
\ [a:root . '/latexmkrc', 1],
\ [a:root . '/.latexmkrc', 1],
\ [fnamemodify('~/.latexmkrc', ':p'), 0],
\]
if !empty($XDG_CONFIG_HOME)
call add(l:files, [$XDG_CONFIG_HOME . '/latexmk/latexmkrc', 0])
endif
let l:result = [a:default, -1]
for [l:file, l:is_local] in l:files
if filereadable(l:file)
let l:match = matchlist(readfile(l:file), l:pattern)
if len(l:match) > 1
let l:result = [l:match[1], l:is_local]
break
end
endif
endfor
" Parse the list
if a:type == 2 && l:result[1] > -1
let l:array = split(l:result[0], ',')
let l:result[0] = []
for l:x in l:array
let l:x = substitute(l:x, "^'", '', '')
let l:x = substitute(l:x, "'$", '', '')
let l:result[0] += [l:x]
endfor
endif
return l:result
endfunction
" }}}1
let s:compiler = {
\ 'name' : 'latexmk',
\ 'executable' : 'latexmk',
\ 'backend' : has('nvim') ? 'nvim'
\ : v:version >= 800 ? 'jobs' : 'process',
\ 'root' : '',
\ 'target' : '',
\ 'target_path' : '',
\ 'background' : 1,
\ 'build_dir' : '',
\ 'callback' : 1,
\ 'continuous' : 1,
\ 'output' : tempname(),
\ 'options' : [
\ '-verbose',
\ '-file-line-error',
\ '-synctex=1',
\ '-interaction=nonstopmode',
\ ],
\ 'hooks' : [],
\ 'shell' : fnamemodify(&shell, ':t'),
\}
function! s:compiler.init(options) abort dict " {{{1
call extend(self, a:options)
call self.init_check_requirements()
call self.init_build_dir_option()
call self.init_pdf_mode_option()
call extend(self, deepcopy(s:compiler_{self.backend}))
" Continuous processes can't run in foreground, neither can processes run
" with the new jobs api
if self.continuous || self.backend !=# 'process'
let self.background = 1
endif
if self.backend !=# 'process'
let self.shell = 'sh'
endif
endfunction
" }}}1
function! s:compiler.init_build_dir_option() abort dict " {{{1
"
" Check if .latexmkrc sets the build_dir - if so this should be respected
"
let l:out_dir =
\ vimtex#compiler#latexmk#get_rc_opt(self.root, 'out_dir', 0, '')[0]
if !empty(l:out_dir)
if !empty(self.build_dir) && (self.build_dir !=# l:out_dir)
call vimtex#log#warning(
\ 'Setting out_dir from latexmkrc overrides build_dir!',
\ 'Changed build_dir from: ' . self.build_dir,
\ 'Changed build_dir to: ' . l:out_dir)
endif
let self.build_dir = l:out_dir
endif
endfunction
" }}}1
function! s:compiler.init_pdf_mode_option() abort dict " {{{1
" If the TeX program directive was not set, and if the pdf_mode is set in
" a .latexmkrc file, then deduce the compiler engine from the value of
" pdf_mode.
" Parse the pdf_mode option. If not found, it is set to -1.
let [l:pdf_mode, l:is_local] =
\ vimtex#compiler#latexmk#get_rc_opt(self.root, 'pdf_mode', 1, -1)
" If pdf_mode has a supported value (1: pdflatex, 4: lualatex, 5: xelatex),
" override the value of self.tex_program.
if l:pdf_mode == 1
let l:tex_program = 'pdflatex'
elseif l:pdf_mode == 3
let l:tex_program = 'pdfdvi'
elseif l:pdf_mode == 4
let l:tex_program = 'lualatex'
elseif l:pdf_mode == 5
let l:tex_program = 'xelatex'
else
return
endif
if self.tex_program ==# '_'
" The TeX program directive was not specified
let self.tex_program = l:tex_program
elseif l:is_local && self.tex_program !=# l:tex_program
call vimtex#log#warning(
\ 'Value of pdf_mode from latexmkrc is inconsistent with ' .
\ 'TeX program directive!',
\ 'TeX program: ' . self.tex_program,
\ 'pdf_mode: ' . l:tex_program,
\ 'The value of pdf_mode will be ignored.')
endif
endfunction
" }}}1
function! s:compiler.init_check_requirements() abort dict " {{{1
" Check option validity
if self.callback
if !(has('clientserver') || has('nvim') || has('job'))
let self.callback = 0
call vimtex#log#warning(
\ 'Can''t use callbacks without +job, +nvim, or +clientserver',
\ 'Callback option has been disabled.')
endif
endif
" Check for required executables
let l:required = [self.executable]
if self.continuous && !(has('win32') || has('win32unix'))
let l:required += ['pgrep']
endif
let l:missing = filter(l:required, '!executable(v:val)')
" Disable latexmk if required programs are missing
if len(l:missing) > 0
for l:cmd in l:missing
call vimtex#log#warning(l:cmd . ' is not executable')
endfor
throw 'vimtex: Requirements not met'
endif
endfunction
" }}}1
function! s:compiler.build_cmd() abort dict " {{{1
if has('win32')
let l:cmd = 'set max_print_line=2000 & ' . self.executable
else
if self.shell ==# 'fish'
let l:cmd = 'set max_print_line 2000; and ' . self.executable
else
let l:cmd = 'max_print_line=2000 ' . self.executable
endif
endif
for l:opt in self.options
let l:cmd .= ' ' . l:opt
endfor
let l:cmd .= ' ' . self.get_engine()
if !empty(self.build_dir)
let l:cmd .= ' -outdir=' . fnameescape(self.build_dir)
endif
if self.continuous
let l:cmd .= ' -pvc'
" Set viewer options
if !get(g:, 'vimtex_view_automatic', 1)
\ || get(get(b:vimtex, 'viewer', {}), 'xwin_id') > 0
\ || get(s:, 'silence_next_callback', 0)
let l:cmd .= ' -view=none'
elseif g:vimtex_view_enabled
\ && has_key(b:vimtex.viewer, 'latexmk_append_argument')
let l:cmd .= b:vimtex.viewer.latexmk_append_argument()
endif
if self.callback
if has('job') || has('nvim')
for [l:opt, l:val] in items({
\ 'success_cmd' : 'vimtex_compiler_callback_success',
\ 'failure_cmd' : 'vimtex_compiler_callback_failure',
\})
let l:func = 'echo ' . l:val
let l:cmd .= vimtex#compiler#latexmk#wrap_option(l:opt, l:func)
endfor
elseif empty(v:servername)
call vimtex#log#warning('Can''t use callbacks with empty v:servername')
else
" Some notes:
" - We excape the v:servername because this seems necessary on Windows
" for neovim, see e.g. Github Issue #877
for [l:opt, l:val] in items({'success_cmd' : 1, 'failure_cmd' : 0})
let l:callback = has('win32')
\ ? '"vimtex#compiler#callback(' . l:val . ')"'
\ : '\"vimtex\#compiler\#callback(' . l:val . ')\"'
let l:func = vimtex#util#shellescape('""')
\ . g:vimtex_compiler_progname
\ . vimtex#util#shellescape('""')
\ . ' --servername ' . vimtex#util#shellescape(v:servername)
\ . ' --remote-expr ' . l:callback
let l:cmd .= vimtex#compiler#latexmk#wrap_option(l:opt, l:func)
endfor
endif
endif
endif
return l:cmd . ' ' . vimtex#util#shellescape(self.target)
endfunction
" }}}1
function! s:compiler.get_engine() abort dict " {{{1
return get(extend(g:vimtex_compiler_latexmk_engines,
\ {
\ 'pdfdvi' : '-pdfdvi',
\ 'pdflatex' : '-pdf',
\ 'luatex' : '-lualatex',
\ 'lualatex' : '-lualatex',
\ 'xelatex' : '-xelatex',
\ 'context (pdftex)' : '-pdf -pdflatex=texexec',
\ 'context (luatex)' : '-pdf -pdflatex=context',
\ 'context (xetex)' : '-pdf -pdflatex=''texexec --xtx''',
\ }, 'keep'), self.tex_program, '-pdf')
endfunction
" }}}1
function! s:compiler.cleanup() abort dict " {{{1
if self.is_running()
call self.kill()
endif
endfunction
" }}}1
function! s:compiler.pprint_items() abort dict " {{{1
let l:configuration = [
\ ['continuous', self.continuous],
\ ['callback', self.callback],
\]
if self.backend ==# 'process' && !self.continuous
call add(l:configuration, ['background', self.background])
endif
if !empty(self.build_dir)
call add(l:configuration, ['build_dir', self.build_dir])
endif
call add(l:configuration, ['latexmk options', self.options])
call add(l:configuration, ['latexmk engine', self.get_engine()])
let l:list = []
call add(l:list, ['backend', self.backend])
if self.executable !=# s:compiler.executable
call add(l:list, ['latexmk executable', self.executable])
endif
if self.background
call add(l:list, ['output', self.output])
endif
if self.target_path !=# b:vimtex.tex
call add(l:list, ['root', self.root])
call add(l:list, ['target', self.target_path])
endif
call add(l:list, ['configuration', l:configuration])
if has_key(self, 'process')
call add(l:list, ['process', self.process])
endif
if has_key(self, 'job')
if self.continuous
if self.backend ==# 'jobs'
call add(l:list, ['job', self.job])
else
call add(l:list, ['pid', self.get_pid()])
endif
endif
call add(l:list, ['cmd', self.cmd])
endif
return l:list
endfunction
" }}}1
function! s:compiler.clean(full) abort dict " {{{1
let l:restart = self.is_running()
if l:restart
call self.stop()
endif
" Define and run the latexmk clean cmd
let l:cmd = (has('win32')
\ ? 'cd /D "' . self.root . '" & '
\ : 'cd ' . vimtex#util#shellescape(self.root) . '; ')
\ . self.executable . ' ' . (a:full ? '-C ' : '-c ')
if !empty(self.build_dir)
let l:cmd .= printf(' -outdir=%s ', fnameescape(self.build_dir))
endif
let l:cmd .= vimtex#util#shellescape(self.target)
call vimtex#process#run(l:cmd)
call vimtex#log#info('Compiler clean finished' . (a:full ? ' (full)' : ''))
if l:restart
let self.silent_next_callback = 1
silent call self.start()
endif
endfunction
" }}}1
function! s:compiler.start(...) abort dict " {{{1
if self.is_running()
call vimtex#log#warning(
\ 'Compiler is already running for `' . self.target . "'")
return
endif
"
" Create build dir if it does not exist
"
if !empty(self.build_dir)
let l:dirs = split(glob(self.root . '/**/*.tex'), '\n')
call map(l:dirs, 'fnamemodify(v:val, '':h'')')
call map(l:dirs, 'strpart(v:val, strlen(self.root) + 1)')
call vimtex#util#uniq(sort(filter(l:dirs, "v:val !=# ''")))
call map(l:dirs,
\ (vimtex#paths#is_abs(self.build_dir) ? '' : "self.root . '/' . ")
\ . "self.build_dir . '/' . v:val")
call filter(l:dirs, '!isdirectory(v:val)')
" Create the non-existing directories
for l:dir in l:dirs
call mkdir(l:dir, 'p')
endfor
endif
call self.exec()
if self.continuous
call vimtex#log#info('Compiler started in continuous mode'
\ . (a:0 > 0 ? ' (single shot)' : ''))
if exists('#User#VimtexEventCompileStarted')
doautocmd <nomodeline> User VimtexEventCompileStarted
endif
else
if self.background
call vimtex#log#info('Compiler started in background!')
else
call vimtex#compiler#callback(!vimtex#qf#inquire(self.target))
endif
endif
endfunction
" }}}1
function! s:compiler.stop() abort dict " {{{1
if self.is_running()
call self.kill()
call vimtex#log#info('Compiler stopped (' . self.target . ')')
if exists('#User#VimtexEventCompileStopped')
doautocmd <nomodeline> User VimtexEventCompileStopped
endif
else
call vimtex#log#warning(
\ 'There is no process to stop (' . self.target . ')')
endif
endfunction
" }}}1
let s:compiler_process = {}
function! s:compiler_process.exec() abort dict " {{{1
let l:process = vimtex#process#new()
let l:process.name = 'latexmk'
let l:process.continuous = self.continuous
let l:process.background = self.background
let l:process.workdir = self.root
let l:process.output = self.output
let l:process.cmd = self.build_cmd()
if l:process.continuous
if (has('win32') || has('win32unix'))
" Not implemented
else
for l:pid in split(system(
\ 'pgrep -f "^[^ ]*perl.*latexmk.*' . self.target . '"'), "\n")
let l:path = resolve('/proc/' . l:pid . '/cwd') . '/' . self.target
if l:path ==# self.target_path
let l:process.pid = str2nr(l:pid)
break
endif
endfor
endif
endif
function! l:process.set_pid() abort dict " {{{2
if (has('win32') || has('win32unix'))
let pidcmd = 'tasklist /fi "imagename eq latexmk.exe"'
let pidinfo = vimtex#process#capture(pidcmd)[-1]
let self.pid = str2nr(split(pidinfo,'\s\+')[1])
else
let self.pid = str2nr(system('pgrep -nf "^[^ ]*perl.*latexmk"')[:-2])
endif
return self.pid
endfunction
" }}}2
let self.process = l:process
call self.process.run()
endfunction
" }}}1
function! s:compiler_process.start_single() abort dict " {{{1
let l:continuous = self.continuous
let self.continuous = self.background && self.callback && !empty(v:servername)
if self.continuous
let g:vimtex_compiler_callback_hooks += ['VimtexSSCallback']
function! VimtexSSCallback(status) abort
silent call vimtex#compiler#stop()
call remove(g:vimtex_compiler_callback_hooks, 'VimtexSSCallback')
endfunction
endif
call self.start(1)
let self.continuous = l:continuous
endfunction
" }}}1
function! s:compiler_process.is_running() abort dict " {{{1
return exists('self.process.pid') && self.process.pid > 0
endfunction
" }}}1
function! s:compiler_process.kill() abort dict " {{{1
call self.process.stop()
endfunction
" }}}1
function! s:compiler_process.get_pid() abort dict " {{{1
return has_key(self, 'process') ? self.process.pid : 0
endfunction
" }}}1
let s:compiler_jobs = {}
function! s:compiler_jobs.exec() abort dict " {{{1
let self.cmd = self.build_cmd()
let l:cmd = has('win32')
\ ? 'cmd /s /c "' . self.cmd . '"'
\ : ['sh', '-c', self.cmd]
let l:options = {
\ 'out_io' : 'file',
\ 'err_io' : 'file',
\ 'out_name' : self.output,
\ 'err_name' : self.output,
\}
if self.continuous
let l:options.out_io = 'pipe'
let l:options.err_io = 'pipe'
let l:options.out_cb = function('s:callback_continuous_output')
let l:options.err_cb = function('s:callback_continuous_output')
call writefile([], self.output, 'a')
else
let s:cb_target = self.target_path !=# b:vimtex.tex
\ ? self.target_path : ''
let l:options.exit_cb = function('s:callback')
endif
call vimtex#paths#pushd(self.root)
let self.job = job_start(l:cmd, l:options)
call vimtex#paths#popd()
endfunction
" }}}1
function! s:compiler_jobs.start_single() abort dict " {{{1
let l:continuous = self.continuous
let self.continuous = 0
call self.start()
let self.continuous = l:continuous
endfunction
" }}}1
function! s:compiler_jobs.kill() abort dict " {{{1
call job_stop(self.job)
endfunction
" }}}1
function! s:compiler_jobs.is_running() abort dict " {{{1
return has_key(self, 'job') && job_status(self.job) ==# 'run'
endfunction
" }}}1
function! s:compiler_jobs.get_pid() abort dict " {{{1
return has_key(self, 'job')
\ ? get(job_info(self.job), 'process') : 0
endfunction
" }}}1
function! s:callback(ch, msg) abort " {{{1
call vimtex#compiler#callback(!vimtex#qf#inquire(s:cb_target))
endfunction
" }}}1
function! s:callback_continuous_output(channel, msg) abort " {{{1
if exists('b:vimtex') && filewritable(b:vimtex.compiler.output)
call writefile([a:msg], b:vimtex.compiler.output, 'a')
endif
if a:msg ==# 'vimtex_compiler_callback_success'
call vimtex#compiler#callback(1)
elseif a:msg ==# 'vimtex_compiler_callback_failure'
call vimtex#compiler#callback(0)
endif
try
for l:Hook in get(get(get(b:, 'vimtex', {}), 'compiler', {}), 'hooks', [])
call l:Hook(a:msg)
endfor
catch /E716/
endtry
endfunction
" }}}1
let s:compiler_nvim = {}
function! s:compiler_nvim.exec() abort dict " {{{1
let self.cmd = self.build_cmd()
let l:cmd = has('win32')
\ ? 'cmd /s /c "' . self.cmd . '"'
\ : ['sh', '-c', self.cmd]
let l:shell = {
\ 'on_stdout' : function('s:callback_nvim_output'),
\ 'on_stderr' : function('s:callback_nvim_output'),
\ 'cwd' : self.root,
\ 'target' : self.target_path,
\ 'output' : self.output,
\}
if !self.continuous
let l:shell.on_exit = function('s:callback_nvim_exit')
endif
" Initialize output file
try
call writefile([], self.output)
endtry
let self.job = jobstart(l:cmd, l:shell)
endfunction
" }}}1
function! s:compiler_nvim.start_single() abort dict " {{{1
let l:continuous = self.continuous
let self.continuous = 0
call self.start()
let self.continuous = l:continuous
endfunction
" }}}1
function! s:compiler_nvim.kill() abort dict " {{{1
call jobstop(self.job)
endfunction
" }}}1
function! s:compiler_nvim.is_running() abort dict " {{{1
try
let pid = jobpid(self.job)
return 1
catch
return 0
endtry
endfunction
" }}}1
function! s:compiler_nvim.get_pid() abort dict " {{{1
try
return jobpid(self.job)
catch
return 0
endtry
endfunction
" }}}1
function! s:callback_nvim_output(id, data, event) abort dict " {{{1
" Filter out unwanted newlines
let l:data = split(substitute(join(a:data, 'QQ'), '^QQ\|QQ$', '', ''), 'QQ')
if !empty(l:data) && filewritable(self.output)
call writefile(l:data, self.output, 'a')
endif
if match(a:data, 'vimtex_compiler_callback_success') != -1
call vimtex#compiler#callback(!vimtex#qf#inquire(self.target))
elseif match(a:data, 'vimtex_compiler_callback_failure') != -1
call vimtex#compiler#callback(0)
endif
try
for l:Hook in get(get(get(b:, 'vimtex', {}), 'compiler', {}), 'hooks', [])
call l:Hook(join(a:data, "\n"))
endfor
catch /E716/
endtry
endfunction
" }}}1
function! s:callback_nvim_exit(id, data, event) abort dict " {{{1
let l:target = self.target !=# b:vimtex.tex ? self.target : ''
call vimtex#compiler#callback(!vimtex#qf#inquire(l:target))
endfunction
" }}}1
endif

View File

@@ -1,250 +0,0 @@
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#compiler#latexrun#init(options) abort " {{{1
let l:compiler = deepcopy(s:compiler)
call l:compiler.init(extend(a:options,
\ get(g:, 'vimtex_compiler_latexrun', {}), 'keep'))
return l:compiler
endfunction
" }}}1
let s:compiler = {
\ 'name' : 'latexrun',
\ 'backend' : has('nvim') ? 'nvim'
\ : v:version >= 800 ? 'jobs' : 'process',
\ 'root' : '',
\ 'target' : '',
\ 'target_path' : '',
\ 'background' : 1,
\ 'build_dir' : '',
\ 'output' : tempname(),
\ 'options' : [
\ '--verbose-cmds',
\ '--latex-args="-synctex=1"',
\ ],
\}
function! s:compiler.init(options) abort dict " {{{1
call extend(self, a:options)
if !executable('latexrun')
call vimtex#log#warning('latexrun is not executable!')
throw 'vimtex: Requirements not met'
endif
call extend(self, deepcopy(s:compiler_{self.backend}))
" Processes run with the new jobs api will not run in the foreground
if self.backend !=# 'process'
let self.background = 1
endif
endfunction
" }}}1
function! s:compiler.build_cmd() abort dict " {{{1
let l:cmd = 'latexrun'
for l:opt in self.options
let l:cmd .= ' ' . l:opt
endfor
let l:cmd .= ' --latex-cmd ' . self.get_engine()
let l:cmd .= ' -O '
\ . (empty(self.build_dir) ? '.' : fnameescape(self.build_dir))
return l:cmd . ' ' . vimtex#util#shellescape(self.target)
endfunction
" }}}1
function! s:compiler.get_engine() abort dict " {{{1
return get(extend(g:vimtex_compiler_latexrun_engines,
\ {
\ '_' : 'pdflatex',
\ 'pdflatex' : 'pdflatex',
\ 'lualatex' : 'lualatex',
\ 'xelatex' : 'xelatex',
\ }, 'keep'), self.tex_program, '_')
endfunction
" }}}1
function! s:compiler.cleanup() abort dict " {{{1
" Pass
endfunction
" }}}1
function! s:compiler.pprint_items() abort dict " {{{1
let l:configuration = []
if self.backend ==# 'process'
call add(l:configuration, ['background', self.background])
endif
if !empty(self.build_dir)
call add(l:configuration, ['build_dir', self.build_dir])
endif
call add(l:configuration, ['latexrun options', self.options])
call add(l:configuration, ['latexrun engine', self.get_engine()])
let l:list = []
call add(l:list, ['backend', self.backend])
if self.background
call add(l:list, ['output', self.output])
endif
if self.target_path !=# b:vimtex.tex
call add(l:list, ['root', self.root])
call add(l:list, ['target', self.target_path])
endif
call add(l:list, ['configuration', l:configuration])
if has_key(self, 'process')
call add(l:list, ['process', self.process])
endif
if has_key(self, 'job')
call add(l:list, ['cmd', self.cmd])
endif
return l:list
endfunction
" }}}1
function! s:compiler.clean(...) abort dict " {{{1
let l:cmd = (has('win32')
\ ? 'cd /D "' . self.root . '" & '
\ : 'cd ' . vimtex#util#shellescape(self.root) . '; ')
\ . 'latexrun --clean-all'
\ . ' -O '
\ . (empty(self.build_dir) ? '.' : fnameescape(self.build_dir))
call vimtex#process#run(l:cmd)
call vimtex#log#info('Compiler clean finished')
endfunction
" }}}1
function! s:compiler.start(...) abort dict " {{{1
call self.exec()
if self.background
call vimtex#log#info('Compiler started in background')
else
call vimtex#compiler#callback(!vimtex#qf#inquire(self.target))
endif
endfunction
" }}}1
function! s:compiler.start_single() abort dict " {{{1
call self.start()
endfunction
" }}}1
function! s:compiler.stop() abort dict " {{{1
" Pass
endfunction
" }}}1
function! s:compiler.is_running() abort dict " {{{1
return 0
endfunction
" }}}1
function! s:compiler.kill() abort dict " {{{1
" Pass
endfunction
" }}}1
function! s:compiler.get_pid() abort dict " {{{1
return 0
endfunction
" }}}1
let s:compiler_process = {}
function! s:compiler_process.exec() abort dict " {{{1
let self.process = vimtex#process#new()
let self.process.name = 'latexrun'
let self.process.background = self.background
let self.process.workdir = self.root
let self.process.output = self.output
let self.process.cmd = self.build_cmd()
call self.process.run()
endfunction
" }}}1
let s:compiler_jobs = {}
function! s:compiler_jobs.exec() abort dict " {{{1
let self.cmd = self.build_cmd()
let l:cmd = has('win32')
\ ? 'cmd /s /c "' . self.cmd . '"'
\ : ['sh', '-c', self.cmd]
let l:options = {
\ 'out_io' : 'file',
\ 'err_io' : 'file',
\ 'out_name' : self.output,
\ 'err_name' : self.output,
\}
let s:cb_target = self.target_path !=# b:vimtex.tex ? self.target_path : ''
let l:options.exit_cb = function('s:callback')
call vimtex#paths#pushd(self.root)
let self.job = job_start(l:cmd, l:options)
call vimtex#paths#popd()
endfunction
" }}}1
function! s:callback(ch, msg) abort " {{{1
call vimtex#compiler#callback(!vimtex#qf#inquire(s:cb_target))
endfunction
" }}}1
let s:compiler_nvim = {}
function! s:compiler_nvim.exec() abort dict " {{{1
let self.cmd = self.build_cmd()
let l:cmd = has('win32')
\ ? 'cmd /s /c "' . self.cmd . '"'
\ : ['sh', '-c', self.cmd]
let l:shell = {
\ 'on_stdout' : function('s:callback_nvim_output'),
\ 'on_stderr' : function('s:callback_nvim_output'),
\ 'on_exit' : function('s:callback_nvim_exit'),
\ 'cwd' : self.root,
\ 'target' : self.target_path,
\ 'output' : self.output,
\}
let self.job = jobstart(l:cmd, l:shell)
endfunction
" }}}1
function! s:callback_nvim_output(id, data, event) abort dict " {{{1
if !empty(a:data)
call writefile(filter(a:data, '!empty(v:val)'), self.output, 'a')
endif
endfunction
" }}}1
function! s:callback_nvim_exit(id, data, event) abort dict " {{{1
let l:target = self.target !=# b:vimtex.tex ? self.target : ''
call vimtex#compiler#callback(!vimtex#qf#inquire(l:target))
endfunction
" }}}1
endif

View File

@@ -1,255 +0,0 @@
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#compiler#tectonic#init(options) abort " {{{1
let l:compiler = deepcopy(s:compiler)
call l:compiler.init(extend(a:options,
\ get(g:, 'vimtex_compiler_tectonic', {}), 'keep'))
return l:compiler
endfunction
" }}}1
let s:compiler = {
\ 'name' : 'tectonic',
\ 'backend' : has('nvim') ? 'nvim'
\ : v:version >= 800 ? 'jobs' : 'process',
\ 'root' : '',
\ 'target' : '',
\ 'target_path' : '',
\ 'background' : 1,
\ 'build_dir' : '',
\ 'output' : tempname(),
\ 'options' : [
\ '--keep-logs',
\ '--synctex'
\ ],
\}
function! s:compiler.init(options) abort dict " {{{1
call extend(self, a:options)
if !executable('tectonic')
call vimtex#log#warning('tectonic is not executable!')
throw 'vimtex: Requirements not met'
endif
call extend(self, deepcopy(s:compiler_{self.backend}))
" Processes run with the new jobs api will not run in the foreground
if self.backend !=# 'process'
let self.background = 1
endif
endfunction
" }}}1
function! s:compiler.build_cmd() abort dict " {{{1
let l:cmd = 'tectonic'
for l:opt in self.options
if l:opt =~# '^-\%(o\|-outdir\)'
call vimtex#log#warning("Don't use --outdir or -o in compiler options,"
\ . ' use build_dir instead, see :help g:vimtex_compiler_tectonic'
\ . ' for more details')
continue
endif
let l:cmd .= ' ' . l:opt
endfor
if empty(self.build_dir)
let self.build_dir = fnamemodify(self.target_path, ':p:h')
elseif !isdirectory(self.build_dir)
call vimtex#log#warning(
\ "build_dir doesn't exist, it will be created: " . self.build_dir)
call mkdir(self.build_dir, 'p')
endif
return l:cmd
\ . ' --outdir=' . self.build_dir
\ . ' ' . vimtex#util#shellescape(self.target)
endfunction
" }}}1
function! s:compiler.cleanup() abort dict " {{{1
" Pass
endfunction
" }}}1
function! s:compiler.pprint_items() abort dict " {{{1
let l:configuration = []
if self.backend ==# 'process'
call add(l:configuration, ['background', self.background])
endif
call add(l:configuration, ['tectonic options', self.options])
let l:list = []
call add(l:list, ['backend', self.backend])
if self.background
call add(l:list, ['output', self.output])
endif
if self.target_path !=# b:vimtex.tex
call add(l:list, ['root', self.root])
call add(l:list, ['target', self.target_path])
endif
call add(l:list, ['configuration', l:configuration])
if has_key(self, 'process')
call add(l:list, ['process', self.process])
endif
if has_key(self, 'job')
call add(l:list, ['cmd', self.cmd])
endif
return l:list
endfunction
" }}}1
function! s:compiler.clean(...) abort dict " {{{1
let l:files = ['synctex.gz', 'toc', 'out', 'aux', 'log']
" If a full clean is required
if a:0 > 0 && a:1
call extend(l:intermediate, ['pdf'])
endif
let l:basename = self.build_dir . '/' . fnamemodify(self.target_path, ':t:r')
call map(l:files, 'l:basename . v:val')
call vimtex#process#run('rm -f ' . join(l:files))
call vimtex#log#info('Compiler clean finished')
endfunction
" }}}1
function! s:compiler.start(...) abort dict " {{{1
call self.exec()
if self.background
call vimtex#log#info('Compiler started in background')
else
call vimtex#compiler#callback(!vimtex#qf#inquire(self.target))
endif
endfunction
" }}}1
function! s:compiler.start_single() abort dict " {{{1
call self.start()
endfunction
" }}}1
function! s:compiler.stop() abort dict " {{{1
" Pass
endfunction
" }}}1
function! s:compiler.is_running() abort dict " {{{1
return 0
endfunction
" }}}1
function! s:compiler.kill() abort dict " {{{1
" Pass
endfunction
" }}}1
function! s:compiler.get_pid() abort dict " {{{1
return 0
endfunction
" }}}1
let s:compiler_process = {}
function! s:compiler_process.exec() abort dict " {{{1
let self.process = vimtex#process#new()
let self.process.name = 'tectonic'
let self.process.background = self.background
let self.process.workdir = self.root
let self.process.output = self.output
let self.process.cmd = self.build_cmd()
call self.process.run()
endfunction
" }}}1
let s:compiler_jobs = {}
function! s:compiler_jobs.exec() abort dict " {{{1
let self.cmd = self.build_cmd()
let l:cmd = has('win32')
\ ? 'cmd /s /c "' . self.cmd . '"'
\ : ['sh', '-c', self.cmd]
let l:options = {
\ 'out_io' : 'file',
\ 'err_io' : 'file',
\ 'out_name' : self.output,
\ 'err_name' : self.output,
\}
let s:cb_target = self.target_path !=# b:vimtex.tex ? self.target_path : ''
let l:options.exit_cb = function('s:callback')
if !empty(self.root)
let l:save_pwd = getcwd()
execute 'lcd' fnameescape(self.root)
endif
let self.job = job_start(l:cmd, l:options)
if !empty(self.root)
execute 'lcd' fnameescape(l:save_pwd)
endif
endfunction
" }}}1
function! s:callback(ch, msg) abort " {{{1
call vimtex#compiler#callback(!vimtex#qf#inquire(s:cb_target))
endfunction
" }}}1
let s:compiler_nvim = {}
function! s:compiler_nvim.exec() abort dict " {{{1
let self.cmd = self.build_cmd()
let l:cmd = has('win32')
\ ? 'cmd /s /c "' . self.cmd . '"'
\ : ['sh', '-c', self.cmd]
let l:shell = {
\ 'on_stdout' : function('s:callback_nvim_output'),
\ 'on_stderr' : function('s:callback_nvim_output'),
\ 'on_exit' : function('s:callback_nvim_exit'),
\ 'cwd' : self.root,
\ 'target' : self.target_path,
\ 'output' : self.output,
\}
let self.job = jobstart(l:cmd, l:shell)
endfunction
" }}}1
function! s:callback_nvim_output(id, data, event) abort dict " {{{1
if !empty(a:data)
call writefile(filter(a:data, '!empty(v:val)'), self.output, 'a')
endif
endfunction
" }}}1
function! s:callback_nvim_exit(id, data, event) abort dict " {{{1
let l:target = self.target !=# b:vimtex.tex ? self.target : ''
call vimtex#compiler#callback(!vimtex#qf#inquire(l:target))
endfunction
" }}}1
endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,114 +0,0 @@
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#debug#stacktrace(...) abort " {{{1
"
" This function builds on Luc Hermite's answer on Stack Exchange:
" http://vi.stackexchange.com/a/6024/21
"
"
" Get stack and exception
"
if empty(v:throwpoint)
try
throw 'dummy'
catch
let l:stack = reverse(split(v:throwpoint, '\.\.'))[1:]
let l:exception = 'Manual stacktrace'
endtry
else
let l:stack = reverse(split(v:throwpoint, '\.\.'))
let l:exception = v:exception
endif
"
" Build the quickfix entries
"
let l:qflist = []
let l:files = {}
for l:func in l:stack
try
let [l:name, l:offset] = (l:func =~# '\S\+\[\d')
\ ? matchlist(l:func, '\(\S\+\)\[\(\d\+\)\]')[1:2]
\ : matchlist(l:func, '\(\S\+\), line \(\d\+\)')[1:2]
catch
let l:name = l:func
let l:offset = 0
endtry
if l:name =~# '\v(\<SNR\>|^)\d+_'
let l:sid = matchstr(l:name, '\v(\<SNR\>|^)\zs\d+\ze_')
let l:name = substitute(l:name, '\v(\<SNR\>|^)\d+_', 's:', '')
let l:filename = substitute(
\ vimtex#util#command('scriptnames')[l:sid-1],
\ '^\s*\d\+:\s*', '', '')
else
let l:func_name = l:name =~# '^\d\+$' ? '{' . l:name . '}' : l:name
let l:filename = matchstr(
\ vimtex#util#command('verbose function ' . l:func_name)[1],
\ v:lang[0:1] ==# 'en'
\ ? 'Last set from \zs.*\.vim' : '\f\+\.vim')
endif
let l:filename = fnamemodify(l:filename, ':p')
if filereadable(l:filename)
if !has_key(l:files, l:filename)
let l:files[l:filename] = reverse(readfile(l:filename))
endif
if l:name =~# '^\d\+$'
let l:lnum = 0
let l:output = vimtex#util#command('function {' . l:name . '}')
let l:text = substitute(
\ matchstr(l:output, '^\s*' . l:offset),
\ '^\d\+\s*', '', '')
else
let l:lnum = l:offset + len(l:files[l:filename])
\ - match(l:files[l:filename], '^\s*fu\%[nction]!\=\s\+' . l:name .'(')
let l:lnum_rev = len(l:files[l:filename]) - l:lnum
let l:text = substitute(l:files[l:filename][l:lnum_rev], '^\s*', '', '')
endif
else
let l:filename = ''
let l:lnum = 0
let l:text = ''
endif
call add(l:qflist, {
\ 'filename': l:filename,
\ 'function': l:name,
\ 'lnum': l:lnum,
\ 'text': len(l:qflist) == 0 ? l:exception : l:text,
\ 'nr': len(l:qflist),
\})
endfor
" Fill in empty filenames
let l:prev_filename = '_'
call reverse(l:qflist)
for l:entry in l:qflist
if empty(l:entry.filename)
let l:entry.filename = l:prev_filename
endif
let l:prev_filename = l:entry.filename
endfor
call reverse(l:qflist)
if a:0 > 0
call setqflist(l:qflist)
execute 'copen' len(l:qflist) + 2
wincmd p
endif
return l:qflist
endfunction
" }}}1
endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,251 +0,0 @@
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#doc#init_buffer() abort " {{{1
command! -buffer -nargs=? VimtexDocPackage call vimtex#doc#package(<q-args>)
nnoremap <buffer> <plug>(vimtex-doc-package) :VimtexDocPackage<cr>
endfunction
" }}}1
function! vimtex#doc#package(word) abort " {{{1
let l:context = empty(a:word)
\ ? s:packages_get_from_cursor()
\ : {
\ 'type': 'word',
\ 'candidates': [a:word],
\ }
if empty(l:context) | return | endif
call s:packages_remove_invalid(l:context)
for l:handler in g:vimtex_doc_handlers
if exists('*' . l:handler)
if call(l:handler, [l:context]) | return | endif
endif
endfor
call s:packages_open(l:context)
endfunction
" }}}1
function! vimtex#doc#make_selection(context) abort " {{{1
if has_key(a:context, 'selected') | return | endif
if len(a:context.candidates) == 0
if exists('a:context.name')
echohl ErrorMsg
echo 'Sorry, no doc for '.a:context.name
echohl NONE
endif
let a:context.selected = ''
return
endif
if len(a:context.candidates) == 1
let a:context.selected = a:context.candidates[0]
return
endif
call vimtex#echo#echo('Multiple candidates detected, please select one:')
let l:count = 0
for l:package in a:context.candidates
let l:count += 1
call vimtex#echo#formatted([
\ ' [' . string(l:count) . '] ',
\ ['VimtexSuccess', l:package]
\])
endfor
call vimtex#echo#echo('Type number (everything else cancels): ')
let l:choice = nr2char(getchar())
if l:choice !~# '\d'
\ || l:choice == 0
\ || l:choice > len(a:context.candidates)
echohl VimtexWarning
echon l:choice =~# '\d' ? l:choice : '-'
echohl NONE
let a:context.selected = ''
else
echon l:choice
let a:context.selected = a:context.candidates[l:choice-1]
let a:context.ask_before_open = 0
endif
endfunction
" }}}1
function! s:packages_get_from_cursor() abort " {{{1
let l:cmd = vimtex#cmd#get_current()
if empty(l:cmd) | return {} | endif
if l:cmd.name ==# '\usepackage'
return s:packages_from_usepackage(l:cmd)
elseif l:cmd.name ==# '\documentclass'
return s:packages_from_documentclass(l:cmd)
else
return s:packages_from_command(strpart(l:cmd.name, 1))
endif
endfunction
" }}}1
function! s:packages_from_usepackage(cmd) abort " {{{1
try
" Gather and clean up candidate list
let l:candidates = substitute(a:cmd.args[0].text, '%.\{-}\n', '', 'g')
let l:candidates = substitute(l:candidates, '\s*', '', 'g')
let l:candidates = split(l:candidates, ',')
let l:context = {
\ 'type': 'usepackage',
\ 'candidates': l:candidates,
\}
let l:cword = expand('<cword>')
if len(l:context.candidates) > 1 && index(l:context.candidates, l:cword) >= 0
let l:context.selected = l:cword
endif
return l:context
catch
call vimtex#log#warning('Could not parse the package from \usepackage!')
return {}
endtry
endfunction
" }}}1
function! s:packages_from_documentclass(cmd) abort " {{{1
try
return {
\ 'type': 'documentclass',
\ 'candidates': [a:cmd.args[0].text],
\}
catch
call vimtex#log#warning('Could not parse the package from \documentclass!')
return {}
endtry
endfunction
" }}}1
function! s:packages_from_command(cmd) abort " {{{1
let l:packages = [
\ 'default',
\ 'class-' . get(b:vimtex, 'documentclass', ''),
\] + keys(b:vimtex.packages)
call filter(l:packages, 'filereadable(s:complete_dir . v:val)')
let l:queue = copy(l:packages)
while !empty(l:queue)
let l:current = remove(l:queue, 0)
let l:includes = filter(readfile(s:complete_dir . l:current), 'v:val =~# ''^\#\s*include:''')
if empty(l:includes) | continue | endif
call map(l:includes, 'matchstr(v:val, ''include:\s*\zs.*\ze\s*$'')')
call filter(l:includes, 'filereadable(s:complete_dir . v:val)')
call filter(l:includes, 'index(l:packages, v:val) < 0')
let l:packages += l:includes
let l:queue += l:includes
endwhile
let l:candidates = []
let l:filter = 'v:val =~# ''^' . a:cmd . '\>'''
for l:package in l:packages
let l:cmds = filter(readfile(s:complete_dir . l:package), l:filter)
if empty(l:cmds) | continue | endif
if l:package ==# 'default'
call extend(l:candidates, ['latex2e', 'lshort'])
else
call add(l:candidates, substitute(l:package, '^class-', '', ''))
endif
endfor
return {
\ 'type': 'command',
\ 'name': a:cmd,
\ 'candidates': l:candidates,
\}
endfunction
" }}}1
function! s:packages_remove_invalid(context) abort " {{{1
let l:invalid_packages = filter(copy(a:context.candidates),
\ 'empty(vimtex#kpsewhich#find(v:val . ''.sty'')) && '
\ . 'empty(vimtex#kpsewhich#find(v:val . ''.cls''))')
call filter(l:invalid_packages,
\ 'index([''latex2e'', ''lshort''], v:val) < 0')
" Warn about invalid candidates
if !empty(l:invalid_packages)
if len(l:invalid_packages) == 1
call vimtex#log#warning(
\ 'Package not recognized: ' . l:invalid_packages[0])
else
call vimtex#log#warning(
\ 'Packages not recognized:',
\ map(copy(l:invalid_packages), "'- ' . v:val"))
endif
endif
" Remove invalid candidates
call filter(a:context.candidates, 'index(l:invalid_packages, v:val) < 0')
" Reset the selection if the selected candidate is not valid
if has_key(a:context, 'selected')
\ && index(a:context.candidates, a:context.selected) < 0
unlet a:context.selected
endif
endfunction
" }}}1
function! s:packages_open(context) abort " {{{1
if !has_key(a:context, 'selected')
call vimtex#doc#make_selection(a:context)
endif
if empty(a:context.selected) | return | endif
if get(a:context, 'ask_before_open', 1)
call vimtex#echo#formatted([
\ 'Open documentation for ',
\ ['VimtexSuccess', a:context.selected], ' [y/N]? '
\])
let l:choice = nr2char(getchar())
if l:choice ==# 'y'
echon 'y'
else
echohl VimtexWarning
echon l:choice =~# '\w' ? l:choice : 'N'
echohl NONE
return
endif
endif
let l:os = vimtex#util#get_os()
let l:url = 'http://texdoc.net/pkg/' . a:context.selected
silent execute (l:os ==# 'linux'
\ ? '!xdg-open'
\ : (l:os ==# 'mac'
\ ? '!open'
\ : '!start'))
\ . ' ' . l:url
\ . (l:os ==# 'win' ? '' : ' &')
redraw!
endfunction
" }}}1
let s:complete_dir = fnamemodify(expand('<sfile>'), ':h') . '/complete/'
endif

View File

@@ -1,121 +0,0 @@
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#echo#echo(message) abort " {{{1
echohl VimtexMsg
echo a:message
echohl None
endfunction
" }}}1
function! vimtex#echo#input(opts) abort " {{{1
if g:vimtex_echo_verbose_input
\ && has_key(a:opts, 'info')
call vimtex#echo#formatted(a:opts.info)
endif
let l:args = [get(a:opts, 'prompt', '> ')]
let l:args += [get(a:opts, 'default', '')]
if has_key(a:opts, 'complete')
let l:args += [a:opts.complete]
endif
echohl VimtexMsg
let l:reply = call('input', l:args)
echohl None
return l:reply
endfunction
" }}}1
function! vimtex#echo#choose(list_or_dict, prompt) abort " {{{1
if empty(a:list_or_dict) | return '' | endif
return type(a:list_or_dict) == type({})
\ ? s:choose_dict(a:list_or_dict, a:prompt)
\ : s:choose_list(a:list_or_dict, a:prompt)
endfunction
" }}}1
function! vimtex#echo#formatted(parts) abort " {{{1
echo ''
try
for part in a:parts
if type(part) == type('')
echohl VimtexMsg
echon part
else
execute 'echohl' part[0]
echon part[1]
endif
unlet part
endfor
finally
echohl None
endtry
endfunction
" }}}1
function! s:choose_dict(dict, prompt) abort " {{{1
if len(a:dict) == 1
return values(a:dict)[0]
endif
while 1
redraw!
if !empty(a:prompt)
echohl VimtexMsg
unsilent echo a:prompt
echohl None
endif
let l:choice = 0
for l:x in values(a:dict)
let l:choice += 1
unsilent call vimtex#echo#formatted([['VimtexWarning', l:choice], ': ', l:x])
endfor
try
let l:choice = str2nr(input('> ')) - 1
if l:choice >= 0 && l:choice < len(a:dict)
return keys(a:dict)[l:choice]
endif
endtry
endwhile
endfunction
" }}}1
function! s:choose_list(list, prompt) abort " {{{1
if len(a:list) == 1 | return a:list[0] | endif
while 1
redraw!
if !empty(a:prompt)
echohl VimtexMsg
unsilent echo a:prompt
echohl None
endif
let l:choice = 0
for l:x in a:list
let l:choice += 1
unsilent call vimtex#echo#formatted([['VimtexWarning', l:choice], ': ', l:x])
endfor
try
let l:choice = str2nr(input('> ')) - 1
if l:choice >= 0 && l:choice < len(a:list)
return a:list[l:choice]
endif
endtry
endwhile
endfunction
" }}}1
endif

View File

@@ -1,202 +0,0 @@
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#env#init_buffer() abort " {{{1
nnoremap <silent><buffer> <plug>(vimtex-env-delete)
\ :<c-u>call <sid>operator_setup('delete', 'env_tex')<bar>normal! g@l<cr>
nnoremap <silent><buffer> <plug>(vimtex-env-change)
\ :<c-u>call <sid>operator_setup('change', 'env_tex')<bar>normal! g@l<cr>
nnoremap <silent><buffer> <plug>(vimtex-env-delete-math)
\ :<c-u>call <sid>operator_setup('delete', 'env_math')<bar>normal! g@l<cr>
nnoremap <silent><buffer> <plug>(vimtex-env-change-math)
\ :<c-u>call <sid>operator_setup('change', 'env_math')<bar>normal! g@l<cr>
nnoremap <silent><buffer> <plug>(vimtex-env-toggle-star)
\ :<c-u>call <sid>operator_setup('toggle_star', '')<bar>normal! g@l<cr>
endfunction
" }}}1
function! vimtex#env#change(open, close, new) abort " {{{1
"
" Set target environment
"
if a:new ==# ''
let [l:beg, l:end] = ['', '']
elseif a:new ==# '$'
let [l:beg, l:end] = ['$', '$']
elseif a:new ==# '$$'
let [l:beg, l:end] = ['$$', '$$']
elseif a:new ==# '\['
let [l:beg, l:end] = ['\[', '\]']
elseif a:new ==# '\('
let [l:beg, l:end] = ['\(', '\)']
else
let l:beg = '\begin{' . a:new . '}'
let l:end = '\end{' . a:new . '}'
endif
let l:line = getline(a:open.lnum)
call setline(a:open.lnum,
\ strpart(l:line, 0, a:open.cnum-1)
\ . l:beg
\ . strpart(l:line, a:open.cnum + len(a:open.match) - 1))
let l:c1 = a:close.cnum
let l:c2 = a:close.cnum + len(a:close.match) - 1
if a:open.lnum == a:close.lnum
let n = len(l:beg) - len(a:open.match)
let l:c1 += n
let l:c2 += n
let pos = vimtex#pos#get_cursor()
if pos[2] > a:open.cnum + len(a:open.match) - 1
let pos[2] += n
call vimtex#pos#set_cursor(pos)
endif
endif
let l:line = getline(a:close.lnum)
call setline(a:close.lnum,
\ strpart(l:line, 0, l:c1-1) . l:end . strpart(l:line, l:c2))
endfunction
function! vimtex#env#change_surrounding_to(type, new) abort " {{{1
let [l:open, l:close] = vimtex#delim#get_surrounding(a:type)
if empty(l:open) | return | endif
return vimtex#env#change(l:open, l:close, a:new)
endfunction
function! vimtex#env#delete(type) abort " {{{1
let [l:open, l:close] = vimtex#delim#get_surrounding(a:type)
if empty(l:open) | return | endif
if a:type ==# 'env_tex'
call vimtex#cmd#delete_all(l:close)
call vimtex#cmd#delete_all(l:open)
else
call l:close.remove()
call l:open.remove()
endif
if getline(l:close.lnum) =~# '^\s*$'
execute l:close.lnum . 'd _'
endif
if getline(l:open.lnum) =~# '^\s*$'
execute l:open.lnum . 'd _'
endif
endfunction
function! vimtex#env#toggle_star() abort " {{{1
let [l:open, l:close] = vimtex#delim#get_surrounding('env_tex')
if empty(l:open) | return | endif
call vimtex#env#change(l:open, l:close,
\ l:open.starred ? l:open.name : l:open.name . '*')
endfunction
" }}}1
function! vimtex#env#is_inside(env) abort " {{{1
let l:re_start = '\\begin\s*{' . a:env . '\*\?}'
let l:re_end = '\\end\s*{' . a:env . '\*\?}'
try
return searchpairpos(l:re_start, '', l:re_end, 'bnW', '', 0, 100)
catch /E118/
let l:stopline = max([line('.') - 500, 1])
return searchpairpos(l:re_start, '', l:re_end, 'bnW', '', l:stopline)
endtry
endfunction
" }}}1
function! vimtex#env#input_complete(lead, cmdline, pos) abort " {{{1
let l:cands = map(vimtex#complete#complete('env', '', '\begin'), 'v:val.word')
" Never include document and remove current env (place it first)
call filter(l:cands, 'index([''document'', s:env_name], v:val) < 0')
" Always include current env and displaymath
let l:cands = [s:env_name] + l:cands + ['\[']
return filter(l:cands, 'v:val =~# ''^' . a:lead . '''')
endfunction
" }}}1
function! s:change_prompt(type) abort " {{{1
let [l:open, l:close] = vimtex#delim#get_surrounding(a:type)
if empty(l:open) | return | endif
if g:vimtex_env_change_autofill
let l:name = get(l:open, 'name', l:open.match)
let s:env_name = l:name
return vimtex#echo#input({
\ 'prompt' : 'Change surrounding environment: ',
\ 'default' : l:name,
\ 'complete' : 'customlist,vimtex#env#input_complete',
\})
else
let l:name = get(l:open, 'name', l:open.is_open
\ ? l:open.match . ' ... ' . l:open.corr
\ : l:open.match . ' ... ' . l:open.corr)
let s:env_name = l:name
return vimtex#echo#input({
\ 'info' :
\ ['Change surrounding environment: ', ['VimtexWarning', l:name]],
\ 'complete' : 'customlist,vimtex#env#input_complete',
\})
endif
endfunction
" }}}1
function! s:operator_setup(operator, type) abort " {{{1
let &opfunc = s:snr() . 'operator_function'
let s:operator_abort = 0
let s:operator = a:operator
let s:operator_type = a:type
" Ask for user input if necessary/relevant
if s:operator ==# 'change'
let l:new_env = s:change_prompt(s:operator_type)
if empty(l:new_env)
let s:operator_abort = 1
return
endif
let s:operator_name = l:new_env
endif
endfunction
" }}}1
function! s:operator_function(_) abort " {{{1
if get(s:, 'operator_abort', 0) | return | endif
let l:type = get(s:, 'operator_type', '')
let l:name = get(s:, 'operator_name', '')
execute 'call vimtex#env#' . {
\ 'change': 'change_surrounding_to(l:type, l:name)',
\ 'delete': 'delete(l:type)',
\ 'toggle_star': 'toggle_star()',
\ }[s:operator]
endfunction
" }}}1
function! s:snr() abort " {{{1
return matchstr(expand('<sfile>'), '<SNR>\d\+_')
endfunction
" }}}1
endif

View File

@@ -1,143 +0,0 @@
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#fold#init_buffer() abort " {{{1
if !g:vimtex_fold_enabled
\ || s:foldmethod_in_modeline() | return | endif
" Set fold options
setlocal foldmethod=expr
setlocal foldexpr=vimtex#fold#level(v:lnum)
setlocal foldtext=vimtex#fold#text()
if g:vimtex_fold_manual
" Remap zx to refresh fold levels
nnoremap <silent><nowait><buffer> zx :call vimtex#fold#refresh('zx')<cr>
nnoremap <silent><nowait><buffer> zX :call vimtex#fold#refresh('zX')<cr>
" Define commands
command! -buffer VimtexRefreshFolds call vimtex#fold#refresh('zx')
" Ensure that folds are refreshed on startup
augroup vimtex_temporary
autocmd! * <buffer>
autocmd CursorMoved <buffer>
\ call vimtex#fold#refresh('zx')
\ | autocmd! vimtex_temporary CursorMoved <buffer>
augroup END
endif
endfunction
" }}}1
function! vimtex#fold#init_state(state) abort " {{{1
"
" Initialize the enabled fold types
"
let a:state.fold_types_dict = {}
for [l:key, l:val] in items(g:vimtex_fold_types_defaults)
let l:config = extend(deepcopy(l:val), get(g:vimtex_fold_types, l:key, {}))
if get(l:config, 'enabled', 1)
let a:state.fold_types_dict[l:key] = vimtex#fold#{l:key}#new(l:config)
endif
endfor
"
" Define ordered list and the global fold regex
"
let a:state.fold_types_ordered = []
let a:state.fold_re = '\v'
\ . '\\%(begin|end)>'
\ . '|^\s*\%'
\ . '|^\s*\]\s*%(\{|$)'
\ . '|^\s*}'
for l:name in [
\ 'preamble',
\ 'cmd_single',
\ 'cmd_single_opt',
\ 'cmd_multi',
\ 'cmd_addplot',
\ 'sections',
\ 'markers',
\ 'comments',
\ 'envs',
\ 'env_options',
\]
let l:type = get(a:state.fold_types_dict, l:name, {})
if !empty(l:type)
call add(a:state.fold_types_ordered, l:type)
if exists('l:type.re.fold_re')
let a:state.fold_re .= '|' . l:type.re.fold_re
endif
endif
endfor
endfunction
" }}}1
function! vimtex#fold#refresh(map) abort " {{{1
setlocal foldmethod=expr
execute 'normal!' a:map
setlocal foldmethod=manual
endfunction
" }}}1
function! vimtex#fold#level(lnum) abort " {{{1
let l:line = getline(a:lnum)
" Filter out lines that do not start any folds (optimization)
if l:line !~# b:vimtex.fold_re | return '=' | endif
" Never fold \begin|end{document}
if l:line =~# '^\s*\\\%(begin\|end\){document}'
return 0
endif
for l:type in b:vimtex.fold_types_ordered
let l:value = l:type.level(l:line, a:lnum)
if !empty(l:value) | return l:value | endif
endfor
" Return foldlevel of previous line
return '='
endfunction
" }}}1
function! vimtex#fold#text() abort " {{{1
let l:line = getline(v:foldstart)
let l:level = v:foldlevel > 1
\ ? repeat('-', v:foldlevel-2) . g:vimtex_fold_levelmarker
\ : ''
for l:type in b:vimtex.fold_types_ordered
if l:line =~# l:type.re.start
let l:text = l:type.text(l:line, l:level)
if !empty(l:text) | return l:text | endif
endif
endfor
endfunction
" }}}1
function! s:foldmethod_in_modeline() abort " {{{1
let l:cursor_pos = vimtex#pos#get_cursor()
let l:fdm_modeline = 'vim:.*\%(foldmethod\|fdm\)'
call vimtex#pos#set_cursor(1, 1)
let l:check_top = search(l:fdm_modeline, 'cn', &modelines)
normal! G$
let l:check_btm = search(l:fdm_modeline, 'b', line('$') + 1 - &modelines)
call vimtex#pos#set_cursor(l:cursor_pos)
return l:check_top || l:check_btm
endfunction
" }}}1
endif

View File

@@ -1,51 +0,0 @@
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#fold#cmd_addplot#new(config) abort " {{{1
return extend(deepcopy(s:folder), a:config).init()
endfunction
" }}}1
let s:folder = {
\ 'name' : 'cmd_addplot',
\ 're' : {},
\ 'opened' : 0,
\ 'cmds' : [],
\}
function! s:folder.init() abort dict " {{{1
let l:re = '\v^\s*\\%(' . join(self.cmds, '|') . ')\s*%(\[[^\]]*\])?'
let self.re.start = l:re . '\s*\w+\s*%(\[[^\]]*\])?\s*\ze\{\s*%($|\%)'
let self.re.end = '^\s*}'
let self.re.fold_re = '\\%(' . join(self.cmds, '|') . ')'
return self
endfunction
" }}}1
function! s:folder.level(line, lnum) abort dict " {{{1
if a:line =~# self.re.start
let self.opened = 1
return 'a1'
elseif self.opened && a:line =~# self.re.end
let self.opened = 0
return 's1'
endif
endfunction
" }}}1
function! s:folder.text(line, level) abort dict " {{{1
return matchstr(a:line, self.re.start) . '{...}'
\ . substitute(getline(v:foldend), self.re.end, '', '')
endfunction
" }}}1
endif

View File

@@ -1,51 +0,0 @@
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#fold#cmd_multi#new(config) abort " {{{1
return extend(deepcopy(s:folder), a:config).init()
endfunction
" }}}1
let s:folder = {
\ 'name' : 'cmd_multi',
\ 're' : {},
\ 'opened' : 0,
\ 'cmds' : [],
\}
function! s:folder.init() abort dict " {{{1
let l:re = '\v^\s*\\%(' . join(self.cmds, '|') . ')\*?'
let self.re.start = l:re . '.*(\{|\[)\s*(\%.*)?$'
let self.re.end = '\v^\s*%(\}\s*\{)*\}\s*%(\%|$)'
let self.re.text = l:re . '\{[^}]*\}'
let self.re.fold_re = '\\%(' . join(self.cmds, '|') . ')'
return self
endfunction
" }}}1
function! s:folder.level(line, lnum) abort dict " {{{1
if a:line =~# self.re.start
let self.opened += 1
return 'a1'
elseif self.opened > 0 && a:line =~# self.re.end
let self.opened -= 1
return 's1'
endif
endfunction
" }}}1
function! s:folder.text(line, level) abort dict " {{{1
return a:line
endfunction
" }}}1
endif

View File

@@ -1,52 +0,0 @@
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#fold#cmd_single#new(config) abort " {{{1
return extend(deepcopy(s:folder), a:config).init()
endfunction
" }}}1
let s:folder = {
\ 'name' : 'cmd_single',
\ 're' : {},
\ 'opened' : 0,
\ 'cmds' : [],
\}
function! s:folder.init() abort dict " {{{1
let l:re = '\v^\s*\\%(' . join(self.cmds, '|') . ')\*?\s*%(\[.*\])?'
let self.re.start = l:re . '\s*\{\s*%($|\%)'
let self.re.end = '^\s*}'
let self.re.text = l:re
let self.re.fold_re = '\\%(' . join(self.cmds, '|') . ')'
return self
endfunction
" }}}1
function! s:folder.level(line, lnum) abort dict " {{{1
if a:line =~# self.re.start
let self.opened = 1
return 'a1'
elseif self.opened && a:line =~# self.re.end
let self.opened = 0
return 's1'
endif
endfunction
" }}}1
function! s:folder.text(line, level) abort dict " {{{1
return matchstr(a:line, self.re.text) . '{...}'
\ . substitute(getline(v:foldend), self.re.end, '', '')
endfunction
" }}}1
endif

View File

@@ -1,53 +0,0 @@
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#fold#cmd_single_opt#new(config) abort " {{{1
return extend(deepcopy(s:folder), a:config).init()
endfunction
" }}}1
let s:folder = {
\ 'name' : 'cmd_single_opt',
\ 're' : {},
\ 'opened' : 0,
\ 'cmds' : [],
\}
function! s:folder.init() abort dict " {{{1
let l:re = '\v^\s*\\%(' . join(self.cmds, '|') . ')\*?'
let self.re.start = l:re . '\s*\[\s*%($|\%)'
let self.re.end = '^\s*\]{'
let self.re.text = l:re
let self.re.fold_re = '\\%(' . join(self.cmds, '|') . ')'
return self
endfunction
" }}}1
function! s:folder.level(line, lnum) abort dict " {{{1
if a:line =~# self.re.start
let self.opened = 1
return 'a1'
elseif self.opened && a:line =~# self.re.end
let self.opened = 0
return 's1'
endif
endfunction
" }}}1
function! s:folder.text(line, level) abort dict " {{{1
let l:col = strlen(matchstr(a:line, '^\s*')) + 1
return matchstr(a:line, self.re.text) . '[...]{'
\ . vimtex#cmd#get_at(v:foldstart, l:col).args[0].text . '}'
endfunction
" }}}1
endif

View File

@@ -1,46 +0,0 @@
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#fold#comments#new(config) abort " {{{1
return extend(deepcopy(s:folder), a:config)
endfunction
" }}}1
let s:folder = {
\ 'name' : 'comments',
\ 're' : {'start' : '^\s*%'},
\ 'opened' : 0,
\}
function! s:folder.level(line, lnum) abort dict " {{{1
if exists('b:vimtex.fold_types_dict.markers.opened')
\ && b:vimtex.fold_types_dict.markers.opened | return | endif
if a:line =~# self.re.start
let l:next = getline(a:lnum-1) !~# self.re.start
let l:prev = getline(a:lnum+1) !~# self.re.start
if l:next && !l:prev
let self.opened = 1
return 'a1'
elseif l:prev && !l:next
let self.opened = 0
return 's1'
endif
endif
endfunction
" }}}1
function! s:folder.text(line, level) abort dict " {{{1
let l:lines = map(getline(v:foldstart, v:foldend), 'matchstr(v:val, ''%\s*\zs.*\ze\s*'')')
return matchstr(a:line, '^.*\s*%') . join(l:lines, ' ')
endfunction
" }}}1
endif

View File

@@ -1,53 +0,0 @@
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#fold#env_options#new(config) abort " {{{1
return extend(deepcopy(s:folder), a:config)
endfunction
" }}}1
let s:folder = {
\ 'name' : 'envs with options',
\ 're' : {
\ 'start' : g:vimtex#re#not_comment . '\\begin\s*\{.{-}\}\[\s*($|\%)',
\ 'end' : '\s*\]\s*$',
\ },
\ 'opened' : 0,
\}
function! s:folder.level(line, lnum) abort dict " {{{1
return self.opened
\ ? self.fold_closed(a:line, a:lnum)
\ : self.fold_opened(a:line, a:lnum)
endfunction
" }}}1
function! s:folder.fold_opened(line, lnum) abort dict " {{{1
if a:line =~# self.re.start
let self.opened = 1
return 'a1'
endif
endfunction
" }}}1
function! s:folder.fold_closed(line, lnum) abort dict " {{{1
if a:line =~# self.re.end
let self.opened = 0
return 's1'
endif
endfunction
" }}}1
function! s:folder.text(line, level) abort dict " {{{1
return a:line . '...] '
endfunction
" }}}1
endif

View File

@@ -1,188 +0,0 @@
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#fold#envs#new(config) abort " {{{1
return extend(deepcopy(s:folder), a:config).init()
endfunction
" }}}1
let s:folder = {
\ 'name' : 'environments',
\ 're' : {
\ 'start' : g:vimtex#re#not_comment . '\\begin\s*\{.{-}\}',
\ 'end' : g:vimtex#re#not_comment . '\\end\s*\{.{-}\}',
\ 'name' : g:vimtex#re#not_comment . '\\%(begin|end)\s*\{\zs.{-}\ze\}'
\ },
\ 'whitelist' : [],
\ 'blacklist' : [],
\}
function! s:folder.init() abort dict " {{{1
" Define the validator as simple as possible
if empty(self.whitelist) && empty(self.blacklist)
function! self.validate(env) abort dict
return 1
endfunction
elseif empty(self.whitelist)
function! self.validate(env) abort dict
return index(self.blacklist, a:env) < 0
endfunction
elseif empty(self.blacklist)
function! self.validate(env) abort dict
return index(self.whitelist, a:env) >= 0
endfunction
else
function! self.validate(env) abort dict
return index(self.whitelist, a:env) >= 0 && index(self.blacklist, a:env) < 0
endfunction
endif
return self
endfunction
" }}}1
function! s:folder.level(line, lnum) abort dict " {{{1
let l:env = matchstr(a:line, self.re.name)
if !empty(l:env) && self.validate(l:env)
if a:line =~# self.re.start
if a:line !~# '\\end'
return 'a1'
endif
elseif a:line =~# self.re.end
if a:line !~# '\\begin'
return 's1'
endif
endif
endif
endfunction
" }}}1
function! s:folder.text(line, level) abort dict " {{{1
let env = matchstr(a:line, self.re.name)
if !self.validate(env) | return | endif
" Set caption/label based on type of environment
if env ==# 'frame'
let label = ''
let caption = self.parse_caption_frame(a:line)
elseif env ==# 'table'
let label = self.parse_label()
let caption = self.parse_caption_table(a:line)
else
let label = self.parse_label()
let caption = self.parse_caption(a:line)
endif
let width_ind = len(matchstr(a:line, '^\s*'))
let width = winwidth(0) - (&number ? &numberwidth : 0) - 4 - width_ind
let width_env = 19
let width_lab = len(label) + 2 > width - width_env
\ ? width - width_env
\ : len(label) + 2
let width_cap = width - width_env - width_lab
if !empty(label)
let label = printf('(%.*S)', width_lab, label)
endif
if !empty(caption)
if strchars(caption) > width_cap
let caption = strpart(caption, 0, width_cap - 4) . '...'
endif
else
let width_env += width_cap
let width_cap = 0
endif
if strlen(env) > width_env - 8
let env = strpart(env, 0, width_env - 11) . '...'
endif
let env = '\begin{' . env . '}'
let title = printf('%*S%-*S %-*S %*S',
\ width_ind, '',
\ width_env, env,
\ width_cap, caption,
\ width_lab, label)
return substitute(title, '\s\+$', '', '')
endfunction
" }}}1
function! s:folder.parse_label() abort dict " {{{1
let i = v:foldend
while i >= v:foldstart
if getline(i) =~# '^\s*\\label'
return matchstr(getline(i), '^\s*\\label\%(\[.*\]\)\?{\zs.*\ze}')
end
let i -= 1
endwhile
return ''
endfunction
" }}}1
function! s:folder.parse_caption(line) abort dict " {{{1
let i = v:foldend
while i >= v:foldstart
if getline(i) =~# '^\s*\\caption'
return matchstr(getline(i),
\ '^\s*\\caption\(\[.*\]\)\?{\zs.\{-1,}\ze\(}\s*\)\?$')
end
let i -= 1
endwhile
" If no caption found, check for a caption comment
return matchstr(a:line,'\\begin\*\?{.*}\s*%\s*\zs.*')
endfunction
" }}}1
function! s:folder.parse_caption_table(line) abort dict " {{{1
let i = v:foldstart
while i <= v:foldend
if getline(i) =~# '^\s*\\caption'
return matchstr(getline(i),
\ '^\s*\\caption\s*\(\[.*\]\)\?\s*{\zs.\{-1,}\ze\(}\s*\)\?$')
end
let i += 1
endwhile
" If no caption found, check for a caption comment
return matchstr(a:line,'\\begin\*\?{.*}\s*%\s*\zs.*')
endfunction
" }}}1
function! s:folder.parse_caption_frame(line) abort dict " {{{1
" Test simple variants first
let caption1 = matchstr(a:line,'\\begin\*\?{.*}\(\[[^]]*\]\)\?{\zs.\+\ze}')
let caption2 = matchstr(a:line,'\\begin\*\?{.*}\(\[[^]]*\]\)\?{\zs.\+')
if !empty(caption1)
return caption1
elseif !empty(caption2)
return caption2
endif
" Search for \frametitle command
let i = v:foldstart
while i <= v:foldend
if getline(i) =~# '^\s*\\frametitle'
return matchstr(getline(i),
\ '^\s*\\frametitle\(\[.*\]\)\?{\zs.\{-1,}\ze\(}\s*\)\?$')
end
let i += 1
endwhile
" If no caption found, check for a caption comment
return matchstr(a:line,'\\begin\*\?{.*}\s*%\s*\zs.*')
endfunction
" }}}1
endif

View File

@@ -1,60 +0,0 @@
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#fold#markers#new(config) abort " {{{1
return extend(deepcopy(s:folder), a:config).init()
endfunction
" }}}1
let s:folder = {
\ 'name' : 'markers',
\ 'open' : '{{{',
\ 'close' : '}}}',
\ 're' : {},
\ 'opened' : 0,
\}
function! s:folder.init() abort dict " {{{1
let self.re.start = '%.*' . self.open
let self.re.end = '%.*' . self.close
let self.re.text = [
\ [self.re.start . '\d\?\s*\zs.*', '% ' . self.open . ' '],
\ ['%\s*\zs.*\ze' . self.open, '% ' . self.open . ' '],
\ ['^.*\ze\s*%', ''],
\]
let self.re.fold_re = escape(self.open . '|' . self.close, '{}%+*.')
return self
endfunction
" }}}1
function! s:folder.level(line, lnum) abort dict " {{{1
if a:line =~# self.re.start
let s:self.opened = 1
return 'a1'
elseif a:line =~# self.re.end
let s:self.opened = 0
return 's1'
endif
endfunction
" }}}1
function! s:folder.text(line, level) abort dict " {{{1
for [l:re, l:pre] in self.re.text
let l:text = matchstr(a:line, l:re)
if !empty(l:text) | return l:pre . l:text | endif
endfor
return '% ' . self.open . ' ' . getline(v:foldstart + 1)
endfunction
" }}}1
endif

View File

@@ -1,36 +0,0 @@
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#fold#preamble#new(config) abort " {{{1
return extend(deepcopy(s:folder), a:config)
endfunction
" }}}1
let s:folder = {
\ 'name' : 'preamble',
\ 're' : {
\ 'start' : '^\s*\\documentclass',
\ 'fold_re' : '\\documentclass',
\ },
\}
function! s:folder.level(line, lnum) abort dict " {{{1
if a:line =~# self.re.start
return '>1'
endif
endfunction
" }}}1
function! s:folder.text(line, level) abort dict " {{{1
return ' Preamble'
endfunction
" }}}1
endif

View File

@@ -1,180 +0,0 @@
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#fold#sections#new(config) abort " {{{1
return extend(deepcopy(s:folder), a:config).init()
endfunction
" }}}1
let s:folder = {
\ 'name' : 'sections',
\ 'parse_levels' : 0,
\ 're' : {},
\ 'folds' : [],
\ 'sections' : [],
\ 'parts' : [],
\ 'time' : 0,
\}
function! s:folder.init() abort dict " {{{1
let self.re.parts = '\v^\s*\\%(' . join(self.parts, '|') . ')'
let self.re.sections = '\v^\s*\\%(' . join(self.sections, '|') . ')'
let self.re.fake_sections = '\v^\s*\% Fake%('
\ . join(self.sections, '|') . ').*'
let self.re.any_sections = '\v^\s*%(\\|\% Fake)%('
\ . join(self.sections, '|') . ').*'
let self.re.start = self.re.parts
\ . '|' . self.re.sections
\ . '|' . self.re.fake_sections
let self.re.secpat1 = self.re.sections . '\*?\s*\{\zs.*'
let self.re.secpat2 = self.re.sections . '\*?\s*\[\zs.*'
let self.re.fold_re = '\\%(' . join(self.parts + self.sections, '|') . ')'
return self
endfunction
" }}}1
function! s:folder.level(line, lnum) abort dict " {{{1
call self.refresh()
" Fold chapters and sections
for [l:part, l:level] in self.folds
if a:line =~# l:part
return '>' . l:level
endif
endfor
endfunction
" }}}1
function! s:folder.text(line, level) abort dict " {{{1
if a:line =~# '\\frontmatter'
let l:title = 'Frontmatter'
elseif a:line =~# '\\mainmatter'
let l:title = 'Mainmatter'
elseif a:line =~# '\\backmatter'
let l:title = 'Backmatter'
elseif a:line =~# '\\appendix'
let l:title = 'Appendix'
elseif a:line =~# self.re.secpat1
let l:title = self.parse_title(matchstr(a:line, self.re.secpat1), 0)
elseif a:line =~# self.re.secpat2
let l:title = self.parse_title(matchstr(a:line, self.re.secpat2), 1)
elseif a:line =~# self.re.fake_sections
let l:title = matchstr(a:line, self.re.fake_sections)
endif
let l:level = self.parse_level(v:foldstart, a:level)
return printf('%-5s %-s', l:level,
\ substitute(strpart(l:title, 0, winwidth(0) - 7), '\s\+$', '', ''))
endfunction
" }}}1
function! s:folder.parse_level(lnum, level) abort dict " {{{1
if !self.parse_levels | return a:level | endif
if !has_key(self, 'toc')
let self.toc = vimtex#toc#new({
\ 'name' : 'Fold text ToC',
\ 'layers' : ['content'],
\ 'refresh_always' : 0,
\})
let self.toc_updated = 0
let self.file_updated = {}
endif
let l:file = expand('%')
let l:ftime = getftime(l:file)
if l:ftime > get(self.file_updated, l:file)
\ || localtime() > self.toc_updated + 300
call self.toc.get_entries(1)
let self.toc_entries = filter(
\ self.toc.get_visible_entries(),
\ '!empty(v:val.number)')
let self.file_updated[l:file] = l:ftime
let self.toc_updated = localtime()
endif
let l:entries = filter(deepcopy(self.toc_entries), 'v:val.line == a:lnum')
if len(l:entries) > 1
call filter(l:entries, "v:val.file ==# expand('%:p')")
endif
return empty(l:entries) ? '' : self.toc.print_number(l:entries[0].number)
endfunction
" }}}1
function! s:folder.parse_title(string, type) abort dict " {{{1
let l:idx = -1
let l:length = strlen(a:string)
let l:level = 1
while l:level >= 1
let l:idx += 1
if l:idx > l:length
break
elseif a:string[l:idx] ==# ['}',']'][a:type]
let l:level -= 1
elseif a:string[l:idx] ==# ['{','['][a:type]
let l:level += 1
endif
endwhile
let l:parsed = strpart(a:string, 0, l:idx)
return empty(l:parsed)
\ ? '<untitled>' : l:parsed
endfunction
" }}}1
function! s:folder.refresh() abort dict " {{{1
"
" Parse current buffer to find which sections to fold and their levels. The
" patterns are predefined to optimize the folding.
"
" We ignore top level parts such as \frontmatter, \appendix, \part, and
" similar, unless there are at least two such commands in a document.
"
" Only refresh if file has been changed
let l:time = getftime(expand('%'))
if l:time == self.time | return | endif
let self.time = l:time
" Initialize
let self.folds = []
let level = 0
let buffer = getline(1,'$')
" Parse part commands (frontmatter, appendix, etc)
" Note: We want a minimum of two top level parts
let lines = filter(copy(buffer), 'v:val =~ ''' . self.re.parts . '''')
if len(lines) >= 2
let level += 1
call insert(self.folds, [self.re.parts, level])
endif
" Parse section commands (part, chapter, [sub...]section)
let lines = filter(copy(buffer), 'v:val =~ ''' . self.re.any_sections . '''')
for part in self.sections
let partpattern = '^\s*\%(\\\|% Fake\)' . part . ':\?\>'
for line in lines
if line =~# partpattern
let level += 1
call insert(self.folds, [partpattern, level])
break
endif
endfor
endfor
endfunction
" }}}1
endif

View File

@@ -1,217 +0,0 @@
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#format#init_buffer() abort " {{{1
if !g:vimtex_format_enabled | return | endif
setlocal formatexpr=vimtex#format#formatexpr()
endfunction
" }}}1
function! vimtex#format#formatexpr() abort " {{{1
if mode() =~# '[iR]' | return -1 | endif
" Temporary disable folds and save view
let l:save_view = winsaveview()
let l:foldenable = &l:foldenable
setlocal nofoldenable
let l:top = v:lnum
let l:bottom = v:lnum + v:count - 1
let l:lines_old = getline(l:top, l:bottom)
let l:tries = 5
let s:textwidth = &l:textwidth == 0 ? 79 : &l:textwidth
" This is a hack to make undo restore the correct position
if mode() !=# 'i'
normal! ix
normal! x
endif
" Main formatting algorithm
while l:tries > 0
" Format the range of lines
let l:bottom = s:format(l:top, l:bottom)
" Ensure proper indentation
if l:top < l:bottom
silent! execute printf('normal! %sG=%sG', l:top+1, l:bottom)
endif
" Check if any lines have changed
let l:lines_new = getline(l:top, l:bottom)
let l:index = s:compare_lines(l:lines_new, l:lines_old)
let l:top += l:index
if l:top > l:bottom | break | endif
let l:lines_old = l:lines_new[l:index : -1]
let l:tries -= 1
endwhile
" Restore fold and view
let &l:foldenable = l:foldenable
call winrestview(l:save_view)
" Set cursor at appropriate position
execute 'normal!' l:bottom . 'G^'
" Don't change the text if the formatting algorithm failed
if l:tries == 0
silent! undo
call vimtex#log#warning('Formatting of selected text failed!')
endif
endfunction
" }}}1
function! s:format(top, bottom) abort " {{{1
let l:bottom = a:bottom
let l:mark = a:bottom
for l:current in range(a:bottom, a:top, -1)
let l:line = getline(l:current)
if vimtex#util#in_mathzone(l:current, 1)
\ && vimtex#util#in_mathzone(l:current, col([l:current, '$']))
let l:mark = l:current - 1
continue
endif
" Skip all lines with comments
if l:line =~# '\v%(^|[^\\])\%'
if l:current < l:mark
let l:bottom += s:format_build_lines(l:current+1, l:mark)
endif
let l:mark = l:current - 1
continue
endif
" Handle long lines
if strdisplaywidth(l:line) > s:textwidth
let l:bottom += s:format_build_lines(l:current, l:mark)
let l:mark = l:current-1
endif
if l:line =~# s:border_end
if l:current < l:mark
let l:bottom += s:format_build_lines(l:current+1, l:mark)
endif
let l:mark = l:current
endif
if l:line =~# s:border_beginning
if l:current < l:mark
let l:bottom += s:format_build_lines(l:current, l:mark)
endif
let l:mark = l:current-1
endif
if l:line =~# '^\s*$'
let l:bottom += s:format_build_lines(l:current+1, l:mark)
let l:mark = l:current-1
endif
endfor
if a:top <= l:mark
let l:bottom += s:format_build_lines(a:top, l:mark)
endif
return l:bottom
endfunction
" }}}1
function! s:format_build_lines(start, end) abort " {{{1
"
" Get the desired text to format as a list of words, but preserve the ending
" line spaces
"
let l:text = join(map(getline(a:start, a:end),
\ 'substitute(v:val, ''^\s*'', '''', '''')'), ' ')
let l:spaces = matchstr(l:text, '\s*$')
let l:words = split(l:text, ' ')
if empty(l:words) | return 0 | endif
"
" Add the words in properly indented and formatted lines
"
let l:lnum = a:start-1
let l:current = s:get_indents(indent(a:start))
for l:word in l:words
if strdisplaywidth(l:word) + strdisplaywidth(l:current) > s:textwidth
call append(l:lnum, substitute(l:current, '\s$', '', ''))
let l:lnum += 1
let l:current = s:get_indents(VimtexIndent(a:start))
endif
let l:current .= l:word . ' '
endfor
if l:current !~# '^\s*$'
call append(l:lnum, substitute(l:current, '\s$', '', ''))
let l:lnum += 1
endif
"
" Append the ending line spaces
"
if !empty(l:spaces)
call setline(l:lnum, getline(l:lnum) . l:spaces)
endif
"
" Remove old text
"
silent! execute printf('%s;+%s delete', l:lnum+1, a:end-a:start)
"
" Return the difference between number of lines of old and new text
"
return l:lnum - a:end
endfunction
" }}}1
function! s:compare_lines(new, old) abort " {{{1
let l:min_length = min([len(a:new), len(a:old)])
for l:i in range(l:min_length)
if a:new[l:i] !=# a:old[l:i]
return l:i
endif
endfor
return l:min_length
endfunction
" }}}1
function! s:get_indents(number) abort " {{{1
return !&l:expandtab && &l:shiftwidth == &l:tabstop
\ ? repeat("\t", a:number/&l:tabstop)
\ : repeat(' ', a:number)
endfunction
" }}}1
" {{{1 Initialize module
let s:border_beginning = '\v^\s*%(' . join([
\ '\\item',
\ '\\begin',
\ '\\end',
\ '%(\\\[|\$\$)\s*$',
\], '|') . ')'
let s:border_end = '\v\\%(' . join([
\ '\\\*?',
\ 'clear%(double)?page',
\ 'linebreak',
\ 'new%(line|page)',
\ 'pagebreak',
\ '%(begin|end)\{[^}]*\}',
\ ], '|') . ')\s*$'
\ . '|^\s*%(\\\]|\$\$)\s*$'
" }}}1
endif

View File

@@ -1,114 +0,0 @@
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#fzf#run(...) abort " {{{1
" Arguments: Two optional arguments
"
" First argument: ToC filter (default: 'ctli')
" This may be used to select certain entry types according to the different
" "layers" of vimtex-toc:
" c: content: This is the main part and the "real" ToC
" t: todo: This shows TODOs from comments and `\todo{...}` commands
" l: label: This shows `\label{...}` commands
" i: include: This shows included files
"
" Second argument: Custom options for fzf
" It should be an object containing the parameters passed to fzf#run().
" Note: The '--with-nth 3..' option hides the first two words from the fzf
" window. These words are the file name and line number and are used by
" the sink.
let l:opts = extend({
\ 'source': <sid>parse_toc(a:0 == 0 ? 'ctli' : a:1),
\ 'sink': function('vimtex#fzf#open_selection'),
\ 'options': '--ansi --with-nth 3..',
\}, a:0 > 1 ? a:2 : {})
call fzf#run(l:opts)
endfunction
" }}}1
function! vimtex#fzf#open_selection(sel) abort " {{{1
let line = split(a:sel)[0]
let file = split(a:sel)[1]
let curr_file = expand('%:p')
if curr_file == file
execute 'normal! ' . line . 'gg'
else
execute printf('edit +%s %s', line, file)
endif
endfunction
" }}}1
function! s:parse_toc(filter) abort " {{{1
" Parsing is mostly adapted from the Denite source
" (see rplugin/python3/denite/source/vimtex.py)
python3 << EOF
import vim
import json
def format_number(n):
if not n or not type(n) is dict or not 'chapter' in n:
return ''
num = [str(n[k]) for k in [
'chapter',
'section',
'subsection',
'subsubsection',
'subsubsubsection'] if n[k] != '0']
if n['appendix'] != '0':
num[0] = chr(int(num[0]) + 64)
return '.'.join(num)
def colorize(e):
try:
from colorama import Fore, Style
color = {'content' : Fore.WHITE,
'include' : Fore.BLUE,
'label' : Fore.GREEN,
'todo' : Fore.RED}[e['type']]
return f"{color}{e['title']:65}{Style.RESET_ALL}"
except ModuleNotFoundError:
import os
if os.name == 'nt':
# Colour support on Windows requires Colorama
return f"{e['title']:65}"
else:
color = {'content' : "\u001b[37m",
'include' : "\u001b[34m",
'label' : "\u001b[32m",
'todo' : "\u001b[31m"}[e['type']]
return f"{color}{e['title']:65}\u001b[0m"
def create_candidate(e, depth):
number = format_number(dict(e['number']))
return f"{e.get('line', 0)} {e['file']} {colorize(e)} {number}"
entries = vim.eval('vimtex#parser#toc()')
depth = max([int(e['level']) for e in entries])
filter = vim.eval("a:filter")
candidates = [create_candidate(e, depth)
for e in entries if e['type'][0] in filter]
# json.dumps will convert single quotes to double quotes
# so that vim understands the ansi escape sequences
vim.command(f"let candidates = {json.dumps(candidates)}")
EOF
return candidates
endfunction
" }}}1
endif

View File

@@ -1,193 +0,0 @@
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#imaps#init_buffer() abort " {{{1
if !g:vimtex_imaps_enabled | return | endif
" Store mappings in buffer
if !exists('b:vimtex_imaps')
let b:vimtex_imaps = []
endif
"
" Create imaps
"
let l:maps = g:vimtex_imaps_list
for l:disable in g:vimtex_imaps_disabled
let l:maps = filter(l:maps, 'v:val.lhs !=# ''' . l:disable . '''')
endfor
for l:map in l:maps + get(s:, 'custom_maps', [])
call s:create_map(l:map)
endfor
"
" Add mappings and commands
"
command! -buffer VimtexImapsList call vimtex#imaps#list()
nnoremap <buffer> <plug>(vimtex-imaps-list) :call vimtex#imaps#list()<cr>
endfunction
" }}}1
function! vimtex#imaps#add_map(map) abort " {{{1
let s:custom_maps = get(s:, 'custom_maps', []) + [a:map]
if exists('b:vimtex_imaps')
call s:create_map(a:map)
endif
endfunction
" }}}1
function! vimtex#imaps#list() abort " {{{1
let l:maps = b:vimtex_imaps
silent new vimtex\ imaps
for l:map in l:maps
call append('$', printf('%5S -> %-30S %S',
\ get(l:map, 'leader', get(g:, 'vimtex_imaps_leader', '`')) . l:map.lhs,
\ l:map.rhs,
\ get(l:map, 'wrapper', 'vimtex#imaps#wrap_math')))
endfor
0delete _
nnoremap <silent><nowait><buffer> q :bwipeout<cr>
nnoremap <silent><nowait><buffer> <esc> :bwipeout<cr>
setlocal bufhidden=wipe
setlocal buftype=nofile
setlocal concealcursor=nvic
setlocal conceallevel=0
setlocal cursorline
setlocal nobuflisted
setlocal nolist
setlocal nospell
setlocal noswapfile
setlocal nowrap
setlocal nonumber
setlocal norelativenumber
setlocal nomodifiable
syntax match VimtexImapsLhs /^.*\ze->/ nextgroup=VimtexImapsArrow
syntax match VimtexImapsArrow /->/ contained nextgroup=VimtexImapsRhs
syntax match VimtexImapsRhs /\s*\S*/ contained nextgroup=VimtexImapsWrapper
syntax match VimtexImapsWrapper /.*/ contained
endfunction
" }}}1
"
" The imap generator
"
function! s:create_map(map) abort " {{{1
if index(b:vimtex_imaps, a:map) >= 0 | return | endif
let l:map = deepcopy(a:map)
let l:leader = get(l:map, 'leader', get(g:, 'vimtex_imaps_leader', '`'))
if l:leader !=# '' && !hasmapto(l:leader, 'i')
silent execute 'inoremap <silent><nowait><buffer>' l:leader . l:leader l:leader
endif
let l:lhs = l:leader . l:map.lhs
let l:wrapper = get(l:map, 'wrapper', 'vimtex#imaps#wrap_math')
if ! exists('*' . l:wrapper)
echoerr 'vimtex error: imaps wrapper does not exist!'
echoerr ' ' . l:wrapper
return
endif
" Some wrappers use a context which must be made available to the wrapper
" function at run time.
if has_key(l:map, 'context')
execute 'let l:key = "' . escape(l:lhs, '<') . '"'
let l:key .= l:map.rhs
if !exists('b:vimtex_context')
let b:vimtex_context = {}
endif
let b:vimtex_context[l:key] = l:map.context
endif
" The rhs may be evaluated before being passed to wrapper, unless expr is
" disabled (which it is by default)
if !get(l:map, 'expr')
let l:map.rhs = string(l:map.rhs)
endif
silent execute 'inoremap <expr><silent><nowait><buffer>' l:lhs
\ l:wrapper . '("' . escape(l:lhs, '\') . '", ' . l:map.rhs . ')'
let b:vimtex_imaps += [l:map]
endfunction
" }}}1
"
" Wrappers
"
function! vimtex#imaps#wrap_trivial(lhs, rhs) abort " {{{1
return a:rhs
endfunction
" }}}1
function! vimtex#imaps#wrap_math(lhs, rhs) abort " {{{1
return s:is_math() ? a:rhs : a:lhs
endfunction
" }}}1
function! vimtex#imaps#wrap_environment(lhs, rhs) abort " {{{1
let l:return = a:lhs
let l:cursor = vimtex#pos#val(vimtex#pos#get_cursor())
let l:value = 0
for l:context in b:vimtex_context[a:lhs . a:rhs]
if type(l:context) == type('')
let l:envs = [l:context]
let l:rhs = a:rhs
elseif type(l:context) == type({})
let l:envs = l:context.envs
let l:rhs = l:context.rhs
endif
for l:env in l:envs
let l:candidate_value = vimtex#pos#val(vimtex#env#is_inside(l:env))
if l:candidate_value > l:value
let l:value = l:candidate_value
let l:return = l:rhs
endif
endfor
unlet l:context
endfor
return l:return
endfunction
" }}}1
"
" Special rhs styles
"
function! vimtex#imaps#style_math(command) " {{{1
return s:is_math()
\ ? '\' . a:command . '{' . nr2char(getchar()) . '}'
\ : ''
endfunction
" }}}1
"
" Helpers
"
function! s:is_math() abort " {{{1
return match(map(synstack(line('.'), max([col('.') - 1, 1])),
\ 'synIDattr(v:val, ''name'')'), '^texMathZone') >= 0
endfunction
" }}}1
endif

View File

@@ -1,150 +0,0 @@
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#include#expr() abort " {{{1
call s:visited.timeout()
let l:fname = substitute(v:fname, '^\s*\|\s*$', '', 'g')
"
" Check if v:fname matches exactly
"
if filereadable(l:fname)
return s:visited.check(l:fname)
endif
"
" Parse \include or \input style lines
"
let l:file = s:input(l:fname, 'tex')
for l:candidate in [l:file, l:file . '.tex']
if filereadable(l:candidate)
return s:visited.check(l:candidate)
endif
endfor
"
" Parse \bibliography or \addbibresource
"
let l:candidate = s:input(l:fname, 'bib')
if filereadable(l:candidate)
return s:visited.check(l:candidate)
endif
"
" Check if v:fname matches in $TEXINPUTS
"
let l:candidate = s:search_candidates_texinputs(l:fname)
if !empty(l:candidate)
return s:visited.check(l:candidate)
endif
"
" Search for file with kpsewhich
"
if g:vimtex_include_search_enabled
let l:candidate = s:search_candidates_kpsewhich(l:fname)
if !empty(l:candidate)
return s:visited.check(l:candidate)
endif
endif
return s:visited.check(l:fname)
endfunction
" }}}1
function! s:input(fname, type) abort " {{{1
let [l:lnum, l:cnum] = searchpos(g:vimtex#re#{a:type}_input, 'bcn', line('.'))
if l:lnum == 0 | return a:fname | endif
let l:cmd = vimtex#cmd#get_at(l:lnum, l:cnum)
if empty(l:cmd) | return a:fname | endif
let l:file = join(map(
\ get(l:cmd, 'args', [{}]),
\ "get(v:val, 'text', '')"),
\ '')
let l:file = substitute(l:file, '^\s*"\|"\s*$', '', 'g')
let l:file = substitute(l:file, '\\space', '', 'g')
if l:file[-3:] !=# a:type
let l:file .= '.' . a:type
endif
return l:file
endfunction
" }}}1
function! s:search_candidates_texinputs(fname) abort " {{{1
for l:suffix in [''] + split(&l:suffixesadd, ',')
let l:candidates = glob(b:vimtex.root . '/**/'
\ . fnameescape(a:fname) . l:suffix, 0, 1)
if !empty(l:candidates)
return l:candidates[0]
endif
endfor
return ''
endfunction
" }}}1
function! s:search_candidates_kpsewhich(fname) abort " {{{1
" Split input list on commas, and if applicable, ensure that the entry that
" the cursor is on is placed first in the queue
let l:files = split(a:fname, '\s*,\s*')
let l:current = expand('<cword>')
let l:index = index(l:files, l:current)
if l:index >= 0
call remove(l:files, l:index)
let l:files = [l:current] + l:files
endif
" Add file extensions to create the final list of candidate files
let l:candidates = []
for l:file in l:files
if !empty(fnamemodify(l:file, ':e'))
call add(l:candidates, l:file)
else
call extend(l:candidates, map(split(&l:suffixesadd, ','), 'l:file . v:val'))
endif
endfor
for l:file in l:candidates
let l:candidate = vimtex#kpsewhich#find(l:file)
if !empty(l:candidate) && filereadable(l:candidate) | return l:candidate | endif
endfor
return ''
endfunction
" }}}1
let s:visited = {
\ 'time' : 0,
\ 'list' : [],
\}
function! s:visited.timeout() abort dict " {{{1
if localtime() - self.time > 1
let self.time = localtime()
let self.list = [expand('%:p')]
endif
endfunction
" }}}1
function! s:visited.check(fname) abort dict " {{{1
if index(self.list, fnamemodify(a:fname, ':p')) < 0
call add(self.list, fnamemodify(a:fname, ':p'))
return a:fname
endif
return ''
endfunction
" }}}1
endif

View File

@@ -1,222 +0,0 @@
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#info#init_buffer() abort " {{{1
command! -buffer -bang VimtexInfo call vimtex#info#open(<q-bang> == '!')
nnoremap <buffer> <plug>(vimtex-info) :VimtexInfo<cr>
nnoremap <buffer> <plug>(vimtex-info-full) :VimtexInfo!<cr>
endfunction
" }}}1
function! vimtex#info#open(global) abort " {{{1
let s:info.global = a:global
call vimtex#scratch#new(s:info)
endfunction
" }}}1
let s:info = {
\ 'name' : 'VimtexInfo',
\ 'global' : 0,
\}
function! s:info.print_content() abort dict " {{{1
for l:line in self.gather_system_info()
call append('$', l:line)
endfor
call append('$', '')
for l:line in self.gather_state_info()
call append('$', l:line)
endfor
endfunction
" }}}1
function! s:info.gather_system_info() abort dict " {{{1
let l:lines = [
\ 'System info',
\ ' OS: ' . s:get_os_info(),
\ ' Vim version: ' . s:get_vim_info(),
\]
if has('clientserver') || has('nvim')
call add(l:lines, ' Has clientserver: true')
call add(l:lines, ' Servername: '
\ . (empty(v:servername) ? 'undefined (vim started without --servername)' : v:servername))
else
call add(l:lines, ' Has clientserver: false')
endif
return l:lines
endfunction
" }}}1
function! s:info.gather_state_info() abort dict " {{{1
if self.global
let l:lines = []
for l:data in vimtex#state#list_all()
let l:lines += s:get_info(l:data)
let l:lines += ['']
endfor
call remove(l:lines, -1)
else
let l:lines = s:get_info(b:vimtex)
endif
return l:lines
endfunction
" }}}1
function! s:info.syntax() abort dict " {{{1
syntax match VimtexInfoOther /.*/
syntax match VimtexInfoKey /^.*:/ nextgroup=VimtexInfoValue
syntax match VimtexInfoValue /.*/ contained
syntax match VimtexInfoTitle /vimtex project:/ nextgroup=VimtexInfoValue
syntax match VimtexInfoTitle /System info/
endfunction
" }}}1
"
" Functions to parse the vimtex state data
"
function! s:get_info(item, ...) abort " {{{1
if empty(a:item) | return [] | endif
let l:indent = a:0 > 0 ? a:1 : 0
if type(a:item) == type({})
return s:parse_dict(a:item, l:indent)
endif
if type(a:item) == type([])
let l:entries = []
for [l:title, l:Value] in a:item
if type(l:Value) == type({})
call extend(l:entries, s:parse_dict(l:Value, l:indent, l:title))
elseif type(l:Value) == type([])
call extend(l:entries, s:parse_list(l:Value, l:indent, l:title))
else
call add(l:entries,
\ repeat(' ', l:indent) . printf('%s: %s', l:title, l:Value))
endif
unlet l:Value
endfor
return l:entries
endif
endfunction
" }}}1
function! s:parse_dict(dict, indent, ...) abort " {{{1
if empty(a:dict) | return [] | endif
let l:dict = a:dict
let l:indent = a:indent
let l:entries = []
if a:0 > 0
let l:title = a:1
let l:name = ''
if has_key(a:dict, 'name')
let l:dict = deepcopy(a:dict)
let l:name = remove(l:dict, 'name')
endif
call add(l:entries,
\ repeat(' ', l:indent) . printf('%s: %s', l:title, l:name))
let l:indent += 1
endif
let l:items = has_key(l:dict, 'pprint_items')
\ ? l:dict.pprint_items() : items(l:dict)
return extend(l:entries, s:get_info(l:items, l:indent))
endfunction
" }}}1
function! s:parse_list(list, indent, title) abort " {{{1
if empty(a:list) | return [] | endif
let l:entries = []
let l:indent = repeat(' ', a:indent)
if type(a:list[0]) == type([])
let l:name = ''
let l:index = 0
" l:entry[0] == title
" l:entry[1] == value
for l:entry in a:list
if l:entry[0] ==# 'name'
let l:name = l:entry[1]
break
endif
let l:index += 1
endfor
if empty(l:name)
let l:list = a:list
else
let l:list = deepcopy(a:list)
call remove(l:list, l:index)
endif
call add(l:entries, l:indent . printf('%s: %s', a:title, l:name))
call extend(l:entries, s:get_info(l:list, a:indent+1))
else
call add(l:entries, l:indent . printf('%s:', a:title))
for l:value in a:list
call add(l:entries, l:indent . printf(' %s', l:value))
endfor
endif
return l:entries
endfunction
" }}}1
"
" Other utility functions
"
function! s:get_os_info() abort " {{{1
let l:os = vimtex#util#get_os()
if l:os ==# 'linux'
let l:result = executable('lsb_release')
\ ? system('lsb_release -d')[12:-2]
\ : system('uname -sr')[:-2]
return substitute(l:result, '^\s*', '', '')
elseif l:os ==# 'mac'
let l:name = system('sw_vers -productName')[:-2]
let l:version = system('sw_vers -productVersion')[:-2]
let l:build = system('sw_vers -buildVersion')[:-2]
return l:name . ' ' . l:version . ' (' . l:build . ')'
else
if !exists('s:win_info')
let s:win_info = vimtex#process#capture('systeminfo')
endif
let l:name = matchstr(s:win_info[1], ':\s*\zs.*')
let l:version = matchstr(s:win_info[2], ':\s*\zs.*')
return l:name . ' (' . l:version . ')'
endif
endfunction
" }}}1
function! s:get_vim_info() abort " {{{1
let l:info = vimtex#util#command('version')
if has('nvim')
return l:info[0]
else
let l:version = 'VIM ' . strpart(l:info[0], 18, 3) . ' ('
let l:index = 2 - (l:info[1] =~# ':\s*\d')
let l:version .= matchstr(l:info[l:index], ':\s*\zs.*') . ')'
return l:version
endif
endfunction
" }}}1
endif

View File

@@ -1,53 +0,0 @@
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#kpsewhich#find(file) abort " {{{1
return s:find_cached(a:file)
endfunction
" }}}1
function! vimtex#kpsewhich#run(args) abort " {{{1
" kpsewhich should be run at the project root directory
if exists('b:vimtex.root')
call vimtex#paths#pushd(b:vimtex.root)
endif
let l:output = vimtex#process#capture('kpsewhich ' . a:args)
if exists('b:vimtex.root')
call vimtex#paths#popd()
endif
" Remove warning lines from output
call filter(l:output, 'stridx(v:val, "kpsewhich: warning: ") == -1')
return l:output
endfunction
" }}}1
function! s:find(file) abort " {{{1
let l:output = vimtex#kpsewhich#run(fnameescape(a:file))
if empty(l:output) | return '' | endif
let l:filename = l:output[0]
" Ensure absolute path
if !vimtex#paths#is_abs(l:filename) && exists('b:vimtex.root')
let l:filename = simplify(b:vimtex.root . '/' . l:filename)
endif
return l:filename
endfunction
" Use caching if possible (requires 'lambda' feature)
let s:find_cached = has('lambda')
\ ? vimtex#cache#wrap(function('s:find'), 'kpsewhich')
\ : function('s:find')
" }}}1
endif

View File

@@ -1,137 +0,0 @@
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#log#init_buffer() abort " {{{1
command! -buffer -bang VimtexLog call vimtex#log#open()
nnoremap <buffer> <plug>(vimtex-log) :VimtexLog<cr>
endfunction
" }}}1
function! vimtex#log#info(...) abort " {{{1
call s:logger.add(a:000, 'info')
endfunction
" }}}1
function! vimtex#log#warning(...) abort " {{{1
call s:logger.add(a:000, 'warning')
endfunction
" }}}1
function! vimtex#log#error(...) abort " {{{1
call s:logger.add(a:000, 'error')
endfunction
" }}}1
function! vimtex#log#get() abort " {{{1
return s:logger.entries
endfunction
" }}}1
function! vimtex#log#open() abort " {{{1
call vimtex#scratch#new(s:logger)
endfunction
" }}}1
function! vimtex#log#toggle_verbose() abort " {{{1
if s:logger.verbose
let s:logger.verbose = 0
call vimtex#log#info('Logging is now quiet')
else
call vimtex#log#info('Logging is now verbose')
let s:logger.verbose = 1
endif
endfunction
" }}}1
let s:logger = {
\ 'name' : 'VimtexMessageLog',
\ 'entries' : [],
\ 'type_to_highlight' : {
\ 'info' : 'VimtexInfo',
\ 'warning' : 'VimtexWarning',
\ 'error' : 'VimtexError',
\ },
\ 'verbose' : get(g:, 'vimtex_log_verbose', 1),
\}
function! s:logger.add(msg_arg, type) abort dict " {{{1
let l:msg_list = []
for l:msg in a:msg_arg
if type(l:msg) == type('')
call add(l:msg_list, l:msg)
elseif type(l:msg) == type([])
call extend(l:msg_list, filter(l:msg, "type(v:val) == type('')"))
endif
endfor
let l:entry = {}
let l:entry.type = a:type
let l:entry.time = strftime('%T')
let l:entry.callstack = vimtex#debug#stacktrace()[1:]
let l:entry.msg = l:msg_list
call add(self.entries, l:entry)
if !self.verbose | return | endif
" Ignore message
for l:re in get(g:, 'vimtex_log_ignore', [])
if join(l:msg_list) =~# l:re | return | endif
endfor
call vimtex#echo#formatted([
\ [self.type_to_highlight[a:type], 'vimtex:'],
\ ' ' . l:msg_list[0]
\])
for l:line in l:msg_list[1:]
call vimtex#echo#echo(' ' . l:line)
endfor
endfunction
" }}}1
function! s:logger.print_content() abort dict " {{{1
for l:entry in self.entries
call append('$', printf('%s: %s', l:entry.time, l:entry.type))
for l:stack in l:entry.callstack
if l:stack.lnum > 0
call append('$', printf(' #%d %s:%d', l:stack.nr, l:stack.filename, l:stack.lnum))
else
call append('$', printf(' #%d %s', l:stack.nr, l:stack.filename))
endif
call append('$', printf(' In %s', l:stack.function))
if !empty(l:stack.text)
call append('$', printf(' %s', l:stack.text))
endif
endfor
for l:msg in l:entry.msg
call append('$', printf(' %s', l:msg))
endfor
call append('$', '')
endfor
endfunction
" }}}1
function! s:logger.syntax() abort dict " {{{1
syntax match VimtexInfoOther /.*/
syntax include @VIM syntax/vim.vim
syntax match VimtexInfoVimCode /^ .*/ transparent contains=@VIM
syntax match VimtexInfoKey /^\S*:/ nextgroup=VimtexInfoValue
syntax match VimtexInfoKey /^ #\d\+/ nextgroup=VimtexInfoValue
syntax match VimtexInfoKey /^ In/ nextgroup=VimtexInfoValue
syntax match VimtexInfoValue /.*/ contained
endfunction
" }}}1
endif

View File

@@ -1,111 +0,0 @@
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#matchparen#init_buffer() abort " {{{1
if !g:vimtex_matchparen_enabled | return | endif
call vimtex#matchparen#enable()
endfunction
" }}}1
function! vimtex#matchparen#enable() abort " {{{1
call s:matchparen.enable()
endfunction
" }}}1
function! vimtex#matchparen#disable() abort " {{{1
call s:matchparen.disable()
endfunction
" }}}1
function! vimtex#matchparen#popup_check(...) abort " {{{1
if pumvisible()
call s:matchparen.highlight()
endif
endfunction
" }}}1
let s:matchparen = {}
function! s:matchparen.enable() abort dict " {{{1
" vint: -ProhibitAutocmdWithNoGroup
execute 'augroup vimtex_matchparen' . bufnr('%')
autocmd!
autocmd CursorMoved <buffer> call s:matchparen.highlight()
autocmd CursorMovedI <buffer> call s:matchparen.highlight()
try
autocmd TextChangedP <buffer> call s:matchparen.highlight()
catch /E216/
silent! let self.timer =
\ timer_start(50, 'vimtex#matchparen#popup_check', {'repeat' : -1})
endtry
augroup END
call self.highlight()
" vint: +ProhibitAutocmdWithNoGroup
endfunction
" }}}1
function! s:matchparen.disable() abort dict " {{{1
call self.clear()
execute 'autocmd! vimtex_matchparen' . bufnr('%')
silent! call timer_stop(self.timer)
endfunction
" }}}1
function! s:matchparen.clear() abort dict " {{{1
silent! call matchdelete(w:vimtex_match_id1)
silent! call matchdelete(w:vimtex_match_id2)
unlet! w:vimtex_match_id1
unlet! w:vimtex_match_id2
endfunction
function! s:matchparen.highlight() abort dict " {{{1
call self.clear()
if vimtex#util#in_comment() | return | endif
" This is a hack to ensure that $ in visual block mode adhers to the rule
" specified in :help v_$
if mode() ==# "\<c-v>"
let l:pos = vimtex#pos#get_cursor()
if len(l:pos) == 5 && l:pos[-1] == 2147483647
call feedkeys('$', 'in')
endif
endif
let l:current = vimtex#delim#get_current('all', 'both')
if empty(l:current) | return | endif
let l:corresponding = vimtex#delim#get_matching(l:current)
if empty(l:corresponding) | return | endif
if empty(l:corresponding.match) | return | endif
let [l:open, l:close] = l:current.is_open
\ ? [l:current, l:corresponding]
\ : [l:corresponding, l:current]
if exists('*matchaddpos')
let w:vimtex_match_id1 = matchaddpos('MatchParen',
\ [[l:open.lnum, l:open.cnum, strlen(l:open.match)]])
let w:vimtex_match_id2 = matchaddpos('MatchParen',
\ [[l:close.lnum, l:close.cnum, strlen(l:close.match)]])
else
let w:vimtex_match_id1 = matchadd('MatchParen',
\ '\%' . l:open.lnum . 'l\%' . l:open.cnum . 'c' . l:open.re.this)
let w:vimtex_match_id2 = matchadd('MatchParen',
\ '\%' . l:close.lnum . 'l\%' . l:close.cnum . 'c' . l:close.re.this)
endif
endfunction
" }}}1
endif

View File

@@ -1,158 +0,0 @@
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#misc#init_buffer() abort " {{{1
command! -buffer VimtexReload call vimtex#misc#reload()
command! -buffer -bang -range=% VimtexCountWords
\ call vimtex#misc#wordcount_display({
\ 'range' : [<line1>, <line2>],
\ 'detailed' : <q-bang> == '!',
\ 'count_letters' : 0,
\ })
command! -buffer -bang -range=% VimtexCountLetters
\ call vimtex#misc#wordcount_display({
\ 'range' : [<line1>, <line2>],
\ 'detailed' : <q-bang> == '!',
\ 'count_letters' : 1,
\ })
nnoremap <buffer> <plug>(vimtex-reload) :VimtexReload<cr>
endfunction
" }}}1
function! vimtex#misc#get_graphicspath(fname) abort " {{{1
for l:root in b:vimtex.graphicspath + ['.']
let l:candidate = simplify(b:vimtex.root . '/' . l:root . '/' . a:fname)
for l:suffix in ['', '.jpg', '.png', '.pdf']
if filereadable(l:candidate . l:suffix)
return l:candidate . l:suffix
endif
endfor
endfor
return a:fname
endfunction
" }}}1
function! vimtex#misc#wordcount(...) abort " {{{1
let l:opts = a:0 > 0 ? a:1 : {}
let l:range = get(l:opts, 'range', [1, line('$')])
if l:range == [1, line('$')]
let l:file = b:vimtex
else
let l:file = vimtex#parser#selection_to_texfile('arg', l:range)
endif
let cmd = 'cd ' . vimtex#util#shellescape(l:file.root)
let cmd .= has('win32') ? '& ' : '; '
let cmd .= 'texcount -nosub -sum '
let cmd .= get(l:opts, 'count_letters') ? '-letter ' : ''
let cmd .= get(l:opts, 'detailed') ? '-inc ' : '-q -1 -merge '
let cmd .= g:vimtex_texcount_custom_arg . ' '
let cmd .= vimtex#util#shellescape(l:file.base)
let lines = vimtex#process#capture(cmd)
if l:file.base !=# b:vimtex.base
call delete(l:file.tex)
endif
if get(l:opts, 'detailed')
return lines
else
call filter(lines, 'v:val !~# ''ERROR\|^\s*$''')
return join(lines, '')
endif
endfunction
" }}}1
function! vimtex#misc#wordcount_display(opts) abort " {{{1
let output = vimtex#misc#wordcount(a:opts)
if !get(a:opts, 'detailed')
call vimtex#log#info('Counted '
\ . (get(a:opts, 'count_letters') ? 'letters: ' : 'words: ')
\ . output)
return
endif
" Create wordcount window
if bufnr('TeXcount') >= 0
bwipeout TeXcount
endif
split TeXcount
" Add lines to buffer
for line in output
call append('$', printf('%s', line))
endfor
0delete _
" Set mappings
nnoremap <buffer><nowait><silent> q :bwipeout<cr>
" Set buffer options
setlocal bufhidden=wipe
setlocal buftype=nofile
setlocal cursorline
setlocal nobuflisted
setlocal nolist
setlocal nospell
setlocal noswapfile
setlocal nowrap
setlocal tabstop=8
setlocal nomodifiable
" Set highlighting
syntax match TexcountText /^.*:.*/ contains=TexcountValue
syntax match TexcountValue /.*:\zs.*/
highlight link TexcountText VimtexMsg
highlight link TexcountValue Constant
endfunction
" }}}1
" {{{1 function! vimtex#misc#reload()
if get(s:, 'reload_guard', 1)
function! vimtex#misc#reload() abort
let s:reload_guard = 0
for l:file in glob(fnamemodify(s:file, ':h') . '/../**/*.vim', 0, 1)
execute 'source' l:file
endfor
" Temporarily unset b:current_syntax (if active)
let l:reload_syntax = get(b:, 'current_syntax', '') ==# 'tex'
if l:reload_syntax
unlet b:current_syntax
endif
call vimtex#init()
" Reload syntax
if l:reload_syntax
runtime! syntax/tex.vim
endif
" Reload indent file
if exists('b:did_vimtex_indent')
unlet b:did_indent
runtime indent/tex.vim
endif
call vimtex#log#info('The plugin has been reloaded!')
unlet s:reload_guard
endfunction
endif
" }}}1
let s:file = expand('<sfile>')
endif

View File

@@ -1,207 +0,0 @@
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#motion#init_buffer() abort " {{{1
if !g:vimtex_motion_enabled | return | endif
" Utility map to avoid conflict with "normal" command
nnoremap <buffer> <sid>(v) v
nnoremap <buffer> <sid>(V) V
" Matching pairs
nnoremap <silent><buffer> <plug>(vimtex-%) :call vimtex#motion#find_matching_pair()<cr>
xnoremap <silent><buffer> <sid>(vimtex-%) :<c-u>call vimtex#motion#find_matching_pair(1)<cr>
xmap <silent><buffer> <plug>(vimtex-%) <sid>(vimtex-%)
onoremap <silent><buffer> <plug>(vimtex-%) :execute "normal \<sid>(v)\<sid>(vimtex-%)"<cr>
" Sections
nnoremap <silent><buffer> <plug>(vimtex-]]) :<c-u>call vimtex#motion#section(0,0,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-][) :<c-u>call vimtex#motion#section(1,0,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-[]) :<c-u>call vimtex#motion#section(1,1,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-[[) :<c-u>call vimtex#motion#section(0,1,0)<cr>
xnoremap <silent><buffer> <sid>(vimtex-]]) :<c-u>call vimtex#motion#section(0,0,1)<cr>
xnoremap <silent><buffer> <sid>(vimtex-][) :<c-u>call vimtex#motion#section(1,0,1)<cr>
xnoremap <silent><buffer> <sid>(vimtex-[]) :<c-u>call vimtex#motion#section(1,1,1)<cr>
xnoremap <silent><buffer> <sid>(vimtex-[[) :<c-u>call vimtex#motion#section(0,1,1)<cr>
xmap <silent><buffer> <plug>(vimtex-]]) <sid>(vimtex-]])
xmap <silent><buffer> <plug>(vimtex-][) <sid>(vimtex-][)
xmap <silent><buffer> <plug>(vimtex-[]) <sid>(vimtex-[])
xmap <silent><buffer> <plug>(vimtex-[[) <sid>(vimtex-[[)
onoremap <silent><buffer> <plug>(vimtex-]])
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-]])"<cr>
onoremap <silent><buffer> <plug>(vimtex-][)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-][)"<cr>
onoremap <silent><buffer> <plug>(vimtex-[])
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-[])"<cr>
onoremap <silent><buffer> <plug>(vimtex-[[)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-[[)"<cr>
" Environments
nnoremap <silent><buffer> <plug>(vimtex-]m) :<c-u>call vimtex#motion#environment(1,0,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-]M) :<c-u>call vimtex#motion#environment(0,0,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-[m) :<c-u>call vimtex#motion#environment(1,1,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-[M) :<c-u>call vimtex#motion#environment(0,1,0)<cr>
xnoremap <silent><buffer> <sid>(vimtex-]m) :<c-u>call vimtex#motion#environment(1,0,1)<cr>
xnoremap <silent><buffer> <sid>(vimtex-]M) :<c-u>call vimtex#motion#environment(0,0,1)<cr>
xnoremap <silent><buffer> <sid>(vimtex-[m) :<c-u>call vimtex#motion#environment(1,1,1)<cr>
xnoremap <silent><buffer> <sid>(vimtex-[M) :<c-u>call vimtex#motion#environment(0,1,1)<cr>
xmap <silent><buffer> <plug>(vimtex-]m) <sid>(vimtex-]m)
xmap <silent><buffer> <plug>(vimtex-]M) <sid>(vimtex-]M)
xmap <silent><buffer> <plug>(vimtex-[m) <sid>(vimtex-[m)
xmap <silent><buffer> <plug>(vimtex-[M) <sid>(vimtex-[M)
onoremap <silent><buffer> <plug>(vimtex-]m)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-]m)"<cr>
onoremap <silent><buffer> <plug>(vimtex-]M)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-]M)"<cr>
onoremap <silent><buffer> <plug>(vimtex-[m)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-[m)"<cr>
onoremap <silent><buffer> <plug>(vimtex-[M)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-[M)"<cr>
" Comments
nnoremap <silent><buffer> <plug>(vimtex-]/) :<c-u>call vimtex#motion#comment(1,0,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-]*) :<c-u>call vimtex#motion#comment(0,0,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-[/) :<c-u>call vimtex#motion#comment(1,1,0)<cr>
nnoremap <silent><buffer> <plug>(vimtex-[*) :<c-u>call vimtex#motion#comment(0,1,0)<cr>
xnoremap <silent><buffer> <sid>(vimtex-]/) :<c-u>call vimtex#motion#comment(1,0,1)<cr>
xnoremap <silent><buffer> <sid>(vimtex-]*) :<c-u>call vimtex#motion#comment(0,0,1)<cr>
xnoremap <silent><buffer> <sid>(vimtex-[/) :<c-u>call vimtex#motion#comment(1,1,1)<cr>
xnoremap <silent><buffer> <sid>(vimtex-[*) :<c-u>call vimtex#motion#comment(0,1,1)<cr>
xmap <silent><buffer> <plug>(vimtex-]/) <sid>(vimtex-]/)
xmap <silent><buffer> <plug>(vimtex-]*) <sid>(vimtex-]*)
xmap <silent><buffer> <plug>(vimtex-[/) <sid>(vimtex-[/)
xmap <silent><buffer> <plug>(vimtex-[*) <sid>(vimtex-[*)
onoremap <silent><buffer> <plug>(vimtex-]/)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-]/)"<cr>
onoremap <silent><buffer> <plug>(vimtex-]*)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-]*)"<cr>
onoremap <silent><buffer> <plug>(vimtex-[/)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-[/)"<cr>
onoremap <silent><buffer> <plug>(vimtex-[*)
\ :execute "normal \<sid>(V)" . v:count1 . "\<sid>(vimtex-[*)"<cr>
endfunction
" }}}1
function! vimtex#motion#find_matching_pair(...) abort " {{{1
if a:0 > 0
normal! gv
endif
let delim = vimtex#delim#get_current('all', 'both')
if empty(delim)
let delim = vimtex#delim#get_next('all', 'both')
if empty(delim) | return | endif
endif
let delim = vimtex#delim#get_matching(delim)
if empty(delim) | return | endif
if empty(delim.match) | return | endif
normal! m`
call vimtex#pos#set_cursor(delim.lnum,
\ (delim.is_open
\ ? delim.cnum
\ : delim.cnum + strlen(delim.match) - 1))
endfunction
" }}}1
function! vimtex#motion#section(type, backwards, visual) abort " {{{1
let l:count = v:count1
if a:visual
normal! gv
endif
" Check trivial cases
let l:top = search(s:re_sec, 'nbW') == 0
let l:bottom = search(a:type == 1 ? s:re_sec_t2 : s:re_sec, 'nW') == 0
if a:backwards && l:top
return vimtex#pos#set_cursor([1, 1])
elseif !a:backwards && l:bottom
return vimtex#pos#set_cursor([line('$'), 1])
endif
" Define search pattern and search flag
let l:re = a:type == 0 ? s:re_sec : s:re_sec_t1
let l:flags = 'W'
if a:backwards
let l:flags .= 'b'
endif
for l:_ in range(l:count)
let l:save_pos = vimtex#pos#get_cursor()
if a:type == 1
call search('\S', 'W')
endif
let l:bottom = search(s:re_sec_t2, 'nW') == 0
if a:type == 1 && !a:backwards && l:bottom
return vimtex#pos#set_cursor([line('$'), 1])
endif
let l:top = search(s:re_sec, 'ncbW') == 0
let l:lnum = search(l:re, l:flags)
if l:top && l:lnum > 0 && a:type == 1 && !a:backwards
let l:lnum = search(l:re, l:flags)
endif
if a:type == 1
call search('\S\s*\n\zs', 'Wb')
" Move to start of file if cursor was moved to top part of document
if search(s:re_sec, 'ncbW') == 0
call vimtex#pos#set_cursor([1, 1])
endif
endif
endfor
endfunction
" }}}1
function! vimtex#motion#environment(begin, backwards, visual) abort " {{{1
let l:count = v:count1
if a:visual
normal! gv
endif
let l:re = g:vimtex#re#not_comment . (a:begin ? '\\begin\s*\{' : '\\end\s*\{')
let l:flags = 'W' . (a:backwards ? 'b' : '')
for l:_ in range(l:count)
call search(l:re, l:flags)
endfor
endfunction
" }}}1
function! vimtex#motion#comment(begin, backwards, visual) abort " {{{1
let l:count = v:count1
if a:visual
normal! gv
endif
let l:re = a:begin
\ ? '\v%(^\s*\%.*\n)@<!\s*\%'
\ : '\v^\s*\%.*\n%(^\s*\%)@!'
let l:flags = 'W' . (a:backwards ? 'b' : '')
for l:_ in range(l:count)
call search(l:re, l:flags)
endfor
endfunction
" }}}1
" Patterns to match section/chapter/...
let s:re_sec = '\v^\s*\\%(%(sub)?paragraph|%(sub)*section|chapter|part|'
\ . 'appendi%(x|ces)|%(front|back|main)matter)>'
let s:re_sec_t1 = '\v%(' . s:re_sec . '|^\s*%(\\end\{document\}|%$))'
let s:re_sec_t2 = '\v%(' . s:re_sec . '|^\s*\\end\{document\})'
endif

View File

@@ -1,144 +0,0 @@
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#parser#tex(file, ...) abort " {{{1
return vimtex#parser#tex#parse(a:file, a:0 > 0 ? a:1 : {})
endfunction
" }}}1
function! vimtex#parser#preamble(file, ...) abort " {{{1
return vimtex#parser#tex#parse_preamble(a:file, a:0 > 0 ? a:1 : {})
endfunction
" }}}1
function! vimtex#parser#auxiliary(file) abort " {{{1
return vimtex#parser#auxiliary#parse(a:file)
endfunction
" }}}1
function! vimtex#parser#fls(file) abort " {{{1
return vimtex#parser#fls#parse(a:file)
endfunction
" }}}1
function! vimtex#parser#toc(...) abort " {{{1
let l:vimtex = a:0 > 0 ? a:1 : b:vimtex
let l:cache = vimtex#cache#open('parsertoc', {
\ 'persistent': 0,
\ 'default': {'entries': [], 'ftime': -1},
\})
let l:current = l:cache.get(l:vimtex.tex)
" Update cache if relevant
let l:ftime = l:vimtex.getftime()
if l:ftime > l:current.ftime
let l:cache.modified = 1
let l:current.ftime = l:ftime
let l:current.entries = vimtex#parser#toc#parse(l:vimtex.tex)
endif
return deepcopy(l:current.entries)
endfunction
" }}}1
function! vimtex#parser#bib(file, ...) abort " {{{1
return vimtex#parser#bib#parse(a:file, a:0 > 0 ? a:1 : {})
endfunction
" }}}1
function! vimtex#parser#get_externalfiles() abort " {{{1
let l:preamble = vimtex#parser#preamble(b:vimtex.tex)
let l:result = []
for l:line in filter(l:preamble, 'v:val =~# ''\\externaldocument''')
let l:name = matchstr(l:line, '{\zs[^}]*\ze}')
call add(l:result, {
\ 'tex' : l:name . '.tex',
\ 'aux' : l:name . '.aux',
\ 'opt' : matchstr(l:line, '\[\zs[^]]*\ze\]'),
\ })
endfor
return l:result
endfunction
" }}}1
function! vimtex#parser#selection_to_texfile(type, ...) range abort " {{{1
"
" Get selected lines. Method depends on type of selection, which may be
" either of
"
" 1. range from argument
" 2. Command range
" 3. Visual mapping
" 4. Operator mapping
"
if a:type ==# 'arg'
let l:lines = getline(a:1[0], a:1[1])
elseif a:type ==# 'cmd'
let l:lines = getline(a:firstline, a:lastline)
elseif a:type ==# 'visual'
let l:lines = getline(line("'<"), line("'>"))
else
let l:lines = getline(line("'["), line("']"))
endif
"
" Use only the part of the selection that is within the
"
" \begin{document} ... \end{document}
"
" environment.
"
let l:start = 0
let l:end = len(l:lines)
for l:n in range(len(l:lines))
if l:lines[l:n] =~# '\\begin\s*{document}'
let l:start = l:n + 1
elseif l:lines[l:n] =~# '\\end\s*{document}'
let l:end = l:n - 1
break
endif
endfor
"
" Check if the selection has any real content
"
if l:start >= len(l:lines)
\ || l:end < 0
\ || empty(substitute(join(l:lines[l:start : l:end], ''), '\s*', '', ''))
return {}
endif
"
" Define the set of lines to compile
"
let l:lines = vimtex#parser#preamble(b:vimtex.tex)
\ + ['\begin{document}']
\ + l:lines[l:start : l:end]
\ + ['\end{document}']
"
" Write content to temporary file
"
let l:file = {}
let l:file.root = b:vimtex.root
let l:file.base = b:vimtex.name . '_vimtex_selected.tex'
let l:file.tex = l:file.root . '/' . l:file.base
let l:file.pdf = fnamemodify(l:file.tex, ':r') . '.pdf'
let l:file.log = fnamemodify(l:file.tex, ':r') . '.log'
call writefile(l:lines, l:file.tex)
return l:file
endfunction
" }}}1
endif

View File

@@ -1,58 +0,0 @@
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#parser#auxiliary#parse(file) abort " {{{1
return s:parse_recurse(a:file, [])
endfunction
" }}}1
function! s:parse_recurse(file, parsed) abort " {{{1
if !filereadable(a:file) || index(a:parsed, a:file) >= 0
return []
endif
call add(a:parsed, a:file)
let l:lines = []
for l:line in readfile(a:file)
call add(l:lines, l:line)
if l:line =~# '\\@input{'
let l:file = s:input_line_parser(l:line, a:file)
call extend(l:lines, s:parse_recurse(l:file, a:parsed))
endif
endfor
return l:lines
endfunction
" }}}1
function! s:input_line_parser(line, file) abort " {{{1
let l:file = matchstr(a:line, '\\@input{\zs[^}]\+\ze}')
" Remove extension to simplify the parsing (e.g. for "my file name".aux)
let l:file = substitute(l:file, '\.aux', '', '')
" Trim whitespaces and quotes from beginning/end of string, append extension
let l:file = substitute(l:file, '^\(\s\|"\)*', '', '')
let l:file = substitute(l:file, '\(\s\|"\)*$', '', '')
let l:file .= '.aux'
" Use absolute paths
if l:file !~# '\v^(\/|[A-Z]:)'
let l:file = fnamemodify(a:file, ':p:h') . '/' . l:file
endif
" Only return filename if it is readable
return filereadable(l:file) ? l:file : ''
endfunction
" }}}1
endif

View File

@@ -1,370 +0,0 @@
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#parser#bib#parse(file, opts) abort " {{{1
if !filereadable(a:file) | return [] | endif
let l:backend = get(a:opts, 'backend', g:vimtex_parser_bib_backend)
if l:backend ==# 'bibtex'
if !executable('bibtex') | let l:backend = 'vim' | endif
elseif l:backend ==# 'bibparse'
if !executable('bibparse') | let l:backend = 'vim' | endif
else
let l:backend = 'vim'
endif
return s:parse_with_{l:backend}(a:file)
endfunction
" }}}1
function! s:parse_with_bibtex(file) abort " {{{1
call s:parse_with_bibtex_init()
if s:bibtex_not_executable | return [] | endif
" Define temporary files
let tmp = {
\ 'aux' : 'tmpfile.aux',
\ 'bbl' : 'tmpfile.bbl',
\ 'blg' : 'tmpfile.blg',
\ }
" Write temporary aux file
call writefile([
\ '\citation{*}',
\ '\bibstyle{' . s:bibtex_bstfile . '}',
\ '\bibdata{' . fnamemodify(a:file, ':r') . '}',
\ ], tmp.aux)
" Create the temporary bbl file
call vimtex#process#run('bibtex -terse ' . fnameescape(tmp.aux), {
\ 'background' : 0,
\ 'silent' : 1,
\})
" Parse temporary bbl file
let lines = join(readfile(tmp.bbl), "\n")
let lines = substitute(lines, '\n\n\@!\(\s\=\)\s*\|{\|}', '\1', 'g')
let lines = vimtex#util#tex2unicode(lines)
let lines = split(lines, "\n")
let l:entries = []
for line in lines
let matches = split(line, '||')
if empty(matches) || empty(matches[0]) | continue | endif
let l:entry = {
\ 'key': matches[0],
\ 'type': matches[1],
\}
if !empty(matches[2])
let l:entry.author = matches[2]
endif
if !empty(matches[3])
let l:entry.year = matches[3]
endif
if !empty(get(matches, 4, ''))
let l:entry.title = get(matches, 4, '')
endif
call add(l:entries, l:entry)
endfor
" Clean up
call delete(tmp.aux)
call delete(tmp.bbl)
call delete(tmp.blg)
return l:entries
endfunction
" }}}1
function! s:parse_with_bibtex_init() abort " {{{1
if exists('s:bibtex_init_done') | return | endif
" Check if bibtex is executable
let s:bibtex_not_executable = !executable('bibtex')
if s:bibtex_not_executable
call vimtex#log#warning(
\ 'bibtex is not executable and may not be used to parse bib files!')
endif
" Check if bstfile contains whitespace (not handled by vimtex)
if stridx(s:bibtex_bstfile, ' ') >= 0
let l:oldbst = s:bibtex_bstfile . '.bst'
let s:bibtex_bstfile = tempname()
call writefile(readfile(l:oldbst), s:bibtex_bstfile . '.bst')
endif
let s:bibtex_init_done = 1
endfunction
let s:bibtex_bstfile = expand('<sfile>:p:h') . '/vimcomplete'
" }}}1
function! s:parse_with_bibparse(file) abort " {{{1
call s:parse_with_bibparse_init()
if s:bibparse_not_executable | return [] | endif
call vimtex#process#run('bibparse ' . fnameescape(a:file)
\ . ' >_vimtex_bibparsed.log', {'background' : 0, 'silent' : 1})
let l:lines = readfile('_vimtex_bibparsed.log')
call delete('_vimtex_bibparsed.log')
let l:current = {}
let l:entries = []
for l:line in l:lines
if l:line[0] ==# '@'
if !empty(l:current)
call add(l:entries, l:current)
let l:current = {}
endif
let l:index = stridx(l:line, ' ')
if l:index > 0
let l:type = l:line[1:l:index-1]
let l:current.type = l:type
let l:current.key = l:line[l:index+1:]
endif
elseif !empty(l:current)
let l:index = stridx(l:line, '=')
if l:index < 0 | continue | endif
let l:key = l:line[:l:index-1]
let l:value = l:line[l:index+1:]
let l:current[tolower(l:key)] = l:value
endif
endfor
if !empty(l:current)
call add(l:entries, l:current)
endif
return l:entries
endfunction
" }}}1
function! s:parse_with_bibparse_init() abort " {{{1
if exists('s:bibparse_init_done') | return | endif
" Check if bibtex is executable
let s:bibparse_not_executable = !executable('bibparse')
if s:bibparse_not_executable
call vimtex#log#warning(
\ 'bibparse is not executable and may not be used to parse bib files!')
endif
let s:bibparse_init_done = 1
endfunction
" }}}1
function! s:parse_with_vim(file) abort " {{{1
" Adheres to the format description found here:
" http://www.bibtex.org/Format/
if !filereadable(a:file)
return []
endif
let l:current = {}
let l:strings = {}
let l:entries = []
for l:line in filter(readfile(a:file), 'v:val !~# ''^\s*\%(%\|$\)''')
if empty(l:current)
if s:parse_type(l:line, l:current, l:strings)
let l:current = {}
endif
continue
endif
if l:current.type ==# 'string'
if s:parse_string(l:line, l:current, l:strings)
let l:current = {}
endif
else
if s:parse_entry(l:line, l:current, l:entries)
let l:current = {}
endif
endif
endfor
return map(l:entries, 's:parse_entry_body(v:val, l:strings)')
endfunction
" }}}1
function! s:parse_type(line, current, strings) abort " {{{1
let l:matches = matchlist(a:line, '\v^\@(\w+)\s*\{\s*(.*)')
if empty(l:matches) | return 0 | endif
let l:type = tolower(l:matches[1])
if index(['preamble', 'comment'], l:type) >= 0 | return 0 | endif
let a:current.level = 1
let a:current.body = ''
if l:type ==# 'string'
return s:parse_string(l:matches[2], a:current, a:strings)
else
let a:current.type = l:type
let a:current.key = matchstr(l:matches[2], '.*\ze,\s*')
return 0
endif
endfunction
" }}}1
function! s:parse_string(line, string, strings) abort " {{{1
let a:string.level += s:count(a:line, '{') - s:count(a:line, '}')
if a:string.level > 0
let a:string.body .= a:line
return 0
endif
let a:string.body .= matchstr(a:line, '.*\ze}')
let l:matches = matchlist(a:string.body, '\v^\s*(\w+)\s*\=\s*"(.*)"\s*$')
if !empty(l:matches) && !empty(l:matches[1])
let a:strings[l:matches[1]] = l:matches[2]
endif
return 1
endfunction
" }}}1
function! s:parse_entry(line, entry, entries) abort " {{{1
let a:entry.level += s:count(a:line, '{') - s:count(a:line, '}')
if a:entry.level > 0
let a:entry.body .= a:line
return 0
endif
let a:entry.body .= matchstr(a:line, '.*\ze}')
call add(a:entries, a:entry)
return 1
endfunction
" }}}1
function! s:parse_entry_body(entry, strings) abort " {{{1
unlet a:entry.level
let l:key = ''
let l:pos = matchend(a:entry.body, '^\s*')
while l:pos >= 0
if empty(l:key)
let [l:key, l:pos] = s:get_key(a:entry.body, l:pos)
else
let [l:value, l:pos] = s:get_value(a:entry.body, l:pos, a:strings)
let a:entry[l:key] = l:value
let l:key = ''
endif
endwhile
unlet a:entry.body
return a:entry
endfunction
" }}}1
function! s:get_key(body, head) abort " {{{1
" Parse the key part of a bib entry tag.
" Assumption: a:body is left trimmed and either empty or starts with a key.
" Returns: The key and the remaining part of the entry body.
let l:matches = matchlist(a:body, '^\v(\w+)\s*\=\s*', a:head)
return empty(l:matches)
\ ? ['', -1]
\ : [tolower(l:matches[1]), a:head + strlen(l:matches[0])]
endfunction
" }}}1
function! s:get_value(body, head, strings) abort " {{{1
" Parse the value part of a bib entry tag, until separating comma or end.
" Assumption: a:body is left trimmed and either empty or starts with a value.
" Returns: The value and the remaining part of the entry body.
"
" A bib entry value is either
" 1. A number.
" 2. A concatenation (with #s) of double quoted strings, curlied strings,
" and/or bibvariables,
"
if a:body[a:head] =~# '\d'
let l:value = matchstr(a:body, '^\d\+', a:head)
let l:head = matchend(a:body, '^\s*,\s*', a:head + len(l:value))
return [l:value, l:head]
else
return s:get_value_string(a:body, a:head, a:strings)
endif
return ['s:get_value failed', -1]
endfunction
" }}}1
function! s:get_value_string(body, head, strings) abort " {{{1
if a:body[a:head] ==# '{'
let l:sum = 1
let l:i1 = a:head + 1
let l:i0 = l:i1
while l:sum > 0
let [l:match, l:_, l:i1] = matchstrpos(a:body, '[{}]', l:i1)
if l:i1 < 0 | break | endif
let l:i0 = l:i1
let l:sum += l:match ==# '{' ? 1 : -1
endwhile
let l:value = a:body[a:head+1:l:i0-2]
let l:head = matchend(a:body, '^\s*', l:i0)
elseif a:body[a:head] ==# '"'
let l:index = match(a:body, '\\\@<!"', a:head+1)
if l:index < 0
return ['s:get_value_string failed', '']
endif
let l:value = a:body[a:head+1:l:index-1]
let l:head = matchend(a:body, '^\s*', l:index+1)
return [l:value, l:head]
elseif a:body[a:head:] =~# '^\w'
let l:value = matchstr(a:body, '^\w\+', a:head)
let l:head = matchend(a:body, '^\s*', a:head + strlen(l:value))
let l:value = get(a:strings, l:value, '@(' . l:value . ')')
else
let l:head = a:head
endif
if a:body[l:head] ==# '#'
let l:head = matchend(a:body, '^\s*', l:head + 1)
let [l:vadd, l:head] = s:get_value_string(a:body, l:head, a:strings)
let l:value .= l:vadd
endif
return [l:value, matchend(a:body, '^,\s*', l:head)]
endfunction
" }}}1
function! s:count(container, item) abort " {{{1
" Necessary because in old Vim versions, count() does not work for strings
try
let l:count = count(a:container, a:item)
catch /E712/
let l:count = count(split(a:container, '\zs'), a:item)
endtry
return l:count
endfunction
" }}}1
endif

View File

@@ -1,19 +0,0 @@
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#parser#fls#parse(file) abort " {{{1
if !filereadable(a:file)
return []
endif
return readfile(a:file)
endfunction
" }}}1
endif

View File

@@ -1,205 +0,0 @@
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#parser#tex#parse(file, opts) abort " {{{1
let l:opts = extend({
\ 'detailed': 1,
\ 'root' : exists('b:vimtex.root') ? b:vimtex.root : '',
\}, a:opts)
let l:cache = vimtex#cache#open('texparser', {
\ 'local': 1,
\ 'persistent': 0,
\ 'default': {'ftime': -2},
\})
let l:parsed = s:parse(a:file, l:opts, l:cache)
if !l:opts.detailed
call map(l:parsed, 'v:val[2]')
endif
return l:parsed
endfunction
" }}}1
function! vimtex#parser#tex#parse_files(file, opts) abort " {{{1
let l:opts = extend({
\ 'root' : exists('b:vimtex.root') ? b:vimtex.root : '',
\}, a:opts)
let l:cache = vimtex#cache#open('texparser', {
\ 'local': 1,
\ 'persistent': 0,
\ 'default': {'ftime': -2},
\})
return vimtex#util#uniq_unsorted(
\ s:parse_files(a:file, l:opts, l:cache))
endfunction
" }}}1
function! vimtex#parser#tex#parse_preamble(file, opts) abort " {{{1
let l:opts = extend({
\ 'inclusive' : 0,
\ 'root' : exists('b:vimtex.root') ? b:vimtex.root : '',
\}, a:opts)
return s:parse_preamble(a:file, l:opts, [])
endfunction
" }}}1
function! s:parse(file, opts, cache) abort " {{{1
let l:current = a:cache.get(a:file)
let l:ftime = getftime(a:file)
if l:ftime > l:current.ftime
let l:current.ftime = l:ftime
call s:parse_current(a:file, a:opts, l:current)
endif
let l:parsed = []
for l:val in l:current.lines
if type(l:val) == type([])
call add(l:parsed, l:val)
else
call extend(l:parsed, s:parse(l:val, a:opts, a:cache))
endif
endfor
return l:parsed
endfunction
" }}}1
function! s:parse_files(file, opts, cache) abort " {{{1
let l:current = a:cache.get(a:file)
let l:ftime = getftime(a:file)
if l:ftime > l:current.ftime
let l:current.ftime = l:ftime
call s:parse_current(a:file, a:opts, l:current)
endif
" Only include existing files
if !filereadable(a:file) | return [] | endif
let l:files = [a:file]
for l:file in l:current.includes
let l:files += s:parse_files(l:file, a:opts, a:cache)
endfor
return l:files
endfunction
" }}}1
function! s:parse_current(file, opts, current) abort " {{{1
let a:current.lines = []
let a:current.includes = []
" Also load includes from glsentries
let l:re_input = g:vimtex#re#tex_input . '|^\s*\\loadglsentries'
if filereadable(a:file)
let l:lnum = 0
for l:line in readfile(a:file)
let l:lnum += 1
call add(a:current.lines, [a:file, l:lnum, l:line])
" Minor optimization: Avoid complex regex on "simple" lines
if stridx(l:line, '\') < 0 | continue | endif
if l:line =~# l:re_input
let l:file = s:input_parser(l:line, a:file, a:opts.root)
call add(a:current.lines, l:file)
call add(a:current.includes, l:file)
endif
endfor
endif
endfunction
" }}}1
function! s:parse_preamble(file, opts, parsed_files) abort " {{{1
if !filereadable(a:file) || index(a:parsed_files, a:file) >= 0
return []
endif
call add(a:parsed_files, a:file)
let l:lines = []
for l:line in readfile(a:file)
if l:line =~# '\\begin\s*{document}'
if a:opts.inclusive
call add(l:lines, l:line)
endif
break
endif
call add(l:lines, l:line)
if l:line =~# g:vimtex#re#tex_input
let l:file = s:input_parser(l:line, a:file, a:opts.root)
call extend(l:lines, s:parse_preamble(l:file, a:opts, a:parsed_files))
endif
endfor
return l:lines
endfunction
" }}}1
function! s:input_parser(line, current_file, root) abort " {{{1
" Handle \space commands
let l:file = substitute(a:line, '\\space\s*', ' ', 'g')
" Handle import package commands
if l:file =~# g:vimtex#re#tex_input_import
let l:root = l:file =~# '\\sub'
\ ? fnamemodify(a:current_file, ':p:h')
\ : a:root
let l:candidate = s:input_to_filename(
\ substitute(copy(l:file), '}\s*{', '', 'g'), l:root)
if !empty(l:candidate)
return l:candidate
else
return s:input_to_filename(
\ substitute(copy(l:file), '{.{-}}', '', ''), l:root)
endif
else
return s:input_to_filename(l:file, a:root)
endif
endfunction
" }}}1
function! s:input_to_filename(input, root) abort " {{{1
let l:file = matchstr(a:input, '\zs[^{}]\+\ze}\s*\%(%\|$\)')
" Trim whitespaces and quotes from beginning/end of string
let l:file = substitute(l:file, '^\(\s\|"\)*', '', '')
let l:file = substitute(l:file, '\(\s\|"\)*$', '', '')
" Ensure that the file name has extension
if empty(fnamemodify(l:file, ':e'))
let l:file .= '.tex'
endif
if vimtex#paths#is_abs(l:file)
return l:file
endif
let l:candidate = a:root . '/' . l:file
if filereadable(l:candidate)
return l:candidate
endif
let l:candidate = vimtex#kpsewhich#find(l:file)
return filereadable(l:candidate) ? l:candidate : l:file
endfunction
" }}}1
endif

View File

@@ -1,782 +0,0 @@
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
"
"
" Parses tex project for ToC-like entries. Each entry is a dictionary
" similar to the following:
"
" entry = {
" title : "Some title",
" number : "3.1.2",
" file : /path/to/file.tex,
" line : 142,
" rank : cumulative line number,
" level : 2,
" type : [content | label | todo | include],
" link : [0 | 1],
" }
"
function! vimtex#parser#toc#parse(file) abort " {{{1
let l:entries = []
let l:content = vimtex#parser#tex(a:file)
let l:max_level = 0
for [l:file, l:lnum, l:line] in l:content
if l:line =~# s:matcher_sections.re
let l:max_level = max([
\ l:max_level,
\ s:sec_to_value[matchstr(l:line, s:matcher_sections.re_level)]
\])
endif
endfor
call s:level.reset('preamble', l:max_level)
" No more parsing if there is no content
if empty(l:content) | return l:entries | endif
"
" Begin parsing LaTeX files
"
let l:lnum_total = 0
let l:matchers = s:matchers_preamble
for [l:file, l:lnum, l:line] in l:content
let l:lnum_total += 1
let l:context = {
\ 'file' : l:file,
\ 'line' : l:line,
\ 'lnum' : l:lnum,
\ 'lnum_total' : l:lnum_total,
\ 'level' : s:level,
\ 'max_level' : l:max_level,
\ 'entry' : get(l:entries, -1, {}),
\ 'num_entries' : len(l:entries),
\}
" Detect end of preamble
if s:level.preamble && l:line =~# '\v^\s*\\begin\{document\}'
let s:level.preamble = 0
let l:matchers = s:matchers_content
continue
endif
" Handle multi-line entries
if exists('s:matcher_continue')
call s:matcher_continue.continue(l:context)
continue
endif
" Apply prefilter - this gives considerable speedup for large documents
if l:line !~# s:re_prefilter | continue | endif
" Apply the matchers
for l:matcher in l:matchers
if l:line =~# l:matcher.re
let l:entry = l:matcher.get_entry(l:context)
if type(l:entry) == type([])
call extend(l:entries, l:entry)
elseif !empty(l:entry)
call add(l:entries, l:entry)
endif
endif
endfor
endfor
for l:matcher in s:matchers
try
call l:matcher.filter(l:entries)
catch /E716/
endtry
endfor
return l:entries
endfunction
" }}}1
function! vimtex#parser#toc#get_topmatters() abort " {{{1
let l:topmatters = s:level.frontmatter
let l:topmatters += s:level.mainmatter
let l:topmatters += s:level.appendix
let l:topmatters += s:level.backmatter
for l:level in get(s:level, 'old', [])
let l:topmatters += l:level.frontmatter
let l:topmatters += l:level.mainmatter
let l:topmatters += l:level.appendix
let l:topmatters += l:level.backmatter
endfor
return l:topmatters
endfunction
" }}}1
function! vimtex#parser#toc#get_entry_general(context) abort dict " {{{1
return {
\ 'title' : self.title,
\ 'number' : '',
\ 'file' : a:context.file,
\ 'line' : a:context.lnum,
\ 'rank' : a:context.lnum_total,
\ 'level' : 0,
\ 'type' : 'content',
\}
endfunction
" }}}1
" IMPORTANT: The following defines a prefilter for optimizing the toc parser.
" Any line that should be parsed has to be matched by this regexp!
" {{{1 let s:re_prefilter = ...
let s:re_prefilter = '\v%(\\' . join([
\ '%(front|main|back)matter',
\ 'add%(global|section)?bib',
\ 'appendix',
\ 'begin',
\ 'bibliography',
\ 'chapter',
\ 'documentclass',
\ 'import',
\ 'include',
\ 'includegraphics',
\ 'input',
\ 'label',
\ 'part',
\ 'printbib',
\ 'printindex',
\ 'paragraph',
\ 'section',
\ 'subfile',
\ 'tableofcontents',
\ 'todo',
\], '|') . ')'
\ . '|\%\s*%(' . join(keys(g:vimtex_toc_todo_labels), '|') . ')'
\ . '|\%\s*vimtex-include'
for s:m in g:vimtex_toc_custom_matchers
if has_key(s:m, 'prefilter')
let s:re_prefilter .= '|' . s:m.prefilter
endif
endfor
" }}}1
" Adds entries for included files
let s:matcher_include = {
\ 're' : vimtex#re#tex_input . '\zs\f{-}\s*\ze\}',
\ 'in_preamble' : 1,
\ 'priority' : 0,
\}
function! s:matcher_include.get_entry(context) abort dict " {{{1
let l:file = matchstr(a:context.line, self.re)
if !vimtex#paths#is_abs(l:file[0])
let l:file = b:vimtex.root . '/' . l:file
endif
let l:file = fnamemodify(l:file, ':~:.')
if !filereadable(l:file)
let l:file .= '.tex'
endif
return {
\ 'title' : 'tex incl: ' . (strlen(l:file) < 70
\ ? l:file
\ : l:file[0:30] . '...' . l:file[-36:]),
\ 'number' : '',
\ 'file' : l:file,
\ 'line' : 1,
\ 'level' : a:context.max_level - a:context.level.current,
\ 'rank' : a:context.lnum_total,
\ 'type' : 'include',
\ }
endfunction
" }}}1
" Adds entries for included graphics files (filetype tikz, tex)
let s:matcher_include_graphics = {
\ 're' : '\v^\s*\\includegraphics\*?%(\s*\[[^]]*\]){0,2}\s*\{\zs[^}]*',
\ 'priority' : 1,
\}
function! s:matcher_include_graphics.get_entry(context) abort dict " {{{1
let l:file = matchstr(a:context.line, self.re)
if !vimtex#paths#is_abs(l:file)
let l:file = vimtex#misc#get_graphicspath(l:file)
endif
let l:file = fnamemodify(l:file, ':~:.')
let l:ext = fnamemodify(l:file, ':e')
return !filereadable(l:file) || index(['asy', 'tikz'], l:ext) < 0
\ ? {}
\ : {
\ 'title' : 'fig incl: ' . (strlen(l:file) < 70
\ ? l:file
\ : l:file[0:30] . '...' . l:file[-36:]),
\ 'number' : '',
\ 'file' : l:file,
\ 'line' : 1,
\ 'level' : a:context.max_level - a:context.level.current,
\ 'rank' : a:context.lnum_total,
\ 'type' : 'include',
\ 'link' : 1,
\ }
endfunction
" }}}1
" Adds entries for included files through vimtex specific syntax (this allows
" to add entries for any filetype or file)
let s:matcher_include_vimtex = {
\ 're' : '^\s*%\s*vimtex-include:\?\s\+\zs\f\+',
\ 'in_preamble' : 1,
\ 'priority' : 1,
\}
function! s:matcher_include_vimtex.get_entry(context) abort dict " {{{1
let l:file = matchstr(a:context.line, self.re)
if !vimtex#paths#is_abs(l:file)
let l:file = b:vimtex.root . '/' . l:file
endif
let l:file = fnamemodify(l:file, ':~:.')
return {
\ 'title' : 'vtx incl: ' . (strlen(l:file) < 70
\ ? l:file
\ : l:file[0:30] . '...' . l:file[-36:]),
\ 'number' : '',
\ 'file' : l:file,
\ 'line' : 1,
\ 'level' : a:context.max_level - a:context.level.current,
\ 'rank' : a:context.lnum_total,
\ 'type' : 'include',
\ 'link' : 1,
\ }
endfunction
" }}}1
let s:matcher_include_bibtex = {
\ 're' : '\v^\s*\\bibliography\s*\{\zs[^}]+\ze\}',
\ 'in_preamble' : 1,
\ 'priority' : 0,
\}
function! s:matcher_include_bibtex.get_entry(context) abort dict " {{{1
let l:entries = []
for l:file in split(matchstr(a:context.line, self.re), ',')
" Ensure that the file name has extension
if l:file !~# '\.bib$'
let l:file .= '.bib'
endif
call add(l:entries, {
\ 'title' : printf('bib incl: %-.67s', fnamemodify(l:file, ':t')),
\ 'number' : '',
\ 'file' : vimtex#kpsewhich#find(l:file),
\ 'line' : 1,
\ 'level' : 0,
\ 'rank' : a:context.lnum_total,
\ 'type' : 'include',
\ 'link' : 1,
\})
endfor
return l:entries
endfunction
" }}}1
let s:matcher_include_biblatex = {
\ 're' : '\v^\s*\\add(bibresource|globalbib|sectionbib)\s*\{\zs[^}]+\ze\}',
\ 'in_preamble' : 1,
\ 'in_content' : 0,
\ 'priority' : 0,
\}
function! s:matcher_include_biblatex.get_entry(context) abort dict " {{{1
let l:file = matchstr(a:context.line, self.re)
return {
\ 'title' : printf('bib incl: %-.67s', fnamemodify(l:file, ':t')),
\ 'number' : '',
\ 'file' : vimtex#kpsewhich#find(l:file),
\ 'line' : 1,
\ 'level' : 0,
\ 'rank' : a:context.lnum_total,
\ 'type' : 'include',
\ 'link' : 1,
\}
endfunction
" }}}1
let s:matcher_preamble = {
\ 're' : '\v^\s*\\documentclass',
\ 'in_preamble' : 1,
\ 'in_content' : 0,
\ 'priority' : 0,
\}
function! s:matcher_preamble.get_entry(context) abort " {{{1
return g:vimtex_toc_show_preamble
\ ? {
\ 'title' : 'Preamble',
\ 'number' : '',
\ 'file' : a:context.file,
\ 'line' : a:context.lnum,
\ 'level' : 0,
\ 'rank' : a:context.lnum_total,
\ 'type' : 'content',
\ }
\ : {}
endfunction
" }}}1
let s:matcher_parts = {
\ 're' : '\v^\s*\\\zs((front|main|back)matter|appendix)>',
\ 'priority' : 0,
\}
function! s:matcher_parts.get_entry(context) abort dict " {{{1
call a:context.level.reset(
\ matchstr(a:context.line, self.re),
\ a:context.max_level)
return {}
endfunction
" }}}1
let s:matcher_sections = {
\ 're' : '\v^\s*\\%(part|chapter|%(sub)*section|%(sub)?paragraph)\*?\s*(\[|\{)',
\ 're_starred' : '\v^\s*\\%(part|chapter|%(sub)*section)\*',
\ 're_level' : '\v^\s*\\\zs%(part|chapter|%(sub)*section|%(sub)?paragraph)',
\ 'priority' : 0,
\}
let s:matcher_sections.re_title = s:matcher_sections.re . '\zs.{-}\ze\%?\s*$'
function! s:matcher_sections.get_entry(context) abort dict " {{{1
let level = matchstr(a:context.line, self.re_level)
let type = matchlist(a:context.line, self.re)[1]
let title = matchstr(a:context.line, self.re_title)
let number = ''
let [l:end, l:count] = s:find_closing(0, title, 1, type)
if l:count == 0
let title = self.parse_title(strpart(title, 0, l:end+1))
else
let self.type = type
let self.count = l:count
let s:matcher_continue = deepcopy(self)
endif
if a:context.line !~# self.re_starred
call a:context.level.increment(level)
if a:context.line !~# '\v^\s*\\%(sub)?paragraph'
let number = deepcopy(a:context.level)
endif
endif
return {
\ 'title' : title,
\ 'number' : number,
\ 'file' : a:context.file,
\ 'line' : a:context.lnum,
\ 'level' : a:context.max_level - a:context.level.current,
\ 'rank' : a:context.lnum_total,
\ 'type' : 'content',
\ }
endfunction
" }}}1
function! s:matcher_sections.parse_title(title) abort dict " {{{1
let l:title = substitute(a:title, '\v%(\]|\})\s*$', '', '')
return s:clear_texorpdfstring(l:title)
endfunction
" }}}1
function! s:matcher_sections.continue(context) abort dict " {{{1
let [l:end, l:count] = s:find_closing(0, a:context.line, self.count, self.type)
if l:count == 0
let a:context.entry.title = self.parse_title(a:context.entry.title . strpart(a:context.line, 0, l:end+1))
unlet! s:matcher_continue
else
let a:context.entry.title .= a:context.line
let self.count = l:count
endif
endfunction
" }}}1
let s:matcher_table_of_contents = {
\ 'title' : 'Table of contents',
\ 're' : '\v^\s*\\tableofcontents',
\ 'priority' : 0,
\}
let s:matcher_index = {
\ 'title' : 'Alphabetical index',
\ 're' : '\v^\s*\\printindex\[?',
\ 'priority' : 0,
\}
let s:matcher_titlepage = {
\ 'title' : 'Titlepage',
\ 're' : '\v^\s*\\begin\{titlepage\}',
\ 'priority' : 0,
\}
let s:matcher_bibliography = {
\ 'title' : 'Bibliography',
\ 're' : '\v^\s*\\%('
\ . 'printbib%(liography|heading)\s*(\{|\[)?'
\ . '|begin\s*\{\s*thebibliography\s*\}'
\ . '|bibliography\s*\{)',
\ 're_biblatex' : '\v^\s*\\printbib%(liography|heading)',
\ 'priority' : 0,
\}
function! s:matcher_bibliography.get_entry(context) abort dict " {{{1
let l:entry = call('vimtex#parser#toc#get_entry_general', [a:context], self)
if a:context.line !~# self.re_biblatex
return l:entry
endif
let self.options = matchstr(a:context.line, self.re_biblatex . '\s*\[\zs.*')
let [l:end, l:count] = s:find_closing(
\ 0, self.options, !empty(self.options), '[')
if l:count == 0
let self.options = strpart(self.options, 0, l:end)
call self.parse_options(a:context, l:entry)
else
let self.count = l:count
let s:matcher_continue = deepcopy(self)
endif
return l:entry
endfunction
" }}}1
function! s:matcher_bibliography.continue(context) abort dict " {{{1
let [l:end, l:count] = s:find_closing(0, a:context.line, self.count, '[')
if l:count == 0
let self.options .= strpart(a:context.line, 0, l:end)
unlet! s:matcher_continue
call self.parse_options(a:context, a:context.entry)
else
let self.options .= a:context.line
let self.count = l:count
endif
endfunction
" }}}1
function! s:matcher_bibliography.parse_options(context, entry) abort dict " {{{1
" Parse the options
let l:opt_pairs = map(split(self.options, ','), 'split(v:val, ''='')')
let l:opts = {}
for [l:key, l:val] in l:opt_pairs
let l:key = substitute(l:key, '^\s*\|\s*$', '', 'g')
let l:val = substitute(l:val, '^\s*\|\s*$', '', 'g')
let l:val = substitute(l:val, '{\|}', '', 'g')
let l:opts[l:key] = l:val
endfor
" Check if entry should appear in the TOC
let l:heading = get(l:opts, 'heading')
let a:entry.added_to_toc = l:heading =~# 'intoc\|numbered'
" Check if entry should be numbered
if l:heading =~# '\v%(sub)?bibnumbered'
if a:context.level.chapter > 0
let l:levels = ['chapter', 'section']
else
let l:levels = ['section', 'subsection']
endif
call a:context.level.increment(l:levels[l:heading =~# '^sub'])
let a:entry.level = a:context.max_level - a:context.level.current
let a:entry.number = deepcopy(a:context.level)
endif
" Parse title
try
let a:entry.title = remove(l:opts, 'title')
catch /E716/
let a:entry.title = l:heading =~# '^sub' ? 'References' : 'Bibliography'
endtry
endfunction
" }}}1
function! s:matcher_bibliography.filter(entries) abort dict " {{{1
if !empty(
\ filter(deepcopy(a:entries), 'get(v:val, "added_to_toc")'))
call filter(a:entries, 'get(v:val, "added_to_toc", 1)')
endif
endfunction
" }}}1
let s:matcher_todos = {
\ 're' : g:vimtex#re#not_bslash . '\%\s+('
\ . join(keys(g:vimtex_toc_todo_labels), '|') . ')[ :]+\s*(.*)',
\ 'in_preamble' : 1,
\ 'priority' : 2,
\}
function! s:matcher_todos.get_entry(context) abort dict " {{{1
let [l:type, l:text] = matchlist(a:context.line, self.re)[1:2]
let l:label = g:vimtex_toc_todo_labels[toupper(l:type)]
return {
\ 'title' : l:label . l:text,
\ 'number' : '',
\ 'file' : a:context.file,
\ 'line' : a:context.lnum,
\ 'level' : a:context.max_level - a:context.level.current,
\ 'rank' : a:context.lnum_total,
\ 'type' : 'todo',
\ }
endfunction
" }}}1
let s:matcher_todonotes = {
\ 're' : g:vimtex#re#not_comment . '\\\w*todo\w*%(\[[^]]*\])?\{\zs.*',
\ 'priority' : 2,
\}
function! s:matcher_todonotes.get_entry(context) abort dict " {{{1
let title = matchstr(a:context.line, self.re)
let [l:end, l:count] = s:find_closing(0, title, 1, '{')
if l:count == 0
let title = strpart(title, 0, l:end)
else
let self.count = l:count
let s:matcher_continue = deepcopy(self)
endif
let l:label = get(g:vimtex_toc_todo_labels, 'TODO', 'TODO: ')
return {
\ 'title' : l:label . title,
\ 'number' : '',
\ 'file' : a:context.file,
\ 'line' : a:context.lnum,
\ 'level' : a:context.max_level - a:context.level.current,
\ 'rank' : a:context.lnum_total,
\ 'type' : 'todo',
\ }
endfunction
" }}}1
function! s:matcher_todonotes.continue(context) abort dict " {{{1
let [l:end, l:count] = s:find_closing(0, a:context.line, self.count, '{')
if l:count == 0
let a:context.entry.title .= strpart(a:context.line, 0, l:end)
unlet! s:matcher_continue
else
let a:context.entry.title .= a:context.line
let self.count = l:count
endif
endfunction
" }}}1
let s:matcher_labels = {
\ 're' : g:vimtex#re#not_comment . '\\label\{\zs.{-}\ze\}',
\ 'priority' : 1,
\}
function! s:matcher_labels.get_entry(context) abort dict " {{{1
return {
\ 'title' : matchstr(a:context.line, self.re),
\ 'number' : '',
\ 'file' : a:context.file,
\ 'line' : a:context.lnum,
\ 'level' : a:context.max_level - a:context.level.current,
\ 'rank' : a:context.lnum_total,
\ 'type' : 'label',
\ }
endfunction
" }}}1
let s:matcher_beamer_frame = {
\ 're' : '^\s*\\begin{frame}',
\ 'priority' : 0,
\}
function! s:matcher_beamer_frame.get_entry(context) abort dict " {{{1
let l:title = vimtex#util#trim(
\ matchstr(a:context.line, self.re . '\s*{\zs.*\ze}\s*$'))
return {
\ 'title' : 'Frame' . (empty(l:title) ? '' : ': ' . l:title),
\ 'number' : '',
\ 'file' : a:context.file,
\ 'line' : a:context.lnum,
\ 'level' : a:context.max_level - a:context.level.current,
\ 'rank' : a:context.lnum_total,
\ 'type' : 'content',
\ }
endfunction
" }}}1
"
" Utility functions
"
function! s:clear_texorpdfstring(title) abort " {{{1
let l:i1 = match(a:title, '\\texorpdfstring')
if l:i1 < 0 | return a:title | endif
" Find start of included part
let [l:i2, l:dummy] = s:find_closing(
\ match(a:title, '{', l:i1+1), a:title, 1, '{')
let l:i2 = match(a:title, '{', l:i2+1)
if l:i2 < 0 | return a:title | endif
" Find end of included part
let [l:i3, l:dummy] = s:find_closing(l:i2, a:title, 1, '{')
if l:i3 < 0 | return a:title | endif
return strpart(a:title, 0, l:i1)
\ . strpart(a:title, l:i2+1, l:i3-l:i2-1)
\ . s:clear_texorpdfstring(strpart(a:title, l:i3+1))
endfunction
" }}}1
function! s:find_closing(start, string, count, type) abort " {{{1
if a:type ==# '{'
let l:re = '{\|}'
let l:open = '{'
else
let l:re = '\[\|\]'
let l:open = '['
endif
let l:i2 = a:start-1
let l:count = a:count
while l:count > 0
let l:i2 = match(a:string, l:re, l:i2+1)
if l:i2 < 0 | break | endif
if a:string[l:i2] ==# l:open
let l:count += 1
else
let l:count -= 1
endif
endwhile
return [l:i2, l:count]
endfunction
" }}}1
function! s:sort_by_priority(d1, d2) abort " {{{1
let l:p1 = get(a:d1, 'priority')
let l:p2 = get(a:d2, 'priority')
return l:p1 >= l:p2 ? l:p1 > l:p2 : -1
endfunction
" }}}1
"
" Section level counter
"
let s:level = {}
function! s:level.reset(part, level) abort dict " {{{1
if a:part ==# 'preamble'
let self.old = []
else
let self.old += [copy(self)]
endif
let self.preamble = 0
let self.frontmatter = 0
let self.mainmatter = 0
let self.appendix = 0
let self.backmatter = 0
let self.part = 0
let self.chapter = 0
let self.section = 0
let self.subsection = 0
let self.subsubsection = 0
let self.subsubsubsection = 0
let self.paragraph = 0
let self.subparagraph = 0
let self.current = a:level
let self[a:part] = 1
endfunction
" }}}1
function! s:level.increment(level) abort dict " {{{1
let self.current = s:sec_to_value[a:level]
let self.part_toggle = 0
if a:level ==# 'part'
let self.part += 1
let self.part_toggle = 1
elseif a:level ==# 'chapter'
let self.chapter += 1
let self.section = 0
let self.subsection = 0
let self.subsubsection = 0
let self.subsubsubsection = 0
let self.paragraph = 0
let self.subparagraph = 0
elseif a:level ==# 'section'
let self.section += 1
let self.subsection = 0
let self.subsubsection = 0
let self.subsubsubsection = 0
let self.paragraph = 0
let self.subparagraph = 0
elseif a:level ==# 'subsection'
let self.subsection += 1
let self.subsubsection = 0
let self.subsubsubsection = 0
let self.paragraph = 0
let self.subparagraph = 0
elseif a:level ==# 'subsubsection'
let self.subsubsection += 1
let self.subsubsubsection = 0
let self.paragraph = 0
let self.subparagraph = 0
elseif a:level ==# 'subsubsubsection'
let self.subsubsubsection += 1
let self.paragraph = 0
let self.subparagraph = 0
elseif a:level ==# 'paragraph'
let self.paragraph += 1
let self.subparagraph = 0
elseif a:level ==# 'subparagraph'
let self.subparagraph += 1
endif
endfunction
" }}}1
let s:sec_to_value = {
\ '_' : 0,
\ 'subparagraph' : 1,
\ 'paragraph' : 2,
\ 'subsubsubsection' : 3,
\ 'subsubsection' : 4,
\ 'subsection' : 5,
\ 'section' : 6,
\ 'chapter' : 7,
\ 'part' : 8,
\ }
"
" Create the lists of matchers
"
let s:matchers = map(
\ filter(items(s:), 'v:val[0] =~# ''^matcher_'''),
\ 'v:val[1]')
\ + g:vimtex_toc_custom_matchers
call sort(s:matchers, function('s:sort_by_priority'))
for s:m in s:matchers
if !has_key(s:m, 'get_entry')
let s:m.get_entry = function('vimtex#parser#toc#get_entry_general')
endif
endfor
unlet! s:m
let s:matchers_preamble = filter(
\ deepcopy(s:matchers), "get(v:val, 'in_preamble')")
let s:matchers_content = filter(
\ deepcopy(s:matchers), "get(v:val, 'in_content', 1)")
endif

View File

@@ -1,91 +0,0 @@
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#paths#pushd(path) abort " {{{1
if empty(a:path) || getcwd() ==# fnamemodify(a:path, ':p')
let s:qpath += ['']
else
let s:qpath += [getcwd()]
execute s:cd fnameescape(a:path)
endif
endfunction
" }}}1
function! vimtex#paths#popd() abort " {{{1
let l:path = remove(s:qpath, -1)
if !empty(l:path)
execute s:cd fnameescape(l:path)
endif
endfunction
" }}}1
function! vimtex#paths#is_abs(path) abort " {{{1
return a:path =~# s:re_abs
endfunction
" }}}1
function! vimtex#paths#shorten_relative(path) abort " {{{1
" Input: An absolute path
" Output: Relative path with respect to the vimtex root, path relative to
" vimtex root (unless absolute path is shorter)
let l:relative = vimtex#paths#relative(a:path, b:vimtex.root)
return strlen(l:relative) < strlen(a:path)
\ ? l:relative : a:path
endfunction
" }}}1
function! vimtex#paths#relative(path, current) abort " {{{1
" Note: This algorithm is based on the one presented by @Offirmo at SO,
" http://stackoverflow.com/a/12498485/51634
let l:target = simplify(substitute(a:path, '\\', '/', 'g'))
let l:common = simplify(substitute(a:current, '\\', '/', 'g'))
" This only works on absolute paths
if !vimtex#paths#is_abs(l:target)
return substitute(a:path, '^\.\/', '', '')
endif
let l:tries = 50
let l:result = ''
while stridx(l:target, l:common) != 0 && l:tries > 0
let l:common = fnamemodify(l:common, ':h')
let l:result = empty(l:result) ? '..' : '../' . l:result
let l:tries -= 1
endwhile
if l:tries == 0 | return a:path | endif
if l:common ==# '/'
let l:result .= '/'
endif
let l:forward = strpart(l:target, strlen(l:common))
if !empty(l:forward)
let l:result = empty(l:result)
\ ? l:forward[1:]
\ : l:result . l:forward
endif
return l:result
endfunction
" }}}1
let s:cd = exists('*haslocaldir') && haslocaldir()
\ ? 'lcd'
\ : exists(':tcd') && haslocaldir(-1) ? 'tcd' : 'cd'
let s:qpath = get(s:, 'qpath', [])
let s:re_abs = has('win32') ? '^[A-Z]:[\\/]' : '^/'
endif

View File

@@ -1,97 +0,0 @@
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#pos#set_cursor(...) abort " {{{1
call cursor(s:parse_args(a:000))
endfunction
" }}}1
function! vimtex#pos#get_cursor() abort " {{{1
return exists('*getcurpos') ? getcurpos() : getpos('.')
endfunction
" }}}1
function! vimtex#pos#get_cursor_line() abort " {{{1
let l:pos = vimtex#pos#get_cursor()
return l:pos[1]
endfunction
" }}}1
function! vimtex#pos#val(...) abort " {{{1
let [l:lnum, l:cnum; l:rest] = s:parse_args(a:000)
return 100000*l:lnum + min([l:cnum, 90000])
endfunction
" }}}1
function! vimtex#pos#next(...) abort " {{{1
let [l:lnum, l:cnum; l:rest] = s:parse_args(a:000)
return l:cnum < strlen(getline(l:lnum))
\ ? [0, l:lnum, l:cnum+1, 0]
\ : [0, l:lnum+1, 1, 0]
endfunction
" }}}1
function! vimtex#pos#prev(...) abort " {{{1
let [l:lnum, l:cnum; l:rest] = s:parse_args(a:000)
return l:cnum > 1
\ ? [0, l:lnum, l:cnum-1, 0]
\ : [0, max([l:lnum-1, 1]), strlen(getline(l:lnum-1)), 0]
endfunction
" }}}1
function! vimtex#pos#larger(pos1, pos2) abort " {{{1
return vimtex#pos#val(a:pos1) > vimtex#pos#val(a:pos2)
endfunction
" }}}1
function! vimtex#pos#equal(p1, p2) abort " {{{1
let l:pos1 = s:parse_args(a:p1)
let l:pos2 = s:parse_args(a:p2)
return l:pos1[:1] == l:pos2[:1]
endfunction
" }}}1
function! vimtex#pos#smaller(pos1, pos2) abort " {{{1
return vimtex#pos#val(a:pos1) < vimtex#pos#val(a:pos2)
endfunction
" }}}1
function! s:parse_args(args) abort " {{{1
"
" The arguments should be in one of the following forms (when unpacked):
"
" [lnum, cnum]
" [bufnum, lnum, cnum, ...]
" {'lnum' : lnum, 'cnum' : cnum}
"
if len(a:args) > 1
return s:parse_args([a:args])
elseif len(a:args) == 1
if type(a:args[0]) == type({})
return [get(a:args[0], 'lnum'), get(a:args[0], 'cnum')]
else
if len(a:args[0]) == 2
return a:args[0]
else
return a:args[0][1:]
endif
endif
else
return a:args
endif
endfunction
" }}}1
endif

View File

@@ -1,233 +0,0 @@
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#process#new(...) abort " {{{1
let l:opts = a:0 > 0 ? a:1 : {}
return extend(deepcopy(s:process), l:opts)
endfunction
" }}}1
function! vimtex#process#run(cmd, ...) abort " {{{1
let l:opts = a:0 > 0 ? a:1 : {}
let l:opts.cmd = a:cmd
let l:process = vimtex#process#new(l:opts)
return l:process.run()
endfunction
" }}}1
function! vimtex#process#capture(cmd) abort " {{{1
return vimtex#process#run(a:cmd, {'capture': 1})
endfunction
" }}}1
function! vimtex#process#start(cmd, ...) abort " {{{1
let l:opts = a:0 > 0 ? a:1 : {}
let l:opts.continuous = 1
return vimtex#process#run(a:cmd, l:opts)
endfunction
" }}}1
let s:process = {
\ 'cmd' : '',
\ 'pid' : 0,
\ 'background' : 1,
\ 'continuous' : 0,
\ 'output' : '',
\ 'workdir' : '',
\ 'silent' : 1,
\ 'capture' : 0,
\ 'result' : '',
\}
function! s:process.run() abort dict " {{{1
if self._do_not_run() | return | endif
call self._pre_run()
call self._prepare()
call self._execute()
call self._restore()
call self._post_run()
return self.capture ? self.result : self
endfunction
" }}}1
function! s:process.stop() abort dict " {{{1
if !self.pid | return | endif
let l:cmd = has('win32')
\ ? 'taskkill /PID ' . self.pid . ' /T /F'
\ : 'kill ' . self.pid
call vimtex#process#run(l:cmd, {'background': 0})
let self.pid = 0
endfunction
" }}}1
function! s:process.pprint_items() abort dict " {{{1
let l:list = [
\ ['pid', self.pid ? self.pid : '-'],
\ ['cmd', get(self, 'prepared_cmd', self.cmd)],
\]
return l:list
endfunction
" }}}1
function! s:process._do_not_run() abort dict " {{{1
if empty(self.cmd)
call vimtex#log#warning('Can''t run empty command')
return 1
endif
if self.pid
call vimtex#log#warning('Process already running!')
return 1
endif
return 0
endfunction
" }}}1
function! s:process._pre_run() abort dict " {{{1
if self.capture
let self.silent = 0
let self.background = 0
elseif empty(self.output) && self.background
let self.output = 'null'
endif
call vimtex#paths#pushd(self.workdir)
endfunction
" }}}1
function! s:process._execute() abort dict " {{{1
if self.capture
let self.result = split(system(self.prepared_cmd), '\n')
elseif self.silent
silent call system(self.prepared_cmd)
elseif self.background
silent execute '!' . self.prepared_cmd
if !has('gui_running')
redraw!
endif
else
execute '!' . self.prepared_cmd
endif
" Capture the pid if relevant
if has_key(self, 'set_pid') && self.continuous
call self.set_pid()
endif
endfunction
" }}}1
function! s:process._post_run() abort dict " {{{1
call vimtex#paths#popd()
endfunction
" }}}1
if has('win32')
function! s:process._prepare() abort dict " {{{1
if &shell !~? 'cmd'
let self.win32_restore_shell = 1
let self.win32_saved_shell = [
\ &shell,
\ &shellcmdflag,
\ &shellxquote,
\ &shellxescape,
\ &shellquote,
\ &shellpipe,
\ &shellredir,
\ &shellslash
\]
set shell& shellcmdflag& shellxquote& shellxescape&
set shellquote& shellpipe& shellredir& shellslash&
else
let self.win32_restore_shell = 0
endif
let l:cmd = self.cmd
if self.background
if !empty(self.output)
let l:cmd .= self.output ==# 'null'
\ ? ' >nul'
\ : ' >' . self.output
let l:cmd = 'cmd /s /c "' . l:cmd . '"'
else
let l:cmd = 'cmd /c "' . l:cmd . '"'
endif
let l:cmd = 'start /b ' . cmd
endif
if self.silent && self.output ==# 'null'
let self.prepared_cmd = '"' . l:cmd . '"'
else
let self.prepared_cmd = l:cmd
endif
endfunction
" }}}1
function! s:process._restore() abort dict " {{{1
if self.win32_restore_shell
let [ &shell,
\ &shellcmdflag,
\ &shellxquote,
\ &shellxescape,
\ &shellquote,
\ &shellpipe,
\ &shellredir,
\ &shellslash] = self.win32_saved_shell
endif
endfunction
" }}}1
function! s:process.get_pid() abort dict " {{{1
let self.pid = 0
endfunction
" }}}1
else
function! s:process._prepare() abort dict " {{{1
let l:cmd = self.cmd
if self.background
if !empty(self.output)
let l:cmd .= ' >'
\ . (self.output ==# 'null'
\ ? '/dev/null'
\ : shellescape(self.output))
\ . ' 2>&1'
endif
let l:cmd .= ' &'
endif
if !self.silent
let l:cmd = escape(l:cmd, '%#')
endif
let self.prepared_cmd = l:cmd
endfunction
" }}}1
function! s:process._restore() abort dict " {{{1
endfunction
" }}}1
function! s:process.get_pid() abort dict " {{{1
let self.pid = 0
endfunction
" }}}1
endif
endif

View File

@@ -1,125 +0,0 @@
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#profile#start() abort " {{{1
profile start prof.log
profile func *
endfunction
" }}}1
function! vimtex#profile#stop() abort " {{{1
profile stop
call s:fix_sids()
endfunction
" }}}1
"
function! vimtex#profile#open() abort " {{{1
source ~/.vim/vimrc
silent edit prof.log
endfunction
" }}}1
function! vimtex#profile#print() abort " {{{1
for l:line in readfile('prof.log')
echo l:line
endfor
echo ''
quit!
endfunction
" }}}1
function! vimtex#profile#file(filename) abort " {{{1
call vimtex#profile#start()
execute 'silent edit' a:filename
call vimtex#profile#stop()
endfunction
" }}}1
function! vimtex#profile#command(cmd) abort " {{{1
call vimtex#profile#start()
execute a:cmd
call vimtex#profile#stop()
endfunction
" }}}1
function! vimtex#profile#filter(sections) abort " {{{1
let l:lines = readfile('prof.log')
" call filter(l:lines, 'v:val !~# ''FTtex''')
" call filter(l:lines, 'v:val !~# ''LoadFTPlugin''')
let l:new = []
for l:sec in a:sections
call extend(l:new, s:get_section(l:sec, l:lines))
endfor
call writefile(l:new, 'prof.log')
endfunction
" }}}1
function! s:fix_sids() abort " {{{1
let l:lines = readfile('prof.log')
let l:new = []
for l:line in l:lines
let l:sid = matchstr(l:line, '\v\<SNR\>\zs\d+\ze_')
if !empty(l:sid)
let l:filename = map(
\ vimtex#util#command('scriptnames'),
\ 'split(v:val, "\\v:=\\s+")[1]')[l:sid-1]
if l:filename =~# 'vimtex'
let l:filename = substitute(l:filename, '^.*autoload\/', '', '')
let l:filename = substitute(l:filename, '\.vim$', '#s:', '')
let l:filename = substitute(l:filename, '\/', '#', 'g')
else
let l:filename .= ':'
endif
call add(l:new, substitute(l:line, '\v\<SNR\>\d+_', l:filename, 'g'))
else
call add(l:new, substitute(l:line, '\s\+$', '', ''))
endif
endfor
call writefile(l:new, 'prof.log')
endfunction
" }}}1
function! s:get_section(name, lines) abort " {{{1
let l:active = 0
let l:section = []
for l:line in a:lines
if l:active
if l:line =~# '^FUNCTION' && l:line !~# a:name
let l:active = 0
else
call add(l:section, l:line)
endif
continue
endif
if l:line =~# a:name
call add(l:section, l:line)
let l:active = 1
endif
endfor
if l:active
call add(l:section, ' ')
endif
return l:section
endfunction
" }}}1
endif

View File

@@ -1,245 +0,0 @@
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#init_buffer() abort " {{{1
if !g:vimtex_quickfix_enabled | return | endif
command! -buffer VimtexErrors call vimtex#qf#toggle()
nnoremap <buffer> <plug>(vimtex-errors) :call vimtex#qf#toggle()<cr>
endfunction
" }}}1
function! vimtex#qf#init_state(state) abort " {{{1
if !g:vimtex_quickfix_enabled | return | endif
try
let l:qf = vimtex#qf#{g:vimtex_quickfix_method}#new()
call l:qf.init(a:state)
unlet l:qf.init
let a:state.qf = l:qf
catch /vimtex: Requirements not met/
call vimtex#log#warning(
\ 'Quickfix state not initialized!',
\ 'Please see :help g:vimtex_quickfix_method')
endtry
endfunction
" }}}1
function! vimtex#qf#toggle() abort " {{{1
if vimtex#qf#is_open()
cclose
else
call vimtex#qf#open(1)
endif
endfunction
" }}}1
function! vimtex#qf#open(force) abort " {{{1
if !exists('b:vimtex.qf.addqflist') | return | endif
try
call vimtex#qf#setqflist()
catch /Vimtex: No log file found/
if a:force
call vimtex#log#warning('No log file found')
endif
if g:vimtex_quickfix_mode > 0
cclose
endif
return
catch
call vimtex#log#error('Something went wrong when parsing log files!')
if g:vimtex_quickfix_mode > 0
cclose
endif
return
endtry
if empty(getqflist())
if a:force
call vimtex#log#info('No errors!')
endif
if g:vimtex_quickfix_mode > 0
cclose
endif
return
endif
"
" There are two options that determine when to open the quickfix window. If
" forced, the quickfix window is always opened when there are errors or
" warnings (forced typically imply that the functions is called from the
" normal mode mapping). Else the behaviour is based on the settings.
"
let l:errors_or_warnings = s:qf_has_errors()
\ || g:vimtex_quickfix_open_on_warning
if a:force || (g:vimtex_quickfix_mode > 0 && l:errors_or_warnings)
call s:window_save()
botright cwindow
if g:vimtex_quickfix_mode == 2
call s:window_restore()
endif
if g:vimtex_quickfix_autoclose_after_keystrokes > 0
augroup vimtex_qf_autoclose
autocmd!
autocmd CursorMoved,CursorMovedI * call s:qf_autoclose_check()
augroup END
endif
redraw
endif
endfunction
" }}}1
function! vimtex#qf#setqflist(...) abort " {{{1
if !exists('b:vimtex.qf.addqflist') | return | endif
if a:0 > 0
let l:tex = a:1
let l:log = fnamemodify(l:tex, ':r') . '.log'
let l:blg = fnamemodify(l:tex, ':r') . '.blg'
let l:jump = 0
else
let l:tex = b:vimtex.tex
let l:log = b:vimtex.log()
let l:blg = b:vimtex.ext('blg')
let l:jump = g:vimtex_quickfix_autojump
endif
try
" Initialize the quickfix list
" Note: Only create new list if the current list is not a vimtex qf list
if get(getqflist({'title': 1}), 'title') =~# 'Vimtex'
call setqflist([], 'r')
else
call setqflist([])
endif
" Parse LaTeX errors
call b:vimtex.qf.addqflist(l:tex, l:log)
" Parse bibliography errors
if has_key(b:vimtex.packages, 'biblatex')
call vimtex#qf#biblatex#addqflist(l:blg)
else
call vimtex#qf#bibtex#addqflist(l:blg)
endif
" Ignore entries if desired
if !empty(g:vimtex_quickfix_ignore_filters)
let l:qflist = getqflist()
for l:re in g:vimtex_quickfix_ignore_filters
call filter(l:qflist, 'v:val.text !~# l:re')
endfor
call setqflist(l:qflist, 'r')
endif
" Set title if supported
try
call setqflist([], 'r', {'title': 'Vimtex errors (' . b:vimtex.qf.name . ')'})
catch
endtry
" Jump to first error if wanted
if l:jump
cfirst
endif
catch /Vimtex: No log file found/
throw 'Vimtex: No log file found'
endtry
endfunction
" }}}1
function! vimtex#qf#inquire(file) abort " {{{1
try
call vimtex#qf#setqflist(a:file)
return s:qf_has_errors()
catch
return 0
endtry
endfunction
" }}}1
function! vimtex#qf#is_open() abort " {{{1
redir => l:bufstring
silent! ls!
redir END
let l:buflist = filter(split(l:bufstring, '\n'), 'v:val =~# ''Quickfix''')
for l:line in l:buflist
let l:bufnr = str2nr(matchstr(l:line, '^\s*\zs\d\+'))
if bufwinnr(l:bufnr) >= 0
\ && getbufvar(l:bufnr, '&buftype', '') ==# 'quickfix'
return 1
endif
endfor
return 0
endfunction
" }}}1
function! s:window_save() abort " {{{1
if exists('*win_gotoid')
let s:previous_window = win_getid()
else
let w:vimtex_remember_window = 1
endif
endfunction
" }}}1
function! s:window_restore() abort " {{{1
if exists('*win_gotoid')
call win_gotoid(s:previous_window)
else
for l:winnr in range(1, winnr('$'))
if getwinvar(l:winnr, 'vimtex_remember_window')
execute l:winnr . 'wincmd p'
unlet! w:vimtex_remember_window
endif
endfor
endif
endfunction
" }}}1
function! s:qf_has_errors() abort " {{{1
return len(filter(getqflist(), 'v:val.type ==# ''E''')) > 0
endfunction
" }}}1
"
function! s:qf_autoclose_check() abort " {{{1
if get(s:, 'keystroke_counter') == 0
let s:keystroke_counter = g:vimtex_quickfix_autoclose_after_keystrokes
endif
redir => l:bufstring
silent! ls!
redir END
if empty(filter(split(l:bufstring, '\n'), 'v:val =~# ''%a- .*Quickfix'''))
let s:keystroke_counter -= 1
else
let s:keystroke_counter = g:vimtex_quickfix_autoclose_after_keystrokes + 1
endif
if s:keystroke_counter == 0
cclose
autocmd! vimtex_qf_autoclose
augroup! vimtex_qf_autoclose
endif
endfunction
" }}}1
endif

View File

@@ -1,250 +0,0 @@
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

View File

@@ -1,187 +0,0 @@
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

View File

@@ -1,209 +0,0 @@
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

View File

@@ -1,98 +0,0 @@
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

View File

@@ -1,67 +0,0 @@
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

View File

@@ -1,110 +0,0 @@
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
"
let g:vimtex#re#not_bslash = '\v%(\\@<!%(\\\\)*)@<='
let g:vimtex#re#not_comment = '\v%(' . g:vimtex#re#not_bslash . '\%.*)@<!'
let g:vimtex#re#tex_input_root =
\ '\v^\s*\%\s*!?\s*[tT][eE][xX]\s+[rR][oO][oO][tT]\s*\=\s*\zs.*\ze\s*$'
let g:vimtex#re#tex_input_latex = '\v\\%('
\ . join(get(g:, 'vimtex_include_indicators',
\ ['input', 'include', 'subfile', 'subfileinclude']),
\ '|') . ')\s*\{'
let g:vimtex#re#tex_input_import =
\ '\v\\%(sub)?%(import|%(input|include)from)\*?\{[^\}]*\}\{'
let g:vimtex#re#tex_input_package =
\ '\v\\%(usepackage|RequirePackage)%(\s*\[[^]]*\])?\s*\{\zs[^}]*\ze\}'
let g:vimtex#re#tex_input = '\v^\s*\zs%(' . join([
\ g:vimtex#re#tex_input_latex,
\ g:vimtex#re#tex_input_import,
\ ], '|') . ')'
let g:vimtex#re#bib_input = '\v\\%(addbibresource|bibliography)>'
let g:vimtex#re#tex_include = g:vimtex#re#tex_input_root
\ . '|' . g:vimtex#re#tex_input . '\zs[^\}]*\ze\}?'
\ . '|' . g:vimtex#re#tex_input_package
" {{{1 Completion regexes
let g:vimtex#re#neocomplete =
\ '\v\\%('
\ . '\a*cite\a*%(\s*\[[^]]*\]){0,2}\s*\{[^}]*'
\ . '|%(text|block)cquote\*?%(\s*\[[^]]*\]){0,2}\s*\{[^}]*'
\ . '|%(for|hy)\w*cquote\*?\{[^}]*}%(\s*\[[^]]*\]){0,2}\s*\{[^}]*'
\ . '|\a*ref%(\s*\{[^}]*|range\s*\{[^,}]*%(}\{)?)'
\ . '|hyperref\s*\[[^]]*'
\ . '|includegraphics\*?%(\s*\[[^]]*\]){0,2}\s*\{[^}]*'
\ . '|%(include%(only)?|input|subfile)\s*\{[^}]*'
\ . '|([cpdr]?(gls|Gls|GLS)|acr|Acr|ACR)\a*\s*\{[^}]*'
\ . '|(ac|Ac|AC)\s*\{[^}]*'
\ . '|includepdf%(\s*\[[^]]*\])?\s*\{[^}]*'
\ . '|includestandalone%(\s*\[[^]]*\])?\s*\{[^}]*'
\ . '|%(usepackage|RequirePackage|PassOptionsToPackage)%(\s*\[[^]]*\])?\s*\{[^}]*'
\ . '|documentclass%(\s*\[[^]]*\])?\s*\{[^}]*'
\ . '|begin%(\s*\[[^]]*\])?\s*\{[^}]*'
\ . '|end%(\s*\[[^]]*\])?\s*\{[^}]*'
\ . '|\a*'
\ . ')'
let g:vimtex#re#deoplete = '\\(?:'
\ . '\w*cite\w*(?:\s*\[[^]]*\]){0,2}\s*{[^}]*'
\ . '|(text|block)cquote\*?(?:\s*\[[^]]*\]){0,2}\s*{[^}]*'
\ . '|(for|hy)\w*cquote\*?{[^}]*}(?:\s*\[[^]]*\]){0,2}\s*{[^}]*'
\ . '|\w*ref(?:\s*\{[^}]*|range\s*\{[^,}]*(?:}{)?)'
\ . '|hyperref\s*\[[^]]*'
\ . '|includegraphics\*?(?:\s*\[[^]]*\]){0,2}\s*\{[^}]*'
\ . '|(?:include(?:only)?|input|subfile)\s*\{[^}]*'
\ . '|([cpdr]?(gls|Gls|GLS)|acr|Acr|ACR)[a-zA-Z]*\s*\{[^}]*'
\ . '|(ac|Ac|AC)\s*\{[^}]*'
\ . '|includepdf(\s*\[[^]]*\])?\s*\{[^}]*'
\ . '|includestandalone(\s*\[[^]]*\])?\s*\{[^}]*'
\ . '|(usepackage|RequirePackage|PassOptionsToPackage)(\s*\[[^]]*\])?\s*\{[^}]*'
\ . '|documentclass(\s*\[[^]]*\])?\s*\{[^}]*'
\ . '|begin(\s*\[[^]]*\])?\s*\{[^}]*'
\ . '|end(\s*\[[^]]*\])?\s*\{[^}]*'
\ . '|\w*'
\ .')'
let g:vimtex#re#ncm2#cmds = [
\ '\\[A-Za-z]+',
\ '\\(usepackage|RequirePackage|PassOptionsToPackage)(\s*\[[^]]*\])?\s*\{[^}]*',
\ '\\documentclass(\s*\[[^]]*\])?\s*\{[^}]*',
\ '\\begin(\s*\[[^]]*\])?\s*\{[^}]*',
\ '\\end(\s*\[[^]]*\])?\s*\{[^}]*',
\]
let g:vimtex#re#ncm2#bibtex = [
\ '\\[A-Za-z]*cite[A-Za-z]*(\[[^]]*\]){0,2}{[^}]*',
\ '\\(text|block)cquote\*?(\[[^]]*\]){0,2}{[^}]*',
\ '\\(for|hy)[A-Za-z]*cquote\*?{[^}]*}(\[[^]]*\]){0,2}{[^}]*',
\]
let g:vimtex#re#ncm2#labels = [
\ '\\[A-Za-z]*ref({[^}]*|range{([^,{}]*(}{)?))',
\ '\\hyperref\[[^]]*',
\ '\\([cpdr]?(gls|Gls|GLS)|acr|Acr|ACR)[a-zA-Z]*\s*\{[^}]*',
\ '\\(ac|Ac|AC)\s*\{[^}]*',
\]
let g:vimtex#re#ncm2#files = [
\ '\\includegraphics\*?(\[[^]]*\]){0,2}{[^}]*',
\ '\\(include(only)?|input|subfile){[^}]*',
\ '\\includepdf(\s*\[[^]]*\])?\s*\{[^}]*',
\ '\\includestandalone(\s*\[[^]]*\])?\s*\{[^}]*',
\]
let g:vimtex#re#ncm2 = g:vimtex#re#ncm2#cmds +
\ g:vimtex#re#ncm2#bibtex +
\ g:vimtex#re#ncm2#labels +
\ g:vimtex#re#ncm2#files
let g:vimtex#re#ncm = copy(g:vimtex#re#ncm2)
let g:vimtex#re#youcompleteme = map(copy(g:vimtex#re#ncm), "'re!' . v:val")
" }}}1
endif

View File

@@ -1,72 +0,0 @@
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#scratch#new(opts) abort " {{{1
let l:buf = extend(deepcopy(s:scratch), a:opts)
call l:buf.open()
endfunction
" }}}1
let s:scratch = {
\ 'name' : 'VimtexScratch'
\}
function! s:scratch.open() abort dict " {{{1
let l:bufnr = bufnr('')
let l:vimtex = get(b:, 'vimtex', {})
silent execute 'keepalt edit' escape(self.name, ' ')
let self.prev_bufnr = l:bufnr
let b:scratch = self
let b:vimtex = l:vimtex
setlocal bufhidden=wipe
setlocal buftype=nofile
setlocal concealcursor=nvic
setlocal conceallevel=0
setlocal nobuflisted
setlocal nolist
setlocal nospell
setlocal noswapfile
setlocal nowrap
setlocal tabstop=8
nnoremap <silent><nowait><buffer> q :call b:scratch.close()<cr>
nnoremap <silent><nowait><buffer> <esc> :call b:scratch.close()<cr>
nnoremap <silent><nowait><buffer> <c-6> :call b:scratch.close()<cr>
nnoremap <silent><nowait><buffer> <c-^> :call b:scratch.close()<cr>
nnoremap <silent><nowait><buffer> <c-e> :call b:scratch.close()<cr>
if has_key(self, 'syntax')
call self.syntax()
endif
call self.fill()
endfunction
" }}}1
function! s:scratch.close() abort dict " {{{1
silent execute 'keepalt buffer' self.prev_bufnr
endfunction
" }}}1
function! s:scratch.fill() abort dict " {{{1
setlocal modifiable
%delete
call self.print_content()
0delete _
setlocal nomodifiable
endfunction
" }}}1
endif

View File

@@ -1,745 +0,0 @@
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#state#init_buffer() abort " {{{1
command! -buffer VimtexToggleMain call vimtex#state#toggle_main()
command! -buffer VimtexReloadState call vimtex#state#reload()
nnoremap <buffer> <plug>(vimtex-toggle-main) :VimtexToggleMain<cr>
nnoremap <buffer> <plug>(vimtex-reload-state) :VimtexReloadState<cr>
endfunction
" }}}1
function! vimtex#state#init() abort " {{{1
let [l:main, l:main_type] = s:get_main()
let l:id = s:get_main_id(l:main)
if l:id >= 0
let b:vimtex_id = l:id
let b:vimtex = s:vimtex_states[l:id]
else
let b:vimtex_id = s:vimtex_next_id
let b:vimtex = s:vimtex.new(l:main, l:main_type, 0)
let s:vimtex_next_id += 1
let s:vimtex_states[b:vimtex_id] = b:vimtex
endif
endfunction
" }}}1
function! vimtex#state#init_local() abort " {{{1
let l:filename = expand('%:p')
let l:preserve_root = get(s:, 'subfile_preserve_root')
unlet! s:subfile_preserve_root
if b:vimtex.tex ==# l:filename | return | endif
let l:vimtex_id = s:get_main_id(l:filename)
if l:vimtex_id < 0
let l:vimtex_id = s:vimtex_next_id
let l:vimtex = s:vimtex.new(l:filename, 'local file', l:preserve_root)
let s:vimtex_next_id += 1
let s:vimtex_states[l:vimtex_id] = l:vimtex
if !has_key(b:vimtex, 'subids')
let b:vimtex.subids = []
endif
call add(b:vimtex.subids, l:vimtex_id)
let l:vimtex.main_id = b:vimtex_id
endif
let b:vimtex_local = {
\ 'active' : 0,
\ 'main_id' : b:vimtex_id,
\ 'sub_id' : l:vimtex_id,
\}
endfunction
" }}}1
function! vimtex#state#reload() abort " {{{1
let l:id = s:get_main_id(expand('%:p'))
if has_key(s:vimtex_states, l:id)
let l:vimtex = remove(s:vimtex_states, l:id)
call l:vimtex.cleanup()
endif
if has_key(s:vimtex_states, get(b:, 'vimtex_id', -1))
let l:vimtex = remove(s:vimtex_states, b:vimtex_id)
call l:vimtex.cleanup()
endif
call vimtex#state#init()
call vimtex#state#init_local()
endfunction
" }}}1
function! vimtex#state#toggle_main() abort " {{{1
if exists('b:vimtex_local')
let b:vimtex_local.active = !b:vimtex_local.active
let b:vimtex_id = b:vimtex_local.active
\ ? b:vimtex_local.sub_id
\ : b:vimtex_local.main_id
let b:vimtex = vimtex#state#get(b:vimtex_id)
call vimtex#log#info('Changed to `' . b:vimtex.base . "' "
\ . (b:vimtex_local.active ? '[local]' : '[main]'))
endif
endfunction
" }}}1
function! vimtex#state#list_all() abort " {{{1
return values(s:vimtex_states)
endfunction
" }}}1
function! vimtex#state#exists(id) abort " {{{1
return has_key(s:vimtex_states, a:id)
endfunction
" }}}1
function! vimtex#state#get(id) abort " {{{1
return s:vimtex_states[a:id]
endfunction
" }}}1
function! vimtex#state#get_all() abort " {{{1
return s:vimtex_states
endfunction
" }}}1
function! vimtex#state#cleanup(id) abort " {{{1
if !vimtex#state#exists(a:id) | return | endif
"
" Count the number of open buffers for the given blob
"
let l:buffers = filter(range(1, bufnr('$')), 'buflisted(v:val)')
let l:ids = map(l:buffers, 'getbufvar(v:val, ''vimtex_id'', -1)')
let l:count = count(l:ids, a:id)
"
" Don't clean up if there are more than one buffer connected to the current
" blob
"
if l:count > 1 | return | endif
let l:vimtex = vimtex#state#get(a:id)
"
" Handle possible subfiles properly
"
if has_key(l:vimtex, 'subids')
let l:subcount = 0
for l:sub_id in get(l:vimtex, 'subids', [])
let l:subcount += count(l:ids, l:sub_id)
endfor
if l:count + l:subcount > 1 | return | endif
for l:sub_id in get(l:vimtex, 'subids', [])
call remove(s:vimtex_states, l:sub_id).cleanup()
endfor
call remove(s:vimtex_states, a:id).cleanup()
else
call remove(s:vimtex_states, a:id).cleanup()
if has_key(l:vimtex, 'main_id')
let l:main = vimtex#state#get(l:vimtex.main_id)
let l:count_main = count(l:ids, l:vimtex.main_id)
for l:sub_id in get(l:main, 'subids', [])
let l:count_main += count(l:ids, l:sub_id)
endfor
if l:count_main + l:count <= 1
call remove(s:vimtex_states, l:vimtex.main_id).cleanup()
endif
endif
endif
endfunction
" }}}1
function! s:get_main_id(main) abort " {{{1
for [l:id, l:state] in items(s:vimtex_states)
if l:state.tex == a:main
return str2nr(l:id)
endif
endfor
return -1
endfunction
function! s:get_main() abort " {{{1
if exists('s:disabled_modules')
unlet s:disabled_modules
endif
"
" Use buffer variable if it exists
"
if exists('b:vimtex_main') && filereadable(b:vimtex_main)
return [fnamemodify(b:vimtex_main, ':p'), 'buffer variable']
endif
"
" Search for TEX root specifier at the beginning of file. This is used by
" several other plugins and editors.
"
let l:candidate = s:get_main_from_texroot()
if !empty(l:candidate)
return [l:candidate, 'texroot specifier']
endif
"
" Check if the current file is a main file
"
if s:file_is_main(expand('%:p'))
return [expand('%:p'), 'current file verified']
endif
"
" Support for subfiles package
"
let l:candidate = s:get_main_from_subfile()
if !empty(l:candidate)
return [l:candidate, 'subfiles']
endif
"
" Search for .latexmain-specifier
"
let l:candidate = s:get_main_latexmain(expand('%:p'))
if !empty(l:candidate)
return [l:candidate, 'latexmain specifier']
endif
"
" Search for .latexmkrc @default_files specifier
"
let l:candidate = s:get_main_latexmk()
if !empty(l:candidate)
return [l:candidate, 'latexmkrc @default_files']
endif
"
" Check if we are class or style file
"
if index(['cls', 'sty'], expand('%:e')) >= 0
let l:id = getbufvar('#', 'vimtex_id', -1)
if l:id >= 0 && has_key(s:vimtex_states, l:id)
return [s:vimtex_states[l:id].tex, 'cls/sty file (inherit from alternate)']
else
let s:disabled_modules = ['latexmk', 'view', 'toc']
return [expand('%:p'), 'cls/sty file']
endif
endif
"
" Search for main file recursively through include specifiers
"
if !get(g:, 'vimtex_disable_recursive_main_file_detection', 0)
let l:candidate = s:get_main_choose(s:get_main_recurse())
if !empty(l:candidate)
return [l:candidate, 'recursive search']
endif
endif
"
" Use fallback candidate or the current file
"
let l:candidate = get(s:, 'cand_fallback', expand('%:p'))
if exists('s:cand_fallback')
unlet s:cand_fallback
return [l:candidate, 'fallback']
else
return [l:candidate, 'current file']
endif
endfunction
" }}}1
function! s:get_main_from_texroot() abort " {{{1
for l:line in getline(1, 5)
let l:file_pattern = matchstr(l:line, g:vimtex#re#tex_input_root)
if empty(l:file_pattern) | continue | endif
if !vimtex#paths#is_abs(l:file_pattern)
let l:file_pattern = simplify(expand('%:p:h') . '/' . l:file_pattern)
endif
let l:candidates = glob(l:file_pattern, 0, 1)
if len(l:candidates) > 1
return s:get_main_choose(l:candidates)
elseif len(l:candidates) == 1
return l:candidates[0]
endif
endfor
return ''
endfunction
" }}}1
function! s:get_main_from_subfile() abort " {{{1
for l:line in getline(1, 5)
let l:filename = matchstr(l:line,
\ '^\C\s*\\documentclass\[\zs.*\ze\]{subfiles}')
if len(l:filename) > 0
if l:filename !~# '\.tex$'
let l:filename .= '.tex'
endif
if vimtex#paths#is_abs(l:filename)
" Specified path is absolute
if filereadable(l:filename) | return l:filename | endif
else
" Try specified path as relative to current file path
let l:candidate = simplify(expand('%:p:h') . '/' . l:filename)
if filereadable(l:candidate) | return l:candidate | endif
" Try specified path as relative to the project main file. This is
" difficult, since the main file is the one we are looking for. We
" therefore assume that the main file lives somewhere upwards in the
" directory tree.
let l:candidate = fnamemodify(findfile(l:filename, '.;'), ':p')
if filereadable(l:candidate)
\ && s:file_reaches_current(l:candidate)
let s:subfile_preserve_root = 1
return fnamemodify(candidate, ':p')
endif
" Check the alternate buffer. This seems sensible e.g. in cases where one
" enters an "outer" subfile through a 'gf' motion from the main file.
let l:vimtex = getbufvar('#', 'vimtex', {})
for l:file in get(l:vimtex, 'sources', [])
if expand('%:p') ==# simplify(l:vimtex.root . '/' . l:file)
let s:subfile_preserve_root = 1
return l:vimtex.tex
endif
endfor
endif
endif
endfor
return ''
endfunction
" }}}1
function! s:get_main_latexmain(file) abort " {{{1
for l:cand in s:findfiles_recursive('*.latexmain', expand('%:p:h'))
let l:cand = fnamemodify(l:cand, ':p:r')
if s:file_reaches_current(l:cand)
return l:cand
else
let s:cand_fallback = l:cand
endif
endfor
return ''
endfunction
function! s:get_main_latexmk() abort " {{{1
let l:root = expand('%:p:h')
let l:results = vimtex#compiler#latexmk#get_rc_opt(
\ l:root, 'default_files', 2, [])
if l:results[1] < 1 | return '' | endif
for l:candidate in l:results[0]
let l:file = l:root . '/' . l:candidate
if filereadable(l:file)
return l:file
endif
endfor
return ''
endfunction
function! s:get_main_recurse(...) abort " {{{1
" Either start the search from the original file, or check if the supplied
" file is a main file (or invalid)
if a:0 == 0
let l:file = expand('%:p')
let l:tried = {}
else
let l:file = a:1
let l:tried = a:2
if s:file_is_main(l:file)
return [l:file]
elseif !filereadable(l:file)
return []
endif
endif
" Create list of candidates that was already tried for the current file
if !has_key(l:tried, l:file)
let l:tried[l:file] = [l:file]
endif
" Apply filters successively (minor optimization)
let l:re_filter1 = fnamemodify(l:file, ':t:r')
let l:re_filter2 = g:vimtex#re#tex_input . '\s*\f*' . l:re_filter1
" Search through candidates found recursively upwards in the directory tree
let l:results = []
for l:cand in s:findfiles_recursive('*.tex', fnamemodify(l:file, ':p:h'))
if index(l:tried[l:file], l:cand) >= 0 | continue | endif
call add(l:tried[l:file], l:cand)
if len(filter(filter(readfile(l:cand),
\ 'v:val =~# l:re_filter1'),
\ 'v:val =~# l:re_filter2')) > 0
let l:results += s:get_main_recurse(fnamemodify(l:cand, ':p'), l:tried)
endif
endfor
return l:results
endfunction
" }}}1
function! s:get_main_choose(list) abort " {{{1
let l:list = vimtex#util#uniq_unsorted(a:list)
if empty(l:list) | return '' | endif
if len(l:list) == 1 | return l:list[0] | endif
let l:all = map(copy(l:list), '[s:get_main_id(v:val), v:val]')
let l:new = map(filter(copy(l:all), 'v:val[0] < 0'), 'v:val[1]')
let l:existing = {}
for [l:key, l:val] in filter(copy(l:all), 'v:val[0] >= 0')
let l:existing[l:key] = l:val
endfor
let l:alternate_id = getbufvar('#', 'vimtex_id', -1)
if len(l:existing) == 1
return values(l:existing)[0]
elseif len(l:existing) > 1 && has_key(l:existing, l:alternate_id)
return l:existing[l:alternate_id]
elseif len(l:existing) < 1 && len(l:new) == 1
return l:new[0]
else
let l:choices = {}
for l:tex in l:list
let l:choices[l:tex] = vimtex#paths#relative(l:tex, getcwd())
endfor
return vimtex#echo#choose(l:choices,
\ 'Please select an appropriate main file:')
endif
endfunction
" }}}1
function! s:file_is_main(file) abort " {{{1
if !filereadable(a:file) | return 0 | endif
"
" Check if a:file is a main file by looking for the \documentclass command,
" but ignore the following:
"
" \documentclass[...]{subfiles}
" \documentclass[...]{standalone}
"
let l:lines = readfile(a:file, 0, 50)
call filter(l:lines, 'v:val =~# ''\C\\documentclass\_\s*[\[{]''')
call filter(l:lines, 'v:val !~# ''{subfiles}''')
call filter(l:lines, 'v:val !~# ''{standalone}''')
if len(l:lines) == 0 | return 0 | endif
" A main file contains `\begin{document}`
let l:lines = vimtex#parser#preamble(a:file, {
\ 'inclusive' : 1,
\ 'root' : fnamemodify(a:file, ':p:h'),
\})
call filter(l:lines, 'v:val =~# ''\\begin\s*{document}''')
return len(l:lines) > 0
endfunction
" }}}1
function! s:file_reaches_current(file) abort " {{{1
" Note: This function assumes that the input a:file is an absolute path
if !filereadable(a:file) | return 0 | endif
for l:line in filter(readfile(a:file), 'v:val =~# g:vimtex#re#tex_input')
let l:file = matchstr(l:line, g:vimtex#re#tex_input . '\zs\f+')
if empty(l:file) | continue | endif
if !vimtex#paths#is_abs(l:file)
let l:file = fnamemodify(a:file, ':h') . '/' . l:file
endif
if l:file !~# '\.tex$'
let l:file .= '.tex'
endif
if expand('%:p') ==# l:file
\ || s:file_reaches_current(l:file)
return 1
endif
endfor
return 0
endfunction
" }}}1
function! s:findfiles_recursive(expr, path) abort " {{{1
let l:path = a:path
let l:dirs = l:path
while l:path != fnamemodify(l:path, ':h')
let l:path = fnamemodify(l:path, ':h')
let l:dirs .= ',' . l:path
endwhile
return split(globpath(fnameescape(l:dirs), a:expr), '\n')
endfunction
" }}}1
let s:vimtex = {}
function! s:vimtex.new(main, main_parser, preserve_root) abort dict " {{{1
let l:new = deepcopy(self)
let l:new.tex = a:main
let l:new.root = fnamemodify(l:new.tex, ':h')
let l:new.base = fnamemodify(l:new.tex, ':t')
let l:new.name = fnamemodify(l:new.tex, ':t:r')
let l:new.main_parser = a:main_parser
if a:preserve_root && exists('b:vimtex')
let l:new.root = b:vimtex.root
let l:new.base = vimtex#paths#relative(a:main, l:new.root)
endif
if exists('s:disabled_modules')
let l:new.disabled_modules = s:disabled_modules
endif
"
" The preamble content is used to parse for the engine directive, the
" documentclass and the package list; we store it as a temporary shared
" object variable
"
let l:new.preamble = vimtex#parser#preamble(l:new.tex, {
\ 'root' : l:new.root,
\})
call l:new.parse_tex_program()
call l:new.parse_documentclass()
call l:new.parse_graphicspath()
call l:new.gather_sources()
call vimtex#view#init_state(l:new)
call vimtex#compiler#init_state(l:new)
call vimtex#qf#init_state(l:new)
call vimtex#toc#init_state(l:new)
call vimtex#fold#init_state(l:new)
" Parsing packages might depend on the compiler setting for build_dir
call l:new.parse_packages()
unlet l:new.preamble
unlet l:new.new
return l:new
endfunction
" }}}1
function! s:vimtex.cleanup() abort dict " {{{1
if exists('self.compiler.cleanup')
call self.compiler.cleanup()
endif
if exists('#User#VimtexEventQuit')
if exists('b:vimtex')
let b:vimtex_tmp = b:vimtex
endif
let b:vimtex = self
doautocmd <nomodeline> User VimtexEventQuit
if exists('b:vimtex_tmp')
let b:vimtex = b:vimtex_tmp
unlet b:vimtex_tmp
else
unlet b:vimtex
endif
endif
" Close quickfix window
silent! cclose
endfunction
" }}}1
function! s:vimtex.parse_tex_program() abort dict " {{{1
let l:lines = copy(self.preamble[:20])
let l:tex_program_re =
\ '\v^\c\s*\%\s*\!?\s*tex\s+%(TS-)?program\s*\=\s*\zs.*\ze\s*$'
call map(l:lines, 'matchstr(v:val, l:tex_program_re)')
call filter(l:lines, '!empty(v:val)')
let self.tex_program = tolower(get(l:lines, -1, '_'))
endfunction
" }}}1
function! s:vimtex.parse_documentclass() abort dict " {{{1
let self.documentclass = ''
for l:line in self.preamble
let l:class = matchstr(l:line, '^\s*\\documentclass.*{\zs\w*\ze}')
if !empty(l:class)
let self.documentclass = l:class
break
endif
endfor
endfunction
" }}}1
function! s:vimtex.parse_graphicspath() abort dict " {{{1
" Combine the preamble as one long string of commands
let l:preamble = join(map(copy(self.preamble),
\ 'substitute(v:val, ''\\\@<!%.*'', '''', '''')'))
" Extract the graphicspath command from this string
let l:graphicspath = matchstr(l:preamble,
\ g:vimtex#re#not_bslash
\ . '\\graphicspath\s*\{\s*\{\s*\zs.{-}\ze\s*\}\s*\}'
\)
" Add all parsed graphicspaths
let self.graphicspath = []
for l:path in split(l:graphicspath, '\s*}\s*{\s*')
let l:path = substitute(l:path, '\/\s*$', '', '')
call add(self.graphicspath, vimtex#paths#is_abs(l:path)
\ ? l:path
\ : simplify(self.root . '/' . l:path))
endfor
endfunction
" }}}1
function! s:vimtex.parse_packages() abort dict " {{{1
let self.packages = get(self, 'packages', {})
" Try to parse .fls file if present, as it is usually more complete. That is,
" it contains a generated list of all the packages that are used.
for l:line in vimtex#parser#fls(self.fls())
let l:package = matchstr(l:line, '^INPUT \zs.\+\ze\.sty$')
let l:package = fnamemodify(l:package, ':t')
if !empty(l:package)
let self.packages[l:package] = {}
endif
endfor
" Now parse preamble as well for usepackage and RequirePackage
if !has_key(self, 'preamble') | return | endif
let l:usepackages = filter(copy(self.preamble), 'v:val =~# ''\v%(usep|RequireP)ackage''')
let l:pat = g:vimtex#re#not_comment . g:vimtex#re#not_bslash
\ . '\v\\%(usep|RequireP)ackage\s*%(\[[^[\]]*\])?\s*\{\s*\zs%([^{}]+)\ze\s*\}'
call map(l:usepackages, 'matchstr(v:val, l:pat)')
call map(l:usepackages, 'split(v:val, ''\s*,\s*'')')
for l:packages in l:usepackages
for l:package in l:packages
let self.packages[l:package] = {}
endfor
endfor
endfunction
" }}}1
function! s:vimtex.gather_sources() abort dict " {{{1
let self.sources = vimtex#parser#tex#parse_files(
\ self.tex, {'root' : self.root})
call map(self.sources, 'vimtex#paths#relative(v:val, self.root)')
endfunction
" }}}1
function! s:vimtex.pprint_items() abort dict " {{{1
let l:items = [
\ ['name', self.name],
\ ['base', self.base],
\ ['root', self.root],
\ ['tex', self.tex],
\ ['out', self.out()],
\ ['log', self.log()],
\ ['aux', self.aux()],
\ ['fls', self.fls()],
\ ['main parser', self.main_parser],
\]
if self.tex_program !=# '_'
call add(l:items, ['tex program', self.tex_program])
endif
if len(self.sources) >= 2
call add(l:items, ['source files', self.sources])
endif
call add(l:items, ['compiler', get(self, 'compiler', {})])
call add(l:items, ['viewer', get(self, 'viewer', {})])
call add(l:items, ['qf', get(self, 'qf', {})])
if exists('self.documentclass')
call add(l:items, ['document class', self.documentclass])
endif
if !empty(self.packages)
call add(l:items, ['packages', sort(keys(self.packages))])
endif
return [['vimtex project', l:items]]
endfunction
" }}}1
function! s:vimtex.log() abort dict " {{{1
return self.ext('log')
endfunction
" }}}1
function! s:vimtex.aux() abort dict " {{{1
return self.ext('aux')
endfunction
" }}}1
function! s:vimtex.fls() abort dict " {{{1
return self.ext('fls')
endfunction
" }}}1
function! s:vimtex.out(...) abort dict " {{{1
return call(self.ext, ['pdf'] + a:000, self)
endfunction
" }}}1
function! s:vimtex.ext(ext, ...) abort dict " {{{1
" First check build dir (latexmk -output_directory option)
if !empty(get(get(self, 'compiler', {}), 'build_dir', ''))
let cand = self.compiler.build_dir . '/' . self.name . '.' . a:ext
if !vimtex#paths#is_abs(self.compiler.build_dir)
let cand = self.root . '/' . cand
endif
if a:0 > 0 || filereadable(cand)
return fnamemodify(cand, ':p')
endif
endif
" Next check for file in project root folder
let cand = self.root . '/' . self.name . '.' . a:ext
if a:0 > 0 || filereadable(cand)
return fnamemodify(cand, ':p')
endif
" Finally return empty string if no entry is found
return ''
endfunction
" }}}1
function! s:vimtex.getftime() abort dict " {{{1
return max(map(copy(self.sources), 'getftime(self.root . ''/'' . v:val)'))
endfunction
" }}}1
" Initialize module
let s:vimtex_states = {}
let s:vimtex_next_id = 0
endif

View File

@@ -1,66 +0,0 @@
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#syntax#init() abort " {{{1
if !get(g:, 'vimtex_syntax_enabled', 1) | return | endif
" The following ensures that syntax addons are not loaded until after the
" filetype plugin has been sourced. See e.g. #1428 for more info.
if exists('b:vimtex')
call vimtex#syntax#load()
else
augroup vimtex_syntax
autocmd!
autocmd User VimtexEventInitPost call vimtex#syntax#load()
augroup END
endif
endfunction
" }}}1
function! vimtex#syntax#load() abort " {{{1
if s:is_loaded() | return | endif
" Initialize project cache (used e.g. for the minted package)
if !has_key(b:vimtex, 'syntax')
let b:vimtex.syntax = {}
endif
" Initialize b:vimtex_syntax
let b:vimtex_syntax = {}
" Reset included syntaxes (necessary e.g. when doing :e)
call vimtex#syntax#misc#include_reset()
" Set some better defaults
syntax spell toplevel
syntax sync maxlines=500
" Load some general syntax improvements
call vimtex#syntax#load#general()
" Load syntax for documentclass and packages
call vimtex#syntax#load#packages()
" Hack to make it possible to determine if vimtex syntax was loaded
syntax match texVimtexLoaded 'dummyVimtexLoadedText' contained
endfunction
" }}}1
function! s:is_loaded() abort " {{{1
if exists('*execute')
let l:result = split(execute('syntax'), "\n")
return !empty(filter(l:result, 'v:val =~# "texVimtexLoaded"'))
else
return 0
endif
endfunction
" }}}1
endif

View File

@@ -1,95 +0,0 @@
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#syntax#load#general() abort " {{{1
if !exists('b:vimtex_syntax') | return | endif
" I don't see why we can't match Math zones in the MatchNMGroup
if !exists('g:tex_no_math')
syntax cluster texMatchNMGroup add=@texMathZones
endif
" Todo elements
syntax match texStatement '\\todo\w*' contains=texTodo
syntax match texTodo '\\todo\w*'
" Fix strange mistake in main syntax file where \usepackage is added to the
" texInputFile group
syntax match texDocType /\\usepackage\>/
\ nextgroup=texBeginEndName,texDocTypeArgs
" Improve support for italic font, bold font and some conceals
if get(g:, 'tex_fast', 'b') =~# 'b'
let s:conceal = (has('conceal') && get(g:, 'tex_conceal', 'b') =~# 'b')
\ ? 'concealends' : ''
for [s:style, s:group, s:commands] in [
\ ['texItalStyle', 'texItalGroup', ['emph', 'textit']],
\ ['texBoldStyle', 'texBoldGroup', ['textbf']],
\]
for s:cmd in s:commands
execute 'syntax region' s:style 'matchgroup=texTypeStyle'
\ 'start="\\' . s:cmd . '\s*{" end="}"'
\ 'contains=@Spell,@' . s:group
\ s:conceal
endfor
execute 'syntax cluster texMatchGroup add=' . s:style
endfor
endif
" Allow arguments in newenvironments
syntax region texEnvName contained matchgroup=Delimiter
\ start="{"rs=s+1 end="}"
\ nextgroup=texEnvBgn,texEnvArgs contained skipwhite skipnl
syntax region texEnvArgs contained matchgroup=Delimiter
\ start="\["rs=s+1 end="]"
\ nextgroup=texEnvBgn,texEnvArgs skipwhite skipnl
syntax cluster texEnvGroup add=texDefParm,texNewEnv,texComment
" Add support for \renewenvironment and \renewcommand
syntax match texNewEnv "\\renewenvironment\>"
\ nextgroup=texEnvName skipwhite skipnl
syntax match texNewCmd "\\renewcommand\>"
\ nextgroup=texCmdName skipwhite skipnl
" Match nested DefParms
syntax match texDefParmNested contained "##\+\d\+"
highlight def link texDefParmNested Identifier
syntax cluster texEnvGroup add=texDefParmNested
syntax cluster texCmdGroup add=texDefParmNested
endfunction
" }}}1
function! vimtex#syntax#load#packages() abort " {{{1
if !exists('b:vimtex_syntax') | return | endif
try
call vimtex#syntax#p#{b:vimtex.documentclass}#load()
catch /E117:/
endtry
for l:pkg in map(keys(b:vimtex.packages), "substitute(v:val, '-', '_', 'g')")
try
call vimtex#syntax#p#{l:pkg}#load()
catch /E117:/
endtry
endfor
for l:pkg in g:vimtex_syntax_autoload_packages
try
call vimtex#syntax#p#{l:pkg}#load()
catch /E117:/
call vimtex#log#warning('Syntax package does not exist: ' . l:pkg,
\ 'Please see :help g:vimtex_syntax_autoload_packages')
endtry
endfor
endfunction
" }}}1
endif

View File

@@ -1,92 +0,0 @@
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#syntax#misc#add_to_section_clusters(group) abort " {{{1
for l:cluster in [
\ 'texPartGroup',
\ 'texChapterGroup',
\ 'texSectionGroup',
\ 'texSubSectionGroup',
\ 'texSubSubSectionGroup',
\ 'texParaGroup',
\]
execute printf('syntax cluster %s add=%s', l:cluster, a:group)
endfor
execute printf('syntax cluster texVimtexGlobal add=%s', a:group)
endfunction
" }}}1
function! vimtex#syntax#misc#include(name) abort " {{{1
let l:inc_name = 'vimtex_nested_' . a:name
if !has_key(s:included, l:inc_name)
let s:included[l:inc_name] = s:include(l:inc_name, a:name)
endif
return s:included[l:inc_name] ? l:inc_name : ''
endfunction
" }}}1
function! vimtex#syntax#misc#include_reset() abort " {{{1
let s:included = {'vimtex_nested_tex': 0}
endfunction
let s:included = {'vimtex_nested_tex': 0}
" }}}1
function! vimtex#syntax#misc#new_math_zone(sfx, mathzone, starred) abort " {{{1
" This function is based on Charles E. Campbell's amsmath.vba file 2018-06-29
if get(g:, 'tex_fast', 'M') !~# 'M' | return | endif
let foldcmd = get(g:, 'tex_fold_enabled') ? ' fold' : ''
let grp = 'texMathZone' . a:sfx
execute 'syntax cluster texMathZones add=' . grp
execute 'syntax region ' . grp
\ . ' start=''\\begin\s*{\s*' . a:mathzone . '\s*}'''
\ . ' end=''\\end\s*{\s*' . a:mathzone . '\s*}'''
\ . foldcmd . ' keepend contains=@texMathZoneGroup'
execute 'highlight def link '.grp.' texMath'
if a:starred
let grp .= 'S'
execute 'syntax cluster texMathZones add=' . grp
execute 'syntax region ' . grp
\ . ' start=''\\begin\s*{\s*' . a:mathzone . '\*\s*}'''
\ . ' end=''\\end\s*{\s*' . a:mathzone . '\*\s*}'''
\ . foldcmd . ' keepend contains=@texMathZoneGroup'
execute 'highlight def link '.grp.' texMath'
endif
execute 'syntax match texBadMath ''\\end\s*{\s*' . a:mathzone . '\*\=\s*}'''
endfunction
" }}}1
function! s:include(cluster, name) abort " {{{1
let l:name = get(g:vimtex_syntax_nested.aliases, a:name, a:name)
let l:path = 'syntax/' . l:name . '.vim'
if empty(globpath(&runtimepath, l:path)) | return 0 | endif
unlet b:current_syntax
execute 'syntax include @' . a:cluster l:path
let b:current_syntax = 'tex'
for l:ignored_group in get(g:vimtex_syntax_nested.ignored, l:name, [])
execute 'syntax cluster' a:cluster 'remove=' . l:ignored_group
endfor
return 1
endfunction
" }}}1
endif

View File

@@ -1,47 +0,0 @@
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
"
scriptencoding utf-8
function! vimtex#syntax#p#amsmath#load() abort " {{{1
if has_key(b:vimtex_syntax, 'amsmath') | return | endif
let b:vimtex_syntax.amsmath = 1
" Allow subequations (fixes #1019)
" - This should be temporary, as it seems subequations is erroneously part of
" texBadMath from Charles Campbell's syntax plugin.
syntax match texBeginEnd
\ "\(\\begin\>\|\\end\>\)\ze{subequations}"
\ nextgroup=texBeginEndName
call vimtex#syntax#misc#new_math_zone('AmsA', 'align', 1)
call vimtex#syntax#misc#new_math_zone('AmsB', 'alignat', 1)
call vimtex#syntax#misc#new_math_zone('AmsD', 'flalign', 1)
call vimtex#syntax#misc#new_math_zone('AmsC', 'gather', 1)
call vimtex#syntax#misc#new_math_zone('AmsD', 'multline', 1)
call vimtex#syntax#misc#new_math_zone('AmsE', 'xalignat', 1)
call vimtex#syntax#misc#new_math_zone('AmsF', 'xxalignat', 0)
call vimtex#syntax#misc#new_math_zone('AmsG', 'mathpar', 1)
" Amsmath [lr][vV]ert (Holger Mitschke)
if has('conceal') && &enc ==# 'utf-8' && get(g:, 'tex_conceal', 'd') =~# 'd'
for l:texmath in [
\ ['\\lvert', '|'] ,
\ ['\\rvert', '|'] ,
\ ['\\lVert', '‖'] ,
\ ['\\rVert', '‖'] ,
\ ]
execute "syntax match texMathDelim '\\\\[bB]igg\\=[lr]\\="
\ . l:texmath[0] . "' contained conceal cchar=" . l:texmath[1]
endfor
endif
endfunction
" }}}1
endif

View File

@@ -1,35 +0,0 @@
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#syntax#p#array#load() abort " {{{1
if has_key(b:vimtex_syntax, 'array') | return | endif
let b:vimtex_syntax.array = 1
call vimtex#syntax#p#tabularx#load()
if !get(g:, 'tex_fast', 'M') =~# 'M' | return | endif
"
" The following code changes inline math so as to support the column
" specifiers [0], e.g.
"
" \begin{tabular}{*{3}{>{$}c<{$}}}
"
" [0]: https://en.wikibooks.org/wiki/LaTeX/Tables#Column_specification_using_.3E.7B.5Ccmd.7D_and_.3C.7B.5Ccmd.7D
"
syntax clear texMathZoneX
if has('conceal') && &enc ==# 'utf-8' && get(g:, 'tex_conceal', 'd') =~# 'd'
syntax region texMathZoneX matchgroup=Delimiter start="\([<>]{\)\@<!\$" skip="\%(\\\\\)*\\\$" matchgroup=Delimiter end="\$" end="%stopzone\>" concealends contains=@texMathZoneGroup
else
syntax region texMathZoneX matchgroup=Delimiter start="\([<>]{\)\@<!\$" skip="\%(\\\\\)*\\\$" matchgroup=Delimiter end="\$" end="%stopzone\>" contains=@texMathZoneGroup
endif
endfunction
" }}}1
endif

View File

@@ -1,34 +0,0 @@
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#syntax#p#asymptote#load() abort " {{{1
if has_key(b:vimtex_syntax, 'asymptote') | return | endif
let b:vimtex_syntax.asymptote = 1
call vimtex#syntax#misc#add_to_section_clusters('texZoneAsymptote')
if !empty(vimtex#syntax#misc#include('asy'))
syntax region texZoneAsymptote
\ start='\\begin{asy\z(def\)\?}'rs=s
\ end='\\end{asy\z1}'re=e
\ keepend
\ transparent
\ contains=texBeginEnd,@vimtex_nested_asy
else
syntax region texZoneAsymptote
\ start='\\begin{asy\z(def\)\?}'rs=s
\ end='\\end{asy\z1}'re=e
\ keepend
\ contains=texBeginEnd
highlight def link texZoneAsymptote texZone
endif
endfunction
" }}}1
endif

View File

@@ -1,32 +0,0 @@
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#syntax#p#beamer#load() abort " {{{1
if has_key(b:vimtex_syntax, 'beamer') | return | endif
let b:vimtex_syntax.beamer = 1
syntax match texBeamerDelimiter '<\|>' contained
syntax match texBeamerOpt '<[^>]*>' contained contains=texBeamerDelimiter
syntax match texStatementBeamer '\\only\(<[^>]*>\)\?' contains=texBeamerOpt
syntax match texStatementBeamer '\\item<[^>]*>' contains=texBeamerOpt
syntax match texInputFile
\ '\\includegraphics<[^>]*>\(\[.\{-}\]\)\=\s*{.\{-}}'
\ contains=texStatement,texBeamerOpt,texInputCurlies,texInputFileOpt
call vimtex#syntax#misc#add_to_section_clusters('texStatementBeamer')
highlight link texStatementBeamer texStatement
highlight link texBeamerOpt Identifier
highlight link texBeamerDelimiter Delimiter
endfunction
" }}}1
endif

View File

@@ -1,84 +0,0 @@
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#syntax#p#biblatex#load() abort " {{{1
if has_key(b:vimtex_syntax, 'biblatex') | return | endif
let b:vimtex_syntax.biblatex = 1
if get(g:, 'tex_fast', 'r') !~# 'r' | return | endif
for l:pattern in [
\ 'bibentry',
\ 'cite[pt]?\*?',
\ 'citeal[tp]\*?',
\ 'cite(num|text|url)',
\ '[Cc]ite%(title|author|year(par)?|date)\*?',
\ '[Pp]arencite\*?',
\ 'foot%(full)?cite%(text)?',
\ 'fullcite',
\ '[Tt]extcite',
\ '[Ss]martcite',
\ 'supercite',
\ '[Aa]utocite\*?',
\ '[Ppf]?[Nn]otecite',
\ '%(text|block)cquote\*?',
\]
execute 'syntax match texStatement'
\ '/\v\\' . l:pattern . '\ze\s*%(\[|\{)/'
\ 'nextgroup=texRefOption,texCite'
endfor
for l:pattern in [
\ '[Cc]ites',
\ '[Pp]arencites',
\ 'footcite%(s|texts)',
\ '[Tt]extcites',
\ '[Ss]martcites',
\ 'supercites',
\ '[Aa]utocites',
\ '[pPfFsStTaA]?[Vv]olcites?',
\ 'cite%(field|list|name)',
\]
execute 'syntax match texStatement'
\ '/\v\\' . l:pattern . '\ze\s*%(\[|\{)/'
\ 'nextgroup=texRefOptions,texCites'
endfor
for l:pattern in [
\ '%(foreign|hyphen)textcquote\*?',
\ '%(foreign|hyphen)blockcquote',
\ 'hybridblockcquote',
\]
execute 'syntax match texStatement'
\ '/\v\\' . l:pattern . '\ze\s*%(\[|\{)/'
\ 'nextgroup=texQuoteLang'
endfor
syntax region texRefOptions contained matchgroup=Delimiter
\ start='\[' end=']'
\ contains=@texRefGroup,texRefZone
\ nextgroup=texRefOptions,texCites
syntax region texCites contained matchgroup=Delimiter
\ start='{' end='}'
\ contains=@texRefGroup,texRefZone,texCites
\ nextgroup=texRefOptions,texCites
syntax region texQuoteLang contained matchgroup=Delimiter
\ start='{' end='}'
\ transparent
\ contains=@texMatchGroup
\ nextgroup=texRefOption,texCite
highlight def link texRefOptions texRefOption
highlight def link texCites texCite
endfunction
" }}}1
endif

View File

@@ -1,23 +0,0 @@
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
"
scriptencoding utf-8
function! vimtex#syntax#p#breqn#load() abort " {{{1
if has_key(b:vimtex_syntax, 'breqn') | return | endif
let b:vimtex_syntax.breqn = 1
call vimtex#syntax#misc#new_math_zone('BreqnA', 'dmath', 1)
call vimtex#syntax#misc#new_math_zone('BreqnB', 'dseries', 1)
call vimtex#syntax#misc#new_math_zone('BreqnC', 'dgroup', 1)
call vimtex#syntax#misc#new_math_zone('BreqnD', 'darray', 1)
endfunction
" }}}1
endif

View File

@@ -1,20 +0,0 @@
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
"
scriptencoding utf-8
function! vimtex#syntax#p#cases#load() abort " {{{1
if has_key(b:vimtex_syntax, 'cases') | return | endif
let b:vimtex_syntax.cases = 1
call VimtexNewMathZone('E', '\(sub\)\?numcases', 0)
endfunction
" }}}1
endif

View File

@@ -1,44 +0,0 @@
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#syntax#p#cleveref#load() abort " {{{1
if has_key(b:vimtex_syntax, 'cleveref') | return | endif
let b:vimtex_syntax.cleveref = 1
if get(g:, 'tex_fast', 'r') !~# 'r' | return | endif
syntax match texStatement '\\\(\(label\)\?c\(page\)\?\|C\|auto\)ref\>'
\ nextgroup=texCRefZone
" \crefrange, \cpagerefrange (these commands expect two arguments)
syntax match texStatement '\\c\(page\)\?refrange\>'
\ nextgroup=texCRefZoneRange skipwhite skipnl
" \label[xxx]{asd}
syntax match texStatement '\\label\[.\{-}\]'
\ nextgroup=texCRefZone skipwhite skipnl
\ contains=texCRefLabelOpts
syntax region texCRefZone contained matchgroup=Delimiter
\ start="{" end="}"
\ contains=@texRefGroup,texRefZone
syntax region texCRefZoneRange contained matchgroup=Delimiter
\ start="{" end="}"
\ contains=@texRefGroup,texRefZone
\ nextgroup=texCRefZone skipwhite skipnl
syntax region texCRefLabelOpts contained matchgroup=Delimiter
\ start='\[' end=']'
\ contains=@texRefGroup,texRefZone
highlight link texCRefZone texRefZone
highlight link texCRefZoneRange texRefZone
highlight link texCRefLabelOpts texCmdArgs
endfunction
" }}}1
endif

View File

@@ -1,18 +0,0 @@
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#syntax#p#csquotes#load() abort " {{{1
if has_key(b:vimtex_syntax, 'csquotes') | return | endif
let b:vimtex_syntax.csquotes = 1
call vimtex#syntax#p#biblatex#load()
endfunction
" }}}1
endif

View File

@@ -1,25 +0,0 @@
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#syntax#p#dot2texi#load() abort " {{{1
if has_key(b:vimtex_syntax, 'dot2texi') | return | endif
let b:vimtex_syntax.dot2texi = 1
call vimtex#syntax#misc#include('dot')
call vimtex#syntax#misc#add_to_section_clusters('texZoneDot')
syntax region texZoneDot
\ start="\\begin{dot2tex}"rs=s
\ end="\\end{dot2tex}"re=e
\ keepend
\ transparent
\ contains=texBeginEnd,@vimtex_nested_dot
endfunction
" }}}1
endif

View File

@@ -1,20 +0,0 @@
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
"
scriptencoding utf-8
function! vimtex#syntax#p#glossaries#load() abort " {{{1
if has_key(b:vimtex_syntax, 'glossaries') | return | endif
let b:vimtex_syntax.glossaries = 1
" Currently nothing here
endfunction
" }}}1
endif

View File

@@ -1,21 +0,0 @@
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
"
scriptencoding utf-8
function! vimtex#syntax#p#glossaries_extra#load() abort " {{{1
if has_key(b:vimtex_syntax, 'glossaries_extra') | return | endif
let b:vimtex_syntax.glossaries_extra = 1
" Load amsmath
call vimtex#syntax#p#glossaries#load()
endfunction
" }}}1
endif

View File

@@ -1,25 +0,0 @@
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#syntax#p#gnuplottex#load() abort " {{{1
if has_key(b:vimtex_syntax, 'gnuplottex') | return | endif
let b:vimtex_syntax.gnuplottex = 1
call vimtex#syntax#misc#include('gnuplot')
call vimtex#syntax#misc#add_to_section_clusters('texZoneGnuplot')
syntax region texZoneGnuplot
\ start='\\begin{gnuplot}\(\_s*\[\_[\]]\{-}\]\)\?'rs=s
\ end='\\end{gnuplot}'re=e
\ keepend
\ transparent
\ contains=texBeginEnd,texBeginEndModifier,@vimtex_nested_gnuplot
endfunction
" }}}1
endif

View File

@@ -1,35 +0,0 @@
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#syntax#p#hyperref#load() abort " {{{1
if has_key(b:vimtex_syntax, 'hyperref') | return | endif
let b:vimtex_syntax.hyperref = 1
syntax match texStatement '\\url\ze[^\ta-zA-Z]' nextgroup=texUrlVerb
syntax region texUrlVerb matchgroup=Delimiter
\ start='\z([^\ta-zA-Z]\)' end='\z1' contained
syntax match texStatement '\\url\ze\s*{' nextgroup=texUrl
syntax region texUrl matchgroup=Delimiter start='{' end='}' contained
syntax match texStatement '\\href' nextgroup=texHref
syntax region texHref matchgroup=Delimiter start='{' end='}' contained
\ nextgroup=texMatcher
syntax match texStatement '\\hyperref' nextgroup=texHyperref
syntax region texHyperref matchgroup=Delimiter start='\[' end='\]' contained
highlight link texUrl Function
highlight link texUrlVerb texUrl
highlight link texHref texUrl
highlight link texHyperref texRefZone
endfunction
" }}}1
endif

View File

@@ -1,75 +0,0 @@
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#syntax#p#listings#load() abort " {{{1
if has_key(b:vimtex_syntax, 'listings') | return | endif
let b:vimtex_syntax.listings = s:get_nested_languages()
" First some general support
syntax match texInputFile
\ "\\lstinputlisting\s*\(\[.\{-}\]\)\={.\{-}}"
\ contains=texStatement,texInputCurlies,texInputFileOpt
syntax match texZone "\\lstinline\s*\(\[.\{-}\]\)\={.\{-}}"
" Set all listings environments to listings
syntax cluster texFoldGroup add=texZoneListings
syntax region texZoneListings
\ start="\\begin{lstlisting}\(\_s*\[\_[^\]]\{-}\]\)\?"rs=s
\ end="\\end{lstlisting}\|%stopzone\>"re=e
\ keepend
\ contains=texBeginEnd
" Next add nested syntax support for desired languages
for l:nested in b:vimtex_syntax.listings
let l:cluster = vimtex#syntax#misc#include(l:nested)
if empty(l:cluster) | continue | endif
let l:group_main = 'texZoneListings' . toupper(l:nested[0]) . l:nested[1:]
let l:group_lstset = l:group_main . 'Lstset'
let l:group_contained = l:group_main . 'Contained'
execute 'syntax cluster texFoldGroup add=' . l:group_main
execute 'syntax cluster texFoldGroup add=' . l:group_lstset
execute 'syntax region' l:group_main
\ 'start="\c\\begin{lstlisting}\s*'
\ . '\[\_[^\]]\{-}language=' . l:nested . '\%(\s*,\_[^\]]\{-}\)\?\]"rs=s'
\ 'end="\\end{lstlisting}"re=e'
\ 'keepend'
\ 'transparent'
\ 'contains=texBeginEnd,@' . l:cluster
execute 'syntax match' l:group_lstset
\ '"\c\\lstset{.*language=' . l:nested . '\%(\s*,\|}\)"'
\ 'transparent'
\ 'contains=texStatement,texMatcher'
\ 'skipwhite skipempty'
\ 'nextgroup=' . l:group_contained
execute 'syntax region' l:group_contained
\ 'start="\\begin{lstlisting}"rs=s'
\ 'end="\\end{lstlisting}"re=e'
\ 'keepend'
\ 'transparent'
\ 'containedin=' . l:group_lstset
\ 'contains=texStatement,texBeginEnd,@' . l:cluster
endfor
highlight link texZoneListings texZone
endfunction
" }}}1
function! s:get_nested_languages() abort " {{{1
return map(
\ filter(getline(1, '$'), "v:val =~# 'language='"),
\ 'matchstr(v:val, ''language=\zs\w\+'')')
endfunction
" }}}1
endif

View File

@@ -1,31 +0,0 @@
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#syntax#p#luacode#load() abort " {{{1
if has_key(b:vimtex_syntax, 'luacode') | return | endif
let b:vimtex_syntax.luacode = 1
call vimtex#syntax#misc#include('lua')
call vimtex#syntax#misc#add_to_section_clusters('texZoneLua')
syntax region texZoneLua
\ start='\\begin{luacode\*\?}'rs=s
\ end='\\end{luacode\*\?}'re=e
\ keepend
\ transparent
\ contains=texBeginEnd,@vimtex_nested_lua
syntax match texStatement '\\\(directlua\|luadirect\)' nextgroup=texZoneLuaArg
syntax region texZoneLuaArg matchgroup=Delimiter
\ start='{'
\ end='}'
\ contained
\ contains=@vimtex_nested_lua
endfunction
" }}}1
endif

View File

@@ -1,43 +0,0 @@
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#syntax#p#markdown#load() abort " {{{1
if has_key(b:vimtex_syntax, 'markdown') | return | endif
let b:vimtex_syntax.markdown = 1
call vimtex#syntax#misc#add_to_section_clusters('texZoneMarkdown')
call vimtex#syntax#misc#include('markdown')
" Don't quite know why this is necessary, but it is
syntax match texBeginEnd
\ '\(\\begin\>\|\\end\>\)\ze{markdown}'
\ nextgroup=texBeginEndName
syntax region texZoneMarkdown
\ start='\\begin{markdown}'rs=s
\ end='\\end{markdown}'re=e
\ keepend
\ transparent
\ contains=@texFoldGroup,@texDocGroup,@vimtex_nested_markdown
" Input files
syntax match texInputFile /\\markdownInput\>/
\ contains=texStatement
\ nextgroup=texInputFileArg
syntax region texInputFileArg
\ matchgroup=texInputCurlies
\ start="{" end="}"
\ contained
\ contains=texComment
highlight default link texInputFileArg texInputFile
endfunction
" }}}1
endif

View File

@@ -1,21 +0,0 @@
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
"
scriptencoding utf-8
function! vimtex#syntax#p#mathtools#load() abort " {{{1
if has_key(b:vimtex_syntax, 'mathtools') | return | endif
let b:vimtex_syntax.mathtools = 1
" Load amsmath
call vimtex#syntax#p#amsmath#load()
endfunction
" }}}1
endif

View File

@@ -1,256 +0,0 @@
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#syntax#p#minted#load() abort " {{{1
if has_key(b:vimtex_syntax, 'minted') | return | endif
let b:vimtex_syntax.minted = 1
" Parse minted macros in the current project
call s:parse_minted_constructs()
" Match minted language names
syntax region texMintedName matchgroup=Delimiter start="{" end="}" contained
syntax region texMintedNameOpt matchgroup=Delimiter start="\[" end="\]" contained
" Match boundaries of minted environments
syntax match texMintedBounds '\\end{minted}'
\ contained
\ contains=texBeginEnd
syntax match texMintedBounds '\\begin{minted}'
\ contained
\ contains=texBeginEnd
\ nextgroup=texMintedBoundsOpts,texMintedName
syntax region texMintedBoundsOpts matchgroup=Delimiter
\ start="\[" end="\]"
\ contained
\ nextgroup=texMintedName
" Match starred custom minted environments with options
syntax match texMintedStarred "\\begin{\w\+\*}"
\ contained
\ contains=texBeginEnd
\ nextgroup=texMintedStarredOpts
syntax region texMintedStarredOpts matchgroup=Delimiter
\ start='{'
\ end='}'
\ contained
\ containedin=texMintedStarred
" Match \newminted type macros
syntax match texStatement '\\newmint\%(ed\|inline\)\?' nextgroup=texMintedName,texMintedNameOpt
" Match "unknown" environments
call vimtex#syntax#misc#add_to_section_clusters('texZoneMinted')
syntax region texZoneMinted
\ start="\\begin{minted}\%(\_s*\[\_[^\]]\{-}\]\)\?\_s*{\w\+}"rs=s
\ end="\\end{minted}"re=e
\ keepend
\ contains=texMintedBounds.*
" Match "unknown" commands
syntax match texArgMinted "{\w\+}"
\ contained
\ contains=texMintedName
\ nextgroup=texZoneMintedCmd
syntax region texZoneMintedCmd matchgroup=Delimiter
\ start='\z([|+/]\)'
\ end='\z1'
\ contained
syntax region texZoneMintedCmd matchgroup=Delimiter
\ start='{'
\ end='}'
\ contained
" Next add nested syntax support for desired languages
for [l:nested, l:config] in items(b:vimtex.syntax.minted)
let l:cluster = vimtex#syntax#misc#include(l:nested)
let l:name = 'Minted' . toupper(l:nested[0]) . l:nested[1:]
let l:group_main = 'texZone' . l:name
let l:group_arg = 'texArg' . l:name
let l:group_arg_zone = 'texArgZone' . l:name
call vimtex#syntax#misc#add_to_section_clusters(l:group_main)
if empty(l:cluster)
let l:transparent = ''
let l:contains_env = ''
let l:contains_macro = ''
execute 'highlight link' l:group_main 'texZoneMinted'
execute 'highlight link' l:group_arg_zone 'texZoneMinted'
else
let l:transparent = 'transparent'
let l:contains_env = ',@' . l:cluster
let l:contains_macro = 'contains=@' . l:cluster
endif
" Match minted environment
execute 'syntax region' l:group_main
\ 'start="\\begin{minted}\%(\_s*\[\_[^\]]\{-}\]\)\?\_s*{' . l:nested . '}"rs=s'
\ 'end="\\end{minted}"re=e'
\ 'keepend'
\ l:transparent
\ 'contains=texMintedBounds.*' . l:contains_env
" Match custom environment names
for l:env in get(l:config, 'environments', [])
execute 'syntax region' l:group_main
\ 'start="\\begin{\z(' . l:env . '\*\?\)}"rs=s'
\ 'end="\\end{\z1}"re=e'
\ 'keepend'
\ l:transparent
\ 'contains=texMintedStarred,texBeginEnd' . l:contains_env
endfor
" Match minted macros
" - \mint[]{lang}|...|
" - \mint[]{lang}{...}
" - \mintinline[]{lang}|...|
" - \mintinline[]{lang}{...}
execute 'syntax match' l:group_arg '''{' . l:nested . '}'''
\ 'contained'
\ 'contains=texMintedName'
\ 'nextgroup=' . l:group_arg_zone
execute 'syntax region' l:group_arg_zone
\ 'matchgroup=Delimiter'
\ 'start=''\z([|+/]\)'''
\ 'end=''\z1'''
\ 'contained'
\ l:contains_macro
execute 'syntax region' l:group_arg_zone
\ 'matchgroup=Delimiter'
\ 'start=''{'''
\ 'end=''}'''
\ 'contained'
\ l:contains_macro
" Match minted custom macros
for l:cmd in sort(get(l:config, 'commands', []))
execute printf('syntax match texStatement ''\\%s'' nextgroup=%s',
\ l:cmd, l:group_arg_zone)
endfor
endfor
" Main matcher for the minted statements/commands
" - Note: This comes last to allow the nextgroup pattern
syntax match texStatement '\\mint\(inline\)\?' nextgroup=texArgOptMinted,texArgMinted.*
syntax region texArgOptMinted matchgroup=Delimiter
\ start='\['
\ end='\]'
\ contained
\ nextgroup=texArgMinted.*
highlight link texZoneMinted texZone
highlight link texZoneMintedCmd texZone
highlight link texMintedName texInputFileOpt
highlight link texMintedNameOpt texMintedName
endfunction
" }}}1
function! s:parse_minted_constructs() abort " {{{1
if has_key(b:vimtex.syntax, 'minted') | return | endif
let l:db = deepcopy(s:db)
let b:vimtex.syntax.minted = l:db.data
let l:in_multi = 0
for l:line in vimtex#parser#tex(b:vimtex.tex, {'detailed': 0})
" Multiline minted environments
if l:in_multi
let l:lang = matchstr(l:line, '\]\s*{\zs\w\+\ze}')
if !empty(l:lang)
call l:db.register(l:lang)
let l:in_multi = 0
endif
continue
endif
if l:line =~# '\\begin{minted}\s*\[[^\]]*$'
let l:in_multi = 1
continue
endif
" Single line minted environments
let l:lang = matchstr(l:line, '\\begin{minted}\%(\s*\[\[^\]]*\]\)\?\s*{\zs\w\+\ze}')
if !empty(l:lang)
call l:db.register(l:lang)
continue
endif
" Simple minted commands
let l:lang = matchstr(l:line, '\\mint\%(\s*\[[^\]]*\]\)\?\s*{\zs\w\+\ze}')
if !empty(l:lang)
call l:db.register(l:lang)
continue
endif
" Custom environments:
" - \newminted{lang}{opts} -> langcode
" - \newminted[envname]{lang}{opts} -> envname
let l:matches = matchlist(l:line,
\ '\\newminted\%(\s*\[\([^\]]*\)\]\)\?\s*{\([a-zA-Z-]\+\)}')
if !empty(l:matches)
call l:db.register(l:matches[2])
call l:db.add_environment(!empty(l:matches[1])
\ ? l:matches[1]
\ : l:matches[2] . 'code')
continue
endif
" Custom macros:
" - \newmint(inline){lang}{opts} -> \lang(inline)
" - \newmint(inline)[macroname]{lang}{opts} -> \macroname
let l:matches = matchlist(l:line,
\ '\\newmint\(inline\)\?\%(\s*\[\([^\]]*\)\]\)\?\s*{\([a-zA-Z-]\+\)}')
if !empty(l:matches)
call l:db.register(l:matches[3])
call l:db.add_macro(!empty(l:matches[2])
\ ? l:matches[2]
\ : l:matches[3] . l:matches[1])
continue
endif
endfor
endfunction
" }}}1
let s:db = {
\ 'data' : {},
\}
function! s:db.register(lang) abort dict " {{{1
" Avoid dashes in langnames
let l:lang = substitute(a:lang, '-', '', 'g')
if !has_key(self.data, l:lang)
let self.data[l:lang] = {
\ 'environments' : [],
\ 'commands' : [],
\}
endif
let self.cur = self.data[l:lang]
endfunction
" }}}1
function! s:db.add_environment(envname) abort dict " {{{1
if index(self.cur.environments, a:envname) < 0
let self.cur.environments += [a:envname]
endif
endfunction
" }}}1
function! s:db.add_macro(macroname) abort dict " {{{1
if index(self.cur.commands, a:macroname) < 0
let self.cur.commands += [a:macroname]
endif
endfunction
" }}}1
endif

View File

@@ -1,26 +0,0 @@
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#syntax#p#moreverb#load() abort " {{{1
if has_key(b:vimtex_syntax, 'moreverb') | return | endif
let b:vimtex_syntax.moreverb = 1
if exists('g:tex_verbspell')
syntax region texZone start="\\begin{verbatimtab}" end="\\end{verbatimtab}\|%stopzone\>" contains=@Spell
syntax region texZone start="\\begin{verbatimwrite}" end="\\end{verbatimwrite}\|%stopzone\>" contains=@Spell
syntax region texZone start="\\begin{boxedverbatim}" end="\\end{boxedverbatim}\|%stopzone\>" contains=@Spell
else
syntax region texZone start="\\begin{verbatimtab}" end="\\end{verbatimtab}\|%stopzone\>"
syntax region texZone start="\\begin{verbatimwrite}" end="\\end{verbatimwrite}\|%stopzone\>"
syntax region texZone start="\\begin{boxedverbatim}" end="\\end{boxedverbatim}\|%stopzone\>"
endif
endfunction
" }}}1
endif

View File

@@ -1,18 +0,0 @@
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#syntax#p#natbib#load() abort " {{{1
if has_key(b:vimtex_syntax, 'natbib') | return | endif
let b:vimtex_syntax.natbib = 1
call vimtex#syntax#p#biblatex#load()
endfunction
" }}}1
endif

View File

@@ -1,33 +0,0 @@
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#syntax#p#pdfpages#load() abort " {{{1
if has_key(b:vimtex_syntax, 'pdfpages') | return | endif
let b:vimtex_syntax.pdfpages = 1
syntax match texInputFile /\\includepdf\>/
\ contains=texStatement
\ nextgroup=texInputFileOpt,texInputFileArg
syntax region texInputFileOpt
\ matchgroup=Delimiter
\ start="\[" end="\]"
\ contained
\ contains=texComment,@NoSpell
\ nextgroup=texInputFileArg
syntax region texInputFileArg
\ matchgroup=texInputCurlies
\ start="{" end="}"
\ contained
\ contains=texComment
highlight default link texInputFileArg texInputFile
endfunction
" }}}1
endif

Some files were not shown because too many files have changed in this diff Show More