tablemode.vim 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. " Private Functions {{{1
  2. function! s:SetBufferOptDefault(opt, val) "{{{2
  3. if !exists('b:' . a:opt)
  4. let b:{a:opt} = a:val
  5. endif
  6. endfunction
  7. function! s:Map(map, to, mode) "{{{2
  8. if !empty(a:to) && !hasmapto(a:map, a:mode)
  9. for l:mode in split(a:mode, '.\zs')
  10. execute l:mode . 'map <buffer>' a:to a:map
  11. endfor
  12. endif
  13. endfunction
  14. function! s:UnMap(map, mode) "{{{2
  15. if !empty(maparg(a:map, a:mode))
  16. for mode in split(a:mode, '.\zs')
  17. execute l:mode . 'unmap <buffer>' a:map
  18. endfor
  19. endif
  20. endfunction
  21. function! s:ToggleMapping() "{{{2
  22. if !g:table_mode_disable_mappings
  23. if tablemode#IsActive()
  24. call s:Map('<Plug>(table-mode-tableize)', g:table_mode_separator_map, 'i')
  25. call s:Map('<Plug>(table-mode-motion-up)', g:table_mode_motion_up_map, 'n')
  26. call s:Map('<Plug>(table-mode-motion-down)', g:table_mode_motion_down_map, 'n')
  27. call s:Map('<Plug>(table-mode-motion-left)', g:table_mode_motion_left_map, 'n')
  28. call s:Map('<Plug>(table-mode-motion-right)', g:table_mode_motion_right_map, 'n')
  29. call s:Map('<Plug>(table-mode-cell-text-object-a)', g:table_mode_cell_text_object_a_map, 'ox')
  30. call s:Map('<Plug>(table-mode-cell-text-object-i)', g:table_mode_cell_text_object_i_map, 'ox')
  31. call s:Map('<Plug>(table-mode-realign)', g:table_mode_realign_map, 'n')
  32. call s:Map('<Plug>(table-mode-delete-row)', g:table_mode_delete_row_map, 'n')
  33. call s:Map('<Plug>(table-mode-delete-column)', g:table_mode_delete_column_map, 'n')
  34. call s:Map('<Plug>(table-mode-insert-column-before)', g:table_mode_insert_column_before_map, 'n')
  35. call s:Map('<Plug>(table-mode-insert-column-after)', g:table_mode_insert_column_after_map, 'n')
  36. call s:Map('<Plug>(table-mode-add-formula)', g:table_mode_add_formula_map, 'n')
  37. call s:Map('<Plug>(table-mode-eval-formula)', g:table_mode_eval_formula_map, 'n')
  38. call s:Map('<Plug>(table-mode-echo-cell)', g:table_mode_echo_cell_map, 'n')
  39. call s:Map('<Plug>(table-mode-sort)', g:table_mode_sort_map, 'n')
  40. else
  41. call s:UnMap(g:table_mode_separator_map, 'i')
  42. call s:UnMap(g:table_mode_motion_up_map, 'n')
  43. call s:UnMap(g:table_mode_motion_down_map, 'n')
  44. call s:UnMap(g:table_mode_motion_left_map, 'n')
  45. call s:UnMap(g:table_mode_motion_right_map, 'n')
  46. call s:UnMap(g:table_mode_cell_text_object_a_map, 'ox')
  47. call s:UnMap(g:table_mode_cell_text_object_i_map, 'ox')
  48. call s:UnMap(g:table_mode_realign_map, 'n')
  49. call s:UnMap(g:table_mode_delete_row_map, 'n')
  50. call s:UnMap(g:table_mode_delete_column_map, 'n')
  51. call s:UnMap(g:table_mode_insert_column_before_map, 'n')
  52. call s:UnMap(g:table_mode_insert_column_after_map, 'n')
  53. call s:UnMap(g:table_mode_add_formula_map, 'n')
  54. call s:UnMap(g:table_mode_eval_formula_map, 'n')
  55. call s:UnMap(g:table_mode_echo_cell_map, 'n')
  56. call s:UnMap(g:table_mode_sort_map, 'n')
  57. endif
  58. endif
  59. endfunction
  60. function! s:ToggleSyntax() "{{{2
  61. if !g:table_mode_syntax | return | endif
  62. if tablemode#IsActive()
  63. exec 'syntax match Table'
  64. \ '/' . tablemode#table#StartExpr() . '\zs|.\+|\ze' . tablemode#table#EndExpr() . '/'
  65. \ 'contains=TableBorder,TableSeparator,TableColumnAlign,yesCell,noCell,maybeCell,redCell,greenCell,yellowCell,blueCell,whiteCell,darkCell'
  66. \ 'containedin=ALL'
  67. syntax match TableSeparator /|/ contained
  68. syntax match TableColumnAlign /:/ contained
  69. syntax match TableBorder /[\-+]\+/ contained
  70. hi! link TableBorder Delimiter
  71. hi! link TableSeparator Delimiter
  72. hi! link TableColumnAlign Type
  73. syntax match redCell '|\@<= *r:[^|]*' contained
  74. hi redCell ctermfg=9 ctermbg=1
  75. syntax match greenCell '|\@<= *g:[^|]*' contained
  76. hi greenCell ctermfg=10 ctermbg=2
  77. syntax match yellowCell '|\@<= *y:[^|]*' contained
  78. hi yellowCell ctermfg=11 ctermbg=3
  79. syntax match blueCell '|\@<= *b:[^|]*' contained
  80. hi blueCell ctermfg=12 ctermbg=4
  81. syntax match whiteCell '|\@<= *w:[^|]*' contained
  82. hi whiteCell ctermfg=0 ctermbg=15
  83. syntax match darkCell '|\@<= *d:[^|]*' contained
  84. hi darkCell ctermfg=15 ctermbg=0
  85. if exists("g:table_mode_color_cells") && g:table_mode_color_cells
  86. syntax match yesCell '|\@<= *yes[^|]*' contained
  87. syntax match noCell '|\@<= *no\A[^|]*' contained " \A to exclude words like notes
  88. syntax match maybeCell '|\@<= *?[^|]*' contained
  89. " '|\@<=' : Match previous characters, excluding them from the group
  90. endif
  91. else
  92. syntax clear Table
  93. syntax clear TableBorder
  94. syntax clear TableSeparator
  95. syntax clear TableColumnAlign
  96. hi! link TableBorder NONE
  97. hi! link TableSeparator NONE
  98. hi! link TableColumnAlign NONE
  99. endif
  100. endfunction
  101. function! s:ToggleAutoAlign() "{{{2
  102. if !g:table_mode_auto_align | return | endif
  103. if tablemode#IsActive()
  104. augroup TableModeAutoAlign
  105. au!
  106. autocmd CursorHold <buffer> nested silent! if &modified | call tablemode#table#Realign('.') | endif
  107. " autocmd InsertLeave <buffer> nested silent! if &modified | call tablemode#table#Realign('.') | endif
  108. augroup END
  109. else
  110. autocmd! TableModeAutoAlign
  111. endif
  112. endfunction
  113. function! s:ToggleOptions() "{{{2
  114. if tablemode#IsActive()
  115. let b:old_update_time = &updatetime
  116. exec 'set updatetime='.g:table_mode_update_time
  117. else
  118. exec 'set updatetime='.get(b:, 'old_update_time', 4000)
  119. endif
  120. endfunction
  121. function! s:SetActive(bool) "{{{2
  122. let b:table_mode_active = a:bool
  123. call s:ToggleSyntax()
  124. call s:ToggleMapping()
  125. call s:ToggleAutoAlign()
  126. call s:ToggleOptions()
  127. if tablemode#IsActive()
  128. doautocmd User TableModeEnabled
  129. else
  130. doautocmd User TableModeDisabled
  131. endif
  132. endfunction
  133. function! s:ConvertDelimiterToSeparator(line, ...) "{{{2
  134. let old_gdefault = &gdefault
  135. set nogdefault
  136. let delim = g:table_mode_delimiter
  137. if a:0 | let delim = a:1 | endif
  138. if delim ==# ','
  139. silent! execute a:line . 's/' . "[\'\"][^\'\"]*\\zs,\\ze[^\'\"]*[\'\"]/__COMMA__/g"
  140. endif
  141. let [cstart, cend] = [tablemode#table#GetCommentStart(), tablemode#table#GetCommentEnd()]
  142. let [match_char_start, match_char_end] = ['.', '.']
  143. if tablemode#utils#strlen(cend) > 0 | let match_char_end = '[^' . cend . ']' | endif
  144. if tablemode#utils#strlen(cstart) > 0 | let match_char_start = '[^' . cstart . ']' | endif
  145. silent! execute a:line . 's/' . tablemode#table#StartExpr() . '\zs\ze' . match_char_start .
  146. \ '\|' . delim . '\|' . match_char_end . '\zs\ze' . tablemode#table#EndExpr() . '/' .
  147. \ g:table_mode_separator . '/g'
  148. if delim ==# ','
  149. silent! execute a:line . 's/' . "[\'\"][^\'\"]*\\zs__COMMA__\\ze[^\'\"]*[\'\"]/,/g"
  150. endif
  151. let &gdefault=old_gdefault
  152. endfunction
  153. function! s:Tableizeline(line, ...) "{{{2
  154. let delim = g:table_mode_delimiter
  155. if a:0 && type(a:1) == type('') && !empty(a:1) | let delim = a:1[1:-1] | endif
  156. call s:ConvertDelimiterToSeparator(a:line, delim)
  157. endfunction
  158. " Public API {{{1
  159. function! tablemode#IsActive() "{{{2
  160. if g:table_mode_always_active | return 1 | endif
  161. call s:SetBufferOptDefault('table_mode_active', 0)
  162. return b:table_mode_active
  163. endfunction
  164. function! tablemode#TableizeInsertMode() "{{{2
  165. if tablemode#IsActive()
  166. if getline('.') =~# (tablemode#table#StartExpr() . g:table_mode_separator . g:table_mode_separator . tablemode#table#EndExpr())
  167. call tablemode#table#AddBorder('.')
  168. normal! A
  169. elseif getline('.') =~# (tablemode#table#StartExpr() . g:table_mode_separator)
  170. let column = tablemode#utils#strlen(substitute(getline('.')[0:col('.')], '[^' . g:table_mode_separator . ']', '', 'g'))
  171. let position = tablemode#utils#strlen(matchstr(getline('.')[0:col('.')], '.*' . g:table_mode_separator . '\s*\zs.*'))
  172. call tablemode#table#Realign('.')
  173. normal! 0
  174. call search(repeat('[^' . g:table_mode_separator . ']*' . g:table_mode_separator, column) . '\s\{-\}' . repeat('.', position), 'ce', line('.'))
  175. endif
  176. endif
  177. endfunction
  178. function! tablemode#Enable() "{{{2
  179. call s:SetActive(1)
  180. endfunction
  181. function! tablemode#Disable() "{{{2
  182. call s:SetActive(0)
  183. endfunction
  184. function! tablemode#Toggle() "{{{2
  185. if g:table_mode_always_active
  186. return 1
  187. endif
  188. call s:SetBufferOptDefault('table_mode_active', 0)
  189. call s:SetActive(!b:table_mode_active)
  190. endfunction
  191. function! tablemode#TableizeRange(...) range "{{{2
  192. let lnum = a:firstline
  193. let total = (a:lastline - a:firstline + 1)
  194. " echom total
  195. let cntr = 1
  196. while cntr <= total
  197. call s:Tableizeline(lnum, a:1)
  198. undojoin
  199. if g:table_mode_tableize_auto_border
  200. if cntr == 1
  201. normal! O
  202. call tablemode#table#AddBorder('.')
  203. normal! j
  204. let lnum += 1
  205. endif
  206. normal! o
  207. call tablemode#table#AddBorder('.')
  208. let lnum += 1
  209. endif
  210. let cntr += 1
  211. let lnum += 1
  212. endwhile
  213. call tablemode#table#Realign(lnum - 1)
  214. endfunction
  215. function! tablemode#TableizeByDelimiter() "{{{2
  216. let delim = input('/')
  217. if delim =~# "\<Esc>" || delim =~# "\<C-C>" | return | endif
  218. let vm = visualmode()
  219. if vm ==? 'line' || vm ==? 'V'
  220. exec line("'<") . ',' . line("'>") . "call tablemode#TableizeRange('/' . delim)"
  221. endif
  222. endfunction
  223. if !hlexists('yesCell') | hi yesCell cterm=bold ctermfg=10 ctermbg=2 | endif |
  224. if !hlexists('noCell') | hi noCell cterm=bold ctermfg=9 ctermbg=1 | endif |
  225. if !hlexists('maybeCell') | hi maybeCell cterm=bold ctermfg=11 ctermbg=3 | endif |