commit c5b7f7e76f7d9b07036948a2f9c1d6cd0167e884
parent bc3bc208d727444da57cff634f3c6a9f12870e48
Author: Julian Prein <druckdev@protonmail.com>
Date: Fri, 23 Jun 2023 01:10:54 +0200
Fix: Handle multibyte chars properly in get_cells (#1298) (fixes #1297)
Previously vimwiki#tbl#get_cells() would act on `line` as a normal
string (i.e. using `[idx]` and strpart()). This breaks when the column
separator (s:s_rep() or rxTableSep) is a multibyte character like the
vertical box drawing character │. In that case the separator is never
found and only one empty cell is returned. This also affects
vimwiki#tbl#format() which in turn clears the whole table each time the
insert mode is left.
Fix this issue by initially splitting the line into a list of the
characters. Getting the elements with `[idx]` now returns each character
instead of a byte. In addition len() is used in place of strlen() as
well as slicing together with join() instead of strpart().
Fixes: #1297 ("Table formatting breaks on multibyte separator")
Diffstat:
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/autoload/vimwiki/tbl.vim b/autoload/vimwiki/tbl.vim
@@ -149,7 +149,9 @@ function! vimwiki#tbl#get_cells(line, ...) abort
let state = 'NONE'
let cell_start = 0
let quote_start = 0
- let len = strlen(a:line) - 1
+ " Split byte string into list of character to properly handle multibyte chars
+ let chars = split(a:line, '\zs')
+ let len = len(chars) - 1
" 'Simple' FSM
while state !=# 'CELL'
@@ -157,10 +159,9 @@ function! vimwiki#tbl#get_cells(line, ...) abort
let state = 'CELL'
endif
for idx in range(quote_start, len)
- " The only way I know Vim can do Unicode...
- let ch = a:line[idx]
+ let ch = chars[idx]
if state ==# 'NONE'
- if ch ==# s:s_sep() && (idx < 1 || a:line[idx-1] !=# '\')
+ if ch ==# s:s_sep() && (idx < 1 || chars[idx-1] !=# '\')
let cell_start = idx + 1
let state = 'CELL'
endif
@@ -168,8 +169,8 @@ function! vimwiki#tbl#get_cells(line, ...) abort
if ch ==# '[' || ch ==# '{'
let state = 'BEFORE_QUOTE_START'
let quote_start = idx
- elseif ch ==# s:s_sep() && (idx < 1 || a:line[idx-1] !=# '\')
- let cell = strpart(a:line, cell_start, idx - cell_start)
+ elseif ch ==# s:s_sep() && (idx < 1 || chars[idx-1] !=# '\')
+ let cell = join(chars[cell_start : idx-1], '')
if a:0 && a:1
let cell = substitute(cell, '^ \(.*\) $', '\1', '')
else
diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt
@@ -4002,9 +4002,11 @@ Contributors and their Github usernames in roughly chronological order:
- Thomas Leyh (@leyhline)
- nebulaeandstars (@nebulaeandstars)
- dmitry kim (@jsn)
+ - Julian Prein (@druckdev)
- Luke Atkinson (@LukeDAtkinson)
- Joe Planisky (@jplanisky)
+
==============================================================================
16. Changelog *vimwiki-changelog*