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 return row
endfunction "}}} endfunction "}}}
function! vimwiki#tbl#get_cells(line) "{{{ function! vimwiki#tbl#get_cells(line, ...) "{{{
let result = [] let result = []
let cell = ''
let quote = ''
let state = 'NONE' let state = 'NONE'
let cell_start = -1
" 'Simple' FSM " 'Simple' FSM
for idx in range(strlen(a:line)) for idx in range(strlen(a:line))
@ -136,44 +135,39 @@ function! vimwiki#tbl#get_cells(line) "{{{
let ch = a:line[idx] let ch = a:line[idx]
if state == 'NONE' if state == 'NONE'
if ch == '|' if ch == '|'
let cell_start = idx + 1
let state = 'CELL' let state = 'CELL'
endif endif
elseif state == 'CELL' elseif state == 'CELL'
if ch == '[' || ch == '{' if ch == '[' || ch == '{'
let state = 'BEFORE_QUOTE_START' let state = 'BEFORE_QUOTE_START'
let quote = ch
elseif ch == '|' elseif ch == '|'
call add(result, vimwiki#u#trim(cell)) let cell = strpart(a:line, cell_start, idx - cell_start)
let cell = "" if a:0 && a:1
else let cell = substitute(cell, '^ \(.*\) $', '\1', '')
let cell .= ch else
let cell = vimwiki#u#trim(cell)
endif
call add(result, cell)
let cell_start = idx + 1
endif endif
elseif state == 'BEFORE_QUOTE_START' elseif state == 'BEFORE_QUOTE_START'
if ch == '[' || ch == '{' if ch == '[' || ch == '{'
let state = 'QUOTE' let state = 'QUOTE'
let quote .= ch
else else
let state = 'CELL' let state = 'CELL'
let cell .= quote.ch
let quote = ''
endif endif
elseif state == 'QUOTE' elseif state == 'QUOTE'
if ch == ']' || ch == '}' if ch == ']' || ch == '}'
let state = 'BEFORE_QUOTE_END' let state = 'BEFORE_QUOTE_END'
endif endif
let quote .= ch
elseif state == 'BEFORE_QUOTE_END' elseif state == 'BEFORE_QUOTE_END'
if ch == ']' || ch == '}' if ch == ']' || ch == '}'
let state = 'CELL' let state = 'CELL'
endif endif
let cell .= quote.ch
let quote = ''
endif endif
endfor endfor
if cell.quote != ''
call add(result, vimwiki#u#trim(cell.quote, '|'))
endif
return result return result
endfunction "}}} endfunction "}}}
@ -201,7 +195,7 @@ function! s:get_indent(lnum) "{{{
return indent return indent
endfunction " }}} endfunction " }}}
function! s:get_rows(lnum) "{{{ function! s:get_rows(lnum, ...) "{{{
if !s:is_table(getline(a:lnum)) if !s:is_table(getline(a:lnum))
return return
endif endif
@ -210,7 +204,9 @@ function! s:get_rows(lnum) "{{{
let lower_rows = [] let lower_rows = []
let lnum = a:lnum - 1 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) let line = getline(lnum)
if s:is_table(line) if s:is_table(line)
call add(upper_rows, [lnum, line]) call add(upper_rows, [lnum, line])
@ -218,6 +214,7 @@ function! s:get_rows(lnum) "{{{
break break
endif endif
let lnum -= 1 let lnum -= 1
let ldepth += 1
endwhile endwhile
call reverse(upper_rows) call reverse(upper_rows)
@ -229,6 +226,9 @@ function! s:get_rows(lnum) "{{{
else else
break break
endif endif
if depth > 0
break
endif
let lnum += 1 let lnum += 1
endwhile endwhile
@ -237,7 +237,8 @@ endfunction "}}}
function! s:get_cell_max_lens(lnum, ...) "{{{ function! s:get_cell_max_lens(lnum, ...) "{{{
let max_lens = {} 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) if s:is_separator(row)
continue continue
endif endif
@ -255,13 +256,32 @@ function! s:get_cell_max_lens(lnum, ...) "{{{
endfunction "}}} endfunction "}}}
function! s:get_aligned_rows(lnum, col1, col2) "{{{ 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 startlnum = rows[0][0]
let cells = [] let cells = []
for [lnum, row] in rows let max_lens = {}
call add(cells, vimwiki#tbl#get_cells(row)) let lrows = len(rows)
endfor if lrows == depth + 1
let max_lens = s:get_cell_max_lens(a:lnum, cells, startlnum) 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 = [] let result = []
for [lnum, row] in rows for [lnum, row] in rows
if s:is_separator(row) 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) for [lnum, row] in s:get_aligned_rows(a:lnum, col1, col2)
let row = indentstring.row let row = indentstring.row
call setline(lnum, row) if getline(lnum) != row
call setline(lnum, row)
endif
endfor endfor
let &tw = s:textwidth let &tw = s:textwidth