Skip to content

Commit 2ea2e1d

Browse files
committed
Improve heuristic for detecting jsxRegion continuation across lines
Instead of only checking that we're still in any jsxRegion, we can do better by verifying that the jsxRegion nesting level is the same before and after the line break. Closes #98.
1 parent f320f04 commit 2ea2e1d

File tree

1 file changed

+27
-13
lines changed

1 file changed

+27
-13
lines changed

after/indent/jsx.vim

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,30 +51,44 @@ fu! SynXMLish(syns)
5151
return SynAttrXMLish(get(a:syns, -1))
5252
endfu
5353

54-
" Check if a synstack has any XMLish attribute.
55-
fu! SynXMLishAny(syns)
56-
for synattr in a:syns
57-
if SynAttrXMLish(synattr)
58-
return 1
59-
endif
60-
endfor
61-
return 0
62-
endfu
63-
6454
" Check if a synstack denotes the end of a JSX block.
6555
fu! SynJSXBlockEnd(syns)
6656
return get(a:syns, -1) =~ '\%(js\|javascript\)Braces' &&
6757
\ SynAttrXMLish(get(a:syns, -2))
6858
endfu
6959

60+
" Determine how many jsxRegions deep a synstack is.
61+
fu! SynJSXDepth(syns)
62+
return len(filter(copy(a:syns), 'v:val ==# "jsxRegion"'))
63+
endfu
64+
65+
" Check whether `cursyn' continues the same jsxRegion as `prevsyn'.
66+
fu! SynJSXContinues(cursyn, prevsyn)
67+
let curdepth = SynJSXDepth(a:cursyn)
68+
let prevdepth = SynJSXDepth(a:prevsyn)
69+
70+
" In most places, we expect the nesting depths to be the same between any
71+
" two consecutive positions within a jsxRegion (e.g., between a parent and
72+
" child node, between two JSX attributes, etc.). The exception is between
73+
" sibling nodes, where after a completed element (with depth N), we return
74+
" to the parent's nesting (depth N - 1). This case is easily detected,
75+
" since it is the only time when the top syntax element in the synstack is
76+
" jsxRegion---specifically, the jsxRegion corresponding to the parent.
77+
return prevdepth == curdepth ||
78+
\ (prevdepth == curdepth + 1 && get(a:cursyn, -1) ==# 'jsxRegion')
79+
endfu
80+
7081
" Cleverly mix JS and XML indentation.
7182
fu! GetJsxIndent()
7283
let cursyn = SynSOL(v:lnum)
7384
let prevsyn = SynEOL(v:lnum - 1)
7485

75-
" Use XML indenting if the syntax at the end of the previous line was either
76-
" JSX or was the closing brace of a jsBlock whose parent syntax was JSX.
77-
if (SynXMLish(prevsyn) || SynJSXBlockEnd(prevsyn)) && SynXMLishAny(cursyn)
86+
" Use XML indenting iff:
87+
" - the syntax at the end of the previous line was either JSX or was the
88+
" closing brace of a jsBlock whose parent syntax was JSX; and
89+
" - the current line continues the same jsxRegion as the previous line.
90+
if (SynXMLish(prevsyn) || SynJSXBlockEnd(prevsyn)) &&
91+
\ SynJSXContinues(cursyn, prevsyn)
7892
let ind = XmlIndentGet(v:lnum, 0)
7993

8094
" Align '/>' and '>' with '<' for multiline tags.

0 commit comments

Comments
 (0)