mirror of
https://github.com/sheerun/vim-polyglot.git
synced 2025-11-08 11:33:52 -05:00
Compare commits
84 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7972e8eea1 | ||
|
|
6ed481e463 | ||
|
|
c1e1870a3d | ||
|
|
f0d6ecff07 | ||
|
|
15e5df246e | ||
|
|
94ababe91f | ||
|
|
080b8cdc60 | ||
|
|
e47af23f64 | ||
|
|
8f5134aef8 | ||
|
|
be8d039e02 | ||
|
|
38ce8e9cb6 | ||
|
|
55ad5a982a | ||
|
|
b2055afaa7 | ||
|
|
63a175357a | ||
|
|
25db54573a | ||
|
|
d1bfe50419 | ||
|
|
22e8e01c1e | ||
|
|
30bef582ba | ||
|
|
74d940cda3 | ||
|
|
54d2386262 | ||
|
|
a47c315b01 | ||
|
|
ff0ada0dc3 | ||
|
|
e194de5875 | ||
|
|
012cf89210 | ||
|
|
ac71777dc2 | ||
|
|
23defeb610 | ||
|
|
114a93bb7c | ||
|
|
f3ab28a287 | ||
|
|
bc3b36088e | ||
|
|
5d0150e326 | ||
|
|
cf8e31ff7f | ||
|
|
0df1bfa0c5 | ||
|
|
f7302d9262 | ||
|
|
7e38f4288a | ||
|
|
e521ba3ae2 | ||
|
|
ee4f51587d | ||
|
|
20a388cbc8 | ||
|
|
81e61a3c5d | ||
|
|
5670985b3a | ||
|
|
69eae22ea6 | ||
|
|
f8cee0172b | ||
|
|
c6936aeeb1 | ||
|
|
6bb111eaba | ||
|
|
dfecb63078 | ||
|
|
00015bd105 | ||
|
|
d821de3142 | ||
|
|
a3bdbcdb3c | ||
|
|
34e01b8b62 | ||
|
|
1e533e5982 | ||
|
|
56121b4e27 | ||
|
|
9c3c0bc082 | ||
|
|
8500ae8bb9 | ||
|
|
d09a56a494 | ||
|
|
abca7c2014 | ||
|
|
8b6c06e723 | ||
|
|
a86c0179eb | ||
|
|
22095febb7 | ||
|
|
ff066ee9f0 | ||
|
|
5b38663027 | ||
|
|
f0b38f2c1d | ||
|
|
6676d61f61 | ||
|
|
f0da1a9f4d | ||
|
|
298d6b6356 | ||
|
|
62f004c3da | ||
|
|
c73ea49ecb | ||
|
|
b2be47befc | ||
|
|
de38ccabbd | ||
|
|
f0f49cf0fa | ||
|
|
224a6348f9 | ||
|
|
00c3f02945 | ||
|
|
df34b4b4fa | ||
|
|
f3804b0892 | ||
|
|
685aeaaeb1 | ||
|
|
a9cc6fd218 | ||
|
|
3c47f192b5 | ||
|
|
c8b350432c | ||
|
|
cdb8e233c2 | ||
|
|
ff282f610f | ||
|
|
74cb75bedd | ||
|
|
42529540df | ||
|
|
a688c66a04 | ||
|
|
0a7c62b3b2 | ||
|
|
c7b5826d53 | ||
|
|
1d348d0c2d |
7
.gitattributes
vendored
7
.gitattributes
vendored
@@ -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
|
||||
21
.github/workflows/test.yml
vendored
Normal file
21
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: Vim Polyglot CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # weekly
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Vim
|
||||
run: |
|
||||
sudo add-apt-repository ppa:jonathonf/vim -y
|
||||
sudo apt-get update -q
|
||||
sudo apt-get install -y vim
|
||||
vim --version
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run Tests
|
||||
run: make test
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
/tmp
|
||||
!*ctags*
|
||||
tags
|
||||
|
||||
11
.travis.yml
11
.travis.yml
@@ -1,11 +0,0 @@
|
||||
language: ruby
|
||||
rvm:
|
||||
- 2.6
|
||||
sudo: false
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- vim-gtk
|
||||
before_script:
|
||||
- "./build"
|
||||
script: xvfb-run bundle exec rspec --format=documentation
|
||||
28
Gemfile.lock
28
Gemfile.lock
@@ -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
|
||||
7
Makefile
Normal file
7
Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
.PHONY: all
|
||||
|
||||
all:
|
||||
@ scripts/build
|
||||
|
||||
test:
|
||||
@ scripts/test
|
||||
116
README.md
116
README.md
@@ -1,22 +1,20 @@
|
||||

|
||||
|
||||
[![Build Status][travis-img-url]][travis-url] []()
|
||||
|
||||
[travis-img-url]: https://travis-ci.org/sheerun/vim-polyglot.svg
|
||||
[travis-url]: https://travis-ci.org/sheerun/vim-polyglot
|
||||
 []()
|
||||
|
||||
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-->155<!--/Package Count--> packages it consists of.
|
||||
- It is more secure because scripts loaded for all extensions are generated by vim-polyglot (ftdetect).
|
||||
- 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 around `19ms` to load.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -38,7 +36,7 @@ mkdir -p ~/.vim/pack/default/start
|
||||
git clone https://github.com/sheerun/vim-polyglot ~/.vim/pack/default/start/vim-polyglot
|
||||
```
|
||||
|
||||
NOTE: Not all features of listed language packs are available. We strip them from functionality slowing vim startup in general (for example we ignore `plugins` folder that is loaded regardless of file type, use `ftplugin` instead).
|
||||
NOTE: Not all features of individual language packs are available. We strip them from functionality slowing vim startup (for example we ignore `plugins` folder that is loaded regardless of file type, instead we prefer `ftplugin` which is loaded lazily).
|
||||
|
||||
If you need full functionality of any plugin, please use it directly with your plugin manager.
|
||||
|
||||
@@ -59,110 +57,117 @@ If you need full functionality of any plugin, please use it directly with your p
|
||||
- [caddyfile](https://github.com/isobit/vim-caddyfile) (syntax, indent, ftplugin)
|
||||
- [carp](https://github.com/hellerve/carp-vim) (syntax)
|
||||
- [cjsx](https://github.com/mtscout6/vim-cjsx) (syntax, ftplugin)
|
||||
- [clojure](https://github.com/guns/vim-clojure-static) (syntax, indent, autoload, ftplugin)
|
||||
- [clojure](https://github.com/guns/vim-clojure-static) (syntax, indent, doc, autoload, ftplugin)
|
||||
- [cmake](https://github.com/pboettch/vim-cmake-syntax) (syntax, indent)
|
||||
- [coffee-script](https://github.com/kchmck/vim-coffee-script) (syntax, compiler, indent, autoload, ftplugin)
|
||||
- [coffee-script](https://github.com/kchmck/vim-coffee-script) (syntax, indent, doc, compiler, autoload, ftplugin)
|
||||
- [cql](https://github.com/elubow/cql-vim) (syntax)
|
||||
- [cryptol](https://github.com/victoredwardocallaghan/cryptol.vim) (syntax, compiler, ftplugin)
|
||||
- [cryptol](https://github.com/victoredwardocallaghan/cryptol.vim) (syntax, doc, compiler, ftplugin)
|
||||
- [crystal](https://github.com/rhysd/vim-crystal) (syntax, indent, autoload, ftplugin)
|
||||
- [csv](https://github.com/chrisbra/csv.vim) (syntax, autoload, ftplugin)
|
||||
- [csv](https://github.com/chrisbra/csv.vim) (syntax, doc, autoload, ftplugin)
|
||||
- [cucumber](https://github.com/tpope/vim-cucumber) (syntax, indent, compiler, ftplugin)
|
||||
- [cue](https://github.com/mgrabovsky/vim-cuesheet) (syntax)
|
||||
- [dart](https://github.com/dart-lang/dart-vim-plugin) (syntax, indent, autoload, ftplugin)
|
||||
- [dhall](https://github.com/vmchale/dhall-vim) (syntax, ftplugin)
|
||||
- [dart](https://github.com/dart-lang/dart-vim-plugin) (syntax, indent, doc, autoload, ftplugin)
|
||||
- [dhall](https://github.com/vmchale/dhall-vim) (syntax, doc, ftplugin)
|
||||
- [dlang](https://github.com/JesseKPhillips/d.vim) (syntax, indent)
|
||||
- [dockerfile](https://github.com/ekalinin/Dockerfile.vim) (syntax, indent, ftplugin)
|
||||
- [elixir](https://github.com/elixir-lang/vim-elixir) (syntax, indent, compiler, autoload, ftplugin)
|
||||
- [elixir](https://github.com/elixir-lang/vim-elixir) (syntax, indent, doc, compiler, autoload, ftplugin)
|
||||
- [elm](https://github.com/andys8/vim-elm-syntax) (syntax, indent)
|
||||
- [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)
|
||||
- [git](https://github.com/tpope/vim-git) (syntax, indent, ftplugin)
|
||||
- [fsharp](https://github.com/ionide/Ionide-vim) (syntax, indent, doc, autoload)
|
||||
- [gdscript](https://github.com/calviken/vim-gdscript3) (syntax, indent)
|
||||
- [git](https://github.com/tpope/vim-git) (syntax, indent, doc, ftplugin)
|
||||
- [glsl](https://github.com/tikhomirov/vim-glsl) (syntax, indent)
|
||||
- [gmpl](https://github.com/maelvalais/gmpl.vim) (syntax)
|
||||
- [gnuplot](https://github.com/vim-scripts/gnuplot-syntax-highlighting) (syntax)
|
||||
- [go](https://github.com/fatih/vim-go) (syntax, compiler, indent)
|
||||
- [go](https://github.com/fatih/vim-go) (syntax, indent, doc, compiler)
|
||||
- [gradle](https://github.com/tfnico/vim-gradle) (compiler)
|
||||
- [graphql](https://github.com/jparise/vim-graphql) (syntax, indent, autoload, ftplugin, after)
|
||||
- [graphql](https://github.com/jparise/vim-graphql) (syntax, indent, autoload, ftplugin, after, doc)
|
||||
- [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)
|
||||
- [haskell](https://github.com/neovimhaskell/haskell-vim) (syntax, indent, doc, ftplugin)
|
||||
- [haxe](https://github.com/yaymukund/vim-haxe) (syntax)
|
||||
- [hcl](https://github.com/b4b4r07/vim-hcl) (syntax, indent, ftplugin)
|
||||
- [helm](https://github.com/towolf/vim-helm) (syntax)
|
||||
- [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)
|
||||
- [idris](https://github.com/idris-hackers/idris-vim) (syntax, indent, ftplugin)
|
||||
- [icalendar](https://github.com/chutzpah/icalendar.vim) (syntax)
|
||||
- [idris](https://github.com/idris-hackers/idris-vim) (syntax, indent, doc, ftplugin)
|
||||
- [ion](https://github.com/vmchale/ion-vim) (syntax, ftplugin)
|
||||
- [javascript](https://github.com/pangloss/vim-javascript) (syntax, indent, compiler, ftplugin, extras)
|
||||
- [javascript](https://github.com/pangloss/vim-javascript) (syntax, indent, 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, doc, 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)
|
||||
- [jsx](https://github.com/MaxMEllon/vim-jsx-pretty) (autoload, after, doc)
|
||||
- [julia](https://github.com/JuliaEditorSupport/julia-vim) (syntax, indent, doc, 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, indent, doc, compiler, autoload)
|
||||
- [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)
|
||||
- [llvm](https://github.com/rhysd/vim-llvm) (syntax, indent, ftplugin)
|
||||
- [log](https://github.com/MTDL9/vim-log-highlighting) (syntax)
|
||||
- [log](https://github.com/MTDL9/vim-log-highlighting) (syntax, doc)
|
||||
- [lua](https://github.com/tbastos/vim-lua) (syntax, indent)
|
||||
- [mako](https://github.com/sophacles/vim-bundle-mako) (syntax, indent, ftplugin)
|
||||
- [markdown](https://github.com/plasticboy/vim-markdown) (syntax, indent, ftplugin)
|
||||
- [markdown](https://github.com/plasticboy/vim-markdown) (syntax, indent, doc, ftplugin)
|
||||
- [mathematica](https://github.com/voldikss/vim-mma) (syntax, ftplugin)
|
||||
- [mdx](https://github.com/jxnblk/vim-mdx-js) (syntax)
|
||||
- [meson](https://github.com/mesonbuild/meson) (syntax, indent, ftplugin)
|
||||
- [moonscript](https://github.com/leafo/moonscript-vim) (syntax, indent, ftplugin)
|
||||
- [nginx](https://github.com/chr4/nginx.vim) (syntax, indent, ftplugin)
|
||||
- [nim](https://github.com/zah/nim.vim) (syntax, compiler, indent)
|
||||
- [nim](https://github.com/zah/nim.vim) (syntax, indent, compiler, autoload)
|
||||
- [nix](https://github.com/LnL7/vim-nix) (syntax, indent, compiler, ftplugin)
|
||||
- [objc](https://github.com/b4winckler/vim-objc) (ftplugin, syntax, indent)
|
||||
- [ocaml](https://github.com/rgrinberg/vim-ocaml) (syntax, indent, compiler, ftplugin)
|
||||
- [ocaml](https://github.com/rgrinberg/vim-ocaml) (syntax, indent, doc, compiler, ftplugin)
|
||||
- [octave](https://github.com/McSinyx/vim-octave) (syntax, indent)
|
||||
- [opencl](https://github.com/petRUShka/vim-opencl) (syntax, indent, ftplugin)
|
||||
- [perl](https://github.com/vim-perl/vim-perl) (syntax, indent, ftplugin)
|
||||
- [pgsql](https://github.com/lifepillar/pgsql.vim) (syntax, indent)
|
||||
- [pgsql](https://github.com/lifepillar/pgsql.vim) (syntax, indent, doc)
|
||||
- [php](https://github.com/StanAngeloff/php.vim) (syntax)
|
||||
- [plantuml](https://github.com/aklt/plantuml-syntax) (syntax, indent, ftplugin)
|
||||
- [pony](https://github.com/jakwings/vim-pony) (syntax, indent, autoload, ftplugin)
|
||||
- [powershell](https://github.com/PProvost/vim-ps1) (syntax, indent, compiler, ftplugin)
|
||||
- [powershell](https://github.com/PProvost/vim-ps1) (syntax, indent, doc, compiler, ftplugin)
|
||||
- [protobuf](https://github.com/uarun/vim-protobuf) (syntax, indent)
|
||||
- [pug](https://github.com/digitaltoad/vim-pug) (syntax, indent, ftplugin)
|
||||
- [puppet](https://github.com/rodjek/vim-puppet) (syntax, indent, autoload, ftplugin, ctags)
|
||||
- [purescript](https://github.com/purescript-contrib/purescript-vim) (syntax, indent, ftplugin)
|
||||
- [python-compiler](https://github.com/aliev/vim-compiler-python) (compiler, autoload)
|
||||
- [python-indent](https://github.com/Vimjas/vim-python-pep8-indent) (indent)
|
||||
- [python](https://github.com/vim-python/python-syntax) (syntax)
|
||||
- [python](https://github.com/vim-python/python-syntax) (syntax, doc)
|
||||
- [qmake](https://github.com/artoj/qmake-syntax-vim) (syntax)
|
||||
- [qml](https://github.com/peterhoeg/vim-qml) (syntax, indent, ftplugin)
|
||||
- [r-lang](https://github.com/vim-scripts/R.vim) (syntax)
|
||||
- [racket](https://github.com/wlangstroth/vim-racket) (syntax, indent, ftplugin)
|
||||
- [ragel](https://github.com/jneen/ragel.vim) (syntax)
|
||||
- [raml](https://github.com/IN3D/vim-raml) (syntax, ftplugin)
|
||||
- [raku](https://github.com/Raku/vim-raku) (syntax, indent, ftplugin)
|
||||
- [raml](https://github.com/IN3D/vim-raml) (syntax, doc, ftplugin)
|
||||
- [razor](https://github.com/adamclerk/vim-razor) (syntax, indent, ftplugin)
|
||||
- [reason](https://github.com/reasonml-editor/vim-reason-plus) (syntax, indent)
|
||||
- [rego](https://github.com/tsandall/vim-rego) (syntax)
|
||||
- [reason](https://github.com/reasonml-editor/vim-reason-plus) (syntax, indent, doc)
|
||||
- [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)
|
||||
- [rust](https://github.com/rust-lang/rust.vim) (syntax, indent, compiler, autoload, ftplugin, ctags)
|
||||
- [ruby](https://github.com/vim-ruby/vim-ruby) (syntax, indent, doc, compiler, autoload, ftplugin)
|
||||
- [rust](https://github.com/rust-lang/rust.vim) (syntax, indent, doc, compiler, autoload, ftplugin, ctags)
|
||||
- [sbt](https://github.com/derekwyatt/vim-sbt) (syntax)
|
||||
- [scala](https://github.com/derekwyatt/vim-scala) (syntax, indent, compiler, ftplugin, ctags)
|
||||
- [scala](https://github.com/derekwyatt/vim-scala) (syntax, indent, doc, 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)
|
||||
- [svg-indent](https://github.com/jasonshell/vim-svg-indent) (indent)
|
||||
@@ -170,60 +175,55 @@ If you need full functionality of any plugin, please use it directly with your p
|
||||
- [swift](https://github.com/keith/swift.vim) (syntax, indent, compiler, ftplugin, ctags)
|
||||
- [sxhkd](https://github.com/baskerville/vim-sxhkdrc) (syntax)
|
||||
- [systemd](https://github.com/wgwoods/vim-systemd-syntax) (syntax, ftplugin)
|
||||
- [terraform](https://github.com/hashivim/vim-terraform) (syntax, indent, autoload, ftplugin)
|
||||
- [textile](https://github.com/timcharper/textile.vim) (syntax, ftplugin)
|
||||
- [terraform](https://github.com/hashivim/vim-terraform) (syntax, indent, doc, autoload, ftplugin)
|
||||
- [textile](https://github.com/timcharper/textile.vim) (syntax, doc, ftplugin)
|
||||
- [thrift](https://github.com/solarnz/thrift.vim) (syntax)
|
||||
- [tmux](https://github.com/ericpruitt/tmux.vim) (syntax, ftplugin)
|
||||
- [tomdoc](https://github.com/wellbredgrapefruit/tomdoc.vim) (syntax)
|
||||
- [toml](https://github.com/cespare/vim-toml) (syntax, ftplugin)
|
||||
- [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) (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)
|
||||
- [vcl](https://github.com/smerrill/vcl-vim-plugin) (syntax)
|
||||
- [vifm](https://github.com/vifm/vifm.vim) (syntax, autoload, ftplugin)
|
||||
- [vm](https://github.com/lepture/vim-velocity) (syntax, indent)
|
||||
- [velocity](https://github.com/lepture/vim-velocity) (syntax, indent)
|
||||
- [vue](https://github.com/posva/vim-vue) (syntax, indent, ftplugin)
|
||||
- [xdc](https://github.com/amal-khailtash/vim-xdc-syntax) (syntax)
|
||||
- [xls](https://github.com/vim-scripts/XSLT-syntax) (syntax)
|
||||
- [xml](https://github.com/amadeus/vim-xml) (syntax)
|
||||
- [xsl](https://github.com/vim-scripts/XSLT-syntax) (syntax)
|
||||
- [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-->
|
||||
|
||||
## Updating
|
||||
|
||||
You can either wait for new patch release with updates or run the `./build` script by yourself.
|
||||
You can either wait for new patch release with updates or run `make` by yourself.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Please make sure you have `syntax on` in your `.vimrc`, otherwise syntax files are not loaded at all.
|
||||
Please make sure you have `syntax on` in your `.vimrc` (or use something like [sheerun/vimrc](https://github.com/sheerun/vimrc))
|
||||
|
||||
Individual language packs can be disabled by setting `g:polyglot_disabled` as follows:
|
||||
|
||||
```viml
|
||||
" ~/.vimrc, declare this variable before polyglot is loaded
|
||||
let g:polyglot_disabled = ['css']
|
||||
```
|
||||
|
||||
Note that disabling languages won't make in general your vim startup any faster / slower (only for specific file type). Vim-polyglot is selection of language plugins that are loaded only on demand.
|
||||
*Please declare this variable before polyglot is loaded (at the top of .vimrc)*
|
||||
|
||||
Please note that disabling a language won't make in your vim startup any faster / slower (only for specific this specific filetype). All plugins are loaded lazily, on demand.
|
||||
|
||||
## Contributing
|
||||
|
||||
Language packs are periodically updated using automated `build` script.
|
||||
Language packs are periodically updated using automated `scripts/build` script.
|
||||
|
||||
Feel free to add your language, and send pull-request. In your pull request, please include:
|
||||
1. How you chose the particular repo from which to pull support for this language.
|
||||
2. An updated https://github.com/sheerun/vim-polyglot/blob/master/build .
|
||||
3. If at all possible, absolutely nothing else (in particular, please don't run `build` and include that in your PR).
|
||||
|
||||
The easier it is to validate that the new language won't do anything wacky, the faster it'll be merged. In particular, languages that utilize global plugins (loaded for every filetype), or plugins with dangerous features (like `call` based on the contents of a file being edited), will never be merged, as they will be slow or dangerous, respectively.
|
||||
Feel free to add your language to `packages.yaml`, and send pull-request. Please don't run `make` and include that in your PR, send just changes to `packages.yaml` and build scripts if really necessary. You can run `make test` to run rough tests.
|
||||
|
||||
## License
|
||||
|
||||
See linked repositories for detailed license information.
|
||||
See linked repositories for detailed license information. This repository is MIT-licensed.
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
37
after/syntax/reason/graphql.vim
Normal file
37
after/syntax/reason/graphql.vim
Normal 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
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -762,6 +762,10 @@ fu! csv#CalculateColumnWidth(row, silent) "{{{3
|
||||
" does not work with fixed width columns
|
||||
" row for the row for which to calculate the width
|
||||
let b:col_width=[]
|
||||
if has( 'vartabs' ) && b:delimiter == "\t"
|
||||
let vts_save=&vts
|
||||
set vts=
|
||||
endif
|
||||
try
|
||||
if exists("b:csv_headerline")
|
||||
if line('.') < b:csv_headerline
|
||||
@@ -780,6 +784,9 @@ fu! csv#CalculateColumnWidth(row, silent) "{{{3
|
||||
" delete buffer content in variable b:csv_list,
|
||||
" this was only necessary for calculating the max width
|
||||
unlet! b:csv_list s:columnize_count s:decimal_column
|
||||
if has( 'vartabs' ) && b:delimiter == "\t"
|
||||
let &vts=vts_save
|
||||
endif
|
||||
endfu
|
||||
fu! csv#Columnize(field) "{{{3
|
||||
" Internal function, not called from external,
|
||||
@@ -1500,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
|
||||
@@ -1536,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)
|
||||
@@ -1949,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
|
||||
@@ -1978,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
|
||||
@@ -2256,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>)',
|
||||
@@ -2304,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()', '')
|
||||
@@ -2339,7 +2350,7 @@ fu! csv#ColumnWidth()
|
||||
endfu
|
||||
|
||||
fu! csv#Map(map, name, definition, ...) "{{{3
|
||||
let keyname = substitute(a:name, '[<>]', '', 'g')
|
||||
let keyname = substitute(substitute(a:name, '[<>]', '', 'g'), '-', '_', 'g')
|
||||
let expr = (exists("a:1") && a:1 == 'expr' ? '<expr>' : '')
|
||||
if !get(g:, "csv_nomap_". tolower(keyname), 0)
|
||||
" All mappings are buffer local
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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()
|
||||
|
||||
517
autoload/fsharp.vim
Normal file
517
autoload/fsharp.vim
Normal file
@@ -0,0 +1,517 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'fsharp') == -1
|
||||
|
||||
" Vim autoload functions
|
||||
|
||||
if exists('g:loaded_autoload_fsharp')
|
||||
finish
|
||||
endif
|
||||
let g:loaded_autoload_fsharp = 1
|
||||
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! s:prompt(msg)
|
||||
let height = &cmdheight
|
||||
if height < 2
|
||||
set cmdheight=2
|
||||
endif
|
||||
echom a:msg
|
||||
let &cmdheight = height
|
||||
endfunction
|
||||
|
||||
function! s:PlainNotification(content)
|
||||
return { 'Content': a:content }
|
||||
endfunction
|
||||
|
||||
function! s:TextDocumentIdentifier(path)
|
||||
let usr_ss_opt = &shellslash
|
||||
set shellslash
|
||||
let uri = fnamemodify(a:path, ":p")
|
||||
if uri[0] == "/"
|
||||
let uri = "file://" . uri
|
||||
else
|
||||
let uri = "file:///" . uri
|
||||
endif
|
||||
let &shellslash = usr_ss_opt
|
||||
return { 'Uri': uri }
|
||||
endfunction
|
||||
|
||||
function! s:Position(line, character)
|
||||
return { 'Line': a:line, 'Character': a:character }
|
||||
endfunction
|
||||
|
||||
function! s:TextDocumentPositionParams(documentUri, line, character)
|
||||
return {
|
||||
\ 'TextDocument': s:TextDocumentIdentifier(a:documentUri),
|
||||
\ 'Position': s:Position(a:line, a:character)
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
function! s:DocumentationForSymbolRequest(xmlSig, assembly)
|
||||
return {
|
||||
\ 'XmlSig': a:xmlSig,
|
||||
\ 'Assembly': a:assembly
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
function! s:ProjectParms(projectUri)
|
||||
return { 'Project': s:TextDocumentIdentifier(a:projectUri) }
|
||||
endfunction
|
||||
|
||||
function! s:WorkspacePeekRequest(directory, deep, excludedDirs)
|
||||
return {
|
||||
\ 'Directory': fnamemodify(a:directory, ":p"),
|
||||
\ 'Deep': a:deep,
|
||||
\ 'ExcludedDirs': a:excludedDirs
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
function! s:WorkspaceLoadParms(files)
|
||||
let prm = []
|
||||
for file in a:files
|
||||
call add(prm, s:TextDocumentIdentifier(file))
|
||||
endfor
|
||||
return { 'TextDocuments': prm }
|
||||
endfunction
|
||||
|
||||
function! s:FsdnRequest(query)
|
||||
return { 'Query': a:query }
|
||||
endfunction
|
||||
|
||||
function! s:call(method, params, cont)
|
||||
call LanguageClient#Call(a:method, a:params, a:cont)
|
||||
endfunction
|
||||
|
||||
function! s:signature(filePath, line, character, cont)
|
||||
return s:call('fsharp/signature', s:TextDocumentPositionParams(a:filePath, a:line, a:character), a:cont)
|
||||
endfunction
|
||||
function! s:signatureData(filePath, line, character, cont)
|
||||
return s:call('fsharp/signatureData', s:TextDocumentPositionParams(a:filePath, a:line, a:character), a:cont)
|
||||
endfunction
|
||||
function! s:lineLens(projectPath, cont)
|
||||
return s:call('fsharp/lineLens', s:ProjectParms(a:projectPath), a:cont)
|
||||
endfunction
|
||||
function! s:compilerLocation(cont)
|
||||
return s:call('fsharp/compilerLocation', {}, a:cont)
|
||||
endfunction
|
||||
function! s:compile(projectPath, cont)
|
||||
return s:call('fsharp/compile', s:ProjectParms(a:projectPath), a:cont)
|
||||
endfunction
|
||||
function! s:workspacePeek(directory, depth, excludedDirs, cont)
|
||||
return s:call('fsharp/workspacePeek', s:WorkspacePeekRequest(a:directory, a:depth, a:excludedDirs), a:cont)
|
||||
endfunction
|
||||
function! s:workspaceLoad(files, cont)
|
||||
return s:call('fsharp/workspaceLoad', s:WorkspaceLoadParms(a:files), a:cont)
|
||||
endfunction
|
||||
function! s:project(projectPath, cont)
|
||||
return s:call('fsharp/project', s:ProjectParms(a:projectPath), a:cont)
|
||||
endfunction
|
||||
function! s:fsdn(signature, cont)
|
||||
return s:call('fsharp/fsdn', s:FsdnRequest(a:signature), a:cont)
|
||||
endfunction
|
||||
function! s:f1Help(filePath, line, character, cont)
|
||||
return s:call('fsharp/f1Help', s:TextDocumentPositionParams(a:filePath, a:line, a:character), a:cont)
|
||||
endfunction
|
||||
function! fsharp#documentation(filePath, line, character, cont)
|
||||
return s:call('fsharp/documentation', s:TextDocumentPositionParams(a:filePath, a:line, a:character), a:cont)
|
||||
endfunction
|
||||
function! s:documentationSymbol(xmlSig, assembly, cont)
|
||||
return s:call('fsharp/documentationSymbol', s:DocumentationForSymbolRequest(a:xmlSig, a:assembly), a:cont)
|
||||
endfunction
|
||||
|
||||
" FSharpConfigDto from https://github.com/fsharp/FsAutoComplete/blob/master/src/FsAutoComplete/LspHelpers.fs
|
||||
"
|
||||
" * The following options seems not working with workspace/didChangeConfiguration
|
||||
" since the initialization has already completed?
|
||||
" 'AutomaticWorkspaceInit',
|
||||
" 'WorkspaceModePeekDeepLevel',
|
||||
"
|
||||
" * Changes made to linter/unused analyzer settings seems not reflected after sending them to FSAC?
|
||||
"
|
||||
let s:config_keys_camel =
|
||||
\ [
|
||||
\ {'key': 'AutomaticWorkspaceInit', 'default': 1},
|
||||
\ {'key': 'WorkspaceModePeekDeepLevel', 'default': 2},
|
||||
\ {'key': 'ExcludeProjectDirectories', 'default': []},
|
||||
\ {'key': 'keywordsAutocomplete', 'default': 1},
|
||||
\ {'key': 'ExternalAutocomplete', 'default': 0},
|
||||
\ {'key': 'Linter', 'default': 1},
|
||||
\ {'key': 'UnionCaseStubGeneration', 'default': 1},
|
||||
\ {'key': 'UnionCaseStubGenerationBody'},
|
||||
\ {'key': 'RecordStubGeneration', 'default': 1},
|
||||
\ {'key': 'RecordStubGenerationBody'},
|
||||
\ {'key': 'InterfaceStubGeneration', 'default': 1},
|
||||
\ {'key': 'InterfaceStubGenerationObjectIdentifier', 'default': 'this'},
|
||||
\ {'key': 'InterfaceStubGenerationMethodBody'},
|
||||
\ {'key': 'UnusedOpensAnalyzer', 'default': 1},
|
||||
\ {'key': 'UnusedDeclarationsAnalyzer', 'default': 1},
|
||||
\ {'key': 'SimplifyNameAnalyzer', 'default': 0},
|
||||
\ {'key': 'ResolveNamespaces', 'default': 1},
|
||||
\ {'key': 'EnableReferenceCodeLens', 'default': 1},
|
||||
\ {'key': 'EnableAnalyzers', 'default': 0},
|
||||
\ {'key': 'AnalyzersPath'},
|
||||
\ {'key': 'DisableInMemoryProjectReferences', 'default': 0},
|
||||
\ {'key': 'LineLens', 'default': {'enabled': 'replaceCodeLens', 'prefix': '//'}},
|
||||
\ {'key': 'UseSdkScripts', 'default': 1},
|
||||
\ {'key': 'dotNetRoot'},
|
||||
\ {'key': 'fsiExtraParameters', 'default': []},
|
||||
\ ]
|
||||
let s:config_keys = []
|
||||
|
||||
function! fsharp#toSnakeCase(str)
|
||||
let sn = substitute(a:str, '\(\<\u\l\+\|\l\+\)\(\u\)', '\l\1_\l\2', 'g')
|
||||
if sn == a:str | return tolower(a:str) | endif
|
||||
return sn
|
||||
endfunction
|
||||
|
||||
function! s:buildConfigKeys()
|
||||
if len(s:config_keys) == 0
|
||||
for key_camel in s:config_keys_camel
|
||||
let key = {}
|
||||
let key.snake = fsharp#toSnakeCase(key_camel.key)
|
||||
let key.camel = key_camel.key
|
||||
if has_key(key_camel, 'default')
|
||||
let key.default = key_camel.default
|
||||
endif
|
||||
call add(s:config_keys, key)
|
||||
endfor
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! g:fsharp#getServerConfig()
|
||||
let fsharp = {}
|
||||
call s:buildConfigKeys()
|
||||
for key in s:config_keys
|
||||
if exists('g:fsharp#' . key.snake)
|
||||
let fsharp[key.camel] = g:fsharp#{key.snake}
|
||||
elseif exists('g:fsharp#' . key.camel)
|
||||
let fsharp[key.camel] = g:fsharp#{key.camel}
|
||||
elseif has_key(key, 'default') && g:fsharp#use_recommended_server_config
|
||||
let g:fsharp#{key.snake} = key.default
|
||||
let fsharp[key.camel] = key.default
|
||||
endif
|
||||
endfor
|
||||
return fsharp
|
||||
endfunction
|
||||
|
||||
function! g:fsharp#updateServerConfig()
|
||||
let fsharp = fsharp#getServerConfig()
|
||||
let settings = {'settings': {'FSharp': fsharp}}
|
||||
call LanguageClient#Notify('workspace/didChangeConfiguration', settings)
|
||||
endfunction
|
||||
|
||||
function! s:findWorkspace(dir, cont)
|
||||
let s:cont_findWorkspace = a:cont
|
||||
function! s:callback_findWorkspace(result)
|
||||
let result = a:result
|
||||
let content = json_decode(result.result.content)
|
||||
if len(content.Data.Found) < 1
|
||||
return []
|
||||
endif
|
||||
let workspace = { 'Type': 'none' }
|
||||
for found in content.Data.Found
|
||||
if workspace.Type == 'none'
|
||||
let workspace = found
|
||||
elseif found.Type == 'solution'
|
||||
if workspace.Type == 'project'
|
||||
let workspace = found
|
||||
else
|
||||
let curLen = len(workspace.Data.Items)
|
||||
let newLen = len(found.Data.Items)
|
||||
if newLen > curLen
|
||||
let workspace = found
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
if workspace.Type == 'solution'
|
||||
call s:cont_findWorkspace([workspace.Data.Path])
|
||||
else
|
||||
call s:cont_findWorkspace(workspace.Data.Fsprojs)
|
||||
endif
|
||||
endfunction
|
||||
call s:workspacePeek(a:dir, g:fsharp#workspace_mode_peek_deep_level, g:fsharp#exclude_project_directories, function("s:callback_findWorkspace"))
|
||||
endfunction
|
||||
|
||||
let s:workspace = []
|
||||
|
||||
function! s:load(arg)
|
||||
let s:loading_workspace = a:arg
|
||||
function! s:callback_load(_)
|
||||
echo "[FSAC] Workspace loaded: " . join(s:loading_workspace, ', ')
|
||||
let s:workspace = s:workspace + s:loading_workspace
|
||||
endfunction
|
||||
call s:workspaceLoad(a:arg, function("s:callback_load"))
|
||||
endfunction
|
||||
|
||||
function! fsharp#loadProject(...)
|
||||
let prjs = []
|
||||
for proj in a:000
|
||||
call add(prjs, fnamemodify(proj, ':p'))
|
||||
endfor
|
||||
call s:load(prjs)
|
||||
endfunction
|
||||
|
||||
function! fsharp#loadWorkspaceAuto()
|
||||
if &ft == 'fsharp'
|
||||
call fsharp#updateServerConfig()
|
||||
if g:fsharp#automatic_workspace_init
|
||||
echom "[FSAC] Loading workspace..."
|
||||
let bufferDirectory = fnamemodify(resolve(expand('%:p')), ':h')
|
||||
call s:findWorkspace(bufferDirectory, function("s:load"))
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! fsharp#reloadProjects()
|
||||
if len(s:workspace) > 0
|
||||
function! s:callback_reloadProjects(_)
|
||||
call s:prompt("[FSAC] Workspace reloaded.")
|
||||
endfunction
|
||||
call s:workspaceLoad(s:workspace, function("s:callback_reloadProjects"))
|
||||
else
|
||||
echom "[FSAC] Workspace is empty"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! fsharp#OnFSProjSave()
|
||||
if &ft == "fsharp_project" && exists('g:fsharp#automatic_reload_workspace') && g:fsharp#automatic_reload_workspace
|
||||
call fsharp#reloadProjects()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! fsharp#showSignature()
|
||||
function! s:callback_showSignature(result)
|
||||
let result = a:result
|
||||
if exists('result.result.content')
|
||||
let content = json_decode(result.result.content)
|
||||
if exists('content.Data')
|
||||
echom substitute(content.Data, '\n\+$', ' ', 'g')
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
call s:signature(expand('%:p'), line('.') - 1, col('.') - 1, function("s:callback_showSignature"))
|
||||
endfunction
|
||||
|
||||
function! fsharp#OnCursorMove()
|
||||
if g:fsharp#show_signature_on_cursor_move
|
||||
call fsharp#showSignature()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! fsharp#showF1Help()
|
||||
let result = s:f1Help(expand('%:p'), line('.') - 1, col('.') - 1)
|
||||
echo result
|
||||
endfunction
|
||||
|
||||
function! fsharp#showTooltip()
|
||||
function! s:callback_showTooltip(result)
|
||||
let result = a:result
|
||||
if exists('result.result.content')
|
||||
let content = json_decode(result.result.content)
|
||||
if exists('content.Data')
|
||||
call LanguageClient#textDocument_hover()
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
" show hover only if signature exists for the current position
|
||||
call s:signature(expand('%:p'), line('.') - 1, col('.') - 1, function("s:callback_showTooltip"))
|
||||
endfunction
|
||||
|
||||
let s:script_root_dir = expand('<sfile>:p:h') . "/../"
|
||||
let s:fsac = fnamemodify(s:script_root_dir . "fsac/fsautocomplete.dll", ":p")
|
||||
let g:fsharp#languageserver_command =
|
||||
\ ['dotnet', s:fsac,
|
||||
\ '--background-service-enabled'
|
||||
\ ]
|
||||
|
||||
function! s:download(branch)
|
||||
echom "[FSAC] Downloading FSAC. This may take a while..."
|
||||
let zip = s:script_root_dir . "fsac.zip"
|
||||
call system(
|
||||
\ 'curl -fLo ' . zip . ' --create-dirs ' .
|
||||
\ '"https://ci.appveyor.com/api/projects/fsautocomplete/fsautocomplete/artifacts/bin/pkgs/fsautocomplete.netcore.zip?branch=' . a:branch . '"'
|
||||
\ )
|
||||
if v:shell_error == 0
|
||||
call system('unzip -o -d ' . s:script_root_dir . "/fsac " . zip)
|
||||
echom "[FSAC] Updated FsAutoComplete to version " . a:branch . ""
|
||||
else
|
||||
echom "[FSAC] Failed to update FsAutoComplete"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! fsharp#updateFSAC(...)
|
||||
if len(a:000) == 0
|
||||
let branch = "master"
|
||||
else
|
||||
let branch = a:000[0]
|
||||
endif
|
||||
call s:download(branch)
|
||||
endfunction
|
||||
|
||||
let s:fsi_buffer = -1
|
||||
let s:fsi_job = -1
|
||||
let s:fsi_width = 0
|
||||
let s:fsi_height = 0
|
||||
|
||||
function! s:win_gotoid_safe(winid)
|
||||
function! s:vimReturnFocus(window)
|
||||
call win_gotoid(a:window)
|
||||
redraw!
|
||||
endfunction
|
||||
if has('nvim')
|
||||
call win_gotoid(a:winid)
|
||||
else
|
||||
call timer_start(1, { -> s:vimReturnFocus(a:winid) })
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:get_fsi_command()
|
||||
let cmd = g:fsharp#fsi_command
|
||||
for prm in g:fsharp#fsi_extra_parameters
|
||||
let cmd = cmd . " " . prm
|
||||
endfor
|
||||
return cmd
|
||||
endfunction
|
||||
|
||||
function! fsharp#openFsi(returnFocus)
|
||||
if bufwinid(s:fsi_buffer) <= 0
|
||||
let fsi_command = s:get_fsi_command()
|
||||
" Neovim
|
||||
if exists('*termopen') || exists('*term_start')
|
||||
let current_win = win_getid()
|
||||
execute g:fsharp#fsi_window_command
|
||||
if s:fsi_width > 0 | execute 'vertical resize' s:fsi_width | endif
|
||||
if s:fsi_height > 0 | execute 'resize' s:fsi_height | endif
|
||||
" if window is closed but FSI is still alive then reuse it
|
||||
if s:fsi_buffer >= 0 && bufexists(str2nr(s:fsi_buffer))
|
||||
exec 'b' s:fsi_buffer
|
||||
normal G
|
||||
if !has('nvim') && mode() == 'n' | execute "normal A" | endif
|
||||
if a:returnFocus | call s:win_gotoid_safe(current_win) | endif
|
||||
" open FSI: Neovim
|
||||
elseif has('nvim')
|
||||
let s:fsi_job = termopen(fsi_command)
|
||||
if s:fsi_job > 0
|
||||
let s:fsi_buffer = bufnr("%")
|
||||
else
|
||||
close
|
||||
echom "[FSAC] Failed to open FSI."
|
||||
return -1
|
||||
endif
|
||||
" open FSI: Vim
|
||||
else
|
||||
let options = {
|
||||
\ "term_name": "F# Interactive",
|
||||
\ "curwin": 1,
|
||||
\ "term_finish": "close"
|
||||
\ }
|
||||
let s:fsi_buffer = term_start(fsi_command, options)
|
||||
if s:fsi_buffer != 0
|
||||
if exists('*term_setkill') | call term_setkill(s:fsi_buffer, "term") | endif
|
||||
let s:fsi_job = term_getjob(s:fsi_buffer)
|
||||
else
|
||||
close
|
||||
echom "[FSAC] Failed to open FSI."
|
||||
return -1
|
||||
endif
|
||||
endif
|
||||
setlocal bufhidden=hide
|
||||
normal G
|
||||
if a:returnFocus | call s:win_gotoid_safe(current_win) | endif
|
||||
return s:fsi_buffer
|
||||
else
|
||||
echom "[FSAC] Your Vim does not support terminal".
|
||||
return 0
|
||||
endif
|
||||
endif
|
||||
return s:fsi_buffer
|
||||
endfunction
|
||||
|
||||
function! fsharp#toggleFsi()
|
||||
let fsiWindowId = bufwinid(s:fsi_buffer)
|
||||
if fsiWindowId > 0
|
||||
let current_win = win_getid()
|
||||
call win_gotoid(fsiWindowId)
|
||||
let s:fsi_width = winwidth('%')
|
||||
let s:fsi_height = winheight('%')
|
||||
close
|
||||
call win_gotoid(current_win)
|
||||
else
|
||||
call fsharp#openFsi(0)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! fsharp#quitFsi()
|
||||
if s:fsi_buffer >= 0 && bufexists(str2nr(s:fsi_buffer))
|
||||
if has('nvim')
|
||||
let winid = bufwinid(s:fsi_buffer)
|
||||
if winid > 0 | execute "close " . winid | endif
|
||||
call jobstop(s:fsi_job)
|
||||
else
|
||||
call job_stop(s:fsi_job, "term")
|
||||
endif
|
||||
let s:fsi_buffer = -1
|
||||
let s:fsi_job = -1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! fsharp#resetFsi()
|
||||
call fsharp#quitFsi()
|
||||
return fsharp#openFsi(1)
|
||||
endfunction
|
||||
|
||||
function! fsharp#sendFsi(text)
|
||||
if fsharp#openFsi(!g:fsharp#fsi_focus_on_send) > 0
|
||||
" Neovim
|
||||
if has('nvim')
|
||||
call chansend(s:fsi_job, a:text . ";;". "\n")
|
||||
" Vim 8
|
||||
else
|
||||
call term_sendkeys(s:fsi_buffer, a:text . ";;" . "\<cr>")
|
||||
call term_wait(s:fsi_buffer)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" https://stackoverflow.com/a/6271254
|
||||
function! s:get_visual_selection()
|
||||
let [line_start, column_start] = getpos("'<")[1:2]
|
||||
let [line_end, column_end] = getpos("'>")[1:2]
|
||||
let lines = getline(line_start, line_end)
|
||||
if len(lines) == 0
|
||||
return ''
|
||||
endif
|
||||
let lines[-1] = lines[-1][: column_end - (&selection == 'inclusive' ? 1 : 2)]
|
||||
let lines[0] = lines[0][column_start - 1:]
|
||||
return lines
|
||||
endfunction
|
||||
|
||||
function! s:get_complete_buffer()
|
||||
return join(getline(1, '$'), "\n")
|
||||
endfunction
|
||||
|
||||
function! fsharp#sendSelectionToFsi() range
|
||||
let lines = s:get_visual_selection()
|
||||
exec 'normal' len(lines) . 'j'
|
||||
let text = join(lines, "\n")
|
||||
return fsharp#sendFsi(text)
|
||||
endfunction
|
||||
|
||||
function! fsharp#sendLineToFsi()
|
||||
let text = getline('.')
|
||||
exec 'normal j'
|
||||
return fsharp#sendFsi(text)
|
||||
endfunction
|
||||
|
||||
function! fsharp#sendAllToFsi()
|
||||
let text = s:get_complete_buffer()
|
||||
return fsharp#sendFsi(text)
|
||||
endfunction
|
||||
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
" vim: sw=4 et sts=4
|
||||
|
||||
endif
|
||||
@@ -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
|
||||
|
||||
@@ -1,164 +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!')
|
||||
|
||||
let l:polyglot = !empty(filter(copy(l:scriptnames), "v:val =~# 'polyglot'"))
|
||||
if l:polyglot
|
||||
call health#report_info('LaTeX-Box is included with vim-polyglot and may be disabled with:')
|
||||
call health#report_info('let g:polyglot_disabled = [''latex'']')
|
||||
endif
|
||||
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
129
autoload/jsonnet.vim
Normal 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
|
||||
744
autoload/ledger.vim
Normal file
744
autoload/ledger.vim
Normal file
@@ -0,0 +1,744 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ledger') == -1
|
||||
|
||||
scriptencoding utf-8
|
||||
" vim:ts=2:sw=2:sts=2:foldmethod=marker
|
||||
function! ledger#transaction_state_toggle(lnum, ...) abort
|
||||
if a:0 == 1
|
||||
let chars = a:1
|
||||
else
|
||||
let chars = ' *'
|
||||
endif
|
||||
let trans = s:transaction.from_lnum(a:lnum)
|
||||
if empty(trans) || has_key(trans, 'expr')
|
||||
return
|
||||
endif
|
||||
|
||||
let old = has_key(trans, 'state') ? trans['state'] : ' '
|
||||
let i = stridx(chars, old) + 1
|
||||
let new = chars[i >= len(chars) ? 0 : i]
|
||||
|
||||
call trans.set_state(new)
|
||||
|
||||
call setline(trans['head'], trans.format_head())
|
||||
endf
|
||||
|
||||
function! ledger#transaction_state_set(lnum, char) abort
|
||||
" modifies or sets the state of the transaction at the cursor,
|
||||
" removing the state altogether if a:char is empty
|
||||
let trans = s:transaction.from_lnum(a:lnum)
|
||||
if empty(trans) || has_key(trans, 'expr')
|
||||
return
|
||||
endif
|
||||
|
||||
call trans.set_state(a:char)
|
||||
|
||||
call setline(trans['head'], trans.format_head())
|
||||
endf
|
||||
|
||||
function! ledger#transaction_date_set(lnum, type, ...) abort
|
||||
let time = a:0 == 1 ? a:1 : localtime()
|
||||
let trans = s:transaction.from_lnum(a:lnum)
|
||||
if empty(trans) || has_key(trans, 'expr')
|
||||
return
|
||||
endif
|
||||
|
||||
let formatted = strftime(g:ledger_date_format, time)
|
||||
if has_key(trans, 'date') && ! empty(trans['date'])
|
||||
let date = split(trans['date'], '=')
|
||||
else
|
||||
let date = [formatted]
|
||||
endif
|
||||
|
||||
if a:type =~? 'effective\|actual'
|
||||
echoerr 'actual/effective arguments were replaced by primary/auxiliary'
|
||||
return
|
||||
endif
|
||||
|
||||
if a:type ==? 'primary'
|
||||
let date[0] = formatted
|
||||
elseif a:type ==? 'auxiliary'
|
||||
if time < 0
|
||||
" remove auxiliary date
|
||||
let date = [date[0]]
|
||||
else
|
||||
" set auxiliary date
|
||||
if len(date) >= 2
|
||||
let date[1] = formatted
|
||||
else
|
||||
call add(date, formatted)
|
||||
endif
|
||||
endif
|
||||
elseif a:type ==? 'unshift'
|
||||
let date = [formatted, date[0]]
|
||||
endif
|
||||
|
||||
let trans['date'] = join(date[0:1], '=')
|
||||
|
||||
call setline(trans['head'], trans.format_head())
|
||||
endf
|
||||
|
||||
" == get transactions ==
|
||||
|
||||
function! ledger#transaction_from_lnum(lnum) abort
|
||||
return s:transaction.from_lnum(a:lnum)
|
||||
endf
|
||||
|
||||
function! ledger#transactions(...) abort
|
||||
if a:0 == 2
|
||||
let lnum = a:1
|
||||
let end = a:2
|
||||
elseif a:0 == 0
|
||||
let lnum = 1
|
||||
let end = line('$')
|
||||
else
|
||||
throw 'wrong number of arguments for get_transactions()'
|
||||
return []
|
||||
endif
|
||||
|
||||
" safe view / position
|
||||
let view = winsaveview()
|
||||
let fe = &foldenable
|
||||
set nofoldenable
|
||||
|
||||
let transactions = []
|
||||
call cursor(lnum, 0)
|
||||
while lnum && lnum < end
|
||||
let trans = s:transaction.from_lnum(lnum)
|
||||
if ! empty(trans)
|
||||
call add(transactions, trans)
|
||||
call cursor(trans['tail'], 0)
|
||||
endif
|
||||
let lnum = search('^[~=[:digit:]]', 'cW')
|
||||
endw
|
||||
|
||||
" restore view / position
|
||||
let &foldenable = fe
|
||||
call winrestview(view)
|
||||
|
||||
return transactions
|
||||
endf
|
||||
|
||||
" == transaction object implementation ==
|
||||
|
||||
let s:transaction = {} "{{{1
|
||||
function! s:transaction.new() abort dict
|
||||
return copy(s:transaction)
|
||||
endf
|
||||
|
||||
function! s:transaction.from_lnum(lnum) abort dict "{{{2
|
||||
let [head, tail] = s:get_transaction_extents(a:lnum)
|
||||
if ! head
|
||||
return {}
|
||||
endif
|
||||
|
||||
let trans = copy(s:transaction)
|
||||
let trans['head'] = head
|
||||
let trans['tail'] = tail
|
||||
|
||||
" split off eventual comments at the end of line
|
||||
let line = split(getline(head), '\ze\s*\%(\t\| \);', 1)
|
||||
if len(line) > 1
|
||||
let trans['appendix'] = join(line[1:], '')
|
||||
endif
|
||||
|
||||
" parse rest of line
|
||||
" FIXME (minor): will not preserve spacing (see 'join(parts)')
|
||||
let parts = split(line[0], '\s\+')
|
||||
if parts[0] ==# '~'
|
||||
let trans['expr'] = join(parts[1:])
|
||||
return trans
|
||||
elseif parts[0] ==# '='
|
||||
let trans['auto'] = join(parts[1:])
|
||||
return trans
|
||||
elseif parts[0] !~# '^\d'
|
||||
" this case is avoided in s:get_transaction_extents(),
|
||||
" but we'll check anyway.
|
||||
return {}
|
||||
endif
|
||||
|
||||
for part in parts
|
||||
if ! has_key(trans, 'date') && part =~# '^\d'
|
||||
let trans['date'] = part
|
||||
elseif ! has_key(trans, 'code') && part =~# '^([^)]*)$'
|
||||
let trans['code'] = part[1:-2]
|
||||
elseif ! has_key(trans, 'state') && part =~# '^[[:punct:]]$'
|
||||
" the first character by itself is assumed to be the state of the transaction.
|
||||
let trans['state'] = part
|
||||
else
|
||||
" everything after date/code or state belongs to the description
|
||||
break
|
||||
endif
|
||||
call remove(parts, 0)
|
||||
endfor
|
||||
|
||||
let trans['description'] = join(parts)
|
||||
return trans
|
||||
endf "}}}
|
||||
|
||||
function! s:transaction.set_state(char) abort dict "{{{2
|
||||
if has_key(self, 'state') && a:char =~# '^\s*$'
|
||||
call remove(self, 'state')
|
||||
else
|
||||
let self['state'] = a:char
|
||||
endif
|
||||
endf "}}}
|
||||
|
||||
function! s:transaction.parse_body(...) abort dict "{{{2
|
||||
if a:0 == 2
|
||||
let head = a:1
|
||||
let tail = a:2
|
||||
elseif a:0 == 0
|
||||
let head = self['head']
|
||||
let tail = self['tail']
|
||||
else
|
||||
throw 'wrong number of arguments for parse_body()'
|
||||
return []
|
||||
endif
|
||||
|
||||
if ! head || tail <= head
|
||||
return []
|
||||
endif
|
||||
|
||||
let lnum = head
|
||||
let tags = {}
|
||||
let postings = []
|
||||
while lnum <= tail
|
||||
let line = split(getline(lnum), '\s*\%(\t\| \);', 1)
|
||||
|
||||
if line[0] =~# '^\s\+[^[:blank:];]'
|
||||
" posting
|
||||
let [state, rest] = matchlist(line[0], '^\s\+\([*!]\?\)\s*\(.*\)$')[1:2]
|
||||
if rest =~# '\t\| '
|
||||
let [account, amount] = matchlist(rest, '^\(.\{-}\)\%(\t\| \)\s*\(.\{-}\)\s*$')[1:2]
|
||||
else
|
||||
let amount = ''
|
||||
let account = matchstr(rest, '^\s*\zs.\{-}\ze\s*$')
|
||||
endif
|
||||
call add(postings, {'account': account, 'amount': amount, 'state': state})
|
||||
end
|
||||
|
||||
" where are tags to be stored?
|
||||
if empty(postings)
|
||||
" they belong to the transaction
|
||||
let tag_container = tags
|
||||
else
|
||||
" they belong to last posting
|
||||
if ! has_key(postings[-1], 'tags')
|
||||
let postings[-1]['tags'] = {}
|
||||
endif
|
||||
let tag_container = postings[-1]['tags']
|
||||
endif
|
||||
|
||||
let comment = join(line[1:], ' ;')
|
||||
if comment =~# '^\s*:'
|
||||
" tags without values
|
||||
for t in s:findall(comment, ':\zs[^:[:blank:]]\([^:]*[^:[:blank:]]\)\?\ze:')
|
||||
let tag_container[t] = ''
|
||||
endfor
|
||||
elseif comment =~# '^\s*[^:[:blank:]][^:]\+:'
|
||||
" tag with value
|
||||
let key = matchstr(comment, '^\s*\zs[^:]\+\ze:')
|
||||
if ! empty(key)
|
||||
let val = matchstr(comment, ':\s*\zs.*\ze\s*$')
|
||||
let tag_container[key] = val
|
||||
endif
|
||||
endif
|
||||
let lnum += 1
|
||||
endw
|
||||
return [tags, postings]
|
||||
endf "}}}
|
||||
|
||||
function! s:transaction.format_head() abort dict "{{{2
|
||||
if has_key(self, 'expr')
|
||||
return '~ '.self['expr']
|
||||
elseif has_key(self, 'auto')
|
||||
return '= '.self['auto']
|
||||
endif
|
||||
|
||||
let parts = []
|
||||
if has_key(self, 'date') | call add(parts, self['date']) | endif
|
||||
if has_key(self, 'state') | call add(parts, self['state']) | endif
|
||||
if has_key(self, 'code') | call add(parts, '('.self['code'].')') | endif
|
||||
if has_key(self, 'description') | call add(parts, self['description']) | endif
|
||||
|
||||
let line = join(parts)
|
||||
if has_key(self, 'appendix') | let line .= self['appendix'] | endif
|
||||
|
||||
return line
|
||||
endf "}}}
|
||||
"}}}
|
||||
|
||||
" == helper functions ==
|
||||
|
||||
" get a list of declared accounts in the buffer
|
||||
function! ledger#declared_accounts(...) abort
|
||||
if a:0 == 2
|
||||
let lnum = a:1
|
||||
let lend = a:2
|
||||
elseif a:0 == 0
|
||||
let lnum = 1
|
||||
let lend = line('$')
|
||||
else
|
||||
throw 'wrong number of arguments for ledger#declared_accounts()'
|
||||
return []
|
||||
endif
|
||||
|
||||
" save view / position
|
||||
let view = winsaveview()
|
||||
let fe = &foldenable
|
||||
set nofoldenable
|
||||
|
||||
let accounts = []
|
||||
call cursor(lnum, 0)
|
||||
while 1
|
||||
let lnum = search('^account\s', 'cW', lend)
|
||||
if !lnum || lnum > lend
|
||||
break
|
||||
endif
|
||||
|
||||
" remove comments at the end and "account" at the front
|
||||
let line = split(getline(lnum), '\s\+;')[0]
|
||||
let line = matchlist(line, 'account\s\+\(.\+\)')[1]
|
||||
|
||||
if len(line) > 1
|
||||
call add(accounts, line)
|
||||
endif
|
||||
|
||||
call cursor(lnum+1,0)
|
||||
endw
|
||||
|
||||
" restore view / position
|
||||
let &foldenable = fe
|
||||
call winrestview(view)
|
||||
|
||||
return accounts
|
||||
endf
|
||||
|
||||
function! s:get_transaction_extents(lnum) abort
|
||||
if ! (indent(a:lnum) || getline(a:lnum) =~# '^[~=[:digit:]]')
|
||||
" only do something if lnum is in a transaction
|
||||
return [0, 0]
|
||||
endif
|
||||
|
||||
" safe view / position
|
||||
let view = winsaveview()
|
||||
let fe = &foldenable
|
||||
set nofoldenable
|
||||
|
||||
call cursor(a:lnum, 0)
|
||||
let head = search('^[~=[:digit:]]', 'bcnW')
|
||||
let tail = search('^[^;[:blank:]]\S\+', 'nW')
|
||||
let tail = tail > head ? tail - 1 : line('$')
|
||||
|
||||
" restore view / position
|
||||
let &foldenable = fe
|
||||
call winrestview(view)
|
||||
|
||||
return head ? [head, tail] : [0, 0]
|
||||
endf
|
||||
|
||||
function! ledger#find_in_tree(tree, levels) abort
|
||||
if empty(a:levels)
|
||||
return []
|
||||
endif
|
||||
let results = []
|
||||
let currentlvl = a:levels[0]
|
||||
let nextlvls = a:levels[1:]
|
||||
let branches = ledger#filter_items(keys(a:tree), currentlvl)
|
||||
for branch in branches
|
||||
let exact = empty(nextlvls)
|
||||
call add(results, [branch, exact])
|
||||
if ! empty(nextlvls)
|
||||
for [result, exact] in ledger#find_in_tree(a:tree[branch], nextlvls)
|
||||
call add(results, [branch.':'.result, exact])
|
||||
endfor
|
||||
endif
|
||||
endfor
|
||||
return results
|
||||
endf
|
||||
|
||||
function! ledger#filter_items(list, keyword) abort
|
||||
" return only those items that start with a specified keyword
|
||||
return filter(copy(a:list), 'v:val =~ ''^\V'.substitute(a:keyword, '\\', '\\\\', 'g').'''')
|
||||
endf
|
||||
|
||||
function! s:findall(text, rx) abort
|
||||
" returns all the matches in a string,
|
||||
" there will be overlapping matches according to :help match()
|
||||
let matches = []
|
||||
|
||||
while 1
|
||||
let m = matchstr(a:text, a:rx, 0, len(matches)+1)
|
||||
if empty(m)
|
||||
break
|
||||
endif
|
||||
|
||||
call add(matches, m)
|
||||
endw
|
||||
|
||||
return matches
|
||||
endf
|
||||
|
||||
" Move the cursor to the specified column, filling the line with spaces if necessary.
|
||||
" Ensure that at least min_spaces are added, and go to the end of the line if
|
||||
" the line is already too long
|
||||
function! s:goto_col(pos, min_spaces) abort
|
||||
exec 'normal!' '$'
|
||||
let diff = max([a:min_spaces, a:pos - virtcol('.')])
|
||||
if diff > 0 | exec 'normal!' diff . 'a ' | endif
|
||||
endf
|
||||
|
||||
" Return character position of decimal separator (multibyte safe)
|
||||
function! s:decimalpos(expr) abort
|
||||
let pos = match(a:expr, '\V' . g:ledger_decimal_sep)
|
||||
if pos > 0
|
||||
let pos = strchars(a:expr[:pos]) - 1
|
||||
endif
|
||||
return pos
|
||||
endf
|
||||
|
||||
" Align the amount expression after an account name at the decimal point.
|
||||
"
|
||||
" This function moves the amount expression of a posting so that the decimal
|
||||
" separator is aligned at the column specified by g:ledger_align_at.
|
||||
"
|
||||
" For example, after selecting:
|
||||
"
|
||||
" 2015/05/09 Some Payee
|
||||
" Expenses:Other $120,23 ; Tags here
|
||||
" Expenses:Something $-4,99
|
||||
" Expenses:More ($12,34 + $16,32)
|
||||
"
|
||||
" :'<,'>call ledger#align_commodity() produces:
|
||||
"
|
||||
" 2015/05/09 Some Payee
|
||||
" Expenses:Other $120,23 ; Tags here
|
||||
" Expenses:Something $-4,99
|
||||
" Expenses:More ($12,34 + $16,32)
|
||||
"
|
||||
function! ledger#align_commodity() abort
|
||||
" Extract the part of the line after the account name (excluding spaces):
|
||||
let l:line = getline('.')
|
||||
let rhs = matchstr(l:line, '\m^\s\+[^;[:space:]].\{-}\(\t\| \)\s*\zs.*$')
|
||||
if rhs !=# ''
|
||||
" Remove everything after the account name (including spaces):
|
||||
call setline('.', substitute(l:line, '\m^\s\+[^[:space:]].\{-}\zs\(\t\| \).*$', '', ''))
|
||||
let pos = -1
|
||||
if g:ledger_decimal_sep !=# ''
|
||||
" Find the position of the first decimal separator:
|
||||
let pos = s:decimalpos(rhs)
|
||||
endif
|
||||
if pos < 0
|
||||
" Find the position after the first digits
|
||||
let pos = matchend(rhs, '\m\d[^[:space:]]*')
|
||||
endif
|
||||
" Go to the column that allows us to align the decimal separator at g:ledger_align_at:
|
||||
if pos > 0
|
||||
call s:goto_col(g:ledger_align_at - pos - 1, 2)
|
||||
else
|
||||
call s:goto_col(g:ledger_align_at - strdisplaywidth(rhs) - 2, 2)
|
||||
endif " Append the part of the line that was previously removed:
|
||||
exe 'normal! a' . rhs
|
||||
endif
|
||||
endf
|
||||
|
||||
" Align the amount under the cursor and append/prepend the default currency.
|
||||
function! ledger#align_amount_at_cursor() abort
|
||||
" Select and cut text:
|
||||
normal! viWd
|
||||
" Find the position of the decimal separator
|
||||
let pos = s:decimalpos(@") " Returns zero when the separator is the empty string
|
||||
if pos <= 0
|
||||
let pos = len(@")
|
||||
endif
|
||||
" Paste text at the correct column and append/prepend default commodity:
|
||||
if g:ledger_commodity_before
|
||||
call s:goto_col(g:ledger_align_at - pos - len(g:ledger_default_commodity) - len(g:ledger_commodity_sep) - 1, 2)
|
||||
exe 'normal! a' . g:ledger_default_commodity . g:ledger_commodity_sep
|
||||
normal! p
|
||||
else
|
||||
call s:goto_col(g:ledger_align_at - pos - 1, 2)
|
||||
exe 'normal! pa' . g:ledger_commodity_sep . g:ledger_default_commodity
|
||||
endif
|
||||
endf
|
||||
|
||||
" Report generation {{{1
|
||||
|
||||
" Helper functions and variables {{{2
|
||||
" Position of report windows
|
||||
let s:winpos_map = {
|
||||
\ 'T': 'to new', 't': 'abo new', 'B': 'bo new', 'b': 'bel new',
|
||||
\ 'L': 'to vnew', 'l': 'abo vnew', 'R': 'bo vnew', 'r': 'bel vnew'
|
||||
\ }
|
||||
|
||||
function! s:error_message(msg) abort
|
||||
redraw " See h:echo-redraw
|
||||
echohl ErrorMsg
|
||||
echo "\r"
|
||||
echomsg a:msg
|
||||
echohl NONE
|
||||
endf
|
||||
|
||||
function! s:warning_message(msg) abort
|
||||
redraw " See h:echo-redraw
|
||||
echohl WarningMsg
|
||||
echo "\r"
|
||||
echomsg a:msg
|
||||
echohl NONE
|
||||
endf
|
||||
|
||||
" Open the quickfix/location window when it is not empty,
|
||||
" closes it if it is empty.
|
||||
"
|
||||
" Optional parameters:
|
||||
" a:1 Quickfix window title.
|
||||
" a:2 Message to show when the window is empty.
|
||||
"
|
||||
" Returns 0 if the quickfix window is empty, 1 otherwise.
|
||||
function! s:quickfix_toggle(...) abort
|
||||
if g:ledger_use_location_list
|
||||
let l:list = 'l'
|
||||
let l:open = (len(getloclist(winnr())) > 0)
|
||||
else
|
||||
let l:list = 'c'
|
||||
let l:open = (len(getqflist()) > 0)
|
||||
endif
|
||||
|
||||
if l:open
|
||||
execute (g:ledger_qf_vertical ? 'vert' : 'botright') l:list.'open' g:ledger_qf_size
|
||||
" Set local mappings to quit the quickfix window or lose focus.
|
||||
nnoremap <silent> <buffer> <tab> <c-w><c-w>
|
||||
execute 'nnoremap <silent> <buffer> q :' l:list.'close<CR>'
|
||||
" Note that the following settings do not persist (e.g., when you close and re-open the quickfix window).
|
||||
" See: https://superuser.com/questions/356912/how-do-i-change-the-quickix-title-status-bar-in-vim
|
||||
if g:ledger_qf_hide_file
|
||||
setl conceallevel=2
|
||||
setl concealcursor=nc
|
||||
syntax match qfFile /^[^|]*/ transparent conceal
|
||||
endif
|
||||
if a:0 > 0
|
||||
let w:quickfix_title = a:1
|
||||
endif
|
||||
return 1
|
||||
endif
|
||||
|
||||
execute l:list.'close'
|
||||
call s:warning_message((a:0 > 1) ? a:2 : 'No results')
|
||||
return 0
|
||||
endf
|
||||
|
||||
" Populate a quickfix/location window with data. The argument must be a String
|
||||
" or a List.
|
||||
function! s:quickfix_populate(data) abort
|
||||
" Note that cexpr/lexpr always uses the global value of errorformat
|
||||
let l:efm = &errorformat " Save global errorformat
|
||||
set errorformat=%EWhile\ parsing\ file\ \"%f\"\\,\ line\ %l:,%ZError:\ %m,%-C%.%#
|
||||
set errorformat+=%tarning:\ \"%f\"\\,\ line\ %l:\ %m
|
||||
" Format to parse command-line errors:
|
||||
set errorformat+=Error:\ %m
|
||||
" Format to parse reports:
|
||||
set errorformat+=%f:%l\ %m
|
||||
set errorformat+=%-G%.%#
|
||||
execute (g:ledger_use_location_list ? 'l' : 'c').'getexpr' 'a:data'
|
||||
let &errorformat = l:efm " Restore global errorformat
|
||||
return
|
||||
endf
|
||||
|
||||
" Build a ledger command to process the given file.
|
||||
function! s:ledger_cmd(file, args) abort
|
||||
let l:options = g:ledger_extra_options
|
||||
if len(g:ledger_date_format) > 0 && !g:ledger_is_hledger
|
||||
let l:options = join([l:options, '--date-format', g:ledger_date_format,
|
||||
\ '--input-date-format', g:ledger_date_format])
|
||||
endif
|
||||
return join([g:ledger_bin, l:options, '-f', shellescape(expand(a:file)), a:args])
|
||||
endf
|
||||
" }}}
|
||||
|
||||
function! ledger#autocomplete_and_align() abort
|
||||
if pumvisible()
|
||||
return "\<c-n>"
|
||||
endif
|
||||
" Align an amount only if there is a digit immediately before the cursor and
|
||||
" such digit is preceded by at least one space (the latter condition is
|
||||
" necessary to avoid situations where a date starting at the first column is
|
||||
" confused with a commodity to be aligned).
|
||||
if match(getline('.'), '\s.*\d\%'.col('.').'c') > -1
|
||||
normal! h
|
||||
call ledger#align_amount_at_cursor()
|
||||
return "\<c-o>A"
|
||||
endif
|
||||
return "\<c-x>\<c-o>"
|
||||
endf
|
||||
|
||||
" Use current line as input to ledger entry and replace with output. If there
|
||||
" are errors, they are echoed instead.
|
||||
function! ledger#entry() abort
|
||||
let l:output = systemlist(s:ledger_cmd(g:ledger_main, join(['entry', getline('.')])))
|
||||
" Filter out warnings
|
||||
let l:output = filter(l:output, "v:val !~? '^Warning: '")
|
||||
" Errors may occur
|
||||
if v:shell_error
|
||||
echomsg join(l:output)
|
||||
return
|
||||
endif
|
||||
" Append output so we insert instead of overwrite, then delete line
|
||||
call append('.', l:output)
|
||||
normal! "_dd
|
||||
endfunc
|
||||
|
||||
" Run an arbitrary ledger command and show the output in a new buffer. If
|
||||
" there are errors, no new buffer is opened: the errors are displayed in a
|
||||
" quickfix window instead.
|
||||
"
|
||||
" Parameters:
|
||||
" file The file to be processed.
|
||||
" args A string of Ledger command-line arguments.
|
||||
"
|
||||
" Returns:
|
||||
" Ledger's output as a String.
|
||||
function! ledger#report(file, args) abort
|
||||
let l:output = systemlist(s:ledger_cmd(a:file, a:args))
|
||||
if v:shell_error " If there are errors, show them in a quickfix/location list.
|
||||
call s:quickfix_populate(l:output)
|
||||
call s:quickfix_toggle('Errors', 'Unable to parse errors')
|
||||
endif
|
||||
return l:output
|
||||
endf
|
||||
|
||||
" Open the output of a Ledger's command in a new buffer.
|
||||
"
|
||||
" Parameters:
|
||||
" report A String containing the output of a Ledger's command.
|
||||
"
|
||||
" Returns:
|
||||
" 1 if a new buffer is created; 0 otherwise.
|
||||
function! ledger#output(report) abort
|
||||
if empty(a:report)
|
||||
call s:warning_message('No results')
|
||||
return 0
|
||||
endif
|
||||
" Open a new buffer to show Ledger's output.
|
||||
execute get(s:winpos_map, g:ledger_winpos, 'bo new')
|
||||
setlocal buftype=nofile bufhidden=wipe modifiable nobuflisted noswapfile nowrap
|
||||
call append(0, a:report)
|
||||
setlocal nomodifiable
|
||||
" Set local mappings to quit window or lose focus.
|
||||
nnoremap <silent> <buffer> <tab> <c-w><c-p>
|
||||
nnoremap <silent> <buffer> q <c-w><c-p>@=winnr('#')<cr><c-w>c
|
||||
" Add some coloring to the report
|
||||
syntax match LedgerNumber /-\@1<!\d\+\([,.]\d\+\)*/
|
||||
syntax match LedgerNegativeNumber /-\d\+\([,.]\d\+\)*/
|
||||
syntax match LedgerImproperPerc /\d\d\d\+%/
|
||||
return 1
|
||||
endf
|
||||
|
||||
" Show an arbitrary register report in a quickfix list.
|
||||
"
|
||||
" Parameters:
|
||||
" file The file to be processed
|
||||
" args A string of Ledger command-line arguments.
|
||||
function! ledger#register(file, args) abort
|
||||
let l:cmd = s:ledger_cmd(a:file, join([
|
||||
\ 'register',
|
||||
\ "--format='" . g:ledger_qf_register_format . "'",
|
||||
\ "--prepend-format='%(filename):%(beg_line) '",
|
||||
\ a:args
|
||||
\ ]))
|
||||
call s:quickfix_populate(systemlist(l:cmd))
|
||||
call s:quickfix_toggle('Register report')
|
||||
endf
|
||||
|
||||
" Reconcile the given account.
|
||||
" This function accepts a file path as a third optional argument.
|
||||
" The default is to use the value of g:ledger_main.
|
||||
"
|
||||
" Parameters:
|
||||
" file The file to be processed
|
||||
" account An account name (String)
|
||||
" target_amount The target amount (Float)
|
||||
function! ledger#reconcile(file, account, target_amount) abort
|
||||
let l:cmd = s:ledger_cmd(a:file, join([
|
||||
\ 'register',
|
||||
\ '--uncleared',
|
||||
\ "--format='" . g:ledger_qf_reconcile_format . "'",
|
||||
\ "--prepend-format='%(filename):%(beg_line) %(pending ? \"P\" : \"U\") '",
|
||||
\ shellescape(a:account)
|
||||
\ ]))
|
||||
let l:file = expand(a:file) " Needed for #show_balance() later
|
||||
call s:quickfix_populate(systemlist(l:cmd))
|
||||
if s:quickfix_toggle('Reconcile ' . a:account, 'Nothing to reconcile')
|
||||
let g:ledger_target_amount = a:target_amount
|
||||
" Show updated account balance upon saving, as long as the quickfix window is open
|
||||
augroup reconcile
|
||||
autocmd!
|
||||
execute "autocmd BufWritePost *.ldg,*.ledger call ledger#show_balance('" . l:file . "','" . a:account . "')"
|
||||
autocmd BufWipeout <buffer> call <sid>finish_reconciling()
|
||||
augroup END
|
||||
" Add refresh shortcut
|
||||
execute "nnoremap <silent> <buffer> <c-l> :<c-u>call ledger#reconcile('"
|
||||
\ . l:file . "','" . a:account . "'," . string(a:target_amount) . ')<cr>'
|
||||
call ledger#show_balance(l:file, a:account)
|
||||
endif
|
||||
endf
|
||||
|
||||
function! s:finish_reconciling() abort
|
||||
unlet g:ledger_target_amount
|
||||
augroup reconcile
|
||||
autocmd!
|
||||
augroup END
|
||||
augroup! reconcile
|
||||
endf
|
||||
|
||||
" Show the pending/cleared balance of an account.
|
||||
" This function has an optional parameter:
|
||||
"
|
||||
" a:1 An account name
|
||||
"
|
||||
" If no account if given, the account in the current line is used.
|
||||
function! ledger#show_balance(file, ...) abort
|
||||
let l:account = a:0 > 0 && !empty(a:1) ? a:1 : matchstr(getline('.'), '\m\( \|\t\)\zs\S.\{-}\ze\( \|\t\|$\)')
|
||||
if empty(l:account)
|
||||
call s:error_message('No account found')
|
||||
return
|
||||
endif
|
||||
let l:cmd = s:ledger_cmd(a:file, join([
|
||||
\ 'cleared',
|
||||
\ shellescape(l:account),
|
||||
\ '--empty',
|
||||
\ '--collapse',
|
||||
\ "--format='%(scrub(get_at(display_total, 0)))|%(scrub(get_at(display_total, 1)))|%(quantity(scrub(get_at(display_total, 1))))'",
|
||||
\ (empty(g:ledger_default_commodity) ? '' : '-X ' . shellescape(g:ledger_default_commodity))
|
||||
\ ]))
|
||||
let l:output = systemlist(l:cmd)
|
||||
" Errors may occur, for example, when the account has multiple commodities
|
||||
" and g:ledger_default_commodity is empty.
|
||||
if v:shell_error
|
||||
call s:quickfix_populate(l:output)
|
||||
call s:quickfix_toggle('Errors', 'Unable to parse errors')
|
||||
return
|
||||
endif
|
||||
let l:amounts = split(l:output[-1], '|')
|
||||
redraw " Necessary in some cases to overwrite previous messages. See :h echo-redraw
|
||||
if len(l:amounts) < 3
|
||||
call s:error_message('Could not determine balance. Did you use a valid account?')
|
||||
return
|
||||
endif
|
||||
echo g:ledger_pending_string
|
||||
echohl LedgerPending
|
||||
echon l:amounts[0]
|
||||
echohl NONE
|
||||
echon ' ' g:ledger_cleared_string
|
||||
echohl LedgerCleared
|
||||
echon l:amounts[1]
|
||||
echohl NONE
|
||||
if exists('g:ledger_target_amount')
|
||||
echon ' ' g:ledger_target_string
|
||||
echohl LedgerTarget
|
||||
echon printf('%.2f', (g:ledger_target_amount - str2float(l:amounts[2])))
|
||||
echohl NONE
|
||||
endif
|
||||
endf
|
||||
" }}}
|
||||
|
||||
endif
|
||||
244
autoload/nim.vim
Normal file
244
autoload/nim.vim
Normal file
@@ -0,0 +1,244 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'nim') == -1
|
||||
|
||||
let g:nim_log = []
|
||||
let s:plugin_path = escape(expand('<sfile>:p:h'), '\')
|
||||
|
||||
if !exists("g:nim_caas_enabled")
|
||||
let g:nim_caas_enabled = 0
|
||||
endif
|
||||
|
||||
if !executable('nim')
|
||||
echoerr "the Nim compiler must be in your system's PATH"
|
||||
endif
|
||||
|
||||
if has("python3")
|
||||
exe 'py3file ' . fnameescape(s:plugin_path) . '/nim_vim.py'
|
||||
elseif has("python")
|
||||
exe 'pyfile ' . fnameescape(s:plugin_path) . '/nim_vim.py'
|
||||
endif
|
||||
|
||||
fun! nim#init()
|
||||
let cmd = printf("nim --dump.format:json --verbosity:0 dump %s", s:CurrentNimFile())
|
||||
let raw_dumpdata = system(cmd)
|
||||
if !v:shell_error && expand("%:e") == "nim"
|
||||
let false = 0 " Needed for eval of json
|
||||
let true = 1 " Needed for eval of json
|
||||
let dumpdata = eval(substitute(raw_dumpdata, "\n", "", "g"))
|
||||
|
||||
let b:nim_project_root = dumpdata['project_path']
|
||||
let b:nim_defined_symbols = dumpdata['defined_symbols']
|
||||
let b:nim_caas_enabled = g:nim_caas_enabled || index(dumpdata['defined_symbols'], 'forcecaas') != -1
|
||||
|
||||
for path in dumpdata['lib_paths']
|
||||
if finddir(path) == path
|
||||
let &l:path = path . "," . &l:path
|
||||
endif
|
||||
endfor
|
||||
else
|
||||
let b:nim_caas_enabled = 0
|
||||
endif
|
||||
endf
|
||||
|
||||
fun! s:UpdateNimLog()
|
||||
setlocal buftype=nofile
|
||||
setlocal bufhidden=hide
|
||||
setlocal noswapfile
|
||||
|
||||
for entry in g:nim_log
|
||||
call append(line('$'), split(entry, "\n"))
|
||||
endfor
|
||||
|
||||
let g:nim_log = []
|
||||
|
||||
match Search /^nim\ .*/
|
||||
endf
|
||||
|
||||
augroup NimVim
|
||||
au!
|
||||
au BufEnter log://nim call s:UpdateNimLog()
|
||||
if has("python3") || has("python")
|
||||
" au QuitPre * :py nimTerminateAll()
|
||||
au VimLeavePre * :py nimTerminateAll()
|
||||
endif
|
||||
augroup END
|
||||
|
||||
command! NimLog :e log://nim
|
||||
|
||||
command! NimTerminateService
|
||||
\ :exe printf("py nimTerminateService('%s')", b:nim_project_root)
|
||||
|
||||
command! NimRestartService
|
||||
\ :exe printf("py nimRestartService('%s')", b:nim_project_root)
|
||||
|
||||
fun! s:CurrentNimFile()
|
||||
let save_cur = getpos('.')
|
||||
call cursor(0, 0, 0)
|
||||
|
||||
let PATTERN = "\\v^\\#\\s*included from \\zs.*\\ze"
|
||||
let l = search(PATTERN, "n")
|
||||
|
||||
if l != 0
|
||||
let f = matchstr(getline(l), PATTERN)
|
||||
let l:to_check = expand('%:h') . "/" . f
|
||||
else
|
||||
let l:to_check = expand("%")
|
||||
endif
|
||||
|
||||
call setpos('.', save_cur)
|
||||
return l:to_check
|
||||
endf
|
||||
|
||||
let g:nim_symbol_types = {
|
||||
\ 'skParam': 'v',
|
||||
\ 'skVar': 'v',
|
||||
\ 'skLet': 'v',
|
||||
\ 'skTemp': 'v',
|
||||
\ 'skForVar': 'v',
|
||||
\ 'skConst': 'v',
|
||||
\ 'skResult': 'v',
|
||||
\ 'skGenericParam': 't',
|
||||
\ 'skType': 't',
|
||||
\ 'skField': 'm',
|
||||
\ 'skProc': 'f',
|
||||
\ 'skMethod': 'f',
|
||||
\ 'skIterator': 'f',
|
||||
\ 'skConverter': 'f',
|
||||
\ 'skMacro': 'f',
|
||||
\ 'skTemplate': 'f',
|
||||
\ 'skEnumField': 'v',
|
||||
\ }
|
||||
|
||||
fun! NimExec(op)
|
||||
let isDirty = getbufvar(bufnr('%'), "&modified")
|
||||
if isDirty
|
||||
let tmp = tempname() . bufname("%") . "_dirty.nim"
|
||||
silent! exe ":w " . tmp
|
||||
|
||||
let cmd = printf("idetools %s --trackDirty:\"%s,%s,%d,%d\" \"%s\"",
|
||||
\ a:op, tmp, expand('%:p'), line('.'), col('.')-1, s:CurrentNimFile())
|
||||
else
|
||||
let cmd = printf("idetools %s --track:\"%s,%d,%d\" \"%s\"",
|
||||
\ a:op, expand('%:p'), line('.'), col('.')-1, s:CurrentNimFile())
|
||||
endif
|
||||
|
||||
if b:nim_caas_enabled
|
||||
exe printf("py nimExecCmd('%s', '%s', False)", b:nim_project_root, cmd)
|
||||
let output = l:py_res
|
||||
else
|
||||
let output = system("nim " . cmd)
|
||||
endif
|
||||
|
||||
call add(g:nim_log, "nim " . cmd . "\n" . output)
|
||||
return output
|
||||
endf
|
||||
|
||||
fun! NimExecAsync(op, Handler)
|
||||
let result = NimExec(a:op)
|
||||
call a:Handler(result)
|
||||
endf
|
||||
|
||||
fun! NimComplete(findstart, base)
|
||||
if b:nim_caas_enabled == 0
|
||||
return -1
|
||||
endif
|
||||
|
||||
if a:findstart
|
||||
if synIDattr(synIDtrans(synID(line("."),col("."),1)), "name") == 'Comment'
|
||||
return -1
|
||||
endif
|
||||
let line = getline('.')
|
||||
let start = col('.') - 1
|
||||
while start > 0 && line[start - 1] =~? '\w'
|
||||
let start -= 1
|
||||
endwhile
|
||||
return start
|
||||
else
|
||||
let result = []
|
||||
let sugOut = NimExec("--suggest")
|
||||
for line in split(sugOut, '\n')
|
||||
let lineData = split(line, '\t')
|
||||
if len(lineData) > 0 && lineData[0] == "sug"
|
||||
let word = split(lineData[2], '\.')[-1]
|
||||
if a:base ==? '' || word =~# '^' . a:base
|
||||
let kind = get(g:nim_symbol_types, lineData[1], '')
|
||||
let c = { 'word': word, 'kind': kind, 'menu': lineData[3], 'dup': 1 }
|
||||
call add(result, c)
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
return result
|
||||
endif
|
||||
endf
|
||||
|
||||
if !exists("g:neocomplcache_omni_patterns")
|
||||
let g:neocomplcache_omni_patterns = {}
|
||||
endif
|
||||
let g:neocomplcache_omni_patterns['nim'] = '[^. *\t]\.\w*'
|
||||
|
||||
if !exists('g:neocomplete#sources#omni#input_patterns')
|
||||
let g:neocomplete#sources#omni#input_patterns = {}
|
||||
endif
|
||||
let g:neocomplete#sources#omni#input_patterns['nim'] = '[^. *\t]\.\w*'
|
||||
|
||||
let g:nim_completion_callbacks = {}
|
||||
|
||||
fun! NimAsyncCmdComplete(cmd, output)
|
||||
call add(g:nim_log, a:output)
|
||||
echom g:nim_completion_callbacks
|
||||
if has_key(g:nim_completion_callbacks, a:cmd)
|
||||
let Callback = get(g:nim_completion_callbacks, a:cmd)
|
||||
call Callback(a:output)
|
||||
" remove(g:nim_completion_callbacks, a:cmd)
|
||||
else
|
||||
echom "ERROR, Unknown Command: " . a:cmd
|
||||
endif
|
||||
return 1
|
||||
endf
|
||||
|
||||
fun! GotoDefinition_nim_ready(def_output)
|
||||
if v:shell_error
|
||||
echo "nim was unable to locate the definition. exit code: " . v:shell_error
|
||||
" echoerr a:def_output
|
||||
return 0
|
||||
endif
|
||||
|
||||
let rawDef = matchstr(a:def_output, 'def\t\([^\n]*\)')
|
||||
if rawDef == ""
|
||||
echo "the current cursor position does not match any definitions"
|
||||
return 0
|
||||
endif
|
||||
|
||||
let defBits = split(rawDef, '\t')
|
||||
let file = defBits[4]
|
||||
let line = defBits[5]
|
||||
exe printf("e +%d %s", line, file)
|
||||
return 1
|
||||
endf
|
||||
|
||||
fun! GotoDefinition_nim()
|
||||
call NimExecAsync("--def", function("GotoDefinition_nim_ready"))
|
||||
endf
|
||||
|
||||
fun! FindReferences_nim()
|
||||
setloclist()
|
||||
endf
|
||||
|
||||
" Syntastic syntax checking
|
||||
fun! SyntaxCheckers_nim_nim_GetLocList()
|
||||
let makeprg = 'nim check --hints:off --listfullpaths ' . s:CurrentNimFile()
|
||||
let errorformat = &errorformat
|
||||
|
||||
return SyntasticMake({ 'makeprg': makeprg, 'errorformat': errorformat })
|
||||
endf
|
||||
|
||||
function! SyntaxCheckers_nim_nim_IsAvailable()
|
||||
return executable("nim")
|
||||
endfunction
|
||||
|
||||
if exists("g:SyntasticRegistry")
|
||||
call g:SyntasticRegistry.CreateAndRegisterChecker({
|
||||
\ 'filetype': 'nim',
|
||||
\ 'name': 'nim'})
|
||||
endif
|
||||
|
||||
endif
|
||||
36
autoload/requirements.vim
Normal file
36
autoload/requirements.vim
Normal 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
|
||||
@@ -55,6 +55,8 @@ function! terraform#commands(ArgLead, CmdLine, CursorPos) abort
|
||||
\ 'graph',
|
||||
\ 'import',
|
||||
\ 'init',
|
||||
\ 'login',
|
||||
\ 'logout',
|
||||
\ 'output',
|
||||
\ 'plan',
|
||||
\ 'providers',
|
||||
|
||||
@@ -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
|
||||
@@ -1,18 +0,0 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vifm') == -1
|
||||
|
||||
" common functions for vifm command-line editing buffer filetype plugins
|
||||
" Maintainer: xaizek <xaizek@posteo.net>
|
||||
" Last Change: August 18, 2013
|
||||
|
||||
" Prepare buffer
|
||||
function! vifm#edit#Init()
|
||||
" Mappings for quick leaving the buffer (behavior similar to Command line
|
||||
" buffer in Vim)
|
||||
nnoremap <buffer> <cr> :copy 0 \| wq<cr>
|
||||
imap <buffer> <cr> <esc><cr>
|
||||
|
||||
" Start buffer editing in insert mode
|
||||
startinsert
|
||||
endfunction
|
||||
|
||||
endif
|
||||
@@ -1,35 +0,0 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vifm') == -1
|
||||
|
||||
" common functions for vifm plugin related to globals
|
||||
" Maintainer: xaizek <xaizek@posteo.net>
|
||||
" Last Change: November 03, 2018
|
||||
|
||||
" Initializes global variables to defaults unless they are already set
|
||||
function! vifm#globals#Init()
|
||||
if !exists('g:vifm_exec')
|
||||
let g:vifm_exec = 'vifm'
|
||||
endif
|
||||
|
||||
if !exists('g:vifm_exec_args')
|
||||
let g:vifm_exec_args = ''
|
||||
endif
|
||||
|
||||
if !exists('g:vifm_term')
|
||||
if has('win32')
|
||||
if filereadable('C:\Windows\system32\cmd.exe')
|
||||
let g:vifm_term = 'C:\Windows\system32\cmd.exe /C'
|
||||
else
|
||||
" If don't find use the integrate shell it work too
|
||||
let g:vifm_term = ''
|
||||
endif
|
||||
else
|
||||
let g:vifm_term = 'xterm -e'
|
||||
endif
|
||||
endif
|
||||
|
||||
if !exists('g:vifm_embed_term')
|
||||
let g:vifm_embed_term = has('gui_running')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
endif
|
||||
@@ -1,707 +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_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_keywords', ['TODO', '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', '')
|
||||
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
|
||||
let l:polyglot = !empty(filter(copy(l:scriptnames), "v:val =~# 'polyglot'"))
|
||||
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!',
|
||||
\])
|
||||
if l:polyglot
|
||||
call vimtex#log#warning([
|
||||
\ 'LaTeX-Box is included with vim-polyglot and may be disabled with:',
|
||||
\ 'let g:polyglot_disabled = [''latex'']',
|
||||
\])
|
||||
endif
|
||||
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
|
||||
@@ -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
|
||||
@@ -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 v:true
|
||||
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 v:true
|
||||
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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
|
||||
@@ -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 v:true
|
||||
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 v:true
|
||||
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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,192 +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
|
||||
|
||||
"
|
||||
" 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('s:created_maps')
|
||||
call s:create_map(a:map)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! vimtex#imaps#list() abort " {{{1
|
||||
silent new vimtex\ imaps
|
||||
|
||||
for l:map in s:created_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(s:created_maps, a:map) >= 0 | return | endif
|
||||
|
||||
let l:leader = get(a: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 . a:map.lhs
|
||||
|
||||
let l:wrapper = get(a: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(a:map, 'context')
|
||||
execute 'let l:key = "' . escape(l:lhs, '<') . '"'
|
||||
let l:key .= a:map.rhs
|
||||
if !exists('b:vimtex_context')
|
||||
let b:vimtex_context = {}
|
||||
endif
|
||||
let b:vimtex_context[l:key] = a:map.context
|
||||
endif
|
||||
|
||||
" The rhs may be evaluated before being passed to wrapper, unless expr is
|
||||
" disabled (which it is by default)
|
||||
if !get(a:map, 'expr')
|
||||
let a:map.rhs = string(a:map.rhs)
|
||||
endif
|
||||
|
||||
silent execute 'inoremap <expr><silent><nowait><buffer>' l:lhs
|
||||
\ l:wrapper . '("' . escape(l:lhs, '\') . '", ' . a:map.rhs . ')'
|
||||
|
||||
let s:created_maps += [a: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
|
||||
|
||||
|
||||
" {{{1 Initialize module
|
||||
|
||||
let s:created_maps = []
|
||||
|
||||
" }}}1
|
||||
|
||||
endif
|
||||
@@ -1,147 +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)
|
||||
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 . '/**/' . 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,778 +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(g:vimtex_toc_todo_keywords, '|') . ')'
|
||||
\ . '|\%\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(g:vimtex_toc_todo_keywords, '|') . ')[ :]+\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]
|
||||
return {
|
||||
\ 'title' : toupper(l:type) . ': ' . 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
|
||||
|
||||
return {
|
||||
\ 'title' : 'TODO: ' . 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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*%(' . 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,82 +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
|
||||
" 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
|
||||
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
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
endif
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user