vimwiki

Personal wiki for vim
git clone https://github.com/vimwiki/vimwiki.git
Log | Files | Refs | README | LICENSE

commit 0303021abde8cb39500d9c1612216c8b755afae6
parent 3c0ae2ff970ea9cf338e667297f3ddd4b87ac806
Author: lyokha <alexey.radkov@gmail.com>
Date:   Thu,  4 Apr 2019 15:05:57 +0300

Fast aligns check

The optimized table formatting algorithm was still O(n) because
calculating aligns required traversal to the separator line on the top
of a table. This heuristic algorithm calculates aligns in O(1) in the
best case by looking at cells in two rows above.

Say, if two above rows are

|      uau | uauyaya         | ya      |
|       ua | uaua            | uaaua   |
| <cursor> |                 |         |

then the aligns can be figured out without need to find the separator
line. If aligns cannot be figured out after this fast check then the
algorithm falls back to O(n) with searching for the separator line.

Diffstat:
Mautoload/vimwiki/tbl.vim | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 57 insertions(+), 10 deletions(-)

diff --git a/autoload/vimwiki/tbl.vim b/autoload/vimwiki/tbl.vim @@ -254,13 +254,6 @@ function! s:get_rows(lnum, ...) while lnum <= line('$') let line = getline(lnum) if s:is_table(line) - if lnum == a:lnum && !s:is_separator(line) - let cells = vimwiki#tbl#get_cells(line) - let clen = len(cells) - let max_lens = repeat([0], clen) - let aligns = repeat(['left'], clen) - let line = s:fmt_row(cells, max_lens, aligns, 0, 0) - endif call add(rows, [lnum, line]) else break @@ -275,9 +268,10 @@ function! s:get_rows(lnum, ...) endfunction -function! s:get_cell_aligns(lnum) +function! s:get_cell_aligns(lnum, ...) let aligns = {} - for [lnum, row] in s:get_rows(a:lnum) + let depth = a:0 > 0 ? a:1 : 0 + for [lnum, row] in s:get_rows(a:lnum, depth) if s:is_separator(row) let cells = vimwiki#tbl#get_cells(row) for idx in range(len(cells)) @@ -303,6 +297,46 @@ function! s:get_cell_aligns(lnum) endfunction +function! s:get_cell_fast_aligns(rows) + let aligns = {} + let clen = 0 + for [lnum, row] in a:rows + if s:is_separator(row) + return s:get_cell_aligns(lnum, 1) + endif + let cells = vimwiki#tbl#get_cells(row, 1) + let clen = len(cells) + for idx in range(clen) + let cell = cells[idx] + if !has_key(aligns, idx) + let cs = matchlist(cell, '^\(\s*\)[^[:space:]].\{-}\(\s*\)$') + if !empty(cs) + let lstart = len(cs[1]) + let lend = len(cs[2]) + if lstart > 0 || lend > 0 + if lstart > 0 && lend > 0 + let aligns[idx] = 'center' + else + if lend > 0 + let aligns[idx] = 'left' + elseif lstart > 0 + let aligns[idx] = 'right' + endif + endif + endif + endif + endif + endfor + endfor + for idx in range(clen) + if !has_key(aligns, idx) + return {} + endif + endfor + return aligns +endfunction + + function! s:get_cell_max_lens(lnum, ...) let max_lens = {} let rows = a:0 > 2 ? a:3 : s:get_rows(a:lnum) @@ -326,6 +360,7 @@ endfunction function! s:get_aligned_rows(lnum, col1, col2, depth) let rows = [] + let aligns = {} let startlnum = 0 let cells = [] let max_lens = {} @@ -335,6 +370,14 @@ function! s:get_aligned_rows(lnum, col1, col2, depth) let startlnum = rows[0][0] let lrows = len(rows) if lrows == a:depth + 1 + let line = rows[-1][1] + if !s:is_separator(line) + let lcells = vimwiki#tbl#get_cells(line) + let lclen = len(lcells) + let lmax_lens = repeat([0], lclen) + let laligns = repeat(['left'], lclen) + let rows[-1][1] = s:fmt_row(lcells, lmax_lens, laligns, 0, 0) + endif let i = 1 for [lnum, row] in rows call add(cells, vimwiki#tbl#get_cells(row, i != lrows - 1)) @@ -348,6 +391,8 @@ function! s:get_aligned_rows(lnum, col1, col2, depth) endif let fst_lens = s:get_cell_max_lens(a:lnum, cells, startlnum, rows[0:0]) let check_all = max_lens != fst_lens + let aligns = s:get_cell_fast_aligns(rows[0:-2]) + let rows[-1][1] = line endif endif if check_all @@ -365,7 +410,9 @@ function! s:get_aligned_rows(lnum, col1, col2, depth) let max_lens[last_index] = 1 endif endif - let aligns = s:get_cell_aligns(a:lnum) + if empty(aligns) + let aligns = s:get_cell_aligns(a:lnum) + endif let result = [] for [lnum, row] in rows if s:is_separator(row)