159 Commits

Author SHA1 Message Date
leafOfTree
04c3fb20ed Load all tags after syntax instead of only style 2023-10-05 11:51:45 +08:00
leafOfTree
58ac69b2c8 Update doc 2023-02-02 12:33:31 +08:00
leafOfTree
4d31393b03 Remove timer usage 2023-01-31 17:29:23 +08:00
leafOfTree
8d75429260 Fix syntax lost issue when using netrw :Vexplore 2023-01-31 15:31:52 +08:00
leafOfTree
ed318345cf Simplify html syntax commands 2023-01-31 15:17:32 +08:00
leafOfTree
84ac1d2359 Highlight <script...> as htmlTagName instead of htmlSpecialTagName from built-in syntax 2022-10-11 14:16:21 +08:00
leafOfTree
4da7d448ae Fix GetVueTag for blank lines between blocks 2022-06-15 14:22:54 +08:00
leafOfTree
ac76f21419 Update doc 2022-06-15 11:59:05 +08:00
leafOfTree
be0f84ebb5 Update doc 2022-06-15 11:41:42 +08:00
leafOfTree
3b90ccad2d Update 2022-06-15 11:32:33 +08:00
leafOfTree
b2bb4dd8f6 Fix miniprogram syntax containing blank 2022-03-03 15:27:17 +08:00
leafOfTree
b4c9fdc87a Update doc 2022-02-21 16:25:10 +08:00
leafOfTree
6569315461 Update doc 2022-02-21 16:24:09 +08:00
leafOfTree
5977fc07fe Update doc 2022-02-21 16:23:04 +08:00
leafOfTree
a8decb75b1 Remove fold timer to support makeview/loadview 2021-11-05 17:50:11 +08:00
leafOfTree
469c43292d Fix syntax error for directives without value 2021-11-05 17:50:11 +08:00
leafOfTree
dd0e3145af Update doc 2021-09-12 10:47:58 +08:00
leafOfTree
a5be3e6c3a Update doc 2021-09-12 10:46:44 +08:00
leafOfTree
7f4c259d27 Fix fold level of blank lines in <script> 2021-09-10 13:20:12 +08:00
leafOfTree
8e121ce67d Update doc 2021-09-10 12:03:57 +08:00
leafOfTree
6678475a50 Update doc 2021-09-06 16:08:55 +08:00
leafOfTree
0432e150dc Update doc 2021-09-06 16:07:32 +08:00
leafOfTree
15143762b8 Update doc 2021-09-06 15:58:31 +08:00
leafOfTree
3fa4bea6df Fix keyword error from containedin pattern 2021-08-13 19:05:46 +08:00
leafOfTree
c248bd1488 Load syntax and then set syntax to fix syntax sync 2021-08-13 16:56:22 +08:00
leafOfTree
6e25aaf388 Fix syntax sync being cleared issue 2021-08-13 16:47:13 +08:00
leafOfTree
8d464e9506 Support vue3 API keywords 2021-08-13 16:29:57 +08:00
leafOfTree
ab96ba2585 Support global api syntax 2021-08-13 13:08:06 +08:00
leafOfTree
4dd559c860 Support vue3 composition api 2021-08-13 12:50:34 +08:00
leafOfTree
d15590dae2 Format code 2021-08-11 18:35:52 +08:00
leafOfTree
eb3bba0ccb Support style v-bind syntax 2021-08-11 18:32:10 +08:00
leafOfTree
e4ddccee90 Update doc 2021-08-05 16:37:20 +08:00
leafOfTree
0e68102487 Improve multiple line tag syntax and custom tag indent 2021-08-04 11:14:15 +08:00
leafOfTree
44b0071e2d Add custom tags 2021-08-02 15:02:30 +08:00
leafOfTree
3d2680a859 Support view block 2021-07-30 14:41:13 +08:00
leafOfTree
cda82484d2 Update doc 2021-06-15 12:30:38 +08:00
leafOfTree
0e341ab4f8 Simplify example config 2021-06-15 12:29:47 +08:00
leafOfTree
a5882eb712 Update doc 2021-06-05 16:02:34 +08:00
leafOfTree
568b571849 Update doc 2021-06-05 16:00:32 +08:00
leafOfTree
b2b08cda9d Improve oneline block syntax 2021-06-02 13:51:42 +08:00
leafOfTree
c43bd87267 Support oneline block 2021-06-02 13:20:40 +08:00
leafOfTree
98e22f2af4 Rename function name for clearer meaning 2021-05-20 11:47:17 +08:00
leafOfTree
43490363a5 Update doc 2021-05-19 11:20:04 +08:00
leafOfTree
50ea0b7bce Update CI config 2021-05-18 16:07:16 +08:00
leafOfTree
696533d262 Update doc 2021-05-12 19:09:04 +08:00
leafOfTree
9ae107ea6f Fix script fold issue 2021-05-10 14:02:08 +08:00
leafOfTree
b8cbd66359 Use user's option when setting 2021-05-10 13:25:38 +08:00
leafOfTree
0f4b6b7b7e Update doc 2021-05-05 21:03:48 +08:00
leafOfTree
12e5eadbad Update doc 2021-05-05 20:59:04 +08:00
leafOfTree
617639320d Update doc 2021-05-05 20:57:51 +08:00
leafOfTree
511fb2fb82 Update doc 2021-05-05 20:56:59 +08:00
leafOfTree
b8f8a45e44 Update doc 2021-05-05 20:54:48 +08:00
leafOfTree
32b89ad2bf Update doc 2021-04-26 16:03:04 +08:00
leafOfTree
9e642cc983 Update doc 2021-04-23 13:21:43 +08:00
leafOfTree
8a913af7a6 setlocal foldenable to default value (on) 2021-04-23 13:06:51 +08:00
leafOfTree
9e55939c89 Rename subtype to syntax 2021-04-23 12:49:55 +08:00
leafOfTree
5067a5cc25 Update doc 2021-04-19 18:59:32 +08:00
leafOfTree
c4847c18e9 Update doc 2021-04-19 14:20:56 +08:00
leafOfTree
d080255fce Fix foldexpr 2021-04-19 14:20:37 +08:00
leafOfTree
8f23970cf9 Update doc 2021-04-19 09:50:11 +08:00
leafOfTree
d8a5c1486b Update doc 2021-04-19 09:39:44 +08:00
leafOfTree
8f0d26991a Update doc 2021-04-19 09:36:57 +08:00
leafOfTree
2a682014a3 Update doc 2021-04-16 16:22:57 +08:00
leafOfTree
483e45e198 Change options order 2021-04-16 16:22:51 +08:00
leafOfTree
f1b7ea05b8 Backwards compatibility with init_indent 2021-04-16 14:46:11 +08:00
leafOfTree
6a94c30ec7 Add new 'initial indent' option 2021-04-16 13:33:56 +08:00
leafOfTree
87922641ad Fix various indent issues 2021-04-15 18:49:29 +08:00
leafOfTree
3ed1e89f55 Defer indent load time 2021-04-15 13:10:22 +08:00
leafOfTree
ed7e1a9898 Use runtime typescript indent for javascript 2021-04-14 22:50:37 +08:00
leafOfTree
c71f55019b Fix Vim built-in javascript indent on closing parenthesis 2021-04-14 12:01:33 +08:00
leafOfTree
5be2325222 Fix Vim built-in javascript indent 2021-04-14 11:44:14 +08:00
leafOfTree
dcbdcbea37 Support full_syntax to be list or string 2021-04-14 11:27:35 +08:00
leafOfTree
26002b6212 Allow empty syntax list 2021-04-14 10:53:03 +08:00
leafOfTree
8d3c18621d Set syntax sync by each block syntax 2021-04-14 10:51:25 +08:00
leafOfTree
255472b126 Comment out syn sync fromstart for now 2021-04-13 15:53:48 +08:00
leafOfTree
f437eea49d Update doc 2021-04-13 15:53:27 +08:00
leafOfTree
f460616735 Add patch for mustache syntax from vim-mustache-handlebars 2021-04-13 15:06:55 +08:00
leafOfTree
8e6080629b Enable syntax sync fromstart 2021-04-13 15:05:37 +08:00
leafOfTree
99f317066a Update doc 2021-04-12 14:11:51 +08:00
leafOfTree
74a917987e Update doc 2021-04-12 12:06:50 +08:00
leafOfTree
6da176f51e Update doc 2021-04-12 11:57:02 +08:00
leafOfTree
c70cd332ad Support template string in vue attr 2021-04-08 18:50:15 +08:00
leafOfTree
15914af39b Update doc 2021-04-06 13:39:54 +08:00
leafOfTree
f50130155e Update doc 2021-04-06 13:37:10 +08:00
leafOfTree
59e9825606 Fix foldexpr on config and custom blocks 2021-04-06 13:37:00 +08:00
leafOfTree
11c04aaf7b Fix no highlight after loading session 2021-04-01 10:33:38 +08:00
leafOfTree
537af6139f Add nvim to test 2021-04-01 09:59:42 +08:00
leafOfTree
b617e1e110 Fix indent for blocks in template 2021-03-31 18:37:28 +08:00
leafOfTree
01e460244f Fix syntax of template blocks inside template 2021-03-31 17:48:22 +08:00
leafOfTree
b601b25226 Update doc 2021-03-30 14:22:14 +08:00
leafOfTree
fe88470ebf Update doc 2021-03-30 14:21:44 +08:00
leafOfTree
d11229e7e1 Update doc 2021-03-30 14:19:42 +08:00
leafOfTree
fc75f3c474 Fix template in pug indent error 2021-03-30 13:20:42 +08:00
leafOfTree
665d8a18b3 Fix syntax for template inside template 2021-03-30 10:29:56 +08:00
leafOfTree
347f62abae Update doc 2021-03-29 19:01:29 +08:00
leafOfTree
5aee4f5a0d Update doc 2021-03-29 18:43:52 +08:00
leafOfTree
950b6dc126 Update doc 2021-03-29 18:31:45 +08:00
leafOfTree
d1a15e095b Update doc 2021-03-29 17:40:53 +08:00
leafOfTree
d90b18e1c7 Update doc/message 2021-03-29 17:31:39 +08:00
leafOfTree
258d30fc6b Update doc 2021-03-29 16:15:32 +08:00
leafOfTree
e1dab23589 Improve code and performance 2021-03-29 15:58:50 +08:00
leafOfTree
6b48092f15 Update doc 2021-03-29 15:58:33 +08:00
leafOfTree
2b050c42c1 Refactor the whole plugin 2021-03-23 11:50:46 +08:00
leafOfTree
b24ce56361 Remove optional function argument 2021-03-12 17:03:34 +08:00
leafOfTree
bfc3d79061 Update doc 2021-03-11 17:04:39 +08:00
leafOfTree
e786110b03 Update doc 2021-03-11 17:03:27 +08:00
leafOfTree
fe9e97cd44 Update doc 2021-03-11 17:00:00 +08:00
leafOfTree
23f28eab69 Update travis config 2021-03-11 16:47:37 +08:00
leafOfTree
36101b1f31 Update travis config 2021-03-11 16:29:38 +08:00
leafOfTree
8e61377bdd Update travis config 2021-03-11 15:29:29 +08:00
leafOfTree
6350c9b114 Update 2021-03-11 14:54:48 +08:00
leafOfTree
9af7723bd1 Support custom blocks syntax and indent 2021-03-11 14:52:38 +08:00
leafOfTree
db71d38675 Fix vue3 keyword syntax for pangloss/vim-javascript 2021-02-22 16:56:17 +08:00
leafOfTree
f3813ab0e4 Preserve shiftwidth across loading sub-syntax indent files 2021-01-13 12:42:10 +08:00
leafOfTree
aa4ca7b23d Update doc 2021-01-05 13:45:21 +08:00
leafOfTree
d975ab169d Update code comments 2020-12-31 16:21:22 +08:00
leafOfTree
017a4002a8 Use syn-match to highlight both transition and transition-group 2020-12-31 16:16:46 +08:00
leaf
04c117ef48 Update lifecycle hooks keyword 2020-12-29 13:57:20 +08:00
leafOfTree
1fefdc214c Highlight transition attributes as htmlArg 2020-12-14 19:29:47 +08:00
leafOfTree
2802a661bd Not set local 'tabstop' and 'shiftwidth' in plugin 2020-12-11 10:13:11 +08:00
leafOfTree
fa9b8f3973 Update doc 2020-12-02 15:18:02 +08:00
leafOfTree
5a32d19c40 Extend cssValueNumber only for scss/sass 2020-12-02 15:17:44 +08:00
leafOfTree
7ab2e3b989 Extend cssValueNumber for scss/sass 2020-12-02 14:45:20 +08:00
leafOfTree
7fd71e34f5 Update doc 2020-11-20 12:31:03 +08:00
leafOfTree
a271e0fbe9 Update doc 2020-11-20 11:58:22 +08:00
leafOfTree
a5e3c10795 Enable fodexpr initially when the line number is less than 1000 2020-11-20 11:46:14 +08:00
leafOfTree
5f175b37ec Update doc 2020-11-19 19:13:18 +08:00
leafOfTree
9f0ed056b6 Support Vue3 composition API syntax 2020-11-19 17:35:22 +08:00
leafOfTree
b32c3a5bf7 Improve code format 2020-11-19 09:52:03 +08:00
leafOfTree
21a15e0c5a Update doc 2020-11-18 10:41:05 +08:00
leafOfTree
c7de4b5005 Update doc 2020-11-18 10:33:29 +08:00
leafOfTree
ad9f8a7f5f Make sure there is syntax to check subtype 2020-11-02 13:06:54 +08:00
leafOfTree
b63f0a9bdf Update doc 2020-10-13 15:31:03 +08:00
leafOfTree
de581bc075 Add Vue subtype onChange event 2020-10-13 14:51:25 +08:00
leafOfTree
09d82e6312 Avoid highlighting VueExpression in htmlComment 2020-10-13 13:52:48 +08:00
leafOfTree
a789d7622e Improve code format 2020-10-10 11:08:20 +08:00
leafOfTree
559d93c6ba Support async before keyword with arrow function 2020-10-10 10:35:30 +08:00
leafOfTree
b8e23259e2 Support async before vue keyword 2020-10-10 10:13:21 +08:00
leafOfTree
aa50c38902 Update doc 2020-08-12 15:17:35 +08:00
leafOfTree
9be92aa256 Highlight keywords with required indent 2020-08-12 15:13:38 +08:00
leafOfTree
069ad44389 Refactor keywords regexp 2020-08-12 15:01:50 +08:00
leafOfTree
042284ed01 Add a: to function arg 'lnum' 2020-08-12 14:38:49 +08:00
leafOfTree
9fb91c4869 Update doc 2020-08-10 11:50:30 +08:00
leafOfTree
c7fed8e6f3 Update doc 2020-07-29 09:14:33 +08:00
leafOfTree
d68a2c9bf9 Set syn-sync minlines to 100 2020-07-29 08:50:43 +08:00
leafOfTree
cacfb8a925 Add group name 'vueObjectKeyword' 2020-07-29 08:50:29 +08:00
leafOfTree
1d99d84ef2 Fix indent after empty tag 2020-07-17 09:05:13 +08:00
leafOfTree
b22a41fb6b Use a help function to get user config 2020-07-17 08:45:06 +08:00
leafOfTree
fe9c81657a Fix invalid link 2020-07-17 08:41:32 +08:00
leafOfTree
e952addbf7 Adjust comments length 2020-07-17 08:02:26 +08:00
leafOfTree
6c09d4787b Add option to highlight vue keywords 2020-07-17 07:46:28 +08:00
leafOfTree
bf0441f48c Use setf vue to avoid setting it twice 2020-07-16 13:31:39 +08:00
leafOfTree
110df06b08 Adjust gh pages config 2020-07-15 10:36:38 +08:00
leafOfTree
158cea262f Fix typo 2020-07-15 08:53:31 +08:00
leafOfTree
27acf5e9c7 Merge branch 'master' of https://github.com/leafOfTree/vim-vue-plugin 2020-07-14 19:58:31 +08:00
leafOfTree
5cd4474b21 Update doc 2020-07-14 19:57:51 +08:00
leafOfTree
b2454ed6b9 Keep backward compatible for use_sass option 2020-07-14 19:56:43 +08:00
leafOfTree
1eeb7b4d42 Support third party scss plugins 2020-07-14 19:53:19 +08:00
leafOfTree
93236bf598 Update doc 2020-07-14 08:06:39 +08:00
24 changed files with 1713 additions and 712 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
README.html
test.vue
.DS_STORE

View File

@@ -1,7 +1,14 @@
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 --depth=1 https://github.com/leafOfTree/test ../test
- git clone https://github.com/leafOfTree/test ../test --depth=1
- git clone https://github.com/digitaltoad/vim-pug ../vim-pug --depth=1
- git clone https://github.com/kchmck/vim-coffee-script ../vim-coffee-script --depth=1

220
README.md
View File

@@ -1,117 +1,198 @@
# 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 `filetype` is set 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 directives.
- 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].^
- A builtin `foldexpr` foldmethod.^
- [emmet-vim][10] HTML/CSS/JavaScript filetype detection.
- `.wpy` files from [WePY][6].
^: see Configuration for details. Relative plugins need to be installed.
- 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
let g:vim_vue_plugin_load_full_syntax = 1
```vim
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,
\}
```
| 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 scss/sass syntax for `<style lang="scss|sass">`. | 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 for `.vue`. 1 for `.wpy` |
| `g:vim_vue_plugin_highlight_vue_attr` | Highlight vue attribute value as expression instead of string. | 0 |
| `g:vim_vue_plugin_use_foldexpr` | Enable builtin `foldexpr` foldmethod. | 0 |
| `g:vim_vue_plugin_debug` | Echo debug messages in `messages` list. Useful to debug if unexpected indents occur. | 0 |
### Description
\*: 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`.
It has the following options
**Note**
- **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`
- `filetype` is set to `vue` so autocmds and other custom settings for `javascript` have to be manually enabled for `vue`.
- `g:vim_vue_plugin_load_full_syntax` currently applies to `HTML/Sass/Less`.
For *boolean* options below, set `1` to enable or `0` to disable
## Context based behavior
As there are more than one language in `.vue` file, the different behaviors like mapping or completion may be expected under different tags.
This plugin provides a function to get the tag where the cursor is in.
- `GetVueTag() => String` Return value is `'template'`, `'script'` or `'style'`.
- **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
```vim
autocmd FileType vue inoremap <buffer><expr> : InsertColon()
Only for demo. Try to set syntax as little as possible for performance.
function! InsertColon()
let tag = GetVueTag()
if tag == 'template'
return ':'
else
return ': '
endif
endfunction
```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,
\}
```
<img alt="screenshot" src="https://raw.githubusercontent.com/leafOfTree/leafOfTree.github.io/master/vue-config-example.png" />
You can still change options later as if they are global variables.
```vim
let g:vim_vue_plugin_config.foldexpr = 0
```
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
autocmd FileType vue inoremap <buffer><expr> : InsertColon()
function! InsertColon()
let tag = GetVueTag()
return tag == 'template' ? ':' : ': '
endfunction
```
- `GetVueSyntax() => String` Return value is one of `'html', 'javascript', 'css', 'scss', ...`
- `OnChangeVueSyntax(syntax)` An event listener that is called when syntax changes
You can define it in your `vimrc` to set local options based on current syntax
```vim
" 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:syntax =~ 'css'
setlocal comments=s1:/*,mb:*,ex:*/ commentstring&
else
setlocal commentstring=//%s
setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,://
endif
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
- runtime! syntax/css.vim
+ if !exists("b:current_loading_main_syntax")
@@ -119,6 +200,14 @@ For example, the builtin syntax `sass.vim` and `less.vim` in vim8.1 runtime and
+ endif
```
`$VIMRUNTIME/syntax/vue.vim`
```diff
- runtime! syntax/html.vim
+ if !exists("b:current_loading_main_syntax")
+ runtime! syntax/html.vim
+ endif
```
## Acknowledgments & Refs
- [mxw/vim-jsx][1]
@@ -129,18 +218,18 @@ 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
[3]: https://vuejs.org/v2/guide/single-file-components.html
[4]: https://github.com/digitaltoad/vim-pug
[5]: https://github.com/tpope/vim-pathogen
[6]: https://tencent.github.io/wepy
[6]: https://github.com/Tencent/wepy
[7]: https://github.com/junegunn/vim-plug
[8]: https://choosealicense.com/licenses/unlicense/
[9]: https://github.com/leafOfTree/vim-svelte-plugin
@@ -151,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

View File

@@ -1,3 +1,4 @@
theme: jekyll-theme-cayman
markdown: CommonMarkGhPages
extensins: ["table"]
commonmark:
extensions: ["table"]

View File

@@ -1,9 +1,334 @@
let s:name = 'vim-vue-plugin'
let s:debug = exists("g:vim_vue_plugin_debug")
\ && g:vim_vue_plugin_debug == 1
" Since vue#Log and vue#GetConfig are always called
" in syntax and indent files,
" this file will be sourced on opening the first vue file
function! s:GetConfig(name, default)
let name = 'g:vim_vue_plugin_'.a:name
let value = exists(name) ? eval(name) : a:default
if a:name == 'config'
let value = s:MergeUserConfigIntoDefault(value)
endif
return value
endfunction
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('*OnChangeVueSyntax') || exists('*OnChangeVueSubtype'))
augroup vim_vue_plugin
autocmd!
autocmd CursorMoved,CursorMovedI,WinEnter *.vue,*.wpy
\ call s:CheckSyntax()
augroup END
if exists('*OnChangeVueSyntax')
let s:OnChangeListener = function('OnChangeVueSyntax')
else
let s:OnChangeListener = function('OnChangeVueSubtype')
endif
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: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 syntax = vue#GetBlockSyntax(line('.'))
return syntax
endfunction
function! GetVueSyntax()
let syntax = vue#GetBlockSyntax(line('.'))
return syntax
endfunction
function! GetVueTag(...)
let lnum = a:0 > 0 ? a:1 : line('.')
return vue#GetBlockTag(lnum)
endfunction
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
let loaded = vue#LoadDefaultSyntax(group, syntax)
if !loaded
call vue#LoadFullSyntax(group, syntax)
endif
endif
endfunction
function! vue#LoadDefaultSyntax(group, syntax)
unlet! b:current_syntax
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, 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'
" 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()

View File

@@ -1 +1 @@
autocmd BufNewFile,BufRead *.vue,*.wpy set filetype=vue
autocmd BufNewFile,BufRead *.vue,*.wpy setf vue

View File

@@ -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'

View File

@@ -1,39 +1,22 @@
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Config {{{
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let s:use_foldexpr = exists("g:vim_vue_plugin_use_foldexpr")
\ && g:vim_vue_plugin_use_foldexpr == 1
"}}}
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 {{{
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
setlocal foldmethod=expr
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
@@ -49,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
@@ -104,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()

View File

@@ -1,243 +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.
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" 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*'
"}}}
if exists('b:did_indent') | finish |endif
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Config {{{
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let s:use_pug = exists("g:vim_vue_plugin_use_pug")
\ && g:vim_vue_plugin_use_pug == 1
let s:use_sass = exists("g:vim_vue_plugin_use_sass")
\ && g:vim_vue_plugin_use_sass == 1
let s:use_stylus = exists("g:vim_vue_plugin_use_stylus")
\ && g:vim_vue_plugin_use_stylus == 1
let s:use_coffee = exists("g:vim_vue_plugin_use_coffee")
\ && g:vim_vue_plugin_use_coffee == 1
let s:use_typescript = exists("g:vim_vue_plugin_use_typescript")
\ && g:vim_vue_plugin_use_typescript == 1
let s:test = exists('g:vim_vue_plugin_test')
let s:has_init_indent = 0
if !exists("g:vim_vue_plugin_has_init_indent")
let ext = expand("%:e")
if ext == 'wpy'
let s:has_init_indent = 1
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
""" Variables
let s:indent = {}
let s:block_tag = '<\/\?\('.join(keys(s:config_syntax), '\|').'\)'
" 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:SetVueIndent()
""" Settings
" JavaScript indentkeys
setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e,:
" XML indentkeys
setlocal indentkeys+=*<Return>,<>>,<<>,/
setlocal indentexpr=GetVueIndent()
endfunction
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
let file = 'indent/'.syntax.'.vim'
endif
elseif g:vim_vue_plugin_has_init_indent == 1
let s:has_init_indent = 1
endif
"}}}
return file
endfunction
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Load indent method {{{
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Use lib/indent/ files for compatibility
unlet! b:did_indent
runtime lib/indent/xml.vim
function! s:SetSyntaxIndentExpr(syntax_list)
let saved_shiftwidth = &shiftwidth
let saved_formatoptions = &formatoptions
unlet! b:did_indent
runtime lib/indent/css.vim
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
" Use normal indent files
unlet! b:did_indent
runtime! indent/javascript.vim
let b:javascript_indentexpr = &indentexpr
let &shiftwidth = saved_shiftwidth
let &formatoptions = saved_formatoptions
endfunction
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_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
"}}}
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Settings {{{
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
setlocal sw=2 ts=2
" 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 prevlnum = prevnonblank(v:lnum - 1)
let prevline = getline(prevlnum)
let prevsyns = s:SynsEOL(prevlnum)
let prevsyn = get(prevsyns, 0, '')
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:GetIndentByContext(tag, syntax)
let ind = -1
let prevline = getline(s:PrevNonBlankNonComment(v:lnum))
let curline = getline(v:lnum)
let cursyns = s:SynsEOL(v:lnum)
let cursyn = get(cursyns, 0, '')
if s:SynHTML(cursyn)
call vue#Log('syntax: html')
let ind = XmlIndentGet(v:lnum, 0)
if prevline =~? s:empty_tag
call vue#Log('previous line is an empty tag')
let ind = ind - &sw
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
" 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')
let ind = indent(v:lnum - 1)
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
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:SynStylus(cursyn)
call vue#Log('syntax: stylus')
let ind = GetStylusIndent()
elseif s:SynStyle(cursyn)
call vue#Log('syntax: style')
let ind = GetCSSIndent()
else
call vue#Log('syntax: javascript')
if len(b:javascript_indentexpr)
let ind = eval(b:javascript_indentexpr)
else
let ind = cindent(v:lnum)
endif
endif
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
if s:SynVueScriptOrStyle(cursyn) && ind < 1
call vue#Log('add initial indent')
let ind = &sw
endif
else
let prevlnum_noncomment = s:PrevNonBlacnkNonComment(v:lnum)
let prevline_noncomment = getline(prevlnum_noncomment)
if prevline_noncomment =~? s:vue_tag_start
call vue#Log('previous line is vue tag start')
" 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
call vue#Log('indent: '.ind)
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:SynStylus(syn)
return a:syn ==? 'cssStylusVueStyle'
endfunction
function! s:SynStyle(syn)
return a:syn =~? 'VueStyle'
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)
@@ -262,49 +175,133 @@ function! s:PrevMultilineEmptyTag(lnum)
endwhile
endfunction
function! s:PrevNonBlacnkNonComment(lnum)
let curline = getline(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! GetVueTag(...)
if a:0 > 0
let lnum = a:1
else
let lnum = getcurpos()[1]
endif
let cursyns = s:SynsEOL(lnum)
let syn = get(cursyns, 0, '')
function! s:AdjustJavaScriptIndent(ind)
let ind = a:ind
let prevlnum = prevnonblank(v:lnum - 1)
let prevline = getline(prevlnum)
let curline = getline(v:lnum)
if syn =~ 'VueTemplate'
let tag = 'template'
elseif syn =~ 'VueScript'
let tag = 'script'
elseif syn =~ 'VueStyle'
let tag = 'style'
else
let tag = ''
if prevline =~ '^\s*\w.*$' && curline =~ '^\s*\.'
call vue#LogWithLnum('current line is the first chain call')
let ind = indent(prevlnum) + &sw
endif
return tag
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
View 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

View File

@@ -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
View 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
View 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

View File

@@ -1,20 +1,31 @@
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Config {{{
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let s:highlight_vue_attr = exists("g:vim_vue_plugin_highlight_vue_attr")
\ && g:vim_vue_plugin_highlight_vue_attr == 1
")}}}
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let s:config = vue#GetConfig('config', {})
let s:attribute = s:config.attribute
"}}}
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" 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)'
syntax match VueComponentName containedin=htmlTagN '\v\C<[a-z0-9]+(-[a-z0-9]+)+>'
syntax match VueComponentName containedin=htmlTagN '\v\C<([A-Z][a-zA-Z0-9]+)+>'
syntax keyword VueComponentName containedin=htmlTagN component transition slot
syntax match VueAttr '\v(\S)@<![v:\@][^=/>[:blank:]]+(\=\"[^"]*\")?'
\ keepend
@@ -29,40 +40,52 @@ syntax region VueQuote contained
syntax match VueInject contained '\v\$\w*'
syntax region VueExpression
\ containedin=html.*
\ containedin=ALLBUT,htmlComment
\ matchgroup=VueBrace
\ 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="{{"
\ end="}}"
" Transition attributes
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
@@ -80,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

View 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
View 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
View 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
View File

@@ -0,0 +1 @@
syntax cluster htmlJavascript remove=javascriptParenthesisBlock

10
syntax/patch/sass.vim Normal file
View 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
View 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
View File

@@ -0,0 +1,5 @@
silent! syntax clear stylusDefinition
syntax region cssStylusDefinition matchgroup=cssBraces
\ contains=@StylusSyntax,cssStylusDefinition
\ contained containedin=cssStylusVueStyle
\ start="{" end="}"

View 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

View 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

View File

@@ -1,311 +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:load_full_syntax = exists("g:vim_vue_plugin_load_full_syntax")
\ && g:vim_vue_plugin_load_full_syntax == 1
let s:use_pug = exists("g:vim_vue_plugin_use_pug")
\ && g:vim_vue_plugin_use_pug == 1
let s:use_less = exists("g:vim_vue_plugin_use_less")
\ && g:vim_vue_plugin_use_less == 1
let s:use_sass = exists("g:vim_vue_plugin_use_sass")
\ && g:vim_vue_plugin_use_sass == 1
let s:use_stylus = exists("g:vim_vue_plugin_use_stylus")
\ && g:vim_vue_plugin_use_stylus == 1
let s:use_coffee = exists("g:vim_vue_plugin_use_coffee")
\ && g:vim_vue_plugin_use_coffee == 1
let s:use_typescript = exists("g:vim_vue_plugin_use_typescript")
\ && g:vim_vue_plugin_use_typescript == 1
"}}}
" <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')
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Functions {{{
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! s:LoadSyntax(group, type)
if s:load_full_syntax
call s:LoadFullSyntax(a:group, a:type)
else
call s:LoadDefaultSyntax(a:group, a:type)
function! s:Init()
""" Configs
let s:config = vue#GetConfig('config', {})
let s:config_syntax = s:config.syntax
" For advanced users, it can be used to avoid overload
let b:current_loading_main_syntax = 'vue'
endfunction
function! s:GetGroupNameForLoading(syntax)
return '@'.a:syntax
endfunction
" 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
return name
endfunction
" 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
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
" For specific syntax, we need to handle it specially
function! s:BeforeLoadSyntax(syntax)
let syntax = a:syntax
" 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
function! s:AfterLoadSyntax(syntax)
let syntax = a:syntax
call s:LoadPatchSyntax(syntax)
call s:LoadAfterSyntax(syntax)
endfunction
function! s:LoadPatchSyntax(syntax)
let file = s:patch_path.'/'.a:syntax.'.vim'
if filereadable(file)
execute 'syntax include '.file
endif
endfunction
function! s:LoadDefaultSyntax(group, type)
unlet! b:current_syntax
let syntaxPaths = ['$VIMRUNTIME', '$VIM/vimfiles', '$HOME/.vim']
for path in syntaxPaths
let file = expand(path).'/syntax/'.a:type.'.vim'
if filereadable(file)
execute 'syntax include '.a:group.' '.file
function! s:LoadAfterSyntax(syntax)
execute 'runtime! after/syntax/'.a:syntax.'.vim'
endfunction
function! s:GetSyntaxLangName(syntax)
let syntax = a:syntax
if syntax == 'typescript'
let syntax = 'ts'
endif
return syntax
endfunction
function! s:SetSyntax(block, syntax, has_lang)
let block = a:block
let syntax = a:syntax
let has_lang = a:has_lang
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 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
" Load all syntax files in 'runtimepath'
" Useful if there is no default syntax file provided by vim
function! s:LoadFullSyntax(group, type)
call s:SetCurrentSyntax(a:type)
execute 'syntax include '.a:group.' syntax/'.a:type.'.vim'
function! s:HighlightVue()
call s:HighlightVueTag()
call s:HighlightVueStyle()
endfunction
" Settings to avoid syntax overload
function! s:SetCurrentSyntax(type)
if a:type == 'coffee'
syntax cluster coffeeJS contains=@htmlJavaScript
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
" Avoid overload of `javascript.vim`
let b:current_syntax = 'vue'
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
unlet! b:current_syntax
setlocal iskeyword+=-
endif
endfunction
"}}}
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Load main syntax {{{
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Load syntax/html.vim to syntax group, which loads full JavaScript and CSS
" syntax. It defines group htmlJavaScript and htmlCss.
call s:LoadSyntax('@HTMLSyntax', 'html')
function! s:SetCurrentSyntax()
let b:current_syntax = 'vue'
endfunction
" Load vue-html syntax
runtime syntax/vue-html.vim
function! s:SetExtraSyntax()
call s:SetIsKeyword()
call s:HighlightVue()
call s:SetCurrentSyntax()
endfunction
" Avoid overload.
if hlexists('cssTagName') == 0
call s:LoadSyntax('@htmlCss', 'css')
endif
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
" Avoid overload
if hlexists('javaScriptComment') == 0
call vue#Log('load javascript cluster')
call s:LoadSyntax('@htmlJavaScript', 'javascript')
endif
"}}}
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Load pre-processors syntax {{{
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" If pug is enabled, load vim-pug syntax
if s:use_pug
call s:LoadFullSyntax('@PugSyntax', 'pug')
syn cluster htmlJavascript remove=javascriptParenthesisBlock
endif
" If less is enabled, load less syntax
if s:use_less
call s:LoadSyntax('@LessSyntax', 'less')
runtime! after/syntax/less.vim
endif
" If sass is enabled, load sass syntax
if s:use_sass
call s:LoadSyntax('@SassSyntax', 'sass')
runtime! after/syntax/sass.vim
endif
" If stylus is enabled, load stylus syntax
if s:use_stylus
call s: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 s:LoadFullSyntax('@htmlCoffeeScript', 'coffee')
endif
" If TypeScript is enabled, load the syntax.
if s:use_typescript
call s: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=@HTMLSyntax
" When template code is not well indented
syntax region htmlVueTemplate fold
\ start=+<template[^>]*>+
\ end=+</template>\ze\n\(^$\n\)*<\(script\|style\)+
\ keepend contains=@HTMLSyntax
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=@SassSyntax,vueTag
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
"}}}
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" 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,$,-
endif
else
setlocal iskeyword+=-
endif
" 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
\ contained containedin=cssLessVueStyle
\ start="{" end="}"
endif
if s:use_sass
silent! syntax clear sassDefinition
syntax region cssSassDefinition matchgroup=cssBraces contains=@SassSyntax
\ contained containedin=sassVueStyle,cssScssVueStyle
\ start="{" end="}"
endif
if s:use_stylus
silent! syntax clear stylusDefinition
syntax region cssStylusDefinition matchgroup=cssBraces contains=@StylusSyntax
\ contained containedin=cssStylusVueStyle
\ start="{" end="}"
endif
" Avoid css syntax interference
silent! syntax clear cssUnitDecorators
" Have to use a different name
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
" Coffee
if s:use_coffee
silent! syntax clear coffeeConstant
syn match coffeeConstant '\v<\u\C[A-Z0-9_]+>' display
\ containedin=@coffeeIdentifier
endif
" JavaScript
" Number with minus
syntax match javaScriptNumber '\v<-?\d+L?>|0[xX][0-9a-fA-F]+>'
\ containedin=@javascriptVueScript display
" HTML
" Clear htmlHead that may cause highlighting out of bounds
silent! syntax clear htmlHead
" html5 data-*
syntax match htmlArg '\v<data(-[.a-z0-9]+)+>' containedin=@HTMLSyntax
"}}}
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Syntax sync {{{
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
syntax sync clear
syntax sync minlines=10
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 b:current_syntax = 'vue'
" vim: fdm=marker
" Entry
call VimVuePluginSyntaxMain()