1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
if has_key(g:polyglot_is_disabled, 'svelte')
finish
endif
" Vim indent file
" Language: Svelte 3 (HTML/JavaScript)
" Author: Evan Lecklider <evan@lecklider.com>
" Maintainer: Evan Lecklide <evan@lecklider.com>
" URL: https://github.com/evanleck/vim-svelte
if exists("b:did_indent")
finish
endif
runtime! indent/html.vim
unlet! b:did_indent
let s:html_indent = &l:indentexpr
let b:did_indent = 1
if !exists('g:svelte_indent_script')
let g:svelte_indent_script = 1
endif
if !exists('g:svelte_indent_style')
let g:svelte_indent_style = 1
endif
setlocal indentexpr=GetSvelteIndent()
setlocal indentkeys=o,O,*<Return>,<>>,{,},0),0],!^F,;,=:else,=:then,=:catch,=/if,=/each,=/await
" Only define the function once.
if exists('*GetSvelteIndent')
finish
endif
function! GetSvelteIndent()
let current_line_number = v:lnum
if current_line_number == 0
return 0
endif
let current_line = getline(current_line_number)
" Opening script and style tags should be all the way outdented.
if current_line =~ '^\s*</\?\(script\|style\)'
return 0
endif
let previous_line_number = prevnonblank(current_line_number - 1)
let previous_line = getline(previous_line_number)
let previous_line_indent = indent(previous_line_number)
" The inside of scripts an styles should be indented unless disabled.
if previous_line =~ '^\s*<script'
if g:svelte_indent_script
return previous_line_indent + shiftwidth()
else
return previous_line_indent
endif
endif
if previous_line =~ '^\s*<style'
if g:svelte_indent_style
return previous_line_indent + shiftwidth()
else
return previous_line_indent
endif
endif
execute "let indent = " . s:html_indent
" For some reason, the HTML CSS indentation keeps indenting the next line over
" and over after each style declaration.
if searchpair('<style>', '', '</style>', 'bW') && previous_line =~ ';$' && current_line !~ '}'
return previous_line_indent
endif
" "/await" or ":catch" or ":then"
if current_line =~ '^\s*{\s*\/await' || current_line =~ '^\s*{\s*:\(catch\|then\)'
let await_start = searchpair('{\s*#await\>', '', '{\s*\/await\>', 'bW')
if await_start
return indent(await_start)
endif
endif
" "/each"
if current_line =~ '^\s*{\s*\/each'
let each_start = searchpair('{\s*#each\>', '', '{\s*\/each\>', 'bW')
if each_start
return indent(each_start)
endif
endif
" "/if"
if current_line =~ '^\s*{\s*\/if'
let if_start = searchpair('{\s*#if\>', '', '{\s*\/if\>', 'bW')
if if_start
return indent(if_start)
endif
endif
" ":else" is tricky because it can match an opening "#each" _or_ an opening
" "#if", so we try to be smart and look for the closest of the two.
if current_line =~ '^\s*{\s*:else'
let if_start = searchpair('{\s*#if\>', '', '{\s*\/if\>', 'bW')
" If it's an "else if" then we know to look for an "#if"
if current_line =~ '^\s*{\s*:else if' && if_start
return indent(if_start)
else
" The greater line number will be closer to the cursor position because
" we're searching backward.
return indent(max([if_start, searchpair('{\s*#each\>', '', '{\s*\/each\>', 'bW')]))
endif
endif
" "#if" or "#each"
if previous_line =~ '^\s*{\s*#\(if\|each\|await\)'
return previous_line_indent + shiftwidth()
endif
" ":else" or ":then"
if previous_line =~ '^\s*{\s*:\(else\|catch\|then\)'
return previous_line_indent + shiftwidth()
endif
" Custom element juggling for abnormal self-closing tags (<Widget />),
" capitalized component tags (<Widget></Widget>), and custom svelte tags
" (<svelte:head></svelte:head>).
if synID(previous_line_number, match(previous_line, '\S') + 1, 0) == hlID('htmlTag')
\ && synID(current_line_number, match(current_line, '\S') + 1, 0) != hlID('htmlEndTag')
let indents_match = indent == previous_line_indent
let previous_closes = previous_line =~ '/>$'
if indents_match && !previous_closes && previous_line =~ '<\(\u\|\l\+:\l\+\)'
return previous_line_indent + shiftwidth()
elseif !indents_match && previous_closes
return previous_line_indent
endif
endif
return indent
endfunction
|