" Private Functions {{{1 function! s:SetBufferOptDefault(opt, val) "{{{2 if !exists('b:' . a:opt) let b:{a:opt} = a:val endif endfunction function! s:Map(map, to, mode) "{{{2 if !empty(a:to) && !hasmapto(a:map, a:mode) for l:mode in split(a:mode, '.\zs') execute l:mode . 'map ' a:to a:map endfor endif endfunction function! s:UnMap(map, mode) "{{{2 if !empty(maparg(a:map, a:mode)) for mode in split(a:mode, '.\zs') execute l:mode . 'unmap ' a:map endfor endif endfunction function! s:ToggleMapping() "{{{2 if !g:table_mode_disable_mappings if tablemode#IsActive() call s:Map('(table-mode-tableize)', g:table_mode_separator_map, 'i') call s:Map('(table-mode-motion-up)', g:table_mode_motion_up_map, 'n') call s:Map('(table-mode-motion-down)', g:table_mode_motion_down_map, 'n') call s:Map('(table-mode-motion-left)', g:table_mode_motion_left_map, 'n') call s:Map('(table-mode-motion-right)', g:table_mode_motion_right_map, 'n') call s:Map('(table-mode-cell-text-object-a)', g:table_mode_cell_text_object_a_map, 'ox') call s:Map('(table-mode-cell-text-object-i)', g:table_mode_cell_text_object_i_map, 'ox') call s:Map('(table-mode-realign)', g:table_mode_realign_map, 'n') call s:Map('(table-mode-delete-row)', g:table_mode_delete_row_map, 'n') call s:Map('(table-mode-delete-column)', g:table_mode_delete_column_map, 'n') call s:Map('(table-mode-insert-column-before)', g:table_mode_insert_column_before_map, 'n') call s:Map('(table-mode-insert-column-after)', g:table_mode_insert_column_after_map, 'n') call s:Map('(table-mode-add-formula)', g:table_mode_add_formula_map, 'n') call s:Map('(table-mode-eval-formula)', g:table_mode_eval_formula_map, 'n') call s:Map('(table-mode-echo-cell)', g:table_mode_echo_cell_map, 'n') call s:Map('(table-mode-sort)', g:table_mode_sort_map, 'n') else call s:UnMap(g:table_mode_separator_map, 'i') call s:UnMap(g:table_mode_motion_up_map, 'n') call s:UnMap(g:table_mode_motion_down_map, 'n') call s:UnMap(g:table_mode_motion_left_map, 'n') call s:UnMap(g:table_mode_motion_right_map, 'n') call s:UnMap(g:table_mode_cell_text_object_a_map, 'ox') call s:UnMap(g:table_mode_cell_text_object_i_map, 'ox') call s:UnMap(g:table_mode_realign_map, 'n') call s:UnMap(g:table_mode_delete_row_map, 'n') call s:UnMap(g:table_mode_delete_column_map, 'n') call s:UnMap(g:table_mode_insert_column_before_map, 'n') call s:UnMap(g:table_mode_insert_column_after_map, 'n') call s:UnMap(g:table_mode_add_formula_map, 'n') call s:UnMap(g:table_mode_eval_formula_map, 'n') call s:UnMap(g:table_mode_echo_cell_map, 'n') call s:UnMap(g:table_mode_sort_map, 'n') endif endif endfunction function! s:ToggleSyntax() "{{{2 if !g:table_mode_syntax | return | endif if tablemode#IsActive() exec 'syntax match Table' \ '/' . tablemode#table#StartExpr() . '\zs|.\+|\ze' . tablemode#table#EndExpr() . '/' \ 'contains=TableBorder,TableSeparator,TableColumnAlign,yesCell,noCell,maybeCell,redCell,greenCell,yellowCell,blueCell,whiteCell,darkCell' \ 'containedin=ALL' syntax match TableSeparator /|/ contained syntax match TableColumnAlign /:/ contained syntax match TableBorder /[\-+]\+/ contained hi! link TableBorder Delimiter hi! link TableSeparator Delimiter hi! link TableColumnAlign Type syntax match redCell '|\@<= *r:[^|]*' contained hi redCell ctermfg=9 ctermbg=1 syntax match greenCell '|\@<= *g:[^|]*' contained hi greenCell ctermfg=10 ctermbg=2 syntax match yellowCell '|\@<= *y:[^|]*' contained hi yellowCell ctermfg=11 ctermbg=3 syntax match blueCell '|\@<= *b:[^|]*' contained hi blueCell ctermfg=12 ctermbg=4 syntax match whiteCell '|\@<= *w:[^|]*' contained hi whiteCell ctermfg=0 ctermbg=15 syntax match darkCell '|\@<= *d:[^|]*' contained hi darkCell ctermfg=15 ctermbg=0 if exists("g:table_mode_color_cells") && g:table_mode_color_cells syntax match yesCell '|\@<= *yes[^|]*' contained syntax match noCell '|\@<= *no\A[^|]*' contained " \A to exclude words like notes syntax match maybeCell '|\@<= *?[^|]*' contained " '|\@<=' : Match previous characters, excluding them from the group endif else syntax clear Table syntax clear TableBorder syntax clear TableSeparator syntax clear TableColumnAlign hi! link TableBorder NONE hi! link TableSeparator NONE hi! link TableColumnAlign NONE endif endfunction function! s:ToggleAutoAlign() "{{{2 if !g:table_mode_auto_align | return | endif if tablemode#IsActive() augroup TableModeAutoAlign au! autocmd CursorHold nested silent! if &modified | call tablemode#table#Realign('.') | endif " autocmd InsertLeave nested silent! if &modified | call tablemode#table#Realign('.') | endif augroup END else autocmd! TableModeAutoAlign endif endfunction function! s:ToggleOptions() "{{{2 if tablemode#IsActive() let b:old_update_time = &updatetime exec 'set updatetime='.g:table_mode_update_time else exec 'set updatetime='.get(b:, 'old_update_time', 4000) endif endfunction function! s:SetActive(bool) "{{{2 let b:table_mode_active = a:bool call s:ToggleSyntax() call s:ToggleMapping() call s:ToggleAutoAlign() call s:ToggleOptions() if tablemode#IsActive() doautocmd User TableModeEnabled else doautocmd User TableModeDisabled endif endfunction function! s:ConvertDelimiterToSeparator(line, ...) "{{{2 let old_gdefault = &gdefault set nogdefault let delim = g:table_mode_delimiter if a:0 | let delim = a:1 | endif if delim ==# ',' silent! execute a:line . 's/' . "[\'\"][^\'\"]*\\zs,\\ze[^\'\"]*[\'\"]/__COMMA__/g" endif let [cstart, cend] = [tablemode#table#GetCommentStart(), tablemode#table#GetCommentEnd()] let [match_char_start, match_char_end] = ['.', '.'] if tablemode#utils#strlen(cend) > 0 | let match_char_end = '[^' . cend . ']' | endif if tablemode#utils#strlen(cstart) > 0 | let match_char_start = '[^' . cstart . ']' | endif silent! execute a:line . 's/' . tablemode#table#StartExpr() . '\zs\ze' . match_char_start . \ '\|' . delim . '\|' . match_char_end . '\zs\ze' . tablemode#table#EndExpr() . '/' . \ g:table_mode_separator . '/g' if delim ==# ',' silent! execute a:line . 's/' . "[\'\"][^\'\"]*\\zs__COMMA__\\ze[^\'\"]*[\'\"]/,/g" endif let &gdefault=old_gdefault endfunction function! s:Tableizeline(line, ...) "{{{2 let delim = g:table_mode_delimiter if a:0 && type(a:1) == type('') && !empty(a:1) | let delim = a:1[1:-1] | endif call s:ConvertDelimiterToSeparator(a:line, delim) endfunction " Public API {{{1 function! tablemode#IsActive() "{{{2 if g:table_mode_always_active | return 1 | endif call s:SetBufferOptDefault('table_mode_active', 0) return b:table_mode_active endfunction function! tablemode#TableizeInsertMode() "{{{2 if tablemode#IsActive() if getline('.') =~# (tablemode#table#StartExpr() . g:table_mode_separator . g:table_mode_separator . tablemode#table#EndExpr()) call tablemode#table#AddBorder('.') normal! A elseif getline('.') =~# (tablemode#table#StartExpr() . g:table_mode_separator) let column = tablemode#utils#strlen(substitute(getline('.')[0:col('.')], '[^' . g:table_mode_separator . ']', '', 'g')) let position = tablemode#utils#strlen(matchstr(getline('.')[0:col('.')], '.*' . g:table_mode_separator . '\s*\zs.*')) call tablemode#table#Realign('.') normal! 0 call search(repeat('[^' . g:table_mode_separator . ']*' . g:table_mode_separator, column) . '\s\{-\}' . repeat('.', position), 'ce', line('.')) endif endif endfunction function! tablemode#Enable() "{{{2 call s:SetActive(1) endfunction function! tablemode#Disable() "{{{2 call s:SetActive(0) endfunction function! tablemode#Toggle() "{{{2 if g:table_mode_always_active return 1 endif call s:SetBufferOptDefault('table_mode_active', 0) call s:SetActive(!b:table_mode_active) endfunction function! tablemode#TableizeRange(...) range "{{{2 let lnum = a:firstline let total = (a:lastline - a:firstline + 1) " echom total let cntr = 1 while cntr <= total call s:Tableizeline(lnum, a:1) undojoin if g:table_mode_tableize_auto_border if cntr == 1 normal! O call tablemode#table#AddBorder('.') normal! j let lnum += 1 endif normal! o call tablemode#table#AddBorder('.') let lnum += 1 endif let cntr += 1 let lnum += 1 endwhile call tablemode#table#Realign(lnum - 1) endfunction function! tablemode#TableizeByDelimiter() "{{{2 let delim = input('/') if delim =~# "\" || delim =~# "\" | return | endif let vm = visualmode() if vm ==? 'line' || vm ==? 'V' exec line("'<") . ',' . line("'>") . "call tablemode#TableizeRange('/' . delim)" endif endfunction if !hlexists('yesCell') | hi yesCell cterm=bold ctermfg=10 ctermbg=2 | endif | if !hlexists('noCell') | hi noCell cterm=bold ctermfg=9 ctermbg=1 | endif | if !hlexists('maybeCell') | hi maybeCell cterm=bold ctermfg=11 ctermbg=3 | endif |