mirror of
https://github.com/leafOfTree/vim-vue-plugin.git
synced 2025-12-15 00:47:05 +08:00
Compare commits
103 Commits
v2021_03_2
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04c3fb20ed | ||
|
|
58ac69b2c8 | ||
|
|
4d31393b03 | ||
|
|
8d75429260 | ||
|
|
ed318345cf | ||
|
|
84ac1d2359 | ||
|
|
4da7d448ae | ||
|
|
ac76f21419 | ||
|
|
be0f84ebb5 | ||
|
|
3b90ccad2d | ||
|
|
b2bb4dd8f6 | ||
|
|
b4c9fdc87a | ||
|
|
6569315461 | ||
|
|
5977fc07fe | ||
|
|
a8decb75b1 | ||
|
|
469c43292d | ||
|
|
dd0e3145af | ||
|
|
a5be3e6c3a | ||
|
|
7f4c259d27 | ||
|
|
8e121ce67d | ||
|
|
6678475a50 | ||
|
|
0432e150dc | ||
|
|
15143762b8 | ||
|
|
3fa4bea6df | ||
|
|
c248bd1488 | ||
|
|
6e25aaf388 | ||
|
|
8d464e9506 | ||
|
|
ab96ba2585 | ||
|
|
4dd559c860 | ||
|
|
d15590dae2 | ||
|
|
eb3bba0ccb | ||
|
|
e4ddccee90 | ||
|
|
0e68102487 | ||
|
|
44b0071e2d | ||
|
|
3d2680a859 | ||
|
|
cda82484d2 | ||
|
|
0e341ab4f8 | ||
|
|
a5882eb712 | ||
|
|
568b571849 | ||
|
|
b2b08cda9d | ||
|
|
c43bd87267 | ||
|
|
98e22f2af4 | ||
|
|
43490363a5 | ||
|
|
50ea0b7bce | ||
|
|
696533d262 | ||
|
|
9ae107ea6f | ||
|
|
b8cbd66359 | ||
|
|
0f4b6b7b7e | ||
|
|
12e5eadbad | ||
|
|
617639320d | ||
|
|
511fb2fb82 | ||
|
|
b8f8a45e44 | ||
|
|
32b89ad2bf | ||
|
|
9e642cc983 | ||
|
|
8a913af7a6 | ||
|
|
9e55939c89 | ||
|
|
5067a5cc25 | ||
|
|
c4847c18e9 | ||
|
|
d080255fce | ||
|
|
8f23970cf9 | ||
|
|
d8a5c1486b | ||
|
|
8f0d26991a | ||
|
|
2a682014a3 | ||
|
|
483e45e198 | ||
|
|
f1b7ea05b8 | ||
|
|
6a94c30ec7 | ||
|
|
87922641ad | ||
|
|
3ed1e89f55 | ||
|
|
ed7e1a9898 | ||
|
|
c71f55019b | ||
|
|
5be2325222 | ||
|
|
dcbdcbea37 | ||
|
|
26002b6212 | ||
|
|
8d3c18621d | ||
|
|
255472b126 | ||
|
|
f437eea49d | ||
|
|
f460616735 | ||
|
|
8e6080629b | ||
|
|
99f317066a | ||
|
|
74a917987e | ||
|
|
6da176f51e | ||
|
|
c70cd332ad | ||
|
|
15914af39b | ||
|
|
f50130155e | ||
|
|
59e9825606 | ||
|
|
11c04aaf7b | ||
|
|
537af6139f | ||
|
|
b617e1e110 | ||
|
|
01e460244f | ||
|
|
b601b25226 | ||
|
|
fe88470ebf | ||
|
|
d11229e7e1 | ||
|
|
fc75f3c474 | ||
|
|
665d8a18b3 | ||
|
|
347f62abae | ||
|
|
5aee4f5a0d | ||
|
|
950b6dc126 | ||
|
|
d1a15e095b | ||
|
|
d90b18e1c7 | ||
|
|
258d30fc6b | ||
|
|
e1dab23589 | ||
|
|
6b48092f15 | ||
|
|
2b050c42c1 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
README.html
|
||||
test.vue
|
||||
.DS_STORE
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
dist: focal
|
||||
|
||||
language: minimal
|
||||
|
||||
before_install:
|
||||
- sudo add-apt-repository ppa:neovim-ppa/stable -y
|
||||
- sudo apt-get update
|
||||
- sudo apt-get -y install neovim
|
||||
|
||||
install:
|
||||
- git clone https://github.com/leafOfTree/test ../test --depth=1
|
||||
|
||||
218
README.md
218
README.md
@@ -1,132 +1,150 @@
|
||||
# vim-vue-plugin [![Build Status][12]](https://travis-ci.com/leafOfTree/vim-vue-plugin)
|
||||
<img src="https://raw.githubusercontent.com/leafOfTree/leafOfTree.github.io/master/vim-vue-plugin-icon.svg" width="60" height="60" alt="icon" align="left"/>
|
||||
|
||||
# vim-vue-plugin
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/altercation/vim-colors-solarized">
|
||||
<img alt="screenshot" src="https://raw.githubusercontent.com/leafOfTree/leafOfTree.github.io/master/vim-vue-plugin-screenshot.png" width="220" />
|
||||
<img alt="screenshot" src="https://raw.githubusercontent.com/leafOfTree/leafOfTree.github.io/master/vim-vue-plugin-screenshot.png" width="260" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Vim syntax and indent plugin for `.vue` files. Mainly inspired by [mxw/vim-jsx][1].
|
||||
Vim syntax and indent plugin for `.vue` files. Mainly inspired by [mxw/vim-jsx][1]
|
||||
|
||||
## Installation
|
||||
|
||||
<details>
|
||||
You could install it just like other plugins. The filetype will be set to `vue`. Feel free to open an issue or a pull request if any questions
|
||||
|
||||
<details>
|
||||
<summary><a>How to install</a></summary>
|
||||
|
||||
- [VundleVim][2]
|
||||
|
||||
Plugin 'leafOfTree/vim-vue-plugin'
|
||||
```vim
|
||||
Plugin 'leafOfTree/vim-vue-plugin'
|
||||
```
|
||||
|
||||
- [vim-pathogen][5]
|
||||
|
||||
cd ~/.vim/bundle && \
|
||||
git clone https://github.com/leafOfTree/vim-vue-plugin --depth 1
|
||||
```
|
||||
cd ~/.vim/bundle
|
||||
git clone https://github.com/leafOfTree/vim-vue-plugin --depth 1
|
||||
```
|
||||
|
||||
- [vim-plug][7]
|
||||
|
||||
Plug 'leafOfTree/vim-vue-plugin'
|
||||
:PlugInstall
|
||||
```vim
|
||||
Plug 'leafOfTree/vim-vue-plugin'
|
||||
:PlugInstall
|
||||
```
|
||||
|
||||
- Or manually, clone this plugin to `path/to/this_plugin`, and add it to `rtp` in vimrc
|
||||
|
||||
set rtp+=path/to/this_plugin
|
||||
```vim
|
||||
set rtp+=path/to/this_plugin
|
||||
|
||||
" If filetype is not set to 'vue', try
|
||||
filetype off
|
||||
set rtp+=path/to/this_plugin
|
||||
filetype plugin indent on
|
||||
```
|
||||
<br />
|
||||
</details>
|
||||
|
||||
This plugin works if it has set `filetype` to `vue`. Please stay up to date. Feel free to open an issue or pull request.
|
||||
|
||||
## How it works
|
||||
|
||||
Since `.vue` is a combination of CSS, HTML and JavaScript, so is `vim-vue-plugin`. (Like XML and JavaScript for `.jsx`).
|
||||
It loads multiple syntax and indent files for `.vue` and enables them to work together
|
||||
|
||||
Supports
|
||||
|
||||
- Vue attribute(directive) and keyword.^
|
||||
- Less/Sass/Scss, Pug with [vim-pug][4], Coffee with [vim-coffee-script][11], TypeScript with [typescript-vim][14] or [yats.vim][15], Stylus with [vim-stylus][16]. ^
|
||||
|
||||
Relative plugins need to be installed.
|
||||
|
||||
- A builtin `foldexpr` foldmethod.^
|
||||
- [emmet-vim][10] HTML/CSS/JavaScript filetype detection.
|
||||
- `.wpy` files from [WePY][6].
|
||||
|
||||
^: see Configuration for details.
|
||||
- Blocks (both `template/script/style` and custom blocks) with any specified syntax, including `pug, typescript, coffee, scss, sass, less, stylus, ...`. Syntax plugins need to be installed if not provided by Vim
|
||||
- Attribute, directive, and keyword highlight
|
||||
- [emmet-vim][10] `html, javascript, css, ...` filetype detection
|
||||
- Context-based behavior, such as to get current tag or syntax, and set local options like `commentstring`
|
||||
- A built-in `foldexpr` foldmethod
|
||||
|
||||
## Configuration
|
||||
|
||||
Set global variable to `1` to enable or `0` to disable. Ex:
|
||||
`g:vim_vue_plugin_config` is the only configuration. You can copy its **default value** below as a starting point
|
||||
|
||||
```vim
|
||||
let g:vim_vue_plugin_load_full_syntax = 1
|
||||
```
|
||||
|
||||
| variable | description | default |
|
||||
|---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|----------------------------|
|
||||
| `g:vim_vue_plugin_load_full_syntax`\* | Enable: load all syntax files in `runtimepath` to enable related syntax plugins.<br> Disable: only in `$VIMRUNTIME/syntax`, `~/.vim/syntax` and `$VIM/vimfiles/syntax`. | 0 |
|
||||
| `g:vim_vue_plugin_use_pug`\* | Enable pug syntax for `<template lang="pug">`. | 0 |
|
||||
| `g:vim_vue_plugin_use_coffee` | Enable coffee syntax for `<script lang="coffee">`. | 0 |
|
||||
| `g:vim_vue_plugin_use_typescript` | Enable typescript syntax for `<script lang="ts">`. | 0 |
|
||||
| `g:vim_vue_plugin_use_less` | Enable less syntax for `<style lang="less">`. | 0 |
|
||||
| `g:vim_vue_plugin_use_sass` | Enable sass syntax for `<style lang="scss\|sass">`. | 0 |
|
||||
| `g:vim_vue_plugin_use_scss` | Enable scss syntax for `<style lang="scss">`. | 0 |
|
||||
| `g:vim_vue_plugin_use_stylus` | Enable stylus syntax for `<style lang="stylus">`. | 0 |
|
||||
| `g:vim_vue_plugin_has_init_indent` | Initially indent one tab inside `style/script` tags. | 0+ |
|
||||
| `g:vim_vue_plugin_highlight_vue_attr` | Highlight vue attribute value as expression instead of string. | 0 |
|
||||
| `g:vim_vue_plugin_highlight_vue_keyword` | Highlight vue keyword like `data`, `methods`, ... | 0 |
|
||||
| `g:vim_vue_plugin_use_foldexpr`\# | Enable builtin `foldexpr` foldmethod. | 0 |
|
||||
| `g:vim_vue_plugin_custom_blocks` | Highlight custom blocks. See details below. | {} |
|
||||
| `g:vim_vue_plugin_debug` | Echo debug messages in `messages` list. Useful to debug if unexpected indents occur. | 0 |
|
||||
|
||||
\*: Vim may be slow if the feature is enabled. Find a balance between syntax highlight and speed. By the way, custom syntax can be added in `~/.vim/syntax` or `$VIM/vimfiles/syntax`.
|
||||
|
||||
\#: In the case when it's enabled, the `foldexpr` is not efficient for large files, so it's not enabled initially when the line number exceeds `1000`. You can enable it mannully by `setlocal foldmethod=expr` when required.
|
||||
|
||||
\+: 0 for `.vue` and 1 for `.wpy`
|
||||
|
||||
**Note**
|
||||
|
||||
- `g:vim_vue_plugin_load_full_syntax` applies to other `HTML/Sass/Less` plugins.
|
||||
- `filetype` is set to `vue` so autocmds and other settings for `javascript` have to be manually enabled for `vue`.
|
||||
|
||||
## Custom blocks
|
||||
|
||||
You can enable highlighting in a custom block by setting `g:vim_vue_plugin_custom_blocks`.
|
||||
|
||||
The structure is `{ block: filetype }` or `{ block: filetype[] }`. When providing a filetype list, you need to add `lang="..."` in the tag. Otherwise, the first one will be used.
|
||||
|
||||
### Example
|
||||
|
||||
```vim
|
||||
let g:vim_vue_plugin_custom_blocks = {
|
||||
\'docs': 'markdown',
|
||||
\'i18n': ['json', 'yaml', 'json5'],
|
||||
let g:vim_vue_plugin_config = {
|
||||
\'syntax': {
|
||||
\ 'template': ['html'],
|
||||
\ 'script': ['javascript'],
|
||||
\ 'style': ['css'],
|
||||
\},
|
||||
\'full_syntax': [],
|
||||
\'initial_indent': [],
|
||||
\'attribute': 0,
|
||||
\'keyword': 0,
|
||||
\'foldexpr': 0,
|
||||
\'debug': 0,
|
||||
\}
|
||||
```
|
||||
|
||||
Should highlight custom blocks in `.vue` such as
|
||||
### Description
|
||||
|
||||
```vue
|
||||
<docs>
|
||||
# This is the documentation for component.
|
||||
</docs>
|
||||
It has the following options
|
||||
|
||||
<i18n lang="yaml">
|
||||
en:
|
||||
hello: "Hello World!"
|
||||
ja:
|
||||
hello: "こんにちは、世界!"
|
||||
</i18n>
|
||||
- **syntax**
|
||||
- **key**: *string*. Block tag name
|
||||
- **value**: *string list*. Block syntax
|
||||
- `lang="..."` on block tag decides the effective syntax
|
||||
- When no valid `lang="..."` is present, the first syntax in the list will be used.
|
||||
- By default, only syntax files from `['$VIMRUNTIME', '$VIM/vimfiles', '$HOME/.vim']` are loaded. If none is found, then **full** syntax files, including those from plugins, will be loaded
|
||||
- **full_syntax**: *string list*. Syntax whose **full** syntax files will always be loaded
|
||||
- **initial_indent**: *string list*. Tag/syntax with initial one tab indent. The format can be `tag.syntax`, `tag`, or `syntax`
|
||||
|
||||
For *boolean* options below, set `1` to enable or `0` to disable
|
||||
|
||||
- **attribute**: *boolean*. Highlight attribute as expression instead of string
|
||||
- **keyword** : *boolean*. Highlight keyword such as `data`, `methods`, ...
|
||||
- **foldexpr**: *boolean*. Enable built-in `foldexpr` foldmethod
|
||||
- **debug**: *boolean*. Echo debug messages in `messages` list
|
||||
|
||||
### Example
|
||||
|
||||
Only for demo. Try to set syntax as little as possible for performance.
|
||||
|
||||
```vim
|
||||
let g:vim_vue_plugin_config = {
|
||||
\'syntax': {
|
||||
\ 'template': ['html', 'pug'],
|
||||
\ 'script': ['javascript', 'typescript', 'coffee'],
|
||||
\ 'style': ['css', 'scss', 'sass', 'less', 'stylus'],
|
||||
\ 'i18n': ['json', 'yaml'],
|
||||
\ 'route': 'json',
|
||||
\},
|
||||
\'full_syntax': ['json'],
|
||||
\'initial_indent': ['i18n', 'i18n.json', 'yaml'],
|
||||
\'attribute': 1,
|
||||
\'keyword': 1,
|
||||
\'foldexpr': 1,
|
||||
\'debug': 0,
|
||||
\}
|
||||
```
|
||||
|
||||
## Context based behavior
|
||||
<img alt="screenshot" src="https://raw.githubusercontent.com/leafOfTree/leafOfTree.github.io/master/vue-config-example.png" />
|
||||
|
||||
As there are more than one language in `.vue` file, the different behaviors like mapping or completion and local options, may be required under different tags or subtypes(current language type).
|
||||
You can still change options later as if they are global variables.
|
||||
|
||||
This plugin provides functions to get the tag/subtype where the cursor is in.
|
||||
```vim
|
||||
let g:vim_vue_plugin_config.foldexpr = 0
|
||||
```
|
||||
|
||||
- `GetVueTag() => String` Return value is one of `'template', 'script', 'style'`.
|
||||
Note
|
||||
|
||||
- `typescript` matches `lang="ts"`
|
||||
- `list` options can be `string` if only one
|
||||
- The first item of syntax list will be used if no "lang=..."
|
||||
- For `.wpy`, `initial_indent` defaults to `['script', 'style']`
|
||||
- You could check `:h dict` and `:h list` for details about the complex data types
|
||||
|
||||
## Context-based behavior
|
||||
|
||||
There are more than one language in `.vue` file. Different mappings, completions, and local options may be required under different tags or syntax (current language filetype)
|
||||
|
||||
This plugin provides functions to get the tag/syntax where the cursor is in
|
||||
|
||||
- `GetVueTag() => String` Return value is one of `'template', 'script', 'style'`
|
||||
|
||||
```vim
|
||||
" Example
|
||||
@@ -138,20 +156,20 @@ This plugin provides functions to get the tag/subtype where the cursor is in.
|
||||
endfunction
|
||||
```
|
||||
|
||||
- `GetVueSubtype() => String` Return value is one of `'html', 'javascript', 'css', 'scss', ...`.
|
||||
- `GetVueSyntax() => String` Return value is one of `'html', 'javascript', 'css', 'scss', ...`
|
||||
|
||||
- `OnChangeVueSubtype(subtype)` An event listener that is called when subtype changes.
|
||||
- `OnChangeVueSyntax(syntax)` An event listener that is called when syntax changes
|
||||
|
||||
You can also define an event listener function `OnChangeVueSubtype(subtype)` in your `vimrc` to get the subtype and set its local options whenever it changes.
|
||||
You can define it in your `vimrc` to set local options based on current syntax
|
||||
|
||||
```vim
|
||||
" Example: set local options based on subtype
|
||||
function! OnChangeVueSubtype(subtype)
|
||||
echom 'Subtype is '.a:subtype
|
||||
if a:subtype == 'html'
|
||||
" Example: set local options based on syntax
|
||||
function! OnChangeVueSyntax(syntax)
|
||||
echom 'Syntax is '.a:syntax
|
||||
if a:syntax == 'html'
|
||||
setlocal commentstring=<!--%s-->
|
||||
setlocal comments=s:<!--,m:\ \ \ \ ,e:-->
|
||||
elseif a:subtype =~ 'css'
|
||||
elseif a:syntax =~ 'css'
|
||||
setlocal comments=s1:/*,mb:*,ex:*/ commentstring&
|
||||
else
|
||||
setlocal commentstring=//%s
|
||||
@@ -160,15 +178,19 @@ This plugin provides functions to get the tag/subtype where the cursor is in.
|
||||
endfunction
|
||||
```
|
||||
|
||||
> It has been renamed to `GetVueSyntax, OnChangeVueSyntax` from `GetVueSubtype, OnChangeVueSubtype` for consistency
|
||||
|
||||
### emmet-vim
|
||||
|
||||
Currently emmet-vim works regarding your HTML/CSS/JavaScript emmet settings, but it depends on how emmet-vim gets `filetype` and may change in the future. Feel free to report an issue if any problem appears.
|
||||
Currently emmet-vim works regarding your `html, javascript, css, ...` emmet settings, but it depends on how emmet-vim gets `filetype` and may change in the future. Feel free to report an issue if any problem appears
|
||||
|
||||
For `sass` using emmet-vim, please check out [this issue][17]
|
||||
|
||||
## Avoid overload
|
||||
|
||||
Since there are many sub languages included, most delays come from syntax files overload. A variable named `b:current_loading_main_syntax` is set to `vue` which can be used as loading condition if you'd like to manually find and modify the syntax files causing overload.
|
||||
Since there are many sub-languages included, most delays come from syntax files overload. A variable named `b:current_loading_main_syntax` is set to `vue` which can be used as a loading condition if you'd like to manually find and modify the syntax files causing overload
|
||||
|
||||
For example, the builtin syntax `sass.vim` and `less.vim` in vim8.1 runtime and `pug.vim` in vim-pug/syntax always load `css.vim` which this plugin already loads. It can be optimized like
|
||||
For example, the built-in syntax `sass.vim` and `less.vim` in vim8.1 runtime and `pug.vim` in vim-pug/syntax always load `css.vim` which this plugin already loads. It can be optimized like
|
||||
|
||||
`$VIMRUNTIME/syntax/sass.vim`
|
||||
```diff
|
||||
@@ -186,7 +208,6 @@ For example, the builtin syntax `sass.vim` and `less.vim` in vim8.1 runtime and
|
||||
+ endif
|
||||
```
|
||||
|
||||
|
||||
## Acknowledgments & Refs
|
||||
|
||||
- [mxw/vim-jsx][1]
|
||||
@@ -197,11 +218,11 @@ For example, the builtin syntax `sass.vim` and `less.vim` in vim8.1 runtime and
|
||||
|
||||
- [vim-svelte-plugin][9]
|
||||
|
||||
[Svelte][13] is a compilation web framework which shares a similar syntax to Vue.
|
||||
[Svelte][13] is a compilation web framework that shares a similar syntax to Vue
|
||||
|
||||
## License
|
||||
|
||||
This plugin is under [The Unlicense][8]. Other than this, `lib/indent/*` files are extracted from vim runtime.
|
||||
This plugin is under [The Unlicense][8]. Other than this, `lib/indent/*` files are extracted from vim runtime
|
||||
|
||||
[1]: https://github.com/mxw/vim-jsx "mxw: vim-jsx"
|
||||
[2]: https://github.com/VundleVim/Vundle.vim
|
||||
@@ -219,3 +240,4 @@ This plugin is under [The Unlicense][8]. Other than this, `lib/indent/*` files a
|
||||
[14]: https://github.com/leafgarland/typescript-vim
|
||||
[15]: https://github.com/HerringtonDarkholme/yats.vim
|
||||
[16]: https://github.com/iloginow/vim-stylus
|
||||
[17]: https://github.com/leafOfTree/vim-vue-plugin/issues/23#issuecomment-628306633
|
||||
|
||||
330
autoload/vue.vim
330
autoload/vue.vim
@@ -1,116 +1,334 @@
|
||||
" Since vue#Log and vue#GetConfig are always called
|
||||
" in syntax and indent files,
|
||||
" this file will be sourced when opening the first vue file
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" this file will be sourced on opening the first vue file
|
||||
|
||||
function! s:GetConfig(name, default)
|
||||
let name = 'g:vim_vue_plugin_'.a:name
|
||||
return exists(name) ? eval(name) : a:default
|
||||
let value = exists(name) ? eval(name) : a:default
|
||||
|
||||
if a:name == 'config'
|
||||
let value = s:MergeUserConfigIntoDefault(value)
|
||||
endif
|
||||
|
||||
return value
|
||||
endfunction
|
||||
|
||||
let s:name = 'vim-vue-plugin'
|
||||
let s:load_full_syntax = s:GetConfig("load_full_syntax", 0)
|
||||
let s:debug = s:GetConfig("debug", 0)
|
||||
function! s:MergeUserConfigIntoDefault(user)
|
||||
let default = {
|
||||
\'syntax': {
|
||||
\ 'template': ['html'],
|
||||
\ 'script': ['javascript'],
|
||||
\ 'style': ['css'],
|
||||
\},
|
||||
\'full_syntax': [],
|
||||
\'initial_indent': [],
|
||||
\'attribute': 0,
|
||||
\'keyword': 0,
|
||||
\'foldexpr': 0,
|
||||
\'debug': 0,
|
||||
\}
|
||||
|
||||
let user = a:user
|
||||
for key in keys(default)
|
||||
if has_key(user, key)
|
||||
let default[key] = user[key]
|
||||
endif
|
||||
endfor
|
||||
|
||||
" For backwards compatibility with 'init_indent'
|
||||
if !has_key(user, 'initial_indent')
|
||||
if has_key(user, 'init_indent')
|
||||
\ ? user.init_indent
|
||||
\ : expand('%:e') == 'wpy'
|
||||
let default.initial_indent = ['script', 'style']
|
||||
endif
|
||||
endif
|
||||
|
||||
return default
|
||||
endfunction
|
||||
|
||||
function! s:CheckVersion()
|
||||
if !exists('g:vim_vue_plugin_config')
|
||||
let prev_configs = [
|
||||
\'g:vim_vue_plugin_load_full_syntax',
|
||||
\'g:vim_vue_plugin_use_pug',
|
||||
\'g:vim_vue_plugin_use_coffee',
|
||||
\'g:vim_vue_plugin_use_typescript',
|
||||
\'g:vim_vue_plugin_use_less',
|
||||
\'g:vim_vue_plugin_use_sass',
|
||||
\'g:vim_vue_plugin_use_scss',
|
||||
\'g:vim_vue_plugin_use_stylus',
|
||||
\'g:vim_vue_plugin_has_init_indent',
|
||||
\'g:vim_vue_plugin_highlight_vue_attr',
|
||||
\'g:vim_vue_plugin_highlight_vue_keyword',
|
||||
\'g:vim_vue_plugin_use_foldexpr',
|
||||
\'g:vim_vue_plugin_custom_blocks',
|
||||
\'g:vim_vue_plugin_debug',
|
||||
\]
|
||||
let has_prev_config = 0
|
||||
for config in prev_configs
|
||||
if exists(config)
|
||||
let has_prev_config = 1
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
|
||||
if has_prev_config
|
||||
let message = 'Hey, it seems that you just upgraded. Please use `g:vim_vue_plugin_config` to replace previous configs'
|
||||
let message2 = 'For details, please check README.md ## Configuration or https://github.com/leafOfTree/vim-vue-plugin'
|
||||
echom '['.s:name.'] '.message
|
||||
echom '['.s:name.'] '.message2
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:Main()
|
||||
let s:name = 'vim-vue-plugin'
|
||||
let s:config = s:GetConfig('config', {})
|
||||
let s:full_syntax = s:config.full_syntax
|
||||
let s:debug = s:config.debug
|
||||
|
||||
call s:CheckVersion()
|
||||
endfunction
|
||||
|
||||
function! vue#Log(msg)
|
||||
if s:debug
|
||||
echom '['.s:name.'] '.a:msg
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! vue#LogWithLnum(msg)
|
||||
if s:debug
|
||||
echom '['.s:name.']['.v:lnum.'] '.a:msg
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! vue#Warn(msg)
|
||||
if s:debug
|
||||
echohl WarningMsg
|
||||
echom '['.s:name.'] '.a:msg
|
||||
echohl None
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! vue#GetConfig(name, default)
|
||||
return s:GetConfig(a:name, a:default)
|
||||
endfunction
|
||||
|
||||
if exists('##CursorMoved') && exists('*OnChangeVueSubtype')
|
||||
if exists('##CursorMoved') && (exists('*OnChangeVueSyntax') || exists('*OnChangeVueSubtype'))
|
||||
augroup vim_vue_plugin
|
||||
autocmd!
|
||||
autocmd CursorMoved,CursorMovedI,WinEnter *.vue,*.wpy
|
||||
\ call s:CheckSubtype()
|
||||
\ call s:CheckSyntax()
|
||||
augroup END
|
||||
|
||||
let s:subtype = ''
|
||||
function! s:CheckSubtype()
|
||||
let subtype = GetVueSubtype()
|
||||
if exists('*OnChangeVueSyntax')
|
||||
let s:OnChangeListener = function('OnChangeVueSyntax')
|
||||
else
|
||||
let s:OnChangeListener = function('OnChangeVueSubtype')
|
||||
endif
|
||||
|
||||
if s:subtype != subtype
|
||||
call OnChangeVueSubtype(subtype)
|
||||
let s:subtype = subtype
|
||||
let s:syntax = ''
|
||||
function! s:CheckSyntax()
|
||||
let syntax = GetVueSyntax()
|
||||
|
||||
if s:syntax != syntax
|
||||
call s:OnChangeListener(syntax)
|
||||
let s:syntax = syntax
|
||||
endif
|
||||
endfunction
|
||||
endif
|
||||
|
||||
function! s:SynsEOL(lnum)
|
||||
let lnum = prevnonblank(a:lnum)
|
||||
let cnum = strlen(getline(lnum))
|
||||
return map(synstack(lnum, cnum), 'synIDattr(v:val, "name")')
|
||||
function! s:SyntaxListAtEnd(lnum)
|
||||
let plnum = prevnonblank(a:lnum)
|
||||
let pline = getline(plnum)
|
||||
|
||||
" return [] if prevnonblank is an end tag
|
||||
if pline =~ '^<\/'
|
||||
return []
|
||||
endif
|
||||
|
||||
let col = strlen(pline)
|
||||
return map(synstack(plnum, col), 'synIDattr(v:val, "name")')
|
||||
endfunction
|
||||
|
||||
function! s:SyntaxAtEnd(lnum)
|
||||
let syns = s:SyntaxListAtEnd(a:lnum)
|
||||
let syntax_name = empty(syns) ? '' : get(syns, 0, '')
|
||||
let syntax_name = s:RemoveCssPrefix(syntax_name)
|
||||
return syntax_name
|
||||
endfunction
|
||||
|
||||
function! vue#SyntaxSecondAtEnd(lnum)
|
||||
let syns = s:SyntaxListAtEnd(a:lnum)
|
||||
return get(syns, 1, '')
|
||||
endfunction
|
||||
|
||||
function! s:GetBlockTag(lnum)
|
||||
let syntax_name = s:SyntaxAtEnd(a:lnum)
|
||||
let tag = matchstr(syntax_name, '\(\u\U\+\)\+\zeBlock')
|
||||
let tag = substitute(tag, '\U\zs\(\u\)', "-\\1", 'g')
|
||||
let tag = tolower(tag)
|
||||
return tag
|
||||
endfunction
|
||||
|
||||
let s:style_with_css_prefix = ['scss', 'less', 'stylus']
|
||||
|
||||
" Adjust syntax name to support emmet-vim by adding css prefix
|
||||
function! vue#AlterSyntaxForEmmetVim(name, syntax)
|
||||
let name = a:name
|
||||
if count(s:style_with_css_prefix, a:syntax)
|
||||
let name = 'css'.toupper(name[0]).name[1:]
|
||||
endif
|
||||
return name
|
||||
endfunction
|
||||
|
||||
" Remove css prefix
|
||||
function! s:RemoveCssPrefix(syntax_name)
|
||||
let syntax_name = a:syntax_name
|
||||
let syntax = matchstr(syntax_name, '^\U\+')
|
||||
if syntax == 'css'
|
||||
let next_syntax = tolower(matchstr(syntax_name, '^\U\+\zs\u\U\+'))
|
||||
if count(s:style_with_css_prefix, next_syntax)
|
||||
let syntax_name = matchstr(syntax_name, '^\U\+\zs.*')
|
||||
let syntax_name = tolower(syntax_name[0]).syntax_name[1:]
|
||||
endif
|
||||
endif
|
||||
return syntax_name
|
||||
endfunction
|
||||
|
||||
function! s:GetBlockSyntax(lnum)
|
||||
let syntax_name = s:SyntaxAtEnd(a:lnum)
|
||||
let syntax = matchstr(syntax_name, '^\U\+')
|
||||
return syntax
|
||||
endfunction
|
||||
|
||||
function! vue#GetBlockTag(lnum)
|
||||
return s:GetBlockTag(a:lnum)
|
||||
endfunction
|
||||
|
||||
function! vue#GetBlockSyntax(lnum)
|
||||
return s:GetBlockSyntax(a:lnum)
|
||||
endfunction
|
||||
|
||||
function! GetVueSubtype()
|
||||
let lnum = line('.')
|
||||
let cursyns = s:SynsEOL(lnum)
|
||||
let syn = !empty(cursyns) ? get(cursyns, 0, '') : ''
|
||||
let syntax = vue#GetBlockSyntax(line('.'))
|
||||
return syntax
|
||||
endfunction
|
||||
|
||||
let subtype = matchstr(syn, '\w\+\zeVue')
|
||||
if subtype =~ 'css\w\+'
|
||||
let subtype = subtype[3:]
|
||||
endif
|
||||
let subtype = tolower(subtype)
|
||||
return subtype
|
||||
function! GetVueSyntax()
|
||||
let syntax = vue#GetBlockSyntax(line('.'))
|
||||
return syntax
|
||||
endfunction
|
||||
|
||||
function! GetVueTag(...)
|
||||
let lnum = a:0 > 0 ? a:1 : line('.')
|
||||
let cursyns = s:SynsEOL(lnum)
|
||||
let syn = get(cursyns, 0, '')
|
||||
|
||||
if syn =~ 'VueTemplate'
|
||||
let tag = 'template'
|
||||
elseif syn =~ 'VueScript'
|
||||
let tag = 'script'
|
||||
elseif syn =~ 'VueStyle'
|
||||
let tag = 'style'
|
||||
else
|
||||
let tag = ''
|
||||
endif
|
||||
|
||||
return tag
|
||||
return vue#GetBlockTag(lnum)
|
||||
endfunction
|
||||
|
||||
function! vue#LoadSyntax(group, type)
|
||||
if s:load_full_syntax
|
||||
call vue#LoadFullSyntax(a:group, a:type)
|
||||
function! vue#LoadSyntax(group, syntax)
|
||||
let group = a:group
|
||||
let syntax = a:syntax
|
||||
if s:IncludeOrEqual(s:full_syntax, syntax)
|
||||
call vue#LoadFullSyntax(group, syntax)
|
||||
else
|
||||
call vue#LoadDefaultSyntax(a:group, a:type)
|
||||
let loaded = vue#LoadDefaultSyntax(group, syntax)
|
||||
if !loaded
|
||||
call vue#LoadFullSyntax(group, syntax)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! vue#LoadDefaultSyntax(group, type)
|
||||
function! vue#LoadDefaultSyntax(group, syntax)
|
||||
unlet! b:current_syntax
|
||||
let syntaxPaths = ['$VIMRUNTIME', '$VIM/vimfiles', '$HOME/.vim']
|
||||
for path in syntaxPaths
|
||||
let file = expand(path).'/syntax/'.a:type.'.vim'
|
||||
let loaded = 0
|
||||
let syntax_paths = ['$VIMRUNTIME', '$VIM/vimfiles', '$HOME/.vim']
|
||||
for path in syntax_paths
|
||||
let file = expand(path).'/syntax/'.a:syntax.'.vim'
|
||||
if filereadable(file)
|
||||
let loaded = 1
|
||||
execute 'syntax include '.a:group.' '.file
|
||||
endif
|
||||
endfor
|
||||
if loaded
|
||||
call vue#Log(a:syntax.': load default')
|
||||
else
|
||||
call vue#Warn(a:syntax.': syntax not found in '.string(syntax_paths))
|
||||
call vue#Warn(a:syntax.': load full instead')
|
||||
endif
|
||||
return loaded
|
||||
endfunction
|
||||
|
||||
" Load all syntax files in 'runtimepath'
|
||||
" Useful if there is no default syntax file provided by vim
|
||||
function! vue#LoadFullSyntax(group, type)
|
||||
call s:SetCurrentSyntax(a:type)
|
||||
execute 'syntax include '.a:group.' syntax/'.a:type.'.vim'
|
||||
function! vue#LoadFullSyntax(group, syntax)
|
||||
call vue#Log(a:syntax.': load full')
|
||||
call s:SetCurrentSyntax(a:syntax)
|
||||
execute 'syntax include '.a:group.' syntax/'.a:syntax.'.vim'
|
||||
endfunction
|
||||
|
||||
" Settings to avoid syntax overload
|
||||
function! s:SetCurrentSyntax(type)
|
||||
if a:type == 'coffee'
|
||||
syntax cluster coffeeJS contains=@htmlJavaScript
|
||||
|
||||
" Avoid overload of `javascript.vim`
|
||||
" Avoid `syntax/javascript.vim` in kchmck/vim-coffee-script
|
||||
let b:current_syntax = 'vue'
|
||||
syntax cluster coffeeJS contains=@javascript,@htmlJavaScript
|
||||
else
|
||||
unlet! b:current_syntax
|
||||
endif
|
||||
endfunction
|
||||
"}}}
|
||||
|
||||
function! vue#GetSyntaxList(config_syntax)
|
||||
let syntax_list = []
|
||||
for syntax in values(a:config_syntax)
|
||||
let type = type(syntax)
|
||||
if type == v:t_string
|
||||
if !count(syntax_list, syntax)
|
||||
call add(syntax_list, syntax)
|
||||
endif
|
||||
elseif type == v:t_list
|
||||
for syn in syntax
|
||||
if !count(syntax_list, syn)
|
||||
call add(syntax_list, syn)
|
||||
endif
|
||||
endfor
|
||||
else
|
||||
echoerr '[vim-vue-plugin] syntax value type'
|
||||
\.' must be either string or list'
|
||||
endif
|
||||
endfor
|
||||
|
||||
call s:ModifySyntaxOrder(syntax_list)
|
||||
|
||||
return syntax_list
|
||||
endfunction
|
||||
|
||||
function! s:IncludeOrEqual(listOrString, item)
|
||||
let listOrString = a:listOrString
|
||||
let item = a:item
|
||||
let type = type(listOrString)
|
||||
return (type == v:t_list && count(listOrString, item))
|
||||
\ || (type == v:t_string && listOrString == item)
|
||||
endfunction
|
||||
|
||||
function! vue#IncludeOrEqual(listOrString, item)
|
||||
return s:IncludeOrEqual(a:listOrString, a:item)
|
||||
endfunction
|
||||
|
||||
function! s:ModifySyntaxOrder(syntax_list)
|
||||
let syntax_list = a:syntax_list
|
||||
|
||||
" Move basic syntax to the end of the list, so we can check
|
||||
" if they are already loaded by other syntax.
|
||||
" Order matters
|
||||
let load_last = ['html', 'javascript', 'css']
|
||||
for syntax in load_last
|
||||
let idx = index(syntax_list, syntax)
|
||||
if idx >= 0
|
||||
call remove(syntax_list, idx)
|
||||
call add(syntax_list, syntax)
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
call s:Main()
|
||||
|
||||
@@ -13,7 +13,7 @@ if exists("loaded_matchit")
|
||||
\ '<\@<=\([^/][^ \t>]*\)[^>]*\%(>\|$\):<\@<=/\1>'
|
||||
endif
|
||||
|
||||
" Indent correctly with template string for vim-javascript/builtin
|
||||
" Indent correctly with template string for vim-javascript/built-in
|
||||
" indentexpr
|
||||
let b:syng_str = '^\%(.*template\)\@!.*string\|special'
|
||||
let b:syng_strcom = '^\%(.*template\)\@!.*string\|comment\|regex\|special\|doc'
|
||||
|
||||
@@ -1,40 +1,22 @@
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Config {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
let s:use_foldexpr = vue#GetConfig("use_foldexpr", 0)
|
||||
"}}}
|
||||
let s:config = vue#GetConfig('config', {})
|
||||
let s:enable_foldexpr = s:config.foldexpr
|
||||
|
||||
if !s:use_foldexpr | finish | endif
|
||||
if !s:enable_foldexpr | finish | endif
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Settings {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
if line('$') < 1000
|
||||
setlocal foldmethod=expr
|
||||
endif
|
||||
setlocal foldexpr=GetVueFold(v:lnum)
|
||||
"}}}
|
||||
" Useful for debugging foldexpr
|
||||
" set debug=msg
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Variables {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
let s:empty_line = '\v^\s*$'
|
||||
let s:block_end = '\v^\s*}|]|\)'
|
||||
let s:vue_tag_start = '\v^\s*\<(script|style|template)'
|
||||
let s:vue_tag_end = '\v^\s*\<\/(script|style|template)'
|
||||
"}}}
|
||||
function! VueFoldMain(...)
|
||||
if line('$') < 1000
|
||||
let s:empty_line = '^\s*$'
|
||||
let s:vue_tag_start = '^<\w\+'
|
||||
let s:vue_tag_end = '^<\/\w\+'
|
||||
|
||||
setlocal foldexpr=GetVueFold(v:lnum)
|
||||
setlocal foldmethod=expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Functions {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" see :h fold-expr
|
||||
" value meaning
|
||||
" 0 the line is not in a fold
|
||||
@@ -50,54 +32,57 @@ let s:vue_tag_end = '\v^\s*\<\/(script|style|template)'
|
||||
" "<1", "<2", .. a fold with this level ends at this line
|
||||
function! GetVueFold(lnum)
|
||||
let this_line = getline(a:lnum)
|
||||
let next_line = getline(a:lnum + 1)
|
||||
if a:lnum > 1
|
||||
let prev_line = getline(a:lnum - 1)
|
||||
endif
|
||||
let value = s:FoldForSpecialLine(this_line)
|
||||
if value == -2
|
||||
" Fold by indent
|
||||
let this_indent = s:IndentLevel(a:lnum)
|
||||
|
||||
" Handle empty lines
|
||||
if this_line =~ s:empty_line
|
||||
return -1
|
||||
" For <script> block
|
||||
if GetVueTag(a:lnum) == 'script'
|
||||
let value = s:FoldForScript(a:lnum, this_line, this_indent)
|
||||
else
|
||||
let value = this_indent
|
||||
endif
|
||||
endif
|
||||
call vue#LogWithLnum('foldlevel '.value)
|
||||
return value
|
||||
endfunction
|
||||
|
||||
" Handle start/end tags
|
||||
if this_line =~ s:vue_tag_start
|
||||
return '>1'
|
||||
endif
|
||||
if this_line =~ s:vue_tag_end
|
||||
" If return '<1', fold will get incorrect with prev line
|
||||
return 1
|
||||
endif
|
||||
|
||||
" Fold by indent
|
||||
function! s:FoldForScript(lnum, this_line, this_indent)
|
||||
let value = -2
|
||||
if a:lnum > 1
|
||||
let prev_indent = s:IndentLevel(a:lnum - 1)
|
||||
else
|
||||
let prev_indent = 0
|
||||
endif
|
||||
let this_indent = s:IndentLevel(a:lnum)
|
||||
let next_indent = s:IndentLevel(s:NextNonBlankLine(a:lnum))
|
||||
|
||||
if GetVueTag(a:lnum) == 'script'
|
||||
" Handle closing '}'
|
||||
if this_line =~ '\v^\s*},?\s*$'
|
||||
return '<'.prev_indent
|
||||
endif
|
||||
let next_indent = s:IndentLevel(nextnonblank(a:lnum + 1))
|
||||
|
||||
if a:this_line =~ '^\s*[]})]\+,\?\s*$'
|
||||
" Closing ']})'
|
||||
let value = '<'.prev_indent
|
||||
elseif a:this_indent < next_indent
|
||||
" --this
|
||||
" ----next
|
||||
if this_indent < next_indent
|
||||
return '>'.next_indent
|
||||
endif
|
||||
|
||||
let value = '>'.next_indent
|
||||
else
|
||||
" ----this
|
||||
" --next
|
||||
if this_indent >= next_indent
|
||||
return this_indent
|
||||
endif
|
||||
let value = a:this_indent
|
||||
endif
|
||||
|
||||
return value
|
||||
endfunction
|
||||
|
||||
function! s:FoldForSpecialLine(this_line)
|
||||
if a:this_line =~ s:empty_line
|
||||
return '='
|
||||
elseif a:this_line =~ s:vue_tag_start
|
||||
return '>1'
|
||||
elseif a:this_line =~ s:vue_tag_end
|
||||
" If return '<1', fold will get incorrect with prev line
|
||||
return 1
|
||||
else
|
||||
" Template or style
|
||||
return this_indent
|
||||
return -2
|
||||
endif
|
||||
endfunction
|
||||
|
||||
@@ -105,20 +90,6 @@ function! s:IndentLevel(lnum)
|
||||
" Add 1 to indentLevel, so start/end tags can fold properly
|
||||
return indent(a:lnum) / &shiftwidth + 1
|
||||
endfunction
|
||||
|
||||
function! s:NextNonBlankLine(lnum)
|
||||
let next_line = a:lnum + 1
|
||||
let last_line = line('$')
|
||||
|
||||
while next_line <= last_line
|
||||
if getline(next_line) =~ '\v\S'
|
||||
return next_line
|
||||
endif
|
||||
|
||||
let next_line += 1
|
||||
endwhile
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
"}}}
|
||||
" vim: fdm=marker
|
||||
|
||||
call VueFoldMain()
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
if exists("b:did_indent")
|
||||
finish
|
||||
endif
|
||||
|
||||
let s:custom_blocks = vue#GetConfig("custom_blocks", {})
|
||||
let s:indent = {}
|
||||
|
||||
function! s:GetSyntaxList()
|
||||
let syntax_list = []
|
||||
for syntax in values(s:custom_blocks)
|
||||
let type = type(syntax)
|
||||
if type == v:t_string
|
||||
if !count(syntax_list, syntax)
|
||||
call add(syntax_list, syntax)
|
||||
endif
|
||||
elseif type == v:t_list && len(syntax)
|
||||
for syn in syntax
|
||||
if !count(syntax_list, syn)
|
||||
call add(syntax_list, syn)
|
||||
endif
|
||||
endfor
|
||||
else
|
||||
echoerr '[vim-vue-plugin] custom_blocks value type'
|
||||
\.' must be either string or list'
|
||||
endif
|
||||
endfor
|
||||
return syntax_list
|
||||
endfunction
|
||||
|
||||
function! s:GetIndentExpr(syntax_list)
|
||||
for syntax in a:syntax_list
|
||||
unlet! b:did_indent
|
||||
execute 'runtime indent/'.syntax.'.vim'
|
||||
let s:indent[syntax] = &l:indentexpr
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! GetVueCustomBlocksIndent(syn)
|
||||
let syntax = matchstr(a:syn, '^\l\+')
|
||||
call vue#Log('custom block syntax: '.syntax)
|
||||
let ind = eval(s:indent[syntax])
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
call s:GetIndentExpr(s:GetSyntaxList())
|
||||
533
indent/vue.vim
533
indent/vue.vim
@@ -1,293 +1,156 @@
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Vim indent file
|
||||
"
|
||||
" Language: Vue
|
||||
" Maintainer: leafOfTree <leafvocation@gmail.com>
|
||||
"
|
||||
" CREDITS: Inspired by mxw/vim-jsx.
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
if exists("b:did_indent")
|
||||
finish
|
||||
endif
|
||||
" Maintainer: leaf <https://github.com/leafOfTree>
|
||||
" Credits: Inspired by mxw/vim-jsx.
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Config {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
let s:use_pug = vue#GetConfig("use_pug", 0)
|
||||
let s:use_sass = vue#GetConfig("use_sass", 0)
|
||||
let s:use_scss = vue#GetConfig("use_scss", 0)
|
||||
let s:use_stylus = vue#GetConfig("use_stylus", 0)
|
||||
let s:use_coffee = vue#GetConfig("use_coffee", 0)
|
||||
let s:use_typescript = vue#GetConfig("use_typescript", 0)
|
||||
let s:has_init_indent = vue#GetConfig("has_init_indent",
|
||||
\ expand("%:e") == 'wpy' ? 1 : 0)
|
||||
let s:custom_blocks = vue#GetConfig("custom_blocks", {})
|
||||
let s:use_custom_blocks = !empty(s:custom_blocks)
|
||||
"}}}
|
||||
if exists('b:did_indent') | finish |endif
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Variables {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Let <template> handled by HTML
|
||||
let s:vue_tag_start = '\v^\s*\<(script|style)'
|
||||
let s:vue_tag_end = '\v^\s*\<\/(script|style)'
|
||||
let s:template_tag = '\v^\s*\<\/?template'
|
||||
let s:empty_tagname = '(area|base|br|col|embed|hr|input|img|keygen|link|meta|param|source|track|wbr)'
|
||||
let s:empty_tag = '\v\<'.s:empty_tagname.'[^/]*\>'
|
||||
let s:empty_tag_start = '\v\<'.s:empty_tagname.'[^\>]*$'
|
||||
let s:empty_tag_end = '\v^\s*[^\<\>\/]*\/?\>\s*'
|
||||
let s:tag_start = '\v^\s*\<\w*'
|
||||
let s:tag_end = '\v^\s*\/?\>\s*' " />
|
||||
let s:full_tag_end = '\v^\s*\<\/' " </...>
|
||||
let s:test = exists('g:vim_vue_plugin_test')
|
||||
|
||||
"}}}
|
||||
function! s:Init()
|
||||
""" Configs
|
||||
let s:config = vue#GetConfig('config', {})
|
||||
let s:config_syntax = s:config.syntax
|
||||
let s:initial_indent = s:config.initial_indent
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Load indent method {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Save shiftwidth
|
||||
let s:sw = &sw
|
||||
""" Variables
|
||||
let s:indent = {}
|
||||
let s:block_tag = '<\/\?\('.join(keys(s:config_syntax), '\|').'\)'
|
||||
|
||||
" Use lib/indent/ files for compatibility
|
||||
unlet! b:did_indent
|
||||
runtime lib/indent/xml.vim
|
||||
|
||||
unlet! b:did_indent
|
||||
runtime lib/indent/css.vim
|
||||
|
||||
" Use normal indent files
|
||||
unlet! b:did_indent
|
||||
runtime! indent/javascript.vim
|
||||
let b:javascript_indentexpr = &indentexpr
|
||||
|
||||
if s:use_custom_blocks
|
||||
unlet! b:did_indent
|
||||
runtime indent/vue-custom-blocks.vim
|
||||
let s:vue_custom_blocks_tag = '<\/\?'.join(keys(s:custom_blocks), '\|')
|
||||
endif
|
||||
|
||||
if s:use_pug
|
||||
unlet! b:did_indent
|
||||
let s:save_formatoptions = &formatoptions
|
||||
runtime! indent/pug.vim
|
||||
let &formatoptions = s:save_formatoptions
|
||||
endif
|
||||
|
||||
if s:use_sass
|
||||
unlet! b:did_indent
|
||||
runtime! indent/sass.vim
|
||||
endif
|
||||
|
||||
if s:use_scss
|
||||
unlet! b:did_indent
|
||||
runtime! indent/scss.vim
|
||||
endif
|
||||
|
||||
if s:use_stylus
|
||||
unlet! b:did_indent
|
||||
runtime! indent/stylus.vim
|
||||
endif
|
||||
|
||||
if s:use_coffee
|
||||
unlet! b:did_indent
|
||||
runtime! indent/coffee.vim
|
||||
endif
|
||||
|
||||
if s:use_typescript
|
||||
unlet! b:did_indent
|
||||
runtime! indent/typescript.vim
|
||||
endif
|
||||
|
||||
" Recover shiftwidth
|
||||
let &sw = s:sw
|
||||
"}}}
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Settings {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" JavaScript indentkeys
|
||||
setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e,:
|
||||
" XML indentkeys
|
||||
setlocal indentkeys+=*<Return>,<>>,<<>,/
|
||||
setlocal indentexpr=GetVueIndent()
|
||||
"}}}
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Functions {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
function! GetVueIndent()
|
||||
let ind = s:GetIndentBySyntax()
|
||||
let ind = s:AdjustIndent(ind)
|
||||
call vue#Log('indent: '.ind)
|
||||
return ind
|
||||
" To adjust HTML
|
||||
let s:empty_tagname = '(area|base|br|col|embed|hr|input|img|'
|
||||
\.'keygen|link|meta|param|source|track|wbr)'
|
||||
let s:empty_tag = '\v\<'.s:empty_tagname.'.*(/)@<!\>'
|
||||
let s:empty_tag_start = '\v\<'.s:empty_tagname.'[^>]*$'
|
||||
let s:empty_tag_end = '\v^\s*[^<>/]*\/?\>\s*'
|
||||
let s:tag_start = '\v^\s*\<\w*' " <
|
||||
let s:tag_end = '\v^\s*\/?\>\s*' " />
|
||||
let s:full_tag_end = '\v^\s*\<\/' " </...>
|
||||
let s:ternary_q = '^\s\+?'
|
||||
let s:ternary_e = '^\s\+:.*,\s*$'
|
||||
endfunction
|
||||
|
||||
function! s:GetIndentBySyntax()
|
||||
let prevlnum = prevnonblank(v:lnum - 1)
|
||||
let prevline = getline(prevlnum)
|
||||
let curline = getline(v:lnum)
|
||||
let cursyn = get(s:SynsEOL(v:lnum), 0, '')
|
||||
function! s:SetVueIndent()
|
||||
""" Settings
|
||||
" JavaScript indentkeys
|
||||
setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e,:
|
||||
" XML indentkeys
|
||||
setlocal indentkeys+=*<Return>,<>>,<<>,/
|
||||
setlocal indentexpr=GetVueIndent()
|
||||
endfunction
|
||||
|
||||
if s:SynHTML(cursyn)
|
||||
call vue#Log('syntax: html')
|
||||
let ind = s:GetHTMLIndent(prevlnum, prevline, curline)
|
||||
elseif s:SynPug(cursyn)
|
||||
call vue#Log('syntax: pug')
|
||||
let ind = GetPugIndent()
|
||||
elseif s:SynCoffee(cursyn)
|
||||
call vue#Log('syntax: coffee')
|
||||
let ind = GetCoffeeIndent(v:lnum)
|
||||
elseif s:SynTypeScript(cursyn)
|
||||
call vue#Log('syntax: typescript')
|
||||
let ind = GetTypescriptIndent()
|
||||
elseif s:SynSASS(cursyn)
|
||||
call vue#Log('syntax: sass')
|
||||
let ind = GetSassIndent()
|
||||
elseif s:SynSCSS(cursyn)
|
||||
call vue#Log('syntax: scss')
|
||||
if exists('*GetSCSSIndent')
|
||||
call vue#Log('indent: scss')
|
||||
let ind = GetSCSSIndent()
|
||||
else
|
||||
call vue#Log('indent: css')
|
||||
let ind = GetCSSIndent()
|
||||
endif
|
||||
elseif s:SynStylus(cursyn)
|
||||
call vue#Log('syntax: stylus')
|
||||
let ind = GetStylusIndent()
|
||||
elseif s:SynStyle(cursyn)
|
||||
call vue#Log('syntax: css')
|
||||
let ind = GetCSSIndent()
|
||||
elseif s:use_custom_blocks && s:SynCustomBlocks(cursyn)
|
||||
call vue#Log('syntax: custom blocks')
|
||||
let ind = GetVueCustomBlocksIndent(cursyn)
|
||||
function! s:GetIndentFile(syntax)
|
||||
let syntax = a:syntax
|
||||
" lib/indent/* files are perferred for better indent result
|
||||
" from previous version Vim
|
||||
if syntax == 'html'
|
||||
let file = 'lib/indent/xml.vim'
|
||||
elseif syntax == 'css'
|
||||
let file = 'lib/indent/css.vim'
|
||||
elseif syntax == 'javascript'
|
||||
let file = 'lib/indent/typescript.vim'
|
||||
else
|
||||
" Default to JavaScript indent
|
||||
call vue#Log('syntax: javascript')
|
||||
if len(b:javascript_indentexpr)
|
||||
let ind = eval(b:javascript_indentexpr)
|
||||
else
|
||||
let ind = cindent(v:lnum)
|
||||
endif
|
||||
let file = 'indent/'.syntax.'.vim'
|
||||
endif
|
||||
return file
|
||||
endfunction
|
||||
|
||||
function! s:SetSyntaxIndentExpr(syntax_list)
|
||||
let saved_shiftwidth = &shiftwidth
|
||||
let saved_formatoptions = &formatoptions
|
||||
|
||||
for syntax in a:syntax_list
|
||||
unlet! b:did_indent
|
||||
let &l:indentexpr = ''
|
||||
execute 'runtime '.s:GetIndentFile(syntax)
|
||||
let s:indent[syntax] = &l:indentexpr
|
||||
endfor
|
||||
|
||||
let &shiftwidth = saved_shiftwidth
|
||||
let &formatoptions = saved_formatoptions
|
||||
endfunction
|
||||
|
||||
function! s:GetBlockIndent(syntax)
|
||||
let syntax = a:syntax
|
||||
let indentexpr = get(s:indent, syntax)
|
||||
if !empty(indentexpr)
|
||||
let ind = eval(indentexpr)
|
||||
else
|
||||
call vue#LogWithLnum('indentexpr not found for '.syntax.', use cindent')
|
||||
let ind = cindent(v:lnum)
|
||||
endif
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! s:AdjustIndent(ind)
|
||||
let ind = a:ind
|
||||
let prevline = getline(prevnonblank(v:lnum - 1))
|
||||
function! s:GetIndentByContext(tag, syntax)
|
||||
let ind = -1
|
||||
let prevline = getline(s:PrevNonBlankNonComment(v:lnum))
|
||||
let curline = getline(v:lnum)
|
||||
let cursyn = get(s:SynsEOL(v:lnum), 0, '')
|
||||
|
||||
if curline =~? s:vue_tag_start
|
||||
\ || curline =~? s:vue_tag_end
|
||||
\ || prevline =~? s:vue_tag_end
|
||||
\ || (curline =~ s:template_tag && s:SynPug(cursyn))
|
||||
call vue#Log('current line is vue tag or previous line is vue end tag')
|
||||
call vue#Log(', or current line is pug template tag')
|
||||
let ind = 0
|
||||
elseif s:has_init_indent && ind < 1 && s:SynVueScriptOrStyle(cursyn)
|
||||
call vue#Log('add initial indent')
|
||||
let ind = &sw
|
||||
elseif getline(s:PrevNonBlacnkNonComment(v:lnum)) =~? s:vue_tag_start
|
||||
call vue#Log('previous line is vue tag start')
|
||||
let ind = 0
|
||||
elseif s:use_custom_blocks && curline =~ s:vue_custom_blocks_tag
|
||||
call vue#Log('current line is vue custom blocks tag')
|
||||
let ind = 0
|
||||
endif
|
||||
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! s:GetHTMLIndent(prevlnum, prevline, curline)
|
||||
let prevlnum = a:prevlnum
|
||||
let prevline = a:prevline
|
||||
let curline = a:curline
|
||||
|
||||
let ind = XmlIndentGet(v:lnum, 0)
|
||||
if prevline =~? s:empty_tag
|
||||
call vue#Log('previous line is an empty tag')
|
||||
let ind = ind - &sw
|
||||
endif
|
||||
|
||||
" Align '/>' and '>' with '<' for multiline tags.
|
||||
if curline =~? s:tag_end
|
||||
let ind = ind - &sw
|
||||
endif
|
||||
" Then correct the indentation of any element following '/>' or '>'.
|
||||
if prevline =~? s:tag_end
|
||||
let ind = ind + &sw
|
||||
|
||||
" Decrease indent if prevlines are a multiline empty tag
|
||||
let [start, end] = s:PrevMultilineEmptyTag(v:lnum)
|
||||
if end == prevlnum
|
||||
call vue#Log('previous line is a multiline empty tag')
|
||||
if curline =~? s:full_tag_end
|
||||
let ind = indent(v:lnum - 1) - &sw
|
||||
else
|
||||
let ind = indent(v:lnum - 1)
|
||||
if a:tag != 'template' && a:syntax == 'html'
|
||||
" Set indent to 0 for custom tag with 'html' syntax
|
||||
if curline =~ s:block_tag && empty(prevline)
|
||||
let ind = 0
|
||||
endif
|
||||
elseif a:tag == 'template'
|
||||
" When 'pug' syntax in <template>, set block tags indent to 0
|
||||
if a:syntax == 'pug'
|
||||
if curline =~ s:block_tag
|
||||
let ind = 0
|
||||
endif
|
||||
endif
|
||||
else
|
||||
" When not in <template> and not 'html'
|
||||
" Set indent to 0 if current or prev line is block tag
|
||||
if curline =~ s:block_tag || prevline =~ s:block_tag
|
||||
let ind = 0
|
||||
endif
|
||||
endif
|
||||
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! s:SynsEOL(lnum)
|
||||
let lnum = prevnonblank(a:lnum)
|
||||
let col = strlen(getline(lnum))
|
||||
return map(synstack(lnum, col), 'synIDattr(v:val, "name")')
|
||||
function! s:PrevNonBlankNonComment(lnum)
|
||||
let lnum = a:lnum - 1
|
||||
let prevlnum = prevnonblank(lnum)
|
||||
let prevsyn = vue#SyntaxSecondAtEnd(prevlnum)
|
||||
while prevsyn =~? 'comment' && lnum > 1
|
||||
let lnum = lnum - 1
|
||||
let prevlnum = prevnonblank(lnum)
|
||||
let prevsyn = vue#SyntaxSecondAtEnd(prevlnum)
|
||||
endwhile
|
||||
return prevlnum
|
||||
endfunction
|
||||
|
||||
function! s:SynHTML(syn)
|
||||
return a:syn ==? 'htmlVueTemplate'
|
||||
function! s:AdjustBlockIndent(syntax, ind)
|
||||
let block = a:block
|
||||
let syntax = a:syntax
|
||||
let ind = a:ind
|
||||
|
||||
if syntax == 'html'
|
||||
let ind = s:AdjustHTMLIndent(ind)
|
||||
elseif syntax == 'javascript'
|
||||
let ind = s:AdjustJavaScriptIndent(ind)
|
||||
elseif syntax == 'css'
|
||||
let ind = s:AdjustCSSIndent(ind)
|
||||
endif
|
||||
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! s:SynPug(syn)
|
||||
return a:syn ==? 'pugVueTemplate'
|
||||
endfunction
|
||||
function! s:CheckInitialIndent(tag, syntax, ind)
|
||||
let ind = a:ind
|
||||
let add = 0
|
||||
|
||||
function! s:SynCoffee(syn)
|
||||
return a:syn ==? 'coffeeVueScript'
|
||||
endfunction
|
||||
|
||||
function! s:SynTypeScript(syn)
|
||||
return a:syn ==? 'typescriptVueScript'
|
||||
endfunction
|
||||
|
||||
function! s:SynSASS(syn)
|
||||
return a:syn ==? 'sassVueStyle'
|
||||
endfunction
|
||||
|
||||
function! s:SynSCSS(syn)
|
||||
return a:syn ==? 'cssScssVueStyle'
|
||||
endfunction
|
||||
|
||||
function! s:SynStylus(syn)
|
||||
return a:syn ==? 'cssStylusVueStyle'
|
||||
endfunction
|
||||
|
||||
function! s:SynStyle(syn)
|
||||
return a:syn =~? 'VueStyle'
|
||||
endfunction
|
||||
|
||||
function! s:SynCustomBlocks(syn)
|
||||
return a:syn =~? 'Block'
|
||||
endfunction
|
||||
|
||||
function! s:SynVueScriptOrStyle(syn)
|
||||
return a:syn =~? '\v(VueStyle)|(VueScript)'
|
||||
if ind == 0 && getline(v:lnum) !~ s:block_tag
|
||||
let add = vue#IncludeOrEqual(s:initial_indent, a:tag.'.'.a:syntax)
|
||||
\ || vue#IncludeOrEqual(s:initial_indent, a:tag)
|
||||
\ || vue#IncludeOrEqual(s:initial_indent, a:syntax)
|
||||
endif
|
||||
if add
|
||||
call vue#LogWithLnum('add initial indent')
|
||||
let ind = &sw
|
||||
endif
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! s:PrevMultilineEmptyTag(lnum)
|
||||
@@ -312,27 +175,133 @@ function! s:PrevMultilineEmptyTag(lnum)
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! s:PrevNonBlacnkNonComment(lnum)
|
||||
let curline = getline(a:lnum)
|
||||
let cursyns = s:SynsEOL(a:lnum)
|
||||
let cursyn = get(cursyns, 1, '')
|
||||
if cursyn =~? 'comment' && !empty(curline)
|
||||
return prevnonblank(a:lnum - 1)
|
||||
function! s:AdjustHTMLIndent(ind)
|
||||
let ind = a:ind
|
||||
let prevlnum = prevnonblank(v:lnum - 1)
|
||||
let prevline = getline(prevlnum)
|
||||
let curline = getline(v:lnum)
|
||||
|
||||
if prevline =~? s:empty_tag
|
||||
call vue#LogWithLnum('previous line is an empty tag')
|
||||
let ind = ind - &sw
|
||||
endif
|
||||
|
||||
let lnum = a:lnum - 1
|
||||
let prevlnum = prevnonblank(lnum)
|
||||
let prevsyns = s:SynsEOL(prevlnum)
|
||||
let prevsyn = get(prevsyns, 1, '')
|
||||
while prevsyn =~? 'comment' && lnum > 1
|
||||
let lnum = lnum - 1
|
||||
let prevlnum = prevnonblank(lnum)
|
||||
let prevsyns = s:SynsEOL(prevlnum)
|
||||
let prevsyn = get(prevsyns, 1, '')
|
||||
endwhile
|
||||
return prevlnum
|
||||
" Align '/>' and '>' with '<'
|
||||
if curline =~? s:tag_end
|
||||
let ind = ind - &sw
|
||||
endif
|
||||
" Then correct the indentation of any element following '/>' or '>'.
|
||||
if prevline =~? s:tag_end
|
||||
let ind = ind + &sw
|
||||
|
||||
" Decrease indent if prevlines are a multiline empty tag
|
||||
let [start, end] = s:PrevMultilineEmptyTag(v:lnum)
|
||||
if prevlnum == end
|
||||
call vue#LogWithLnum('previous line is a multiline empty tag')
|
||||
let ind = indent(v:lnum - 1)
|
||||
if curline =~? s:full_tag_end
|
||||
let ind = ind - &sw
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
" Multiline array/object in attribute like v-*="[
|
||||
" ...
|
||||
" ]
|
||||
if prevline =~ '[[{]\s*$'
|
||||
call vue#LogWithLnum('previous line is an open bracket')
|
||||
let ind = indent(prevlnum) + &sw
|
||||
endif
|
||||
if curline =~ '^\s*[]}][^"]*"\?\s*$'
|
||||
call vue#LogWithLnum('current line is a closing bracket')
|
||||
let ind = indent(prevlnum) - &sw
|
||||
endif
|
||||
|
||||
" Multiline ternary 'a ? b : c' in attribute
|
||||
if curline =~ s:ternary_q
|
||||
call vue#LogWithLnum('current line is ?...')
|
||||
let ind = indent(prevlnum) + &sw
|
||||
endif
|
||||
if curline =~ s:ternary_e && prevline =~ s:ternary_q
|
||||
call vue#LogWithLnum('current line is :...')
|
||||
let ind = indent(prevlnum)
|
||||
endif
|
||||
if prevline =~ s:ternary_e
|
||||
call vue#LogWithLnum('prevline line is :...')
|
||||
let ind = indent(prevlnum) - &sw
|
||||
endif
|
||||
|
||||
" Angle bracket in attribute, like v-if="isEnabled('item.<name>')"
|
||||
if prevline =~ '="[^"]*<[^"]*>[^"]*"'
|
||||
call vue#LogWithLnum('prevline line is angle bracket in attribute')
|
||||
let ind = ind - &sw
|
||||
endif
|
||||
|
||||
return ind
|
||||
endfunction
|
||||
"}}}
|
||||
|
||||
function! s:AdjustJavaScriptIndent(ind)
|
||||
let ind = a:ind
|
||||
let prevlnum = prevnonblank(v:lnum - 1)
|
||||
let prevline = getline(prevlnum)
|
||||
let curline = getline(v:lnum)
|
||||
|
||||
if prevline =~ '^\s*\w.*$' && curline =~ '^\s*\.'
|
||||
call vue#LogWithLnum('current line is the first chain call')
|
||||
let ind = indent(prevlnum) + &sw
|
||||
endif
|
||||
|
||||
if prevline =~ '\s=>\s.*,\s*$' && curline !~ '^\s*[]}])\?,\?\s*$'
|
||||
call vue#LogWithLnum('previous line is arrow function property')
|
||||
let ind = indent(prevlnum)
|
||||
endif
|
||||
if prevline =~ '\s||\s*$'
|
||||
call vue#LogWithLnum('previous line ends with "||"')
|
||||
let ind = indent(prevlnum) + &sw
|
||||
endif
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! s:AdjustCSSIndent(ind)
|
||||
let ind = a:ind
|
||||
let prevlnum = prevnonblank(v:lnum - 1)
|
||||
let prevline = getline(prevlnum)
|
||||
let curline = getline(v:lnum)
|
||||
|
||||
if prevline =~ ':\s.*,\s*$'
|
||||
call vue#LogWithLnum('previous line is css function')
|
||||
let ind = indent(prevlnum) + &sw
|
||||
endif
|
||||
if curline =~ '^\s*);\?\s*$'
|
||||
call vue#LogWithLnum('curline is closing round bracket')
|
||||
let ind = indent(prevlnum) - &sw
|
||||
endif
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! GetVueIndent()
|
||||
let tag = vue#GetBlockTag(v:lnum)
|
||||
let syntax = vue#GetBlockSyntax(v:lnum)
|
||||
let ind = s:GetIndentByContext(tag, syntax)
|
||||
if ind == -1
|
||||
let ind = s:GetBlockIndent(syntax)
|
||||
let ind = s:AdjustBlockIndent(syntax, ind)
|
||||
call vue#LogWithLnum('syntax '.syntax.', ind '.ind)
|
||||
else
|
||||
call vue#LogWithLnum('context, ind '.ind)
|
||||
endif
|
||||
|
||||
let ind = s:CheckInitialIndent(tag, syntax, ind)
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! VimVuePluginIndentMain(...)
|
||||
call s:Init()
|
||||
let syntax_list = vue#GetSyntaxList(s:config_syntax)
|
||||
call s:SetSyntaxIndentExpr(syntax_list)
|
||||
call s:SetVueIndent()
|
||||
endfunction
|
||||
|
||||
call VimVuePluginIndentMain()
|
||||
|
||||
let b:did_indent = 1
|
||||
" vim: fdm=marker
|
||||
|
||||
518
lib/indent/typescript.vim
Normal file
518
lib/indent/typescript.vim
Normal file
@@ -0,0 +1,518 @@
|
||||
" Vim indent file
|
||||
" Language: TypeScript
|
||||
" Maintainer: See https://github.com/HerringtonDarkholme/yats.vim
|
||||
" Last Change: 2019 Oct 18
|
||||
" Acknowledgement: Based off of vim-ruby maintained by Nikolai Weibull http://vim-ruby.rubyforge.org
|
||||
|
||||
" 0. Initialization {{{1
|
||||
" =================
|
||||
|
||||
" Only load this indent file when no other was loaded.
|
||||
if exists("b:did_indent")
|
||||
finish
|
||||
endif
|
||||
let b:did_indent = 1
|
||||
|
||||
setlocal nosmartindent
|
||||
|
||||
" Now, set up our indentation expression and keys that trigger it.
|
||||
setlocal indentexpr=GetTypescriptIndent()
|
||||
setlocal formatexpr=Fixedgq(v:lnum,v:count)
|
||||
setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e
|
||||
|
||||
" Only define the function once.
|
||||
if exists("*GetTypescriptIndent")
|
||||
finish
|
||||
endif
|
||||
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
" 1. Variables {{{1
|
||||
" ============
|
||||
|
||||
let s:js_keywords = '^\s*\(break\|case\|catch\|continue\|debugger\|default\|delete\|do\|else\|finally\|for\|function\|if\|in\|instanceof\|new\|return\|switch\|this\|throw\|try\|typeof\|var\|void\|while\|with\)'
|
||||
|
||||
" Regex of syntax group names that are or delimit string or are comments.
|
||||
let s:syng_strcom = 'string\|regex\|comment\c'
|
||||
|
||||
" Regex of syntax group names that are strings.
|
||||
let s:syng_string = 'regex\c'
|
||||
|
||||
" Regex of syntax group names that are strings or documentation.
|
||||
let s:syng_multiline = 'comment\c'
|
||||
|
||||
" Regex of syntax group names that are line comment.
|
||||
let s:syng_linecom = 'linecomment\c'
|
||||
|
||||
" Expression used to check whether we should skip a match with searchpair().
|
||||
let s:skip_expr = "synIDattr(synID(line('.'),col('.'),1),'name') =~ '".s:syng_strcom."'"
|
||||
|
||||
let s:line_term = '\s*\%(\%(\/\/\).*\)\=$'
|
||||
|
||||
" Regex that defines continuation lines, not including (, {, or [.
|
||||
let s:continuation_regex = '\%([\\*+/.:]\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\|[^=]=[^=].*,\)' . s:line_term
|
||||
|
||||
" Regex that defines continuation lines.
|
||||
" TODO: this needs to deal with if ...: and so on
|
||||
let s:msl_regex = s:continuation_regex
|
||||
let s:msl_exclude_regex = '++'
|
||||
|
||||
let s:one_line_scope_regex = '\<\%(if\|else\|for\|while\)\>[^{;]*' . s:line_term
|
||||
let s:one_line_scope_exclue_regex = '\<return\>'
|
||||
let s:closing_bracket = '[]}],\?\s*$'
|
||||
|
||||
" Regex that defines blocks.
|
||||
let s:block_regex = '\%([{[]\)\s*\%(|\%([*@]\=\h\w*,\=\s*\)\%(,\s*[*@]\=\h\w*\)*|\)\=' . s:line_term
|
||||
|
||||
let s:var_stmt = '^\s*var'
|
||||
|
||||
let s:comma_first = '^\s*,'
|
||||
let s:comma_last = ',\s*$'
|
||||
|
||||
let s:ternary = '^\s\+[?|:]'
|
||||
let s:ternary_q = '^\s\+?'
|
||||
let s:ternary_e = '^\s\+:'
|
||||
|
||||
" 2. Auxiliary Functions {{{1
|
||||
" ======================
|
||||
|
||||
" Check if the character at lnum:col is inside a string, comment, or is ascii.
|
||||
function s:IsInStringOrComment(lnum, col)
|
||||
return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_strcom
|
||||
endfunction
|
||||
|
||||
" Check if the character at lnum:col is inside a string.
|
||||
function s:IsInString(lnum, col)
|
||||
return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_string
|
||||
endfunction
|
||||
|
||||
" Check if the character at lnum:col is inside a multi-line comment.
|
||||
function s:IsInMultilineComment(lnum, col)
|
||||
return !s:IsLineComment(a:lnum, a:col) && synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_multiline
|
||||
endfunction
|
||||
|
||||
" Check if the character at lnum:col is a line comment.
|
||||
function s:IsLineComment(lnum, col)
|
||||
return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_linecom
|
||||
endfunction
|
||||
|
||||
" Find line above 'lnum' that isn't empty, in a comment, or in a string.
|
||||
function s:PrevNonBlankNonString(lnum)
|
||||
let in_block = 0
|
||||
let lnum = prevnonblank(a:lnum)
|
||||
while lnum > 0
|
||||
" Go in and out of blocks comments as necessary.
|
||||
" If the line isn't empty (with opt. comment) or in a string, end search.
|
||||
let line = getline(lnum)
|
||||
if line =~ '/\*'
|
||||
if in_block
|
||||
let in_block = 0
|
||||
else
|
||||
break
|
||||
endif
|
||||
elseif !in_block && line =~ '\*/'
|
||||
let in_block = 1
|
||||
elseif !in_block && line !~ '^\s*\%(//\).*$' && !(s:IsInStringOrComment(lnum, 1) && s:IsInStringOrComment(lnum, strlen(line)))
|
||||
break
|
||||
endif
|
||||
let lnum = prevnonblank(lnum - 1)
|
||||
endwhile
|
||||
return lnum
|
||||
endfunction
|
||||
|
||||
" Find line above 'lnum' that started the continuation 'lnum' may be part of.
|
||||
function s:GetMSL(lnum, in_one_line_scope)
|
||||
" Start on the line we're at and use its indent.
|
||||
let msl = a:lnum
|
||||
if s:Match(msl, s:closing_bracket)
|
||||
return msl
|
||||
endif
|
||||
|
||||
let lnum = s:PrevNonBlankNonString(a:lnum - 1)
|
||||
while lnum > 0
|
||||
" If we have a continuation line, or we're in a string, use line as MSL.
|
||||
" Otherwise, terminate search as we have found our MSL already.
|
||||
let line = getline(lnum)
|
||||
let col = match(line, s:msl_exclude_regex) == -1
|
||||
\ && match(line, s:msl_regex) + 1
|
||||
if (col > 0 && !s:IsInStringOrComment(lnum, col)) || s:IsInString(lnum, strlen(line))
|
||||
let msl = lnum
|
||||
else
|
||||
" Don't use lines that are part of a one line scope as msl unless the
|
||||
" flag in_one_line_scope is set to 1
|
||||
"
|
||||
if a:in_one_line_scope
|
||||
break
|
||||
end
|
||||
let msl_one_line = s:Match(lnum, s:one_line_scope_regex)
|
||||
\ && !s:Match(lnum, s:one_line_scope_exclude_regex)
|
||||
if msl_one_line == 0
|
||||
break
|
||||
endif
|
||||
endif
|
||||
let lnum = s:PrevNonBlankNonString(lnum - 1)
|
||||
endwhile
|
||||
return msl
|
||||
endfunction
|
||||
|
||||
function s:RemoveTrailingComments(content)
|
||||
let single = '\/\/\(.*\)\s*$'
|
||||
let multi = '\/\*\(.*\)\*\/\s*$'
|
||||
return substitute(substitute(a:content, single, '', ''), multi, '', '')
|
||||
endfunction
|
||||
|
||||
" Find if the string is inside var statement (but not the first string)
|
||||
function s:InMultiVarStatement(lnum)
|
||||
let lnum = s:PrevNonBlankNonString(a:lnum - 1)
|
||||
|
||||
" let type = synIDattr(synID(lnum, indent(lnum) + 1, 0), 'name')
|
||||
|
||||
" loop through previous expressions to find a var statement
|
||||
while lnum > 0
|
||||
let line = getline(lnum)
|
||||
|
||||
" if the line is a js keyword
|
||||
if (line =~ s:js_keywords)
|
||||
" check if the line is a var stmt
|
||||
" if the line has a comma first or comma last then we can assume that we
|
||||
" are in a multiple var statement
|
||||
if (line =~ s:var_stmt)
|
||||
return lnum
|
||||
endif
|
||||
|
||||
" other js keywords, not a var
|
||||
return 0
|
||||
endif
|
||||
|
||||
let lnum = s:PrevNonBlankNonString(lnum - 1)
|
||||
endwhile
|
||||
|
||||
" beginning of program, not a var
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" Find line above with beginning of the var statement or returns 0 if it's not
|
||||
" this statement
|
||||
function s:GetVarIndent(lnum)
|
||||
let lvar = s:InMultiVarStatement(a:lnum)
|
||||
let prev_lnum = s:PrevNonBlankNonString(a:lnum - 1)
|
||||
|
||||
if lvar
|
||||
let line = s:RemoveTrailingComments(getline(prev_lnum))
|
||||
|
||||
" if the previous line doesn't end in a comma, return to regular indent
|
||||
if (line !~ s:comma_last)
|
||||
return indent(prev_lnum) - shiftwidth()
|
||||
else
|
||||
return indent(lvar) + shiftwidth()
|
||||
endif
|
||||
endif
|
||||
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
|
||||
" Check if line 'lnum' has more opening brackets than closing ones.
|
||||
function s:LineHasOpeningBrackets(lnum)
|
||||
let open_0 = 0
|
||||
let open_2 = 0
|
||||
let open_4 = 0
|
||||
let line = getline(a:lnum)
|
||||
let pos = match(line, '[][(){}]', 0)
|
||||
while pos != -1
|
||||
if !s:IsInStringOrComment(a:lnum, pos + 1)
|
||||
let idx = stridx('(){}[]', line[pos])
|
||||
if idx % 2 == 0
|
||||
let open_{idx} = open_{idx} + 1
|
||||
else
|
||||
let open_{idx - 1} = open_{idx - 1} - 1
|
||||
endif
|
||||
endif
|
||||
let pos = match(line, '[][(){}]', pos + 1)
|
||||
endwhile
|
||||
return (open_0 > 0) . (open_2 > 0) . (open_4 > 0)
|
||||
endfunction
|
||||
|
||||
function s:Match(lnum, regex)
|
||||
let col = match(getline(a:lnum), a:regex) + 1
|
||||
return col > 0 && !s:IsInStringOrComment(a:lnum, col) ? col : 0
|
||||
endfunction
|
||||
|
||||
function s:IndentWithContinuation(lnum, ind, width)
|
||||
" Set up variables to use and search for MSL to the previous line.
|
||||
let p_lnum = a:lnum
|
||||
let lnum = s:GetMSL(a:lnum, 1)
|
||||
let line = getline(lnum)
|
||||
|
||||
" If the previous line wasn't a MSL and is continuation return its indent.
|
||||
" TODO: the || s:IsInString() thing worries me a bit.
|
||||
if p_lnum != lnum
|
||||
if s:Match(p_lnum,s:continuation_regex)||s:IsInString(p_lnum,strlen(line))
|
||||
return a:ind
|
||||
endif
|
||||
endif
|
||||
|
||||
" Set up more variables now that we know we aren't continuation bound.
|
||||
let msl_ind = indent(lnum)
|
||||
|
||||
" If the previous line ended with [*+/.-=], start a continuation that
|
||||
" indents an extra level.
|
||||
if s:Match(lnum, s:continuation_regex)
|
||||
if lnum == p_lnum
|
||||
return msl_ind + a:width
|
||||
else
|
||||
return msl_ind
|
||||
endif
|
||||
endif
|
||||
|
||||
return a:ind
|
||||
endfunction
|
||||
|
||||
function s:InOneLineScope(lnum)
|
||||
let msl = s:GetMSL(a:lnum, 1)
|
||||
if msl > 0 && s:Match(msl, s:one_line_scope_regex)
|
||||
\ && !s:Match(msl, s:one_line_scope_exclude_regex)
|
||||
return msl
|
||||
endif
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function s:ExitingOneLineScope(lnum)
|
||||
let msl = s:GetMSL(a:lnum, 1)
|
||||
if msl > 0
|
||||
" if the current line is in a one line scope ..
|
||||
if s:Match(msl, s:one_line_scope_regex)
|
||||
\ && !s:Match(msl, s:one_line_scope_exclude_regex)
|
||||
return 0
|
||||
else
|
||||
let prev_msl = s:GetMSL(msl - 1, 1)
|
||||
if s:Match(prev_msl, s:one_line_scope_regex)
|
||||
\ && !s:Match(prev_msl, s:one_line_scope_exclude_regex)
|
||||
return prev_msl
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" 3. GetTypescriptIndent Function {{{1
|
||||
" =========================
|
||||
|
||||
function GetTypescriptIndent()
|
||||
" 3.1. Setup {{{2
|
||||
" ----------
|
||||
|
||||
" Set up variables for restoring position in file. Could use v:lnum here.
|
||||
let vcol = col('.')
|
||||
|
||||
" 3.2. Work on the current line {{{2
|
||||
" -----------------------------
|
||||
|
||||
let ind = -1
|
||||
" Get the current line.
|
||||
let line = getline(v:lnum)
|
||||
" previous nonblank line number
|
||||
let prevline = prevnonblank(v:lnum - 1)
|
||||
|
||||
" If we got a closing bracket on an empty line, find its match and indent
|
||||
" according to it. For parentheses we indent to its column - 1, for the
|
||||
" others we indent to the containing line's MSL's level. Return -1 if fail.
|
||||
let col = matchend(line, '^\s*[],})]')
|
||||
if col > 0 && !s:IsInStringOrComment(v:lnum, col)
|
||||
call cursor(v:lnum, col)
|
||||
|
||||
let lvar = s:InMultiVarStatement(v:lnum)
|
||||
if lvar
|
||||
let prevline_contents = s:RemoveTrailingComments(getline(prevline))
|
||||
|
||||
" check for comma first
|
||||
if (line[col - 1] =~ ',')
|
||||
" if the previous line ends in comma or semicolon don't indent
|
||||
if (prevline_contents =~ '[;,]\s*$')
|
||||
return indent(s:GetMSL(line('.'), 0))
|
||||
" get previous line indent, if it's comma first return prevline indent
|
||||
elseif (prevline_contents =~ s:comma_first)
|
||||
return indent(prevline)
|
||||
" otherwise we indent 1 level
|
||||
else
|
||||
return indent(lvar) + shiftwidth()
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2)
|
||||
if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0
|
||||
if line[col-1]==')' && col('.') != col('$') - 1
|
||||
let ind = virtcol('.')-1
|
||||
else
|
||||
let ind = indent(s:GetMSL(line('.'), 0))
|
||||
endif
|
||||
endif
|
||||
return ind
|
||||
endif
|
||||
|
||||
" If the line is comma first, dedent 1 level
|
||||
if (getline(prevline) =~ s:comma_first)
|
||||
return indent(prevline) - shiftwidth()
|
||||
endif
|
||||
|
||||
if (line =~ s:ternary)
|
||||
if (getline(prevline) =~ s:ternary_q)
|
||||
return indent(prevline)
|
||||
else
|
||||
return indent(prevline) + shiftwidth()
|
||||
endif
|
||||
elseif (getline(prevline) =~ s:ternary_e)
|
||||
return indent(prevline) - shiftwidth()
|
||||
endif
|
||||
|
||||
" If we are in a multi-line comment, cindent does the right thing.
|
||||
if s:IsInMultilineComment(v:lnum, 1) && !s:IsLineComment(v:lnum, 1)
|
||||
return cindent(v:lnum)
|
||||
endif
|
||||
|
||||
" Check for multiple var assignments
|
||||
" let var_indent = s:GetVarIndent(v:lnum)
|
||||
" if var_indent >= 0
|
||||
" return var_indent
|
||||
" endif
|
||||
|
||||
" 3.3. Work on the previous line. {{{2
|
||||
" -------------------------------
|
||||
|
||||
" If the line is empty and the previous nonblank line was a multi-line
|
||||
" comment, use that comment's indent. Deduct one char to account for the
|
||||
" space in ' */'.
|
||||
if line =~ '^\s*$' && s:IsInMultilineComment(prevline, 1)
|
||||
return indent(prevline) - 1
|
||||
endif
|
||||
|
||||
" Find a non-blank, non-multi-line string line above the current line.
|
||||
let lnum = s:PrevNonBlankNonString(v:lnum - 1)
|
||||
|
||||
" If the line is empty and inside a string, use the previous line.
|
||||
if line =~ '^\s*$' && lnum != prevline
|
||||
return indent(prevnonblank(v:lnum))
|
||||
endif
|
||||
|
||||
" At the start of the file use zero indent.
|
||||
if lnum == 0
|
||||
return 0
|
||||
endif
|
||||
|
||||
" Set up variables for current line.
|
||||
let line = getline(lnum)
|
||||
let ind = indent(lnum)
|
||||
|
||||
" If the previous line ended with a block opening, add a level of indent.
|
||||
if s:Match(lnum, s:block_regex)
|
||||
return indent(s:GetMSL(lnum, 0)) + shiftwidth()
|
||||
endif
|
||||
|
||||
" If the previous line contained an opening bracket, and we are still in it,
|
||||
" add indent depending on the bracket type.
|
||||
if line =~ '[[({]'
|
||||
let counts = s:LineHasOpeningBrackets(lnum)
|
||||
if counts[0] == '1' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0
|
||||
if col('.') + 1 == col('$')
|
||||
return ind + shiftwidth()
|
||||
else
|
||||
return virtcol('.')
|
||||
endif
|
||||
elseif counts[1] == '1' || counts[2] == '1'
|
||||
return ind + shiftwidth()
|
||||
else
|
||||
call cursor(v:lnum, vcol)
|
||||
end
|
||||
endif
|
||||
|
||||
" 3.4. Work on the MSL line. {{{2
|
||||
" --------------------------
|
||||
|
||||
let ind_con = ind
|
||||
let ind = s:IndentWithContinuation(lnum, ind_con, shiftwidth())
|
||||
|
||||
" }}}2
|
||||
"
|
||||
"
|
||||
let ols = s:InOneLineScope(lnum)
|
||||
if ols > 0
|
||||
let ind = ind + shiftwidth()
|
||||
else
|
||||
let ols = s:ExitingOneLineScope(lnum)
|
||||
while ols > 0 && ind > 0
|
||||
let ind = ind - shiftwidth()
|
||||
let ols = s:InOneLineScope(ols - 1)
|
||||
endwhile
|
||||
endif
|
||||
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
function! Fixedgq(lnum, count)
|
||||
let l:tw = &tw ? &tw : 80
|
||||
|
||||
let l:count = a:count
|
||||
let l:first_char = indent(a:lnum) + 1
|
||||
|
||||
if mode() == 'i' " gq was not pressed, but tw was set
|
||||
return 1
|
||||
endif
|
||||
|
||||
" This gq is only meant to do code with strings, not comments
|
||||
if s:IsLineComment(a:lnum, l:first_char) || s:IsInMultilineComment(a:lnum, l:first_char)
|
||||
return 1
|
||||
endif
|
||||
|
||||
if len(getline(a:lnum)) < l:tw && l:count == 1 " No need for gq
|
||||
return 1
|
||||
endif
|
||||
|
||||
" Put all the lines on one line and do normal spliting after that
|
||||
if l:count > 1
|
||||
while l:count > 1
|
||||
let l:count -= 1
|
||||
normal J
|
||||
endwhile
|
||||
endif
|
||||
|
||||
let l:winview = winsaveview()
|
||||
|
||||
call cursor(a:lnum, l:tw + 1)
|
||||
let orig_breakpoint = searchpairpos(' ', '', '\.', 'bcW', '', a:lnum)
|
||||
call cursor(a:lnum, l:tw + 1)
|
||||
let breakpoint = searchpairpos(' ', '', '\.', 'bcW', s:skip_expr, a:lnum)
|
||||
|
||||
" No need for special treatment, normal gq handles edgecases better
|
||||
if breakpoint[1] == orig_breakpoint[1]
|
||||
call winrestview(l:winview)
|
||||
return 1
|
||||
endif
|
||||
|
||||
" Try breaking after string
|
||||
if breakpoint[1] <= indent(a:lnum)
|
||||
call cursor(a:lnum, l:tw + 1)
|
||||
let breakpoint = searchpairpos('\.', '', ' ', 'cW', s:skip_expr, a:lnum)
|
||||
endif
|
||||
|
||||
|
||||
if breakpoint[1] != 0
|
||||
call feedkeys("r\<CR>")
|
||||
else
|
||||
let l:count = l:count - 1
|
||||
endif
|
||||
|
||||
" run gq on new lines
|
||||
if l:count == 1
|
||||
call feedkeys("gqq")
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
@@ -16,7 +16,7 @@ let s:keepcpo= &cpo
|
||||
set cpo&vim
|
||||
|
||||
" [-- local settings (must come before aborting the script) --]
|
||||
setlocal indentexpr=XmlIndentGet(v:lnum,1)
|
||||
setlocal indentexpr=XmlIndentGet(v:lnum,0)
|
||||
setlocal indentkeys=o,O,*<Return>,<>>,<<>,/,{,}
|
||||
|
||||
if !exists('b:xml_indent_open')
|
||||
|
||||
3
syntax/patch/coffee.vim
Normal file
3
syntax/patch/coffee.vim
Normal file
@@ -0,0 +1,3 @@
|
||||
silent! syntax clear coffeeConstant
|
||||
syn match coffeeConstant '\v<\u\C[A-Z0-9_]+>' display
|
||||
\ containedin=@coffeeIdentifier
|
||||
14
syntax/patch/css.vim
Normal file
14
syntax/patch/css.vim
Normal file
@@ -0,0 +1,14 @@
|
||||
" Use a different name in order to avoid css syntax interference
|
||||
silent! syntax clear cssUnitDecorators
|
||||
syntax match cssUnitDecorators2
|
||||
\ /\(#\|-\|+\|%\|mm\|cm\|in\|pt\|pc\|em\|ex\|px\|ch\|rem\|vh\|vw\|vmin\|vmax\|dpi\|dppx\|dpcm\|Hz\|kHz\|s\|ms\|deg\|grad\|rad\)\ze\(;\|$\)/
|
||||
\ contained
|
||||
\ containedin=cssAttrRegion,sassCssAttribute,lessCssAttribute,stylusCssAttribute
|
||||
|
||||
silent! syntax clear cssKeyFrameProp
|
||||
syn match cssKeyFrameProp2 /\d*%\|from\|to/
|
||||
\ contained nextgroup=cssDefinition
|
||||
\ containedin=cssAttrRegion,sassCssAttribute,lessCssAttribute,stylusCssAttribute
|
||||
|
||||
highlight default link cssUnitDecorators2 Number
|
||||
highlight default link cssKeyFrameProp2 Constant
|
||||
@@ -3,7 +3,8 @@
|
||||
" Config {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
let s:highlight_vue_attr = vue#GetConfig("highlight_vue_attr", 0)
|
||||
let s:config = vue#GetConfig('config', {})
|
||||
let s:attribute = s:config.attribute
|
||||
"}}}
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
@@ -11,6 +12,15 @@ let s:highlight_vue_attr = vue#GetConfig("highlight_vue_attr", 0)
|
||||
" Syntax highlight {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Clear htmlHead that may cause highlighting out of bounds
|
||||
silent! syntax clear htmlHead
|
||||
|
||||
" html5 data-*
|
||||
syntax match htmlArg '\v<data(-[.a-z0-9]+)+>' containedin=@html
|
||||
|
||||
" Vue ref attribute
|
||||
syntax match htmlArg 'ref' containedin=@html
|
||||
|
||||
" Use syn-match in order to highlight both transition and transition-group
|
||||
" according to syn-priority
|
||||
syntax match VueComponentName containedin=htmlTagN '\v(component|slot|transition)'
|
||||
@@ -35,8 +45,11 @@ syntax region VueExpression
|
||||
\ transparent
|
||||
\ start="{{"
|
||||
\ end="}}"
|
||||
|
||||
" Just to avoid error when using pattern in containedin
|
||||
syntax match htmlTemplateBlock /htmlTemplateBlock/
|
||||
syntax region VueExpression
|
||||
\ containedin=htmlVueTemplate,pugVueTemplate,VueValue,htmlString,htmlValue
|
||||
\ containedin=VueValue,htmlString,htmlValue,.*TemplateBlock,html.*Block
|
||||
\ contains=@simpleJavascriptExpression
|
||||
\ matchgroup=VueBrace
|
||||
\ start="{{"
|
||||
@@ -46,27 +59,33 @@ syntax region VueExpression
|
||||
syntax match htmlArg contained "\<\(enter-from-class\|enter-active-class\|enter-to-class\|leave-from-class\|leave-active-class\|leave-to-class\)\>"
|
||||
|
||||
" Wepy directive syntax
|
||||
syntax match VueAttr '\v(\S)@<!wx[^\=]+(\=\"[^"]*\")?'
|
||||
syntax match VueAttr '\v(\S)@<!wx[^\=>[:blank:]]+(\=\"[^"]*\")?'
|
||||
\ containedin=htmlTag
|
||||
\ contains=VueKey,VueQuote
|
||||
|
||||
syntax match VueKey contained '\vwx[^\=]+'
|
||||
syntax match VueCustomTag containedin=htmlTagN '\v<(view|text|block|image)>'
|
||||
" Mini program syntax
|
||||
syntax match VueKey contained '\vwx[^\=>[:blank:]]+'
|
||||
syntax match VueCustomTag containedin=htmlTagN '\v<(view|text|block|image|checkbox|radio)>'
|
||||
|
||||
syntax cluster simpleJavascriptExpression contains=javaScriptStringS,javaScriptStringD,javascriptNumber,javaScriptOperator
|
||||
syntax cluster simpleJavascriptExpression contains=\CjavaScript.*
|
||||
|
||||
" JavaScript syntax
|
||||
syntax region javaScriptStringS
|
||||
\ start=+'+ skip=+\\\\\|\\'+ end=+'\|$+ contained
|
||||
syntax region javaScriptStringD
|
||||
\ start=+"+ skip=+\\\\\|\\"+ end=+"\|$+ contained
|
||||
syntax match javaScriptNumber '\v<-?\d+L?>|0[xX][0-9a-fA-F]+>' contained
|
||||
syntax match javaScriptOperator '[-!|&+<>=%*~^]' contained
|
||||
syntax match javaScriptOperator '\v(*)@<!/(/|*)@!' contained
|
||||
syntax keyword javaScriptOperator delete instanceof typeof void new in of contained
|
||||
syntax region javaScriptTemplateString
|
||||
\ start=+`+ skip=+\\`+ end=+`|$+ contained
|
||||
\ contains=javaScriptTemplateExpression
|
||||
syntax region javaScriptTemplateExpression
|
||||
\ matchgroup=VueBrace
|
||||
\ start=+${+ end=+}+ contained
|
||||
\ contains=@simpleJavascriptExpression
|
||||
|
||||
syntax keyword htmlTagName contained template script style
|
||||
|
||||
highlight default link VueAttr htmlTag
|
||||
if s:highlight_vue_attr
|
||||
if s:attribute
|
||||
syntax match VueValue contained '\v\"\zs[^"]+\ze\"'
|
||||
\ contains=VueInject,@simpleJavascriptExpression
|
||||
highlight default link VueKey Type
|
||||
@@ -84,7 +103,8 @@ highlight default link VueComponentName htmlTagName
|
||||
highlight default link VueCustomTag htmlTagName
|
||||
highlight default link javaScriptStringS String
|
||||
highlight default link javaScriptStringD String
|
||||
highlight default link javaScriptTemplateString String
|
||||
highlight default link javaScriptNumber Constant
|
||||
highlight default link javaScriptOperator Operator
|
||||
highlight default link htmlJavaScriptOperator Operator
|
||||
"}}}
|
||||
" vim: fdm=marker
|
||||
10
syntax/patch/javascript.vim
Normal file
10
syntax/patch/javascript.vim
Normal file
@@ -0,0 +1,10 @@
|
||||
" Number with minus
|
||||
syntax match javaScriptNumber '\v<-?\d+L?>|0[xX][0-9a-fA-F]+>'
|
||||
\ containedin=@javascript display
|
||||
highlight link javaScriptNumber Constant
|
||||
|
||||
let s:config = vue#GetConfig('config', {})
|
||||
let s:keyword = s:config.keyword
|
||||
if s:keyword
|
||||
source <sfile>:h/vue-keyword.vim
|
||||
endif
|
||||
6
syntax/patch/less.vim
Normal file
6
syntax/patch/less.vim
Normal file
@@ -0,0 +1,6 @@
|
||||
" Use emmet-vim css type.
|
||||
silent! syntax clear lessDefinition
|
||||
syntax region cssLessDefinition matchgroup=cssBraces
|
||||
\ contains=@LessSyntax,cssLessDefinition
|
||||
\ contained containedin=cssLessVueStyle
|
||||
\ start="{" end="}"
|
||||
14
syntax/patch/mustache.vim
Normal file
14
syntax/patch/mustache.vim
Normal file
@@ -0,0 +1,14 @@
|
||||
" Patch for https://github.com/mustache/vim-mustache-handlebars
|
||||
" Use containedin=mustacheTemplateBlock in place of containedin=Top
|
||||
|
||||
syntax clear mustacheBlockComment
|
||||
syntax region mustacheBlockComment start=/{{!--/rs=s+2 skip=/{{.\{-}}}/ end=/--}}/re=e-2 contains=Todo contained extend containedin=mustacheTemplateBlock,@mustacheInside,@htmlMustacheContainer
|
||||
|
||||
syntax clear mustacheComment
|
||||
syntax region mustacheComment start=/{{!/rs=s+2 skip=/{{.\{-}}}/ end=/}}/re=e-2 contains=Todo contained containedin=mustacheTemplateBlock,@mustacheInside,@htmlMustacheContainer
|
||||
|
||||
syntax clear mustacheAngleComponent
|
||||
syntax region mustacheAngleComponent start=/<\/\?[[:upper:]]/ end=/>/ keepend containedin=mustacheTemplateBlock,@htmlMustacheContainer
|
||||
|
||||
syntax clear mustacheHbsComponent
|
||||
syntax region mustacheHbsComponent start=/{{[^!][$#^/]\?/ end=/}}}\?/ keepend containedin=mustacheTemplateBlock,@htmlMustacheContainer
|
||||
1
syntax/patch/pug.vim
Normal file
1
syntax/patch/pug.vim
Normal file
@@ -0,0 +1 @@
|
||||
syntax cluster htmlJavascript remove=javascriptParenthesisBlock
|
||||
10
syntax/patch/sass.vim
Normal file
10
syntax/patch/sass.vim
Normal file
@@ -0,0 +1,10 @@
|
||||
silent! syntax clear sassDefinition
|
||||
syntax region sassDefinition matchgroup=cssBraces
|
||||
\ contains=@SassSyntax,sassDefinition
|
||||
\ contained containedin=sassVueStyle
|
||||
\ start="{" end="}"
|
||||
|
||||
" Extend to highlight all numbers in expression
|
||||
syntax match cssValueNumber
|
||||
\ /\W\zs\d\+\(\.\d\+\)\?%\?\ze\W/
|
||||
\ contained containedin=sassDefinition
|
||||
13
syntax/patch/scss.vim
Normal file
13
syntax/patch/scss.vim
Normal file
@@ -0,0 +1,13 @@
|
||||
" If not loading https://github.com/cakebaker/scss-syntax.vim
|
||||
if !hlexists('scssNestedProperty')
|
||||
silent! syntax clear scssDefinition
|
||||
syntax region cssScssDefinition transparent matchgroup=cssBraces
|
||||
\ contains=@ScssSyntax,cssScssDefinition
|
||||
\ contained containedin=cssScssVueStyle
|
||||
\ start="{" end="}"
|
||||
|
||||
" Extend to highlight all numbers in expression
|
||||
syntax match cssValueNumber
|
||||
\ /\W\zs\d\+\(\.\d\+\)\?%\?\ze\W/
|
||||
\ contained containedin=cssScssDefinition
|
||||
endif
|
||||
5
syntax/patch/stylus.vim
Normal file
5
syntax/patch/stylus.vim
Normal file
@@ -0,0 +1,5 @@
|
||||
silent! syntax clear stylusDefinition
|
||||
syntax region cssStylusDefinition matchgroup=cssBraces
|
||||
\ contains=@StylusSyntax,cssStylusDefinition
|
||||
\ contained containedin=cssStylusVueStyle
|
||||
\ start="{" end="}"
|
||||
5
syntax/patch/typescript.vim
Normal file
5
syntax/patch/typescript.vim
Normal file
@@ -0,0 +1,5 @@
|
||||
let s:config = vue#GetConfig('config', {})
|
||||
let s:keyword = s:config.keyword
|
||||
if s:keyword
|
||||
source <sfile>:h/vue-keyword.vim
|
||||
endif
|
||||
85
syntax/patch/vue-keyword.vim
Normal file
85
syntax/patch/vue-keyword.vim
Normal file
@@ -0,0 +1,85 @@
|
||||
function! s:GetIndent()
|
||||
let config = vue#GetConfig('config', {})
|
||||
|
||||
let enable_initial_indent = 0
|
||||
for val in config.initial_indent
|
||||
if val =~ 'script'
|
||||
let enable_initial_indent = 1
|
||||
endif
|
||||
endfor
|
||||
|
||||
let indent = &sw * (1 + enable_initial_indent)
|
||||
return indent
|
||||
endfunction
|
||||
|
||||
function! s:GetMatchOption()
|
||||
" Currently support https://github.com/pangloss/vim-javascript
|
||||
let useJavaScriptPlugin = hlexists('jsAsyncKeyword')
|
||||
if useJavaScriptPlugin
|
||||
let containedin = 'jsObject,jsFuncBlock,@jsExpression'
|
||||
else
|
||||
" Just to avoid error from the containedin pattern
|
||||
syntax match javascriptScriptBlock /javascriptScriptBlock/
|
||||
let containedin = '.*ScriptBlock'
|
||||
endif
|
||||
let containedin .= ',typescriptIdentifierName'
|
||||
|
||||
let contains = useJavaScriptPlugin
|
||||
\? 'jsAsyncKeyword'
|
||||
\: 'javaScriptReserved'
|
||||
let match_option =
|
||||
\' containedin='.containedin
|
||||
\.' contains='.contains
|
||||
\.' skipwhite skipempty'
|
||||
return match_option
|
||||
endfunction
|
||||
|
||||
" Vue keywords as option key
|
||||
let s:vue_keywords = 'name parent functional delimiters comments components directives filters extends mixins inheritAttrs model props propsData data computed watch methods template render renderError inject provide beforeCreate created beforeMount mounted beforeUpdate updated activated deactivated beforeDestroy destroyed setup beforeUnmount unmounted errorCaptured renderTracked renderTriggered'
|
||||
|
||||
let s:indent = s:GetIndent()
|
||||
let s:keywords_regexp = '\v^\s{'.s:indent.'}(async )?<('
|
||||
\.join(split(s:vue_keywords, ' '), '|')
|
||||
\.')\ze'
|
||||
let s:match_option = s:GetMatchOption()
|
||||
|
||||
execute 'syntax match vueObjectKey display /'
|
||||
\.s:keywords_regexp
|
||||
\.'\s*:/'
|
||||
\.s:match_option
|
||||
\.' nextgroup=jsObjectValue'
|
||||
|
||||
execute 'syntax match vueObjectFuncName display /'
|
||||
\.s:keywords_regexp
|
||||
\.'\_s*\(/'
|
||||
\.s:match_option
|
||||
\.' nextgroup=jsFuncArgs'
|
||||
|
||||
execute 'syntax match vueObjectFuncKey display /'
|
||||
\.s:keywords_regexp
|
||||
\.'\s*:\s*function>/'
|
||||
\.s:match_option
|
||||
\.' nextgroup=jsFuncArgs'
|
||||
|
||||
" Vue3 keywords as API, https://v3.vuejs.org/api/
|
||||
let s:basic_reactive = 'reactive readonly isProxy isReactive isReadonly toRaw markRaw shallowReactive shallowReadonly'
|
||||
let s:refs = 'ref unref toRef toRefs isRef customRef shallowRef triggerRef'
|
||||
let s:computed_and_watch = 'computed watchEffect watchPostEffect watchSyncEffect watch'
|
||||
let s:composition = 'setup onBeforeMount onMounted onBeforeUpdate onUpdated onBeforeUnmount onUnmounted onErrorCaptured onRenderTracked onRenderTriggered onActivated onDeactivated getCurrentInstance InjectionKey provide inject'
|
||||
let s:global = 'createApp h defineComponent defineAsyncComponent defineCustomElement resolveComponent resolveDynamicComponent resolveDirective withDirectives createRenderer nextTick mergeProps useCssModule'
|
||||
let s:vue3_keywords = join([s:basic_reactive, s:refs, s:computed_and_watch, s:composition, s:global], ' ')
|
||||
|
||||
let s:vue3_keywords_regexp = '\v<('
|
||||
\.join(split(s:vue3_keywords, ' '), '|')
|
||||
\.')\ze'
|
||||
|
||||
execute 'syntax match vue3Keyword display /'
|
||||
\.s:vue3_keywords_regexp
|
||||
\.'\_s*\(/'
|
||||
\.s:match_option
|
||||
|
||||
highlight default link vueObjectKey vueObjectKeyword
|
||||
highlight default link vueObjectFuncName vueObjectKeyword
|
||||
highlight default link vue3Keyword vueObjectKeyword
|
||||
highlight default link vueObjectFuncKey vueObjectKeyword
|
||||
highlight default link vueObjectKeyword Type
|
||||
@@ -1,64 +0,0 @@
|
||||
let s:custom_blocks = vue#GetConfig("custom_blocks", {})
|
||||
|
||||
if empty(s:custom_blocks)
|
||||
finish
|
||||
endif
|
||||
|
||||
function! s:LoadSyntax()
|
||||
let syntax_list = []
|
||||
for syntax in values(s:custom_blocks)
|
||||
let type = type(syntax)
|
||||
if type == v:t_string
|
||||
if !count(syntax_list, syntax)
|
||||
call add(syntax_list, syntax)
|
||||
endif
|
||||
elseif type == v:t_list && len(syntax)
|
||||
for syn in syntax
|
||||
if !count(syntax_list, syn)
|
||||
call add(syntax_list, syn)
|
||||
endif
|
||||
endfor
|
||||
else
|
||||
echoerr '[vim-vue-plugin] custom_blocks value type'
|
||||
\.' must be either string or list'
|
||||
endif
|
||||
endfor
|
||||
for syntax in syntax_list
|
||||
let syntaxGroup = '@'.syntax
|
||||
call vue#LoadFullSyntax(syntaxGroup, syntax)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:SetSyntax(block, syntax, lang)
|
||||
let block = a:block
|
||||
let syntax = a:syntax
|
||||
let lang = a:lang
|
||||
|
||||
let region_name = syntax.toupper(block[0]).block[1:].'Block'
|
||||
let syntax_lang = lang ? 'lang=["'']'.syntax.'["''][^>]*' : ''
|
||||
let start = '<'.block.'[^>]*'.syntax_lang.'>'
|
||||
let end = '</'.block.'>'
|
||||
let syntaxGroup = '@'.syntax
|
||||
|
||||
execute 'syntax region '.region_name.' fold matchgroup=vueTag'
|
||||
\.' start=+'.start.'+'
|
||||
\.' end=+'.end.'+'
|
||||
\.' keepend contains='.syntaxGroup
|
||||
endfunction
|
||||
|
||||
function! s:Highlight()
|
||||
for [block, syntax] in items(s:custom_blocks)
|
||||
let type = type(syntax)
|
||||
if type == v:t_string
|
||||
call s:SetSyntax(block, syntax, 0)
|
||||
elseif type == v:t_list && len(syntax)
|
||||
call s:SetSyntax(block, syntax[0], 0)
|
||||
for syn in syntax
|
||||
call s:SetSyntax(block, syn, 1)
|
||||
endfor
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
call s:LoadSyntax()
|
||||
call s:Highlight()
|
||||
@@ -1,75 +0,0 @@
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Config {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
let s:highlight_vue_keyword = vue#GetConfig("highlight_vue_keyword", 0)
|
||||
if !s:highlight_vue_keyword | finish | endif
|
||||
|
||||
let s:has_init_indent = vue#GetConfig("has_init_indent",
|
||||
\ expand("%:e") == 'wpy' ? 1 : 0)
|
||||
"}}}
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Syntax highlight {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
let s:vue_keywords = 'name parent functional delimiters comments components directives filters extends mixins inheritAttrs model props propsData data computed watch methods template render renderError inject provide beforeCreate created beforeMount mounted beforeUpdate updated activated deactivated beforeDestroy destroyed setup beforeUnmount unmounted errorCaptured renderTracked renderTriggered'
|
||||
|
||||
let s:indent = &sw * (1 + s:has_init_indent)
|
||||
let s:keywords_regexp = '\v^\s{'.s:indent.'}(async )?<('
|
||||
\.join(split(s:vue_keywords, ' '), '|')
|
||||
\.')\ze'
|
||||
|
||||
" Currently support https://github.com/pangloss/vim-javascript
|
||||
let s:useJavaScriptPlugin = hlexists('jsAsyncKeyword')
|
||||
let s:containedin = s:useJavaScriptPlugin
|
||||
\? 'jsObject,jsFuncBlock,@jsExpression'
|
||||
\: 'javascriptVueScript'
|
||||
let s:contains = s:useJavaScriptPlugin
|
||||
\? 'jsAsyncKeyword'
|
||||
\: 'javaScriptReserved'
|
||||
let s:match_option =
|
||||
\' containedin='.s:containedin
|
||||
\.' contains='.s:contains
|
||||
\.' skipwhite skipempty'
|
||||
|
||||
execute 'syntax match vueObjectKey /'
|
||||
\.s:keywords_regexp
|
||||
\.'\s*:/'
|
||||
\.s:match_option
|
||||
\.' nextgroup=jsObjectValue'
|
||||
|
||||
execute 'syntax match vueObjectFuncName /'
|
||||
\.s:keywords_regexp
|
||||
\.'\_s*\(/'
|
||||
\.s:match_option
|
||||
\.' nextgroup=jsFuncArgs'
|
||||
|
||||
execute 'syntax match vueObjectFuncKey /'
|
||||
\.s:keywords_regexp
|
||||
\.'\s*:\s*function>/'
|
||||
\.s:match_option
|
||||
\.' nextgroup=jsFuncArgs'
|
||||
|
||||
let s:vue3_keywords = 'ref reactive toRefs watch computed'.
|
||||
\' onBeforeMount onMounted onBeforeUpdate onUpdated onBeforeUnmount'.
|
||||
\' onUnmounted onErrorCaptured onRenderTracked onRenderTriggered'.
|
||||
\' getCurrentInstance'
|
||||
let s:vue3_keywords_regexp = '\v<('
|
||||
\.join(split(s:vue3_keywords, ' '), '|')
|
||||
\.')\ze'
|
||||
|
||||
execute 'syntax match vue3Keyword /'
|
||||
\.s:vue3_keywords_regexp
|
||||
\.'\_s*\(/'
|
||||
\.s:match_option
|
||||
|
||||
highlight default link vueObjectKey vueObjectKeyword
|
||||
highlight default link vueObjectFuncName vueObjectKeyword
|
||||
highlight default link vue3Keyword vueObjectKeyword
|
||||
highlight default link vueObjectFuncKey vueObjectKeyword
|
||||
highlight default link vueObjectKeyword Type
|
||||
"}}}
|
||||
" vim: fdm=marker
|
||||
477
syntax/vue.vim
477
syntax/vue.vim
@@ -1,306 +1,211 @@
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Vim syntax file
|
||||
"
|
||||
" Language: Vue
|
||||
" Maintainer: leaf <leafvocation@gmail.com>
|
||||
"
|
||||
" CREDITS: Inspired by mxw/vim-jsx.
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
if exists("b:current_syntax") && b:current_syntax == 'vue'
|
||||
" Maintainer: leaf <https://github.com/leafOfTree>
|
||||
" Credits: Inspired by mxw/vim-jsx.
|
||||
|
||||
if exists('b:current_syntax') && b:current_syntax == 'vue'
|
||||
finish
|
||||
endif
|
||||
|
||||
" For advanced users, this variable can be used to avoid overload
|
||||
let b:current_loading_main_syntax = 'vue'
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Config {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
let s:use_pug = vue#GetConfig("use_pug", 0)
|
||||
let s:use_less = vue#GetConfig("use_less", 0)
|
||||
let s:use_sass = vue#GetConfig("use_sass", 0)
|
||||
let s:use_scss = vue#GetConfig("use_scss", 0)
|
||||
let s:use_stylus = vue#GetConfig("use_stylus", 0)
|
||||
let s:use_coffee = vue#GetConfig("use_coffee", 0)
|
||||
let s:use_typescript = vue#GetConfig("use_typescript", 0)
|
||||
"}}}
|
||||
" <sfile> is replaced with the file name of the sourced file
|
||||
let s:patch_path = expand('<sfile>:p:h').'/patch'
|
||||
let s:test = exists('g:vim_vue_plugin_test')
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Load main syntax {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
function! s:Init()
|
||||
""" Configs
|
||||
let s:config = vue#GetConfig('config', {})
|
||||
let s:config_syntax = s:config.syntax
|
||||
|
||||
" Load syntax/html.vim to syntax group, which loads full JavaScript and CSS
|
||||
" syntax. It defines group @html, @htmlJavaScript, and @htmlCss.
|
||||
call vue#LoadSyntax('@html', 'html')
|
||||
" For advanced users, it can be used to avoid overload
|
||||
let b:current_loading_main_syntax = 'vue'
|
||||
endfunction
|
||||
|
||||
" Avoid overload
|
||||
if !hlexists('cssTagName')
|
||||
call vue#LoadSyntax('@htmlCss', 'css')
|
||||
endif
|
||||
function! s:GetGroupNameForLoading(syntax)
|
||||
return '@'.a:syntax
|
||||
endfunction
|
||||
|
||||
" Avoid overload
|
||||
if !hlexists('javaScriptComment')
|
||||
call vue#Log('load javascript cluster')
|
||||
call vue#LoadSyntax('@htmlJavaScript', 'javascript')
|
||||
endif
|
||||
|
||||
" Load vue-html syntax
|
||||
runtime syntax/vue-html.vim
|
||||
|
||||
" Load vue-javascript syntax
|
||||
runtime syntax/vue-javascript.vim
|
||||
"}}}
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Load pre-processors syntax {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" If pug is enabled, load vim-pug syntax
|
||||
if s:use_pug
|
||||
call vue#LoadFullSyntax('@PugSyntax', 'pug')
|
||||
syn cluster htmlJavascript remove=javascriptParenthesisBlock
|
||||
endif
|
||||
|
||||
" If less is enabled, load less syntax
|
||||
if s:use_less
|
||||
call vue#LoadSyntax('@LessSyntax', 'less')
|
||||
runtime! after/syntax/less.vim
|
||||
endif
|
||||
|
||||
" If sass is enabled, load sass syntax
|
||||
if s:use_sass
|
||||
call vue#LoadSyntax('@SassSyntax', 'sass')
|
||||
runtime! after/syntax/sass.vim
|
||||
endif
|
||||
|
||||
" If scss is enabled, load sass syntax
|
||||
if s:use_scss
|
||||
call vue#LoadSyntax('@ScssSyntax', 'scss')
|
||||
runtime! after/syntax/scss.vim
|
||||
endif
|
||||
|
||||
" If stylus is enabled, load stylus syntax
|
||||
if s:use_stylus
|
||||
call vue#LoadFullSyntax('@StylusSyntax', 'stylus')
|
||||
runtime! after/syntax/stylus.vim
|
||||
endif
|
||||
|
||||
" If CoffeeScript is enabled, load the syntax. Keep name consistent with
|
||||
" vim-coffee-script/after/html.vim
|
||||
if s:use_coffee
|
||||
call vue#LoadFullSyntax('@htmlCoffeeScript', 'coffee')
|
||||
endif
|
||||
|
||||
" If TypeScript is enabled, load the syntax.
|
||||
if s:use_typescript
|
||||
call vue#LoadFullSyntax('@TypeScript', 'typescript')
|
||||
endif
|
||||
"}}}
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Syntax highlight {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" All start with html/javascript/css for emmet-vim in-file type detection
|
||||
syntax region htmlVueTemplate fold
|
||||
\ start=+<template[^>]*>+
|
||||
\ end=+^</template>+
|
||||
\ keepend contains=@html
|
||||
" When template code is not well indented
|
||||
syntax region htmlVueTemplate fold
|
||||
\ start=+<template[^>]*>+
|
||||
\ end=+</template>\ze\n\(^$\n\)*<\(script\|style\)+
|
||||
\ keepend contains=@html
|
||||
|
||||
syntax region javascriptVueScript fold
|
||||
\ start=+<script[^>]*>+
|
||||
\ end=+</script>+
|
||||
\ keepend contains=@htmlJavaScript,jsImport,jsExport,vueTag
|
||||
|
||||
|
||||
syntax region cssVueStyle fold
|
||||
\ start=+<style[^>]*>+
|
||||
\ end=+</style>+
|
||||
\ keepend contains=@htmlCss,vueTag
|
||||
|
||||
" Preprocessors syntax
|
||||
syntax region pugVueTemplate fold
|
||||
\ start=+<template[^>]*lang=["']pug["'][^>]*>+
|
||||
\ end=+</template>+
|
||||
\ keepend contains=@PugSyntax,vueTag
|
||||
|
||||
syntax region coffeeVueScript fold
|
||||
\ start=+<script[^>]*lang=["']coffee["'][^>]*>+
|
||||
\ end=+</script>+
|
||||
\ keepend contains=@htmlCoffeeScript,jsImport,jsExport,vueTag
|
||||
|
||||
syntax region typescriptVueScript fold
|
||||
\ start=+<script[^>]*lang=["']ts["'][^>]*>+
|
||||
\ end=+</script>+
|
||||
\ keepend contains=@TypeScript,vueTag
|
||||
|
||||
syntax region cssLessVueStyle fold
|
||||
\ start=+<style[^>]*lang=["']less["'][^>]*>+
|
||||
\ end=+</style>+
|
||||
\ keepend contains=@LessSyntax,vueTag
|
||||
syntax region sassVueStyle fold
|
||||
\ start=+<style[^>]*lang=["']sass["'][^>]*>+
|
||||
\ end=+</style>+
|
||||
\ keepend contains=@SassSyntax,vueTag
|
||||
syntax region cssScssVueStyle fold
|
||||
\ start=+<style[^>]*lang=["']scss["'][^>]*>+
|
||||
\ end=+</style>+
|
||||
\ keepend contains=@ScssSyntax,vueTag
|
||||
|
||||
" Backward compatiable for `use_sass` option
|
||||
if s:use_sass && !s:use_scss
|
||||
syntax region cssScssVueStyle fold
|
||||
\ start=+<style[^>]*lang=["']scss["'][^>]*>+
|
||||
\ end=+</style>+
|
||||
\ keepend contains=@SassSyntax,vueTag
|
||||
endif
|
||||
|
||||
syntax region cssStylusVueStyle fold
|
||||
\ start=+<style[^>]*lang=["']stylus["'][^>]*>+
|
||||
\ end=+</style>+
|
||||
\ keepend contains=@StylusSyntax,vueTag
|
||||
|
||||
syntax region vueTag fold
|
||||
\ start=+^<[^/]+ end=+>+ skip=+></+
|
||||
\ contained contains=htmlTagN,htmlString,htmlArg
|
||||
syntax region vueTag
|
||||
\ start=+^</+ end=+>+
|
||||
\ contains=htmlTagN,htmlString,htmlArg
|
||||
|
||||
highlight default link vueTag htmlTag
|
||||
highlight default link cssUnitDecorators2 Number
|
||||
highlight default link cssKeyFrameProp2 Constant
|
||||
"}}}
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Custom blocks {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
runtime syntax/vue-custom-blocks.vim
|
||||
"}}}
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Syntax patch {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Patch 7.4.1142
|
||||
if has("patch-7.4-1142")
|
||||
if has("win32")
|
||||
syntax iskeyword @,48-57,_,128-167,224-235,$,-
|
||||
else
|
||||
syntax iskeyword @,48-57,_,192-255,$,-
|
||||
" Extend group name as
|
||||
" html defines group @htmlJavaScript and @htmlCss.
|
||||
" coffee defines group @coffeeJS.
|
||||
function! s:GetGroupNameForHighlight(syntax)
|
||||
let syntax = a:syntax
|
||||
let name = '@'.a:syntax
|
||||
if syntax == 'javascript'
|
||||
let name = '@javascript,@htmlJavaScript,@coffeeJS'
|
||||
elseif syntax == 'css'
|
||||
let name = '@css,@htmlCss'
|
||||
endif
|
||||
else
|
||||
setlocal iskeyword+=-
|
||||
endif
|
||||
return name
|
||||
endfunction
|
||||
|
||||
" Style
|
||||
" Redefine (less|sass|stylus)Definition to highlight <style> correctly and
|
||||
" enable emmet-vim css type.
|
||||
if s:use_less
|
||||
silent! syntax clear lessDefinition
|
||||
syntax region cssLessDefinition matchgroup=cssBraces
|
||||
\ contains=@LessSyntax,cssLessDefinition
|
||||
\ contained containedin=cssLessVueStyle
|
||||
\ start="{" end="}"
|
||||
endif
|
||||
if s:use_sass
|
||||
silent! syntax clear sassDefinition
|
||||
syntax region sassDefinition matchgroup=cssBraces
|
||||
\ contains=@SassSyntax,sassDefinition
|
||||
\ contained containedin=sassVueStyle
|
||||
\ start="{" end="}"
|
||||
" Return name with format '<syntax><Tagname>Block'
|
||||
function! s:GetSynatxName(block, syntax)
|
||||
let block = a:block
|
||||
let syntax = a:syntax
|
||||
let name = syntax.toupper(block[0]).block[1:].'Block'
|
||||
let name = substitute(name, '-\(.\)', "\\U\\1", 'g')
|
||||
let name = vue#AlterSyntaxForEmmetVim(name, syntax)
|
||||
return name
|
||||
endfunction
|
||||
|
||||
" Extend to highlight all numbers in expression
|
||||
syntax match cssValueNumber
|
||||
\ /\W\zs\d\+\(\.\d\+\)\?%\?\ze\W/
|
||||
\ contained containedin=sassDefinition
|
||||
endif
|
||||
" If not loading https://github.com/cakebaker/scss-syntax.vim
|
||||
if s:use_scss && !hlexists('scssNestedProperty')
|
||||
silent! syntax clear scssDefinition
|
||||
syntax region cssScssDefinition transparent matchgroup=cssBraces
|
||||
\ contains=@ScssSyntax,cssScssDefinition
|
||||
\ contained containedin=cssScssVueStyle
|
||||
\ start="{" end="}"
|
||||
function! s:LoadSyntaxList(syntax_list)
|
||||
for syntax in a:syntax_list
|
||||
let loaded = s:BeforeLoadSyntax(syntax)
|
||||
if !loaded
|
||||
let syntax_group = s:GetGroupNameForLoading(syntax)
|
||||
call vue#LoadSyntax(syntax_group, syntax)
|
||||
endif
|
||||
call s:AfterLoadSyntax(syntax)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" Extend to highlight all numbers in expression
|
||||
syntax match cssValueNumber
|
||||
\ /\W\zs\d\+\(\.\d\+\)\?%\?\ze\W/
|
||||
\ contained containedin=cssScssDefinition
|
||||
endif
|
||||
if s:use_stylus
|
||||
silent! syntax clear stylusDefinition
|
||||
syntax region cssStylusDefinition matchgroup=cssBraces
|
||||
\ contains=@StylusSyntax,cssStylusDefinition
|
||||
\ contained containedin=cssStylusVueStyle
|
||||
\ start="{" end="}"
|
||||
endif
|
||||
" For specific syntax, we need to handle it specially
|
||||
function! s:BeforeLoadSyntax(syntax)
|
||||
let syntax = a:syntax
|
||||
|
||||
" Use a different name in order to avoid css syntax interference
|
||||
silent! syntax clear cssUnitDecorators
|
||||
syntax match cssUnitDecorators2
|
||||
\ /\(#\|-\|+\|%\|mm\|cm\|in\|pt\|pc\|em\|ex\|px\|ch\|rem\|vh\|vw\|vmin\|vmax\|dpi\|dppx\|dpcm\|Hz\|kHz\|s\|ms\|deg\|grad\|rad\)\ze\(;\|$\)/
|
||||
\ contained
|
||||
\ containedin=cssAttrRegion,sassCssAttribute,lessCssAttribute,stylusCssAttribute
|
||||
" Avoid overload if group already exists
|
||||
let loaded = 0
|
||||
if syntax == 'javascript'
|
||||
let loaded = hlexists('javaScriptComment')
|
||||
elseif syntax == 'css'
|
||||
let loaded = hlexists('cssTagName')
|
||||
endif
|
||||
return loaded
|
||||
endfunction
|
||||
|
||||
silent! syntax clear cssKeyFrameProp
|
||||
syn match cssKeyFrameProp2 /\d*%\|from\|to/
|
||||
\ contained nextgroup=cssDefinition
|
||||
\ containedin=cssAttrRegion,sassCssAttribute,lessCssAttribute,stylusCssAttribute
|
||||
function! s:AfterLoadSyntax(syntax)
|
||||
let syntax = a:syntax
|
||||
call s:LoadPatchSyntax(syntax)
|
||||
call s:LoadAfterSyntax(syntax)
|
||||
endfunction
|
||||
|
||||
" Coffee
|
||||
if s:use_coffee
|
||||
silent! syntax clear coffeeConstant
|
||||
syn match coffeeConstant '\v<\u\C[A-Z0-9_]+>' display
|
||||
\ containedin=@coffeeIdentifier
|
||||
endif
|
||||
function! s:LoadPatchSyntax(syntax)
|
||||
let file = s:patch_path.'/'.a:syntax.'.vim'
|
||||
if filereadable(file)
|
||||
execute 'syntax include '.file
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" JavaScript
|
||||
" Number with minus
|
||||
syntax match javaScriptNumber '\v<-?\d+L?>|0[xX][0-9a-fA-F]+>'
|
||||
\ containedin=@javascriptVueScript display
|
||||
function! s:LoadAfterSyntax(syntax)
|
||||
execute 'runtime! after/syntax/'.a:syntax.'.vim'
|
||||
endfunction
|
||||
|
||||
" HTML
|
||||
" Clear htmlHead that may cause highlighting out of bounds
|
||||
silent! syntax clear htmlHead
|
||||
function! s:GetSyntaxLangName(syntax)
|
||||
let syntax = a:syntax
|
||||
if syntax == 'typescript'
|
||||
let syntax = 'ts'
|
||||
endif
|
||||
return syntax
|
||||
endfunction
|
||||
|
||||
" html5 data-*
|
||||
syntax match htmlArg '\v<data(-[.a-z0-9]+)+>' containedin=@html
|
||||
"}}}
|
||||
function! s:SetSyntax(block, syntax, has_lang)
|
||||
let block = a:block
|
||||
let syntax = a:syntax
|
||||
let has_lang = a:has_lang
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Syntax sync {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
syntax sync clear
|
||||
syntax sync minlines=100
|
||||
syntax sync match vueHighlight groupthere NONE "</\(script\|template\|style\)"
|
||||
syntax sync match scriptHighlight groupthere javascriptVueScript "<script"
|
||||
syntax sync match scriptHighlight groupthere coffeeVueScript "<script[^>]*lang=["']coffee["'][^>]*>"
|
||||
syntax sync match scriptHighlight groupthere typescriptVueScript "<script[^>]*lang=["']ts["'][^>]*>"
|
||||
syntax sync match templateHighlight groupthere htmlVueTemplate "<template"
|
||||
syntax sync match templateHighlight groupthere pugVueTemplate "<template[^>]*lang=["']pug["'][^>]*>"
|
||||
syntax sync match styleHighlight groupthere cssVueStyle "<style"
|
||||
syntax sync match styleHighlight groupthere cssLessVueStyle "<style[^>]*lang=["']less["'][^>]*>"
|
||||
syntax sync match styleHighlight groupthere sassVueStyle "<style[^>]*lang=["']sass["'][^>]*>"
|
||||
syntax sync match styleHighlight groupthere cssScssVueStyle "<style[^>]*lang=["']scss["'][^>]*>"
|
||||
syntax sync match styleHighlight groupthere cssStylusVueStyle "<style[^>]*lang=["']stylus["'][^>]*>"
|
||||
"}}}
|
||||
let name = s:GetSynatxName(block, syntax)
|
||||
if has_lang
|
||||
let lang_name = s:GetSyntaxLangName(syntax)
|
||||
let lang = 'lang=["'']'.lang_name.'["'']'
|
||||
else
|
||||
let lang = ''
|
||||
endif
|
||||
|
||||
let b:current_syntax = 'vue'
|
||||
" vim: fdm=marker
|
||||
let start = '^<'.block.'[^>]*'.lang
|
||||
let end_tag = '</'.block.'>'
|
||||
let end = '^'.end_tag
|
||||
let syntax_group = s:GetGroupNameForHighlight(syntax)
|
||||
|
||||
" Block like
|
||||
" <script lang="ts">
|
||||
" ...
|
||||
" </script>
|
||||
execute 'syntax region '.name.' fold '
|
||||
\.' start=+'.start.'+'
|
||||
\.' end=+'.end.'+'
|
||||
\.' keepend contains='.syntax_group.', vueTag'
|
||||
|
||||
execute 'syntax sync match vueSync groupthere '.name.' +'.start.'+'
|
||||
execute 'syntax sync match vueSync groupthere NONE +'.end.'+'
|
||||
|
||||
" Block like <script src="...">...</script>
|
||||
let oneline = start.'.*'.end_tag
|
||||
execute 'syntax match '.name.' fold '
|
||||
\.' +'.oneline.'+'
|
||||
\.' keepend contains='.syntax_group.', vueTag, vueTagOneline'
|
||||
endfunction
|
||||
|
||||
function! s:SetBlockSyntax(config_syntax)
|
||||
syntax sync clear
|
||||
|
||||
for [block, syntax] in items(a:config_syntax)
|
||||
let type = type(syntax)
|
||||
if type == v:t_string
|
||||
call s:SetSyntax(block, syntax, 0)
|
||||
elseif type == v:t_list && len(syntax)
|
||||
call s:SetSyntax(block, syntax[0], 0)
|
||||
for syn in syntax
|
||||
call s:SetSyntax(block, syn, 1)
|
||||
endfor
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:HighlightVue()
|
||||
call s:HighlightVueTag()
|
||||
call s:HighlightVueStyle()
|
||||
endfunction
|
||||
|
||||
function! s:HighlightVueTag()
|
||||
syntax region vueTag fold
|
||||
\ start=+^<[^/]+ end=+>+ skip=+></+
|
||||
\ contained contains=htmlTagN,htmlString,htmlArg
|
||||
syntax region vueTag
|
||||
\ start=+^</+ end=+>+
|
||||
\ contained contains=htmlTagN,htmlString,htmlArg
|
||||
syntax region vueTagOneline
|
||||
\ start=+</+ end=+>$+
|
||||
\ contained contains=htmlTagN,htmlString,htmlArg
|
||||
highlight default link vueTag htmlTag
|
||||
highlight default link vueTagOneline htmlTag
|
||||
endfunction
|
||||
|
||||
function! s:HighlightVueStyle()
|
||||
syntax keyword cssPseudoClassId contained deep slotted global
|
||||
syntax region cssFunction contained matchgroup=cssFunctionName
|
||||
\ start="\<\(v-bind\)\s*(" end=")"
|
||||
\ contains=cssCustomProp,cssValue.*,cssFunction,cssColor,cssStringQ,cssStringQQ
|
||||
\ oneline
|
||||
endfunction
|
||||
|
||||
function! s:SetIsKeyword()
|
||||
if has("patch-7.4-1142")
|
||||
if has("win32")
|
||||
syntax iskeyword @,48-57,_,128-167,224-235,$,-
|
||||
else
|
||||
syntax iskeyword @,48-57,_,192-255,$,-
|
||||
endif
|
||||
else
|
||||
setlocal iskeyword+=-
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:SetCurrentSyntax()
|
||||
let b:current_syntax = 'vue'
|
||||
endfunction
|
||||
|
||||
function! s:SetExtraSyntax()
|
||||
call s:SetIsKeyword()
|
||||
call s:HighlightVue()
|
||||
call s:SetCurrentSyntax()
|
||||
endfunction
|
||||
|
||||
function! VimVuePluginSyntaxMain(...)
|
||||
call s:Init()
|
||||
let syntax_list = vue#GetSyntaxList(s:config_syntax)
|
||||
call s:LoadSyntaxList(syntax_list)
|
||||
call s:SetBlockSyntax(s:config_syntax)
|
||||
call s:SetExtraSyntax()
|
||||
endfunction
|
||||
|
||||
" Entry
|
||||
call VimVuePluginSyntaxMain()
|
||||
|
||||
Reference in New Issue
Block a user