summaryrefslogtreecommitdiffstats
path: root/indent
diff options
context:
space:
mode:
Diffstat (limited to 'indent')
-rw-r--r--indent/cython.vim100
-rw-r--r--indent/go.vim25
-rw-r--r--indent/gohtmltmpl.vim8
-rw-r--r--indent/handlebars.vim41
-rw-r--r--indent/lua.vim2
-rw-r--r--indent/python.vim100
6 files changed, 174 insertions, 102 deletions
diff --git a/indent/cython.vim b/indent/cython.vim
index b44839d8..2f590edd 100644
--- a/indent/cython.vim
+++ b/indent/cython.vim
@@ -40,6 +40,15 @@ if !exists('g:python_pep8_indent_hang_closing')
let g:python_pep8_indent_hang_closing = 0
endif
+" TODO: check required patch for timeout argument, likely lower than 7.3.429 though.
+if !exists('g:python_pep8_indent_searchpair_timeout')
+ if has('patch-8.0.1483')
+ let g:python_pep8_indent_searchpair_timeout = 150
+ else
+ let g:python_pep8_indent_searchpair_timeout = 0
+ endif
+endif
+
let s:block_rules = {
\ '^\s*elif\>': ['if', 'elif'],
\ '^\s*except\>': ['try', 'except'],
@@ -59,28 +68,34 @@ else
endif
let s:stop_statement = '^\s*\(break\|continue\|raise\|return\|pass\)\>'
-" Skip strings and comments. Return 1 for chars to skip.
-" jedi* refers to syntax definitions from jedi-vim for call signatures, which
-" are inserted temporarily into the buffer.
-let s:skip_special_chars = 'synIDattr(synID(line("."), col("."), 0), "name") ' .
- \ '=~? "\\vstring|comment|^pythonbytes%(contents)=$|jedi\\S"'
-
let s:skip_after_opening_paren = 'synIDattr(synID(line("."), col("."), 0), "name") ' .
\ '=~? "\\vcomment|jedi\\S"'
-" Also ignore anything concealed.
-" Wrapper around synconcealed for older Vim (7.3.429, used on Travis CI).
-function! s:is_concealed(line, col)
- let concealed = synconcealed(a:line, a:col)
- return len(concealed) && concealed[0]
-endfunction
-if has('conceal')
- let s:skip_special_chars .= '|| s:is_concealed(line("."), col("."))'
-endif
-
+if !get(g:, 'python_pep8_indent_skip_concealed', 0) || !has('conceal')
+ " Skip strings and comments. Return 1 for chars to skip.
+ " jedi* refers to syntax definitions from jedi-vim for call signatures, which
+ " are inserted temporarily into the buffer.
+ function! s:_skip_special_chars(line, col)
+ return synIDattr(synID(a:line, a:col, 0), 'name')
+ \ =~? "\\vstring|comment|^pythonbytes%(contents)=$|jedi\\S"
+ endfunction
+else
+ " Also ignore anything concealed.
+ " TODO: doc; likely only necessary with jedi-vim, where a better version is
+ " planned (https://github.com/Vimjas/vim-python-pep8-indent/pull/98).
+
+ " Wrapper around synconcealed for older Vim (7.3.429, used on Travis CI).
+ function! s:is_concealed(line, col)
+ let concealed = synconcealed(a:line, a:col)
+ return len(concealed) && concealed[0]
+ endfunction
-let s:skip_search = 'synIDattr(synID(line("."), col("."), 0), "name") ' .
- \ '=~? "comment"'
+ function! s:_skip_special_chars(line, col)
+ return synIDattr(synID(a:line, a:col, 0), 'name')
+ \ =~? "\\vstring|comment|^pythonbytes%(contents)=$|jedi\\S"
+ \ || s:is_concealed(a:line, a:col)
+ endfunction
+endif
" Use 'shiftwidth()' instead of '&sw'.
" (Since Vim patch 7.3.629, 'shiftwidth' can be set to 0 to follow 'tabstop').
@@ -95,24 +110,21 @@ else
endif
" Find backwards the closest open parenthesis/bracket/brace.
-function! s:find_opening_paren(...)
- " optional arguments: line and column (defaults to 1) to search around
- if a:0 > 0
- let view = winsaveview()
- call cursor(a:1, a:0 > 1 ? a:2 : 1)
- let ret = s:find_opening_paren()
- call winrestview(view)
- return ret
+function! s:find_opening_paren(lnum, col)
+ " Return if cursor is in a comment.
+ if synIDattr(synID(a:lnum, a:col, 0), 'name') =~? 'comment'
+ return [0, 0]
endif
- " Return if cursor is in a comment.
- exe 'if' s:skip_search '| return [0, 0] | endif'
+ call cursor(a:lnum, a:col)
let nearest = [0, 0]
+ let timeout = g:python_pep8_indent_searchpair_timeout
+ let skip_special_chars = 's:_skip_special_chars(line("."), col("."))'
for [p, maxoff] in items(s:paren_pairs)
let stopline = max([0, line('.') - maxoff, nearest[0]])
let next = searchpairpos(
- \ '\V'.p[0], '', '\V'.p[1], 'bnW', s:skip_special_chars, stopline)
+ \ '\V'.p[0], '', '\V'.p[1], 'bnW', skip_special_chars, stopline, timeout)
if next[0] && (next[0] > nearest[0] || (next[0] == nearest[0] && next[1] > nearest[1]))
let nearest = next
endif
@@ -127,7 +139,7 @@ function! s:find_start_of_multiline_statement(lnum)
if getline(lnum - 1) =~# '\\$'
let lnum = prevnonblank(lnum - 1)
else
- let [paren_lnum, _] = s:find_opening_paren(lnum)
+ let [paren_lnum, _] = s:find_opening_paren(lnum, 1)
if paren_lnum < 1
return lnum
else
@@ -184,7 +196,7 @@ endfunction
" Line up with open parenthesis/bracket/brace.
function! s:indent_like_opening_paren(lnum)
- let [paren_lnum, paren_col] = s:find_opening_paren(a:lnum)
+ let [paren_lnum, paren_col] = s:find_opening_paren(a:lnum, 1)
if paren_lnum <= 0
return -2
endif
@@ -214,7 +226,7 @@ function! s:indent_like_opening_paren(lnum)
" from the next logical line.
if text =~# b:control_statement && res == base + s:sw()
" But only if not inside parens itself (Flake's E127).
- let [paren_lnum, _] = s:find_opening_paren(paren_lnum)
+ let [paren_lnum, _] = s:find_opening_paren(paren_lnum, 1)
if paren_lnum <= 0
return res + s:sw()
endif
@@ -267,24 +279,23 @@ function! s:indent_like_previous_line(lnum)
let base = indent(start)
let current = indent(a:lnum)
- " Jump to last character in previous line.
- call cursor(lnum, len(text))
- let ignore_last_char = eval(s:skip_special_chars)
+ " Ignore last character in previous line?
+ let lastcol = len(text)
+ let col = lastcol
" Search for final colon that is not inside something to be ignored.
while 1
- let curpos = getpos('.')[2]
- if curpos == 1 | break | endif
- if eval(s:skip_special_chars) || text[curpos-1] =~# '\s'
- normal! h
+ if col == 1 | break | endif
+ if text[col-1] =~# '\s' || s:_skip_special_chars(lnum, col)
+ let col = col - 1
continue
- elseif text[curpos-1] ==# ':'
+ elseif text[col-1] ==# ':'
return base + s:sw()
endif
break
endwhile
- if text =~# '\\$' && !ignore_last_char
+ if text =~# '\\$' && !s:_skip_special_chars(lnum, lastcol)
" If this line is the continuation of a control statement
" indent further to distinguish the continuation line
" from the next logical line.
@@ -315,7 +326,7 @@ function! s:indent_like_previous_line(lnum)
return -1
endif
- if !empty && s:is_dedented_already(current, base)
+ if (current || !empty) && s:is_dedented_already(current, base)
return -1
endif
@@ -366,11 +377,12 @@ function! GetPythonPEPIndent(lnum)
if match_quotes != -1
" closing multiline string
let quotes = line[match_quotes:(match_quotes+2)]
- let pairpos = searchpairpos(quotes, '', quotes, 'b')
+ call cursor(a:lnum, 1)
+ let pairpos = searchpairpos(quotes, '', quotes, 'bW', '', 0, g:python_pep8_indent_searchpair_timeout)
if pairpos[0] != 0
return indent(pairpos[0])
else
- " TODO: test to cover this!
+ return -1
endif
endif
diff --git a/indent/go.vim b/indent/go.vim
index 887fb587..d31a6a1d 100644
--- a/indent/go.vim
+++ b/indent/go.vim
@@ -26,7 +26,11 @@ if exists("*GoIndent")
finish
endif
-function! GoIndent(lnum)
+" don't spam the user when Vim is started in Vi compatibility mode
+let s:cpo_save = &cpo
+set cpo&vim
+
+function! GoIndent(lnum) abort
let prevlnum = prevnonblank(a:lnum-1)
if prevlnum == 0
" top of file
@@ -40,10 +44,17 @@ function! GoIndent(lnum)
let ind = previ
- if prevl =~ ' = `[^`]*$'
- " previous line started a multi-line raw string
- return 0
- endif
+ for synid in synstack(a:lnum, 1)
+ if synIDattr(synid, 'name') == 'goRawString'
+ if prevl =~ '\%(\%(:\?=\)\|(\|,\)\s*`[^`]*$'
+ " previous line started a multi-line raw string
+ return 0
+ endif
+ " return -1 to keep the current indent.
+ return -1
+ endif
+ endfor
+
if prevl =~ '[({]\s*$'
" previous line opened a block
let ind += shiftwidth()
@@ -70,6 +81,10 @@ function! GoIndent(lnum)
return ind
endfunction
+" restore Vi compatibility settings
+let &cpo = s:cpo_save
+unlet s:cpo_save
+
" vim: sw=2 ts=2 et
endif
diff --git a/indent/gohtmltmpl.vim b/indent/gohtmltmpl.vim
index ed9e2eb5..93a4969b 100644
--- a/indent/gohtmltmpl.vim
+++ b/indent/gohtmltmpl.vim
@@ -15,6 +15,10 @@ if exists("*GetGoHTMLTmplIndent")
finish
endif
+" don't spam the user when Vim is started in Vi compatibility mode
+let s:cpo_save = &cpo
+set cpo&vim
+
function! GetGoHTMLTmplIndent(lnum)
" Get HTML indent
if exists('*HtmlIndent')
@@ -45,6 +49,10 @@ function! GetGoHTMLTmplIndent(lnum)
return ind
endfunction
+" restore Vi compatibility settings
+let &cpo = s:cpo_save
+unlet s:cpo_save
+
" vim: sw=2 ts=2 et
endif
diff --git a/indent/handlebars.vim b/indent/handlebars.vim
index a3ffbb88..e91dbd0b 100644
--- a/indent/handlebars.vim
+++ b/indent/handlebars.vim
@@ -4,8 +4,8 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'handlebars') ==
" Language: Mustache, Handlebars
" Maintainer: Juvenn Woo <machese@gmail.com>
" Screenshot: http://imgur.com/6F408
-" Version: 2
-" Last Change: Oct 10th 2015
+" Version: 3
+" Last Change: 26 Nov 2018
" Remarks: based on eruby indent plugin by tpope
" References:
" [Mustache](http://github.com/defunkt/mustache)
@@ -21,6 +21,9 @@ endif
unlet! b:did_indent
setlocal indentexpr=
+" keep track of whether or not we are in a block expression for indenting
+unlet! s:in_block_expr
+
runtime! indent/html.vim
unlet! b:did_indent
@@ -75,26 +78,48 @@ function! GetHandlebarsIndent(...)
let b:indent.lnum = -1
endif
let lnum = prevnonblank(v:lnum-1)
- let line = getline(lnum)
- let cline = getline(v:lnum)
+ let prevLine = getline(lnum)
+ let currentLine = getline(v:lnum)
" all indent rules only apply if the block opening/closing
" tag is on a separate line
" indent after block {{#block
- if line =~# '\v\s*\{\{\#.*\s*'
+ if prevLine =~# '\v\s*\{\{\#.*\s*'
+ let s:in_block_expr = 1
let ind = ind + sw
endif
+ " but not if the block ends on the same line
+ if prevLine =~# '\v\s*\{\{\#(.+)(\s+|\}\}).*\{\{\/\1'
+ let s:in_block_expr = 0
+ let ind = ind - sw
+ endif
" unindent after block close {{/block}}
- if cline =~# '\v^\s*\{\{\/\S*\}\}\s*'
+ if currentLine =~# '\v^\s*\{\{\/\S*\}\}\s*'
+ let s:in_block_expr = 0
+ let ind = ind - sw
+ endif
+ " indent after component block {{a-component
+ if prevLine =~# '\v\s*\{\{\w'
+ let s:in_block_expr = 0
+ let ind = ind + sw
+ endif
+ " but not if the component block ends on the same line
+ if prevLine =~# '\v\s*\{\{\w(.+)\}\}'
let ind = ind - sw
endif
+ " unindent }} lines, and following lines if not inside a block expression
+ if currentLine =~# '\v^\s*\}\}\s*$' || (currentLine !~# '\v^\s*\{\{\/' && prevLine =~# '\v^\s*[^\{\} \t]+\}\}\s*$')
+ if !s:in_block_expr
+ let ind = ind - sw
+ endif
+ endif
" unindent {{else}}
- if cline =~# '\v^\s*\{\{else.*\}\}\s*$'
+ if currentLine =~# '\v^\s*\{\{else.*\}\}\s*$'
let ind = ind - sw
endif
" indent again after {{else}}
- if line =~# '\v^\s*\{\{else.*\}\}\s*$'
+ if prevLine =~# '\v^\s*\{\{else.*\}\}\s*$'
let ind = ind + sw
endif
diff --git a/indent/lua.vim b/indent/lua.vim
index 8e5e63ed..6d102d89 100644
--- a/indent/lua.vim
+++ b/indent/lua.vim
@@ -113,7 +113,7 @@ function GetLuaIndent()
" restore cursor
call setpos(".", original_cursor_pos)
- return indent(prev_line) + (&sw * i)
+ return indent(prev_line) + (shiftwidth() * i)
endfunction
diff --git a/indent/python.vim b/indent/python.vim
index b44839d8..2f590edd 100644
--- a/indent/python.vim
+++ b/indent/python.vim
@@ -40,6 +40,15 @@ if !exists('g:python_pep8_indent_hang_closing')
let g:python_pep8_indent_hang_closing = 0
endif
+" TODO: check required patch for timeout argument, likely lower than 7.3.429 though.
+if !exists('g:python_pep8_indent_searchpair_timeout')
+ if has('patch-8.0.1483')
+ let g:python_pep8_indent_searchpair_timeout = 150
+ else
+ let g:python_pep8_indent_searchpair_timeout = 0
+ endif
+endif
+
let s:block_rules = {
\ '^\s*elif\>': ['if', 'elif'],
\ '^\s*except\>': ['try', 'except'],
@@ -59,28 +68,34 @@ else
endif
let s:stop_statement = '^\s*\(break\|continue\|raise\|return\|pass\)\>'
-" Skip strings and comments. Return 1 for chars to skip.
-" jedi* refers to syntax definitions from jedi-vim for call signatures, which
-" are inserted temporarily into the buffer.
-let s:skip_special_chars = 'synIDattr(synID(line("."), col("."), 0), "name") ' .
- \ '=~? "\\vstring|comment|^pythonbytes%(contents)=$|jedi\\S"'
-
let s:skip_after_opening_paren = 'synIDattr(synID(line("."), col("."), 0), "name") ' .
\ '=~? "\\vcomment|jedi\\S"'
-" Also ignore anything concealed.
-" Wrapper around synconcealed for older Vim (7.3.429, used on Travis CI).
-function! s:is_concealed(line, col)
- let concealed = synconcealed(a:line, a:col)
- return len(concealed) && concealed[0]
-endfunction
-if has('conceal')
- let s:skip_special_chars .= '|| s:is_concealed(line("."), col("."))'
-endif
-
+if !get(g:, 'python_pep8_indent_skip_concealed', 0) || !has('conceal')
+ " Skip strings and comments. Return 1 for chars to skip.
+ " jedi* refers to syntax definitions from jedi-vim for call signatures, which
+ " are inserted temporarily into the buffer.
+ function! s:_skip_special_chars(line, col)
+ return synIDattr(synID(a:line, a:col, 0), 'name')
+ \ =~? "\\vstring|comment|^pythonbytes%(contents)=$|jedi\\S"
+ endfunction
+else
+ " Also ignore anything concealed.
+ " TODO: doc; likely only necessary with jedi-vim, where a better version is
+ " planned (https://github.com/Vimjas/vim-python-pep8-indent/pull/98).
+
+ " Wrapper around synconcealed for older Vim (7.3.429, used on Travis CI).
+ function! s:is_concealed(line, col)
+ let concealed = synconcealed(a:line, a:col)
+ return len(concealed) && concealed[0]
+ endfunction
-let s:skip_search = 'synIDattr(synID(line("."), col("."), 0), "name") ' .
- \ '=~? "comment"'
+ function! s:_skip_special_chars(line, col)
+ return synIDattr(synID(a:line, a:col, 0), 'name')
+ \ =~? "\\vstring|comment|^pythonbytes%(contents)=$|jedi\\S"
+ \ || s:is_concealed(a:line, a:col)
+ endfunction
+endif
" Use 'shiftwidth()' instead of '&sw'.
" (Since Vim patch 7.3.629, 'shiftwidth' can be set to 0 to follow 'tabstop').
@@ -95,24 +110,21 @@ else
endif
" Find backwards the closest open parenthesis/bracket/brace.
-function! s:find_opening_paren(...)
- " optional arguments: line and column (defaults to 1) to search around
- if a:0 > 0
- let view = winsaveview()
- call cursor(a:1, a:0 > 1 ? a:2 : 1)
- let ret = s:find_opening_paren()
- call winrestview(view)
- return ret
+function! s:find_opening_paren(lnum, col)
+ " Return if cursor is in a comment.
+ if synIDattr(synID(a:lnum, a:col, 0), 'name') =~? 'comment'
+ return [0, 0]
endif
- " Return if cursor is in a comment.
- exe 'if' s:skip_search '| return [0, 0] | endif'
+ call cursor(a:lnum, a:col)
let nearest = [0, 0]
+ let timeout = g:python_pep8_indent_searchpair_timeout
+ let skip_special_chars = 's:_skip_special_chars(line("."), col("."))'
for [p, maxoff] in items(s:paren_pairs)
let stopline = max([0, line('.') - maxoff, nearest[0]])
let next = searchpairpos(
- \ '\V'.p[0], '', '\V'.p[1], 'bnW', s:skip_special_chars, stopline)
+ \ '\V'.p[0], '', '\V'.p[1], 'bnW', skip_special_chars, stopline, timeout)
if next[0] && (next[0] > nearest[0] || (next[0] == nearest[0] && next[1] > nearest[1]))
let nearest = next
endif
@@ -127,7 +139,7 @@ function! s:find_start_of_multiline_statement(lnum)
if getline(lnum - 1) =~# '\\$'
let lnum = prevnonblank(lnum - 1)
else
- let [paren_lnum, _] = s:find_opening_paren(lnum)
+ let [paren_lnum, _] = s:find_opening_paren(lnum, 1)
if paren_lnum < 1
return lnum
else
@@ -184,7 +196,7 @@ endfunction
" Line up with open parenthesis/bracket/brace.
function! s:indent_like_opening_paren(lnum)
- let [paren_lnum, paren_col] = s:find_opening_paren(a:lnum)
+ let [paren_lnum, paren_col] = s:find_opening_paren(a:lnum, 1)
if paren_lnum <= 0
return -2
endif
@@ -214,7 +226,7 @@ function! s:indent_like_opening_paren(lnum)
" from the next logical line.
if text =~# b:control_statement && res == base + s:sw()
" But only if not inside parens itself (Flake's E127).
- let [paren_lnum, _] = s:find_opening_paren(paren_lnum)
+ let [paren_lnum, _] = s:find_opening_paren(paren_lnum, 1)
if paren_lnum <= 0
return res + s:sw()
endif
@@ -267,24 +279,23 @@ function! s:indent_like_previous_line(lnum)
let base = indent(start)
let current = indent(a:lnum)
- " Jump to last character in previous line.
- call cursor(lnum, len(text))
- let ignore_last_char = eval(s:skip_special_chars)
+ " Ignore last character in previous line?
+ let lastcol = len(text)
+ let col = lastcol
" Search for final colon that is not inside something to be ignored.
while 1
- let curpos = getpos('.')[2]
- if curpos == 1 | break | endif
- if eval(s:skip_special_chars) || text[curpos-1] =~# '\s'
- normal! h
+ if col == 1 | break | endif
+ if text[col-1] =~# '\s' || s:_skip_special_chars(lnum, col)
+ let col = col - 1
continue
- elseif text[curpos-1] ==# ':'
+ elseif text[col-1] ==# ':'
return base + s:sw()
endif
break
endwhile
- if text =~# '\\$' && !ignore_last_char
+ if text =~# '\\$' && !s:_skip_special_chars(lnum, lastcol)
" If this line is the continuation of a control statement
" indent further to distinguish the continuation line
" from the next logical line.
@@ -315,7 +326,7 @@ function! s:indent_like_previous_line(lnum)
return -1
endif
- if !empty && s:is_dedented_already(current, base)
+ if (current || !empty) && s:is_dedented_already(current, base)
return -1
endif
@@ -366,11 +377,12 @@ function! GetPythonPEPIndent(lnum)
if match_quotes != -1
" closing multiline string
let quotes = line[match_quotes:(match_quotes+2)]
- let pairpos = searchpairpos(quotes, '', quotes, 'b')
+ call cursor(a:lnum, 1)
+ let pairpos = searchpairpos(quotes, '', quotes, 'bW', '', 0, g:python_pep8_indent_searchpair_timeout)
if pairpos[0] != 0
return indent(pairpos[0])
else
- " TODO: test to cover this!
+ return -1
endif
endif