From 85a5e3d4e17110748f676a4b59d64202bcab096c Mon Sep 17 00:00:00 2001 From: ibbem Date: Fri, 3 Apr 2020 23:41:56 +0200 Subject: [PATCH] Fix the column modifications on escaped separators If a g:table_mode_separator is escaped by a backslash, the table is aligned ignoring this instance of the g:table_mode_separator, but the column deletion and insertion functions did not consider this behaviour. The g:table_mode_escaped_separator regex is simplified and optimized a little bit. Also more care is taken to prevent unexpected behaviour if special characters are used as g:table_mode_separator. --- autoload/tablemode/spreadsheet.vim | 25 +++++++++++++++---------- autoload/tablemode/utils.vim | 4 ++++ plugin/table-mode.vim | 2 +- t/config/options.vim | 2 +- t/fixtures/escaped_seperator.txt | 9 +++++++++ t/spreadsheet.vim | 30 ++++++++++++++++++++++++++++++ 6 files changed, 60 insertions(+), 12 deletions(-) create mode 100644 t/fixtures/escaped_seperator.txt diff --git a/autoload/tablemode/spreadsheet.vim b/autoload/tablemode/spreadsheet.vim index dfda45a..357efe7 100644 --- a/autoload/tablemode/spreadsheet.vim +++ b/autoload/tablemode/spreadsheet.vim @@ -132,13 +132,11 @@ function! tablemode#spreadsheet#ColumnNr(pos) "{{{2 return 0 endif let row_start = stridx(getline(pos[0]), g:table_mode_separator) - return tablemode#utils#strlen(substitute(getline(pos[0])[(row_start):pos[1]-2], '[^' . g:table_mode_separator . ']', '', 'g')) + return tablemode#utils#SeparatorCount(getline(pos[0])[row_start:pos[1]-2]) endfunction function! tablemode#spreadsheet#ColumnCount(line) "{{{2 - let line = tablemode#utils#line(a:line) - - return tablemode#utils#strlen(substitute(getline(line), '[^' . g:table_mode_separator . ']', '', 'g'))-1 + return tablemode#utils#SeparatorCount(getline(tablemode#utils#line(a:line))) - 1 endfunction function! tablemode#spreadsheet#IsFirstCell() "{{{2 @@ -150,11 +148,15 @@ function! tablemode#spreadsheet#IsLastCell() "{{{2 endfunction function! tablemode#spreadsheet#MoveToStartOfCell() "{{{2 - if getline('.')[col('.')-1] ==# g:table_mode_separator && !tablemode#spreadsheet#IsLastCell() - normal! 2l - else - execute 'normal! F' . g:table_mode_separator . '2l' + if getline('.')[col('.')-1] !=# g:table_mode_separator || tablemode#spreadsheet#IsLastCell() + call search(g:table_mode_escaped_separator_regex, 'b', line('.')) endif + normal! 2l +endfunction + +function! tablemode#spreadsheet#MoveToEndOfCell() "{{{2 + call search(g:table_mode_escaped_separator_regex, 'z', line('.')) + normal! 2h endfunction function! tablemode#spreadsheet#DeleteColumn() "{{{2 @@ -162,7 +164,9 @@ function! tablemode#spreadsheet#DeleteColumn() "{{{2 for i in range(v:count1) call tablemode#spreadsheet#MoveToStartOfCell() call tablemode#spreadsheet#MoveToFirstRowOrHeader() - silent! execute "normal! h\f" . g:table_mode_separator + silent! execute "normal! h\" + call tablemode#spreadsheet#MoveToEndOfCell() + normal! 2l call tablemode#spreadsheet#MoveToLastRow() normal! d endfor @@ -194,7 +198,8 @@ function! tablemode#spreadsheet#InsertColumn(after) "{{{2 call tablemode#spreadsheet#MoveToFirstRowOrHeader() call tablemode#spreadsheet#MoveToStartOfCell() if a:after - execute "normal! f".g:table_mode_separator + call tablemode#spreadsheet#MoveToEndOfCell() + normal! 3l endif execute "normal! h\" call tablemode#spreadsheet#MoveToLastRow() diff --git a/autoload/tablemode/utils.vim b/autoload/tablemode/utils.vim index 9dc32f2..1a3dadb 100644 --- a/autoload/tablemode/utils.vim +++ b/autoload/tablemode/utils.vim @@ -60,3 +60,7 @@ function tablemode#utils#MoveToLine(line) "{{{2 execute "normal! ".(-offset)."k" endif endfunction + +function! tablemode#utils#SeparatorCount(str) + return tablemode#utils#strlen(substitute(a:str, '\V\C\(\\' . escape(g:table_mode_separator, '\') . '\|\[^' . escape(g:table_mode_separator, ']^-\') . ']\)', '', 'g')) +endfunction diff --git a/plugin/table-mode.vim b/plugin/table-mode.vim index 099d316..576d4c4 100644 --- a/plugin/table-mode.vim +++ b/plugin/table-mode.vim @@ -18,7 +18,7 @@ endfunction call s:SetGlobalOptDefault('table_mode_corner', '+') call s:SetGlobalOptDefault('table_mode_verbose', 1) call s:SetGlobalOptDefault('table_mode_separator', '|') -call s:SetGlobalOptDefault('table_mode_escaped_separator_regex', '\(\\\)\@t') diff --git a/t/config/options.vim b/t/config/options.vim index a330d7e..d386f96 100644 --- a/t/config/options.vim +++ b/t/config/options.vim @@ -1,6 +1,6 @@ let g:table_mode_corner = '+' let g:table_mode_separator = '|' -let g:table_mode_escaped_separator_regex = '\(\\\)\@t' diff --git a/t/fixtures/escaped_seperator.txt b/t/fixtures/escaped_seperator.txt new file mode 100644 index 0000000..f561539 --- /dev/null +++ b/t/fixtures/escaped_seperator.txt @@ -0,0 +1,9 @@ +|-------------------+---------------------------| +| The \| works as | It can be escaped by a \. | +| a separator. | | +| | | +| Escaping \ with | This feature would | +| a \ doesn't work. | be unnecessary, because | +| | a separator must be | +| | preceded by a space. | +|-------------------+---------------------------| diff --git a/t/spreadsheet.vim b/t/spreadsheet.vim index 0350b00..f119080 100644 --- a/t/spreadsheet.vim +++ b/t/spreadsheet.vim @@ -226,4 +226,34 @@ describe 'spreadsheet' Expect tablemode#spreadsheet#ColumnCount('.') == 4 end end + + describe 'Escaped table separators' + before + new + normal! ggdG + read t/fixtures/escaped_seperator.txt + call cursor(2, 3) + end + + it 'should not prevent the deletion of rows' + Expect tablemode#spreadsheet#RowCount('.') == 7 + call tablemode#spreadsheet#DeleteRow() + Expect tablemode#spreadsheet#RowCount('.') == 6 + Expect getline('.') == '| a separator. | |' + end + + it 'should not prevent the deletion of columns' + Expect tablemode#spreadsheet#ColumnCount('.') == 2 + call tablemode#spreadsheet#DeleteColumn() + Expect tablemode#spreadsheet#ColumnCount('.') == 1 + Expect getline('.') == '| It can be escaped by a \. |' + end + + it 'should not prevent the insertion of columns' + Expect tablemode#spreadsheet#ColumnCount('.') == 2 + call tablemode#spreadsheet#InsertColumn(1) + Expect tablemode#spreadsheet#ColumnCount('.') == 3 + Expect getline('.') == '| The \| works as | | It can be escaped by a \. |' + end + end end