summaryrefslogtreecommitdiffstats
path: root/autoload
diff options
context:
space:
mode:
Diffstat (limited to 'autoload')
-rw-r--r--autoload/go/config.vim28
-rw-r--r--autoload/jsx_pretty/indent.vim733
2 files changed, 592 insertions, 169 deletions
diff --git a/autoload/go/config.vim b/autoload/go/config.vim
index ee9a0bb9..f4ec3ccf 100644
--- a/autoload/go/config.vim
+++ b/autoload/go/config.vim
@@ -463,6 +463,14 @@ function! go#config#HighlightVariableDeclarations() abort
return get(g:, 'go_highlight_variable_declarations', 0)
endfunction
+function! go#config#HighlightDiagnosticErrors() abort
+ return get(g:, 'go_highlight_diagnostic_errors', 1)
+endfunction
+
+function! go#config#HighlightDiagnosticWarnings() abort
+ return get(g:, 'go_highlight_diagnostic_warnings', 1)
+endfunction
+
function! go#config#HighlightDebug() abort
return get(g:, 'go_highlight_debug', 1)
endfunction
@@ -487,6 +495,26 @@ function! go#config#Updatetime() abort
return go_updatetime == 0 ? &updatetime : go_updatetime
endfunction
+function! go#config#ReferrersMode() abort
+ return get(g:, 'go_referrers_mode', 'gopls')
+endfunction
+
+function! go#config#GoplsCompleteUnimported() abort
+ return get(g:, 'go_gopls_complete_unimported', 0)
+endfunction
+
+function! go#config#GoplsDeepCompletion() abort
+ return get(g:, 'go_gopls_deep_completion', 1)
+endfunction
+
+function! go#config#GoplsFuzzyMatching() abort
+ return get(g:, 'go_gopls_fuzzy_matching', 1)
+endfunction
+
+function! go#config#GoplsUsePlaceholders() abort
+ return get(g:, 'go_gopls_use_placeholders', 0)
+endfunction
+
" Set the default value. A value of "1" is a shortcut for this, for
" compatibility reasons.
if exists("g:go_gorename_prefill") && g:go_gorename_prefill == 1
diff --git a/autoload/jsx_pretty/indent.vim b/autoload/jsx_pretty/indent.vim
index 15e177e0..03bdf29b 100644
--- a/autoload/jsx_pretty/indent.vim
+++ b/autoload/jsx_pretty/indent.vim
@@ -10,209 +10,604 @@ else
endfunction
endif
-" Get the syntax group of start of line
-function! s:syn_sol(lnum)
- let line = getline(a:lnum)
- let sol = matchstr(line, '^\s*')
- return map(synstack(a:lnum, len(sol) + 1), 'synIDattr(v:val, "name")')
+" Regexp for the start tag
+let s:start_tag = '<\_s*\%(>\|\${\|\%(\<[-:._$A-Za-z0-9]\+\>\)\)'
+" Regexp for the end tag
+let s:end_tag = '\%(<\_s*/\_s*\%(\<[-:._$A-Za-z0-9]\+\>\)\_s*>\|/\_s*>\)'
+
+" Get the syntax stack at the given position
+function s:syntax_stack_at(lnum, col)
+ return map(synstack(a:lnum, a:col), 'synIDattr(v:val, "name")')
endfunction
-" Get the syntax group of end of line
-function! s:syn_eol(lnum)
- let lnum = prevnonblank(a:lnum)
- let col = strlen(getline(lnum))
- return map(synstack(lnum, col), 'synIDattr(v:val, "name")')
+" Get the syntax at the given position
+function s:syntax_at(lnum, col)
+ return synIDattr(synID(a:lnum, a:col, 1), 'name')
endfunction
-function! s:prev_indent(lnum)
- let lnum = prevnonblank(a:lnum - 1)
- return indent(lnum)
+" Get the start col of the non-space charactor
+function s:start_col(lnum)
+ return len(matchstr(getline(a:lnum), '^\s*')) + 1
endfunction
-function! s:prev_line(lnum)
- let lnum = prevnonblank(a:lnum - 1)
- return substitute(getline(lnum), '^\s*\|\s*$', '', 'g')
+" Get the end col of the non-space charactor
+function s:end_col(lnum)
+ return len(substitute(getline(a:lnum), '\s*$', '', 'g'))
endfunction
-function! s:syn_attr_jsx(synattr)
- return a:synattr =~? "^jsx"
+" Get the start syntax of a given line number
+function s:start_syntax(lnum)
+ return s:syntax_at(a:lnum, s:start_col(a:lnum))
endfunction
-function! s:syn_xmlish(syns)
- return s:syn_attr_jsx(get(a:syns, -1))
+" Get the end syntax of a given line number
+function s:end_syntax(lnum)
+ let end_col = len(substitute(getline(a:lnum), '\s*$', '', 'g'))
+ return s:syntax_at(a:lnum, end_col)
endfunction
-function! s:syn_jsx_element(syns)
- return get(a:syns, -1) =~? 'jsxElement'
+" The skip function for searchpair
+function s:skip_if_not(current_lnum, ...)
+ " Skip the match in current line
+ if line('.') == a:current_lnum
+ return 1
+ endif
+
+ let syntax = s:syntax_at(line('.'), col('.'))
+ return syntax !~? join(a:000, '\|')
endfunction
-function! s:syn_js_comment(syns)
- return get(a:syns, -1) =~? 'Comment$'
+" Whether the specified stytax group is an jsx-related syntax
+function s:is_jsx(syntax_name)
+ return a:syntax_name =~ '^jsx' && a:syntax_name !=? 'jsxEscapeJs'
endfunction
-function! s:syn_jsx_escapejs(syns)
- return get(a:syns, -1) =~? '\(\(js\(Template\)\?\|javaScript\(Embed\)\?\|typescript\)Braces\|javascriptTemplateSB\|typescriptInterpolationDelimiter\)' &&
- \ (get(a:syns, -2) =~? 'jsxEscapeJs' ||
- \ get(a:syns, -3) =~? 'jsxEscapeJs')
+" Whether the specified line is start with jsx-related syntax
+function s:start_with_jsx(lnum)
+ let start_syntax = s:start_syntax(a:lnum)
+ return s:is_jsx(start_syntax)
endfunction
-function! s:syn_jsx_attrib(syns)
- return len(filter(copy(a:syns), 'v:val =~? "jsxAttrib"'))
+" Whether the specified line is end with jsx-related syntax
+function s:end_with_jsx(lnum)
+ let end_syntax = s:end_syntax(a:lnum)
+ return s:is_jsx(end_syntax)
endfunction
-let s:start_tag = '<\s*\([-:_\.\$0-9A-Za-z]\+\|>\)'
-" match `/end_tag>` and `//>`
-let s:end_tag = '/\%(\s*[-:_\.\$0-9A-Za-z]*\s*\|/\)>'
-let s:opfirst = '^' . get(g:,'javascript_opfirst',
- \ '\C\%([<>=,.?^%|/&]\|\([-:+]\)\1\@!\|\*\+\|!=\|in\%(stanceof\)\=\>\)')
+" Whether the specified line is comment related syntax
+function s:is_comment(syntax)
+ return a:syntax =~? 'comment'
+endfunction
-function! jsx_pretty#indent#get(js_indent)
- let lnum = v:lnum
- let line = substitute(getline(lnum), '^\s*\|\s*$', '', 'g')
- let current_syn = s:syn_sol(lnum)
- let current_syn_eol = s:syn_eol(lnum)
- let prev_line_num = prevnonblank(lnum - 1)
- let prev_syn_sol = s:syn_sol(prev_line_num)
- let prev_syn_eol = s:syn_eol(prev_line_num)
- let prev_line = s:prev_line(lnum)
- let prev_ind = s:prev_indent(lnum)
-
- if s:syn_xmlish(current_syn)
-
- if !s:syn_xmlish(prev_syn_sol)
- \ && !s:syn_jsx_escapejs(prev_syn_sol)
- \ && !s:syn_jsx_escapejs(prev_syn_eol)
- \ && !s:syn_js_comment(prev_syn_sol)
- if line =~ '^/\s*>' || line =~ '^<\s*' . s:end_tag
- return prev_ind
- else
- return prev_ind + s:sw()
+" Whether the specified line is embedded comment in jsxTag
+function s:is_embedded_comment(lnum)
+ let start_col = s:start_col(a:lnum)
+ let syntax_stack = s:syntax_stack_at(a:lnum, start_col)
+ let last = get(syntax_stack, -1)
+ let last_2nd = get(syntax_stack, -2)
+
+ " Patch code for pangloss/vim-javascript
+ " <div
+ " /* hello */ <-- syntax stack is [..., jsxTag, jsComment, jsComment]
+ " >
+ if last_2nd =~ 'comment'
+ let last_2nd = get(syntax_stack, -3)
+ endif
+
+ return last =~? 'comment' && last_2nd =~? 'jsxTag' &&
+ \ trim(getline(a:lnum)) =~ '\%(^/[*/]\)\|\%(\*/$\)'
+endfunction
+
+" Whether the specified stytax group is the opening tag
+function s:is_opening_tag(syntax)
+ return a:syntax =~? 'jsxOpenPunct'
+endfunction
+
+" Whether the specified stytax group is the closing tag
+function s:is_closing_tag(syntax)
+ return a:syntax =~? 'jsxClose'
+endfunction
+
+" Whether the specified stytax group is the jsxAttrib
+function s:is_jsx_attr(syntax)
+ return a:syntax =~? 'jsxAttrib'
+endfunction
+
+" Whether the specified syntax group is the jsxElement
+function s:is_jsx_element(syntax)
+ return a:syntax =~? 'jsxElement'
+endfunction
+
+" Whether the specified syntax group is the jsxTag
+function s:is_jsx_tag(syntax)
+ return a:syntax =~? 'jsxTag'
+endfunction
+
+" Whether the specified syntax group is the jsxBraces
+function s:is_jsx_brace(syntax)
+ return a:syntax =~? 'jsxBraces'
+endfunction
+
+" Whether the specified syntax group is the jsxComment
+function s:is_jsx_comment(syntax)
+ return a:syntax =~? 'jsxComment'
+endfunction
+
+" Whether the specified syntax group is the jsxComment
+function s:is_jsx_backticks(syntax)
+ return a:syntax =~? 'jsxBackticks'
+endfunction
+
+" Get the prvious line number
+function s:prev_lnum(lnum)
+ return prevnonblank(a:lnum - 1)
+endfunction
+
+" Given a lnum and get the information of its previous line
+function s:prev_info(lnum)
+ let prev_lnum = s:prev_lnum(a:lnum)
+ let prev_start_syntax = s:start_syntax(prev_lnum)
+ let prev_end_syntax = s:end_syntax(prev_lnum)
+
+ return [prev_lnum, prev_start_syntax, prev_end_syntax]
+endfunction
+
+" Get the length difference between syntax stack a and b
+function s:syntax_stack_length_compare(lnum_a, col_a, lnum_b, col_b)
+ let stack_a = s:syntax_stack_at(a:lnum_a, a:col_a)
+ let stack_b = s:syntax_stack_at(a:lnum_b, a:col_b)
+
+ return len(stack_a) - len(stack_b)
+endfunction
+
+" Determine whether child is a element of parent
+function s:is_element_of(parent_lnum, child_lnum)
+ let parent_stack = s:syntax_stack_at(a:parent_lnum, s:start_col(a:parent_lnum))
+ let child_stack = s:syntax_stack_at(a:child_lnum, s:start_col(a:child_lnum))
+
+ let element_index = len(child_stack) - index(reverse(child_stack), 'jsxElement')
+ let rest = parent_stack[element_index:]
+
+ return index(rest, 'jsxElement') == -1
+endfunction
+
+" Compute the indention of the opening tag
+function s:jsx_indent_opening_tag(lnum)
+ let [prev_lnum, prev_start_syntax, prev_end_syntax] = s:prev_info(a:lnum)
+
+ " If current line is start with >
+ if trim(getline(a:lnum)) =~ '^>'
+ let pair_line = searchpair('<', '', '>', 'bW', 's:skip_if_not(a:lnum, "jsxOpenPunct", "jsxClose")')
+ return indent(pair_line)
+ endif
+
+ " If both the start and the end of the previous line are not jsx-related syntax
+ " return (
+ " <div></div> <--
+ " )
+ if !s:end_with_jsx(prev_lnum) && !s:start_with_jsx(prev_lnum)
+ " return -1, so that it will use the default js indent function
+ return -1
+ endif
+
+ " If the end of the previous line is not jsx-related syntax
+ " [
+ " <div></div>,
+ " <div></div> <--
+ " ]
+ " should not affect
+ " <div
+ " render={() => (
+ " <div> <--
+ " </div>
+ " )}
+ " >
+ " </div>
+ " <div>
+ " {items.map(() => (
+ " <Item /> <--
+ " ))}
+ " </div>
+ if !s:end_with_jsx(prev_lnum) &&
+ \ !s:is_jsx_attr(prev_start_syntax) &&
+ \ !s:is_jsx_brace(prev_start_syntax)
+ return indent(prev_lnum)
+ endif
+
+ " If the start of the previous line is not jsx-related syntax
+ " return <div>
+ " <div></div> <--
+ " </div>
+ if !s:start_with_jsx(prev_lnum)
+ return indent(prev_lnum) + s:sw()
+ endif
+ endif
+
+ " <div>
+ " <span>
+ " </span>
+ " <div> <--
+ " </div>
+ " </div>
+ if s:is_closing_tag(prev_start_syntax)
+ return indent(prev_lnum)
+ endif
+
+ " If the previous line is end with a closing tag
+ " <div>
+ " <br />
+ " <div></div> <--
+ " </div>
+ " should not affect case like
+ " <div><br />
+ " <span> <--
+ " </div>
+ if s:is_closing_tag(prev_end_syntax) &&
+ \ s:syntax_stack_length_compare(
+ \ prev_lnum, s:start_col(prev_lnum), prev_lnum, s:end_col(prev_lnum)) == 2
+ return indent(prev_lnum)
+ endif
+
+ " If the start of the previous line is the jsxElement
+ " <div>
+ " hello
+ " <div></div> <--
+ " </div>
+ if s:is_jsx_element(prev_start_syntax) ||
+ \ s:is_jsx_comment(prev_start_syntax)
+ return indent(prev_lnum)
+ endif
+
+ " If the start of the prvious line is the jsxBraces {
+ " <div>
+ " {foo}
+ " <div></div> <--
+ " </div>
+ " should not affect case like
+ " <div>
+ " {
+ " <div></div> <--
+ " }
+ " </div>
+ if s:is_jsx_brace(prev_start_syntax) &&
+ \ trim(getline(prev_lnum)) =~ '^[$]\?{' &&
+ \ s:syntax_stack_length_compare(
+ \ prev_lnum, s:start_col(prev_lnum), a:lnum, s:start_col(a:lnum)) == -2
+ return indent(prev_lnum)
+ endif
+
+ " If the start of the prvious line is the jsxBraces }
+ " <div>
+ " {
+ " foo
+ " }
+ " <div></div> <--
+ " </div>
+ if s:is_jsx_brace(prev_start_syntax) &&
+ \ trim(getline(prev_lnum)) =~ '}' &&
+ \ s:syntax_stack_length_compare(
+ \ prev_lnum, s:start_col(prev_lnum), a:lnum, s:start_col(a:lnum)) == -3
+ return indent(prev_lnum)
+ endif
+
+ " Otherwise, indent s:sw() spaces
+ return indent(prev_lnum) + s:sw()
+endfunction
+
+" Compute the indention of the closing tag
+function s:jsx_indent_closing_tag(lnum)
+ let pair_line = searchpair(s:start_tag, '', s:end_tag, 'bW', 's:skip_if_not(a:lnum, "jsxOpenPunct", "jsxClose")')
+ return pair_line ? indent(pair_line) : indent(a:lnum)
+endfunction
+
+" Compute the indention of the jsxAttrib
+function s:jsx_indent_attr(lnum)
+ let [prev_lnum, prev_start_syntax, prev_end_syntax] = s:prev_info(a:lnum)
+
+ " If the start of the previous line is not jsx-related syntax
+ " return <div
+ " attr="hello" <--
+ " >
+ " should not affect
+ " <div
+ " // comment here
+ " attr="hello"
+ " >
+ " </div>
+ if !s:start_with_jsx(prev_lnum) &&
+ \ !s:is_comment(prev_start_syntax)
+ return indent(prev_lnum) + s:sw()
+ endif
+
+ " If the start of the previous line is the opening tag
+ " <div
+ " title="title" <--
+ " >
+ if s:is_opening_tag(prev_start_syntax)
+ return indent(prev_lnum) + s:sw()
+ endif
+
+ " Otherwise, align the attribute with its previous line
+ return indent(prev_lnum)
+endfunction
+
+" Compute the indentation of the jsxElement
+function s:jsx_indent_element(lnum)
+ let [prev_lnum, prev_start_syntax, prev_end_syntax] = s:prev_info(a:lnum)
+
+ " Fix test case like
+ " <div|> <-- press enter
+ " should indent as
+ " <div
+ " > <--
+ if trim(getline(a:lnum)) =~ '^>' && !s:is_opening_tag(prev_end_syntax)
+ return indent(prev_lnum)
+ endif
+
+ " If the start of the previous line is start with >
+ " <div
+ " attr="foo"
+ " >
+ " text <--
+ " </div>
+ if s:is_opening_tag(prev_start_syntax) &&
+ \ trim(getline(prev_lnum)) =~ '^>$'
+ return indent(prev_lnum) + s:sw()
+ endif
+
+ " <div>
+ " text <--
+ " </div>
+ " should not affect case like
+ " <div>
+ " <br />
+ " hello <--
+ " </div>
+ if s:is_opening_tag(prev_start_syntax) &&
+ \ s:is_element_of(prev_lnum, a:lnum)
+ return indent(prev_lnum) + s:sw()
+ endif
+
+ " return <div>
+ " text <--
+ " </div>
+ if !s:start_with_jsx(prev_lnum)
+ return indent(prev_lnum) + s:sw()
+ endif
+
+ " Otherwise, align with the previous line
+ " <div>
+ " {foo}
+ " text <--
+ " </div>
+ return indent(prev_lnum)
+endfunction
+
+" Compute the indentation of jsxBraces
+function s:jsx_indent_brace(lnum)
+ let [prev_lnum, prev_start_syntax, prev_end_syntax] = s:prev_info(a:lnum)
+
+ " If the start of the previous line is start with >
+ " <div
+ " attr="foo"
+ " >
+ " {foo} <--
+ " </div>
+ if s:is_opening_tag(prev_start_syntax) &&
+ \ trim(getline(prev_lnum)) =~ '^>$'
+ return indent(prev_lnum) + s:sw()
+ endif
+
+ " <div>
+ " {foo} <--
+ " </div>
+ " should not affect case like
+ " <div>
+ " <br />
+ " {foo} <--
+ " text
+ " {foo} <--
+ " </div>
+ if s:is_opening_tag(prev_start_syntax) &&
+ \ s:syntax_stack_length_compare(
+ \ prev_lnum, s:start_col(prev_lnum), a:lnum, s:start_col(a:lnum)) == 1
+ return indent(prev_lnum) + s:sw()
+ endif
+
+ " If current line is the close brace }
+ if trim(getline(a:lnum)) =~ '^}'
+ let pair_line = searchpair('{', '', '}', 'bW', 's:skip_if_not(a:lnum, "jsxBraces")')
+ return indent(pair_line)
+ endif
+
+ " return <div>
+ " {foo} <--
+ " </div>
+ " should not affect
+ " <div
+ " // js comment
+ " {...props} <--
+ " >
+ " </div>
+ if !s:start_with_jsx(prev_lnum) &&
+ \ !s:is_comment(prev_start_syntax)
+ return indent(prev_lnum) + s:sw()
+ endif
+
+ return indent(prev_lnum)
+endfunction
+
+" Compute the indentation of the comment
+function s:jsx_indent_comment(lnum)
+ let [prev_lnum, prev_start_syntax, prev_end_syntax] = s:prev_info(a:lnum)
+
+ " If current line is jsxComment
+ if s:is_jsx_comment(s:start_syntax(a:lnum))
+ let line = trim(getline(a:lnum))
+ if line =~ '^<!--'
+ " Patch code for yajs.vim
+ " ${logs.map(log => html`
+ " <${Log} class="log" ...${log} />
+ " `)} <-- The backtick here is Highlighted as javascriptTemplate
+ " <!-- <-- Correct the indentation here
+ if !s:start_with_jsx(prev_lnum) && s:end_with_jsx(prev_lnum)
+ return indent(prev_lnum)
endif
- elseif !s:syn_xmlish(prev_syn_sol) && !s:syn_js_comment(prev_syn_sol) && s:syn_jsx_attrib(current_syn)
- " For #79
- return prev_ind + s:sw()
- " {
- " <div></div>
- " ##} <--
- elseif s:syn_jsx_element(current_syn) && line =~ '}$'
- let pair_line = searchpair('{', '', '}', 'b')
+
+ " Return the element indent for the opening comment
+ return s:jsx_indent_element(a:lnum)
+ elseif line =~ '^-->'
+ " Return the paired indent for the closing comment
+ let pair_line = searchpair('<!--', '', '-->', 'bW')
return indent(pair_line)
- elseif line =~ '^-->$'
- if prev_line =~ '^<!--'
- return prev_ind
- else
- return prev_ind - s:sw()
- endif
- elseif prev_line =~ '-->$'
- return prev_ind
- " close tag </tag> or /> including </>
- elseif prev_line =~ s:end_tag . '$'
- if line =~ '^<\s*' . s:end_tag
- return prev_ind - s:sw()
- elseif s:syn_jsx_attrib(prev_syn_sol)
- return prev_ind - s:sw()
- else
- return prev_ind
- endif
- elseif line =~ '^\(>\|/\s*>\)'
- if prev_line =~ '^<'
- return prev_ind
- else
- return prev_ind - s:sw()
- endif
- elseif prev_line =~ '^\(<\|>\)' &&
- \ (s:syn_xmlish(prev_syn_eol) || s:syn_js_comment(prev_syn_eol))
- if line =~ '^<\s*' . s:end_tag
- return prev_ind
- else
- return prev_ind + s:sw()
- endif
- elseif line =~ '^<\s*' . s:end_tag
- if !s:syn_xmlish(prev_syn_sol)
- if s:syn_jsx_escapejs(prev_syn_eol)
- \ || s:syn_jsx_escapejs(prev_syn_sol)
- return prev_ind - s:sw()
- else
- return prev_ind
- endif
- elseif prev_line =~ '^\<return'
- return prev_ind
- else
- return prev_ind - s:sw()
- endif
- elseif !s:syn_xmlish(prev_syn_eol)
- if prev_line =~ '\(&&\|||\|=>\|[([{]\|`\)$'
- " <div>
- " {
- " }
- " </div>
- if line =~ '^[)\]}]'
- return prev_ind
- else
- return prev_ind + s:sw()
- endif
- else
- return prev_ind
- endif
else
- return prev_ind
- endif
- elseif s:syn_jsx_escapejs(current_syn)
- if line =~ '^}'
- let char = getline('.')[col('.') - 1]
- " When pressing enter after the }, keep the indent
- if char != '}' && search('}', 'b', lnum)
- return indent(lnum)
- else
- let pair_line = searchpair('{', '', '}', 'bW')
- return indent(pair_line)
- endif
- elseif line =~ '^{' || line =~ '^\${'
- if s:syn_jsx_escapejs(prev_syn_eol)
- \ || s:syn_jsx_attrib(prev_syn_sol)
- return prev_ind
- elseif s:syn_xmlish(prev_syn_eol) && (prev_line =~ s:end_tag || prev_line =~ '-->$')
- return prev_ind
+ if trim(getline(prev_lnum)) =~ '^<!--'
+ " <!--
+ " comment <--
+ " -->
+ return indent(prev_lnum) + s:sw()
else
- return prev_ind + s:sw()
+ " <!--
+ " comment
+ " comment <--
+ " -->
+ return indent(prev_lnum)
endif
endif
- elseif line =~ '^`' && s:syn_jsx_escapejs(current_syn_eol)
- " For `} of template syntax
- let pair_line = searchpair('{', '', '}', 'bW')
- return indent(pair_line)
- elseif line =~ '^/[/*]' " js comment in jsx tag
- if get(prev_syn_sol, -1) =~ 'Punct'
- return prev_ind + s:sw()
- elseif synIDattr(synID(lnum - 1, 1, 1), 'name') =~ 'jsxTag'
- return prev_ind
- else
- return a:js_indent()
+ endif
+
+ " For comment inside the jsxTag
+ if s:is_opening_tag(prev_start_syntax)
+ return indent(prev_lnum) + s:sw()
+ endif
+
+ if trim(getline(a:lnum)) =~ '\*/$'
+ let pair_line = searchpair('/\*', '', '\*/', 'bW', 's:skip_if_not(a:lnum)')
+ return indent(pair_line) + 1
+ endif
+
+ return indent(prev_lnum)
+endfunction
+
+function s:jsx_indent_backticks(lnum)
+ let tags = get(g:, 'vim_jsx_pretty_template_tags', ['html', 'jsx'])
+ let start_tag = '\%(' . join(tags, '\|') . '\)`'
+ let end_tag = '\%(' . join(tags, '\|') . '\)\@<!`'
+ let pair_line = searchpair(start_tag, '', end_tag, 'bW', 's:skip_if_not(a:lnum)')
+
+ return indent(pair_line)
+endfunction
+
+" Compute the indentation for the jsx-related element
+function s:jsx_indent(lnum)
+ let start_syntax = s:start_syntax(a:lnum)
+
+ if s:is_opening_tag(start_syntax)
+ return s:jsx_indent_opening_tag(a:lnum)
+ elseif s:is_closing_tag(start_syntax)
+ return s:jsx_indent_closing_tag(a:lnum)
+ elseif s:is_jsx_attr(start_syntax)
+ return s:jsx_indent_attr(a:lnum)
+ elseif s:is_jsx_element(start_syntax)
+ return s:jsx_indent_element(a:lnum)
+ elseif s:is_jsx_brace(start_syntax)
+ return s:jsx_indent_brace(a:lnum)
+ elseif s:is_jsx_comment(start_syntax)
+ return s:jsx_indent_comment(a:lnum)
+ elseif s:is_jsx_backticks(start_syntax)
+ return s:jsx_indent_backticks(a:lnum)
+ endif
+
+ return -1
+endfunction
+
+" Return the jsx context of the specified line
+function s:jsx_context(lnum)
+ if !s:end_with_jsx(prev_lnum)
+ return 'non-jsx'
+ endif
+
+ let prev_lnum = s:prev_lnum(a:lnum)
+ let start_syntax = s:start_syntax(prev_lnum)
+ let end_col = s:end_col(prev_lnum)
+ let end_syntax_stack = s:syntax_stack_at(prev_lnum, end_col)
+ let reversed = reverse(end_syntax_stack)
+
+ for item in reversed
+ if item =~? 'jsxEscapeJs'
+ return 'unknown'
+ elseif s:is_jsx_element(item) && s:is_jsx(start_syntax) && start_syntax !~? 'jsxEscapeJs'
+ " <div>
+ " <br /> <-- press o
+ " </div>
+ " --------------------
+ " <div>
+ " {
+ " a > 0 ? 1 <div>|</div> <-- press enter
+ " }
+ " </div>
+ return 'jsxElement'
+ elseif s:is_jsx_tag(item)
+ return 'jsxTag'
+ elseif s:is_jsx_brace(item) && trim(getline(prev_lnum)) =~ '{$'
+ return 'jsxBraces'
endif
+ endfor
+
+ return 'unknown'
+endfunction
+
+function! jsx_pretty#indent#get(js_indent)
+ " The start column index of the current line (one-based)
+ let start_col = s:start_col(v:lnum)
+ " The end column index of the current line (one-based)
+ let end_col = s:end_col(v:lnum)
+
+ if s:start_with_jsx(v:lnum)
+ let ind = s:jsx_indent(v:lnum)
+ return ind == -1 ? a:js_indent() : ind
+ elseif s:is_embedded_comment(v:lnum)
+ return s:jsx_indent_comment(v:lnum)
else
- let ind = a:js_indent()
-
- " Issue #68
- " return (<div>
- " |<div>)
- if (line =~ '^/\s*>' || line =~ '^<\s*' . s:end_tag)
- \ && !s:syn_xmlish(prev_syn_sol)
- return prev_ind
+ let line = trim(getline(v:lnum))
+ let prev_lnum = s:prev_lnum(v:lnum)
+
+ " Fix the case where pressing enter at the cursor
+ " return <div>|</div>
+ if line =~ '^' . s:end_tag &&
+ \ s:end_with_jsx(s:prev_lnum(v:lnum))
+ return s:jsx_indent_closing_tag(v:lnum)
endif
- " If current syntax is not a jsx syntax group
- if s:syn_xmlish(prev_syn_eol) && line !~ '^[)\]}]'
- let sol = matchstr(line, s:opfirst)
- if sol is ''
- " Fix javascript continue indent
- return ind - s:sw()
- else
- return ind
+ " Fix cases for the new line
+ if empty(line)
+ let context = s:jsx_context(v:lnum)
+
+ if context == 'jsxElement'
+ " <div> <-- press o
+ " </div>
+ return s:jsx_indent_element(v:lnum)
+ elseif context == 'jsxTag'
+ " <div <-- press o
+ " >
+ " </div>
+ " -----------------------
+ " <div
+ " attr="attr" <-- press o
+ " >
+ " </div>
+ return s:jsx_indent_attr(v:lnum)
+ elseif context == 'jsxBraces'
+ " <div>
+ " { <-- press o
+ " }
+ " </div>
+ return indent(prev_lnum) + s:sw()
endif
endif
- return ind
- endif
+ return a:js_indent()
+ endif
endfunction
endif