Completed a fully custom formatexpr (#436)

This commit is contained in:
Karl Yngve Lervåg 2016-08-01 22:57:43 +02:00
parent b82a8d3798
commit 0fdaee31ed
3 changed files with 115 additions and 24 deletions

View File

@ -44,7 +44,8 @@ function! vimtex#format#formatexpr() " {{{1
let l:top = v:lnum
let l:bottom = v:lnum + v:count - 1
let l:mark = l:bottom
let l:lines_old = getline(l:top, l:bottom)
let l:tries = 5
" This is a hack to make undo restore the correct position
if mode() !=# 'i'
@ -52,7 +53,43 @@ function! vimtex#format#formatexpr() " {{{1
normal! x
endif
for l:current in range(l:bottom, l:top, -1)
" Main formatting algorithm
while l:tries > 0
" Format the range of lines
let l:bottom = s:format(l:top, l:bottom)
" Ensure proper indentation
silent! execute printf('normal! %sG=%sG', l:top, l:bottom)
" Check if any lines have changed
let l:lines_new = getline(l:top, l:bottom)
let l:index = s:compare_lines(l:lines_new, l:lines_old)
let l:top += l:index
if l:top > l:bottom | break | endif
let l:lines_old = l:lines_new[l:index:]
let l:tries -= 1
endwhile
" Move cursor to first non-blank of the last formatted line
if mode() !=# 'i'
execute 'normal!' l:bottom . 'G^'
endif
" Don't change the text if the formatting algorithm failed
if l:tries == 0
silent! undo
call vimtex#echo#warning('Formatting of selected text failed!')
endif
let &l:foldenable = l:foldenable
endfunction
" }}}1
function! s:format(top, bottom) " {{{1
let l:bottom = a:bottom
let l:mark = a:bottom
for l:current in range(a:bottom, a:top, -1)
let l:line = getline(l:current)
if vimtex#util#in_mathzone(l:current, 1)
@ -63,24 +100,79 @@ function! vimtex#format#formatexpr() " {{{1
if l:line =~# s:border_end
if l:current < l:mark
execute 'normal!' (l:current+1) . 'Ggw' . l:mark . 'G'
let l:bottom += s:format_build_lines(l:current+1, l:mark)
endif
let l:mark = l:current
endif
if l:line =~# s:border_beginning
if l:current < l:mark
execute 'normal!' l:current . 'Ggw' . l:mark . 'G'
let l:bottom += s:format_build_lines(l:current, l:mark)
endif
let l:mark = l:current-1
endif
endwhile
if l:top <= l:mark
execute 'normal!' l:top . 'Ggw' . l:mark . 'G'
if l:line =~# '^\s*$'
let l:bottom += s:format_build_lines(l:current+1, l:mark)
let l:mark = l:current-1
endif
endfor
if a:top <= l:mark
let l:bottom += s:format_build_lines(a:top, l:mark)
endif
let &l:foldenable = l:foldenable
return l:bottom
endfunction
" }}}1
function! s:format_build_lines(start, end) " {{{1
"
" Get the desired text to format as a list of words
"
let l:words = split(join(map(getline(a:start, a:end),
\ 'substitute(v:val, ''^\s*'', '''', '''')'), ' '), ' ')
if empty(l:words) | return 0 | endif
"
" Add the words in properly indented and formatted lines
"
let l:lnum = a:start-1
let l:current = repeat(' ', VimtexIndent(a:start))
for l:word in l:words
if len(l:word) + len(l:current) > &tw
call append(l:lnum, substitute(l:current, '\s$', '', ''))
let l:lnum += 1
let l:current = repeat(' ', VimtexIndent(a:start))
endif
let l:current .= l:word . ' '
endfor
if l:current !~# '^\s*$'
call append(l:lnum, substitute(l:current, '\s$', '', ''))
let l:lnum += 1
endif
"
" Remove old text
"
silent! execute printf('%s;+%s delete', l:lnum+1, a:end-a:start)
"
" Return the difference between number of lines of old and new text
"
return l:lnum - a:end
endfunction
" }}}1
function! s:compare_lines(new, old) " {{{1
let l:min_length = min([len(a:new), len(a:old)])
for l:i in range(l:min_length)
if a:new[l:i] !=# a:old[l:i]
return l:i
endif
endfor
return l:min_length
endfunction
" }}}1

View File

@ -17,31 +17,31 @@ let s:cpo_save = &cpo
set cpo&vim
setlocal autoindent
setlocal indentexpr=VimtexIndent()
setlocal indentexpr=VimtexIndent(v:lnum)
setlocal indentkeys&
setlocal indentkeys+=[,(,{,),},],\&,=item
function! VimtexIndent() " {{{1
let l:nprev = s:get_prev_line(prevnonblank(v:lnum - 1))
function! VimtexIndent(lnum) " {{{1
let l:nprev = s:get_prev_line(prevnonblank(a:lnum - 1))
if l:nprev == 0 | return 0 | endif
" Get current and previous line and remove comments
let l:cur = substitute(getline(v:lnum), '\\\@<!%.*', '', '')
let l:cur = substitute(getline(a:lnum), '\\\@<!%.*', '', '')
let l:prev = substitute(getline(l:nprev), '\\\@<!%.*', '', '')
" Check for verbatim modes
if s:is_verbatim(l:cur, v:lnum)
return empty(l:cur) ? indent(l:nprev) : indent(v:lnum)
if s:is_verbatim(l:cur, a:lnum)
return empty(l:cur) ? indent(l:nprev) : indent(a:lnum)
endif
" Align on ampersands
if l:cur =~# '^\s*&' && l:prev =~# '\\\@<!&.*'
return indent(v:lnum) + match(l:prev, '\\\@<!&') - stridx(l:cur, '&')
return indent(a:lnum) + match(l:prev, '\\\@<!&') - stridx(l:cur, '&')
endif
" Use previous indentation for comments
if l:cur =~# '^\s*%'
return indent(v:lnum)
return indent(a:lnum)
endif
let l:nprev = s:get_prev_line(l:nprev, 'ignore-ampersands')
@ -50,7 +50,7 @@ function! VimtexIndent() " {{{1
let l:ind = indent(l:nprev)
let l:ind += s:indent_envs(l:cur, l:prev)
let l:ind += s:indent_delims(l:cur, l:prev)
let l:ind += s:indent_delims(l:cur, l:prev, a:lnum)
let l:ind += s:indent_tikz(l:nprev, l:prev)
return l:ind
endfunction
@ -105,8 +105,8 @@ let s:envs_begitem = s:envs_item . '\|' . s:envs_beglist
let s:envs_enditem = s:envs_item . '\|' . s:envs_endlist
" }}}1
function! s:indent_delims(cur, prev) " {{{1
let [l:open, l:close] = vimtex#delim#get_valid_regexps(v:lnum, col('.'))
function! s:indent_delims(cur, prev, lnum) " {{{1
let [l:open, l:close] = vimtex#delim#get_valid_regexps(a:lnum, col('.'))
return &sw*( max([s:count(a:prev, l:open) - s:count(a:prev, l:close), 0])
\ - max([s:count(a:cur, l:close) - s:count(a:cur, l:open), 0]))
endfunction

View File

@ -168,9 +168,8 @@ Expect tex (Verify):
distribution over $x^u$ when sampled at label $\vec x$ some time later; another
population started around $\vec x_1$ carries a different history when it, too,
visits $\vec x$ later. Therefore, for instance the effective drift $\vec v(\vec
x)$ will be different in the two cases. We conclude that, if unobserved
degrees of freedom have dynamics on the time scale of the experiment
eq.~\ref{eq:fpe} is an approximation whose coefficients become
\emph{non-universal} (dependent on intial conditions) and
\emph{time-dependent}.
x)$ will be different in the two cases. We conclude that, if unobserved degrees
of freedom have dynamics on the time scale of the experiment eq.~\ref{eq:fpe}
is an approximation whose coefficients become \emph{non-universal} (dependent
on intial conditions) and \emph{time-dependent}.