further large table optimizations

1. s:get_aligned_rows(): getting 2 last rows is enough for having been
   formatted tables
2. vimwiki#tbl#get_cells(): using faster strpart() instead concatenating
   every new character into variables cell and quote
3. checking by getline() whether the line was changed before setline()
   does matter on slower computers
This commit is contained in:
Alexey Radkov 2014-05-04 15:46:19 +04:00
parent 411d8da0a4
commit b79977d6b8

View File

@ -124,11 +124,10 @@ function! s:create_row_sep(cols) "{{{
return row
endfunction "}}}
function! vimwiki#tbl#get_cells(line) "{{{
function! vimwiki#tbl#get_cells(line, ...) "{{{
let result = []
let cell = ''
let quote = ''
let state = 'NONE'
let cell_start = -1
" 'Simple' FSM
for idx in range(strlen(a:line))
@ -136,44 +135,39 @@ function! vimwiki#tbl#get_cells(line) "{{{
let ch = a:line[idx]
if state == 'NONE'
if ch == '|'
let cell_start = idx + 1
let state = 'CELL'
endif
elseif state == 'CELL'
if ch == '[' || ch == '{'
let state = 'BEFORE_QUOTE_START'
let quote = ch
elseif ch == '|'
call add(result, vimwiki#u#trim(cell))
let cell = ""
else
let cell .= ch
let cell = strpart(a:line, cell_start, idx - cell_start)
if a:0 && a:1
let cell = substitute(cell, '^ \(.*\) $', '\1', '')
else
let cell = vimwiki#u#trim(cell)
endif
call add(result, cell)
let cell_start = idx + 1
endif
elseif state == 'BEFORE_QUOTE_START'
if ch == '[' || ch == '{'
let state = 'QUOTE'
let quote .= ch
else
let state = 'CELL'
let cell .= quote.ch
let quote = ''
endif
elseif state == 'QUOTE'
if ch == ']' || ch == '}'
let state = 'BEFORE_QUOTE_END'
endif
let quote .= ch
elseif state == 'BEFORE_QUOTE_END'
if ch == ']' || ch == '}'
let state = 'CELL'
endif
let cell .= quote.ch
let quote = ''
endif
endfor
if cell.quote != ''
call add(result, vimwiki#u#trim(cell.quote, '|'))
endif
return result
endfunction "}}}
@ -201,7 +195,7 @@ function! s:get_indent(lnum) "{{{
return indent
endfunction " }}}
function! s:get_rows(lnum) "{{{
function! s:get_rows(lnum, ...) "{{{
if !s:is_table(getline(a:lnum))
return
endif
@ -210,7 +204,9 @@ function! s:get_rows(lnum) "{{{
let lower_rows = []
let lnum = a:lnum - 1
while lnum >= 1
let depth = a:0 > 0 ? a:1 : 0
let ldepth = 0
while lnum >= 1 && (depth == 0 || ldepth < depth)
let line = getline(lnum)
if s:is_table(line)
call add(upper_rows, [lnum, line])
@ -218,6 +214,7 @@ function! s:get_rows(lnum) "{{{
break
endif
let lnum -= 1
let ldepth += 1
endwhile
call reverse(upper_rows)
@ -229,6 +226,9 @@ function! s:get_rows(lnum) "{{{
else
break
endif
if depth > 0
break
endif
let lnum += 1
endwhile
@ -237,7 +237,8 @@ endfunction "}}}
function! s:get_cell_max_lens(lnum, ...) "{{{
let max_lens = {}
for [lnum, row] in s:get_rows(a:lnum)
let rows = a:0 > 2 ? a:3 : s:get_rows(a:lnum)
for [lnum, row] in rows
if s:is_separator(row)
continue
endif
@ -255,13 +256,32 @@ function! s:get_cell_max_lens(lnum, ...) "{{{
endfunction "}}}
function! s:get_aligned_rows(lnum, col1, col2) "{{{
let rows = s:get_rows(a:lnum)
" getting 2 last rows is enough for having been formatted tables
let depth = 2
let rows = s:get_rows(a:lnum, depth)
let startlnum = rows[0][0]
let cells = []
for [lnum, row] in rows
call add(cells, vimwiki#tbl#get_cells(row))
endfor
let max_lens = s:get_cell_max_lens(a:lnum, cells, startlnum)
let max_lens = {}
let lrows = len(rows)
if lrows == depth + 1
let i = 1
for [lnum, row] in rows
call add(cells, vimwiki#tbl#get_cells(row, i == lrows - 1 ? 0 : 1))
let i += 1
endfor
let max_lens = s:get_cell_max_lens(a:lnum, cells, startlnum, rows)
let fst_lens = s:get_cell_max_lens(a:lnum, cells, startlnum, rows[0:0])
if max_lens != fst_lens
" all the table must be re-formatted
let rows = s:get_rows(a:lnum)
let startlnum = rows[0][0]
let cells = []
for [lnum, row] in rows
call add(cells, vimwiki#tbl#get_cells(row))
endfor
let max_lens = s:get_cell_max_lens(a:lnum, cells, startlnum, rows)
endif
endif
let result = []
for [lnum, row] in rows
if s:is_separator(row)
@ -520,7 +540,9 @@ function! vimwiki#tbl#format(lnum, ...) "{{{
for [lnum, row] in s:get_aligned_rows(a:lnum, col1, col2)
let row = indentstring.row
call setline(lnum, row)
if getline(lnum) != row
call setline(lnum, row)
endif
endfor
let &tw = s:textwidth