spreadsheet.vim 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. " Private Functions {{{1
  2. function! s:TotalCells(list) "{{{2
  3. let result = 0
  4. for item in a:list
  5. if type(item) == type([])
  6. let result += s:TotalCells(item)
  7. else
  8. let result += 1
  9. endif
  10. endfor
  11. return result
  12. endfunction
  13. function! s:Min(list) "{{{2
  14. let found = v:false
  15. let result = 0
  16. for item in a:list
  17. if empty(item)
  18. continue
  19. endif
  20. if type(item) == type(1) || type(item) == type(1.0)
  21. if found == v:false || item < result
  22. let found = v:true
  23. let result = item
  24. endif
  25. elseif type(item) == type('')
  26. let val = str2float(item)
  27. if found == v:false || val < result
  28. let found = v:true
  29. let result = val
  30. endif
  31. elseif type(item) == type([])
  32. let val = s:Min(item)
  33. if found == v:false || val < result
  34. let found = v:true
  35. let result = val
  36. endif
  37. endif
  38. endfor
  39. return result
  40. endfunction
  41. function! s:Max(list) "{{{2
  42. let found = v:false
  43. let result = 0
  44. for item in a:list
  45. if empty(item)
  46. continue
  47. endif
  48. if type(item) == type(1) || type(item) == type(1.0)
  49. if found == v:false || item > result
  50. let found = v:true
  51. let result = item
  52. endif
  53. elseif type(item) == type('')
  54. let val = str2float(item)
  55. if found == v:false || val > result
  56. let found = v:true
  57. let result = val
  58. endif
  59. elseif type(item) == type([])
  60. let val = s:Max(item)
  61. if found == v:false || val > result
  62. let found = v:true
  63. let result = val
  64. endif
  65. endif
  66. endfor
  67. return result
  68. endfunction
  69. function! s:CountE(list) "{{{2
  70. let result = 0
  71. for item in a:list
  72. if empty(item)
  73. let result += 1
  74. elseif type(item) == type([])
  75. let result += s:CountE(item)
  76. endif
  77. endfor
  78. return result
  79. endfunction
  80. function! s:CountNE(list) "{{{2
  81. let result = 0
  82. for item in a:list
  83. if type(item) == type([])
  84. let result += s:CountNE(item)
  85. elseif !empty(item)
  86. let result += 1
  87. endif
  88. endfor
  89. return result
  90. endfunction
  91. function! s:PercentE(list) "{{{2
  92. return (s:CountE(a:list)*100)/s:TotalCells(a:list)
  93. endfunction
  94. function! s:PercentNE(list) "{{{2
  95. return (s:CountNE(a:list)*100)/s:TotalCells(a:list)
  96. endfunction
  97. function! s:Sum(list) "{{{2
  98. let result = 0.0
  99. for item in a:list
  100. if type(item) == type(1) || type(item) == type(1.0)
  101. let result += item
  102. elseif type(item) == type('')
  103. let result += str2float(item)
  104. elseif type(item) == type([])
  105. let result += s:Sum(item)
  106. endif
  107. endfor
  108. return result
  109. endfunction
  110. function! s:Average(list) "{{{2
  111. return s:Sum(a:list)/s:TotalCells(a:list)
  112. endfunction
  113. function! s:AverageNE(list) "{{{2
  114. return s:Sum(a:list)/s:CountNE(a:list)
  115. endfunction
  116. " Public Functions {{{1
  117. function! tablemode#spreadsheet#GetFirstRow(line) "{{{2
  118. if tablemode#table#IsRow(a:line)
  119. let line = tablemode#utils#line(a:line)
  120. while !tablemode#table#IsHeader(line - 1) && (tablemode#table#IsRow(line - 1) || tablemode#table#IsBorder(line - 1))
  121. let line -= 1
  122. endwhile
  123. if tablemode#table#IsBorder(line) | let line += 1 | endif
  124. return line
  125. endif
  126. endfunction
  127. function! tablemode#spreadsheet#GetFirstRowOrHeader(line) "{{{2
  128. if tablemode#table#IsRow(a:line)
  129. let line = tablemode#utils#line(a:line)
  130. while tablemode#table#IsTable(line - 1)
  131. let line -= 1
  132. endwhile
  133. if tablemode#table#IsBorder(line) | let line += 1 | endif
  134. return line
  135. endif
  136. endfunction
  137. function! tablemode#spreadsheet#MoveToFirstRow() "{{{2
  138. if tablemode#table#IsRow('.')
  139. call tablemode#utils#MoveToLine(tablemode#spreadsheet#GetFirstRow('.'))
  140. endif
  141. endfunction
  142. function! tablemode#spreadsheet#MoveToFirstRowOrHeader() "{{{2
  143. if tablemode#table#IsRow('.')
  144. call tablemode#utils#MoveToLine(tablemode#spreadsheet#GetFirstRowOrHeader('.'))
  145. endif
  146. endfunction
  147. function! tablemode#spreadsheet#GetLastRow(line) "{{{2
  148. if tablemode#table#IsRow(a:line)
  149. let line = tablemode#utils#line(a:line)
  150. while tablemode#table#IsTable(line + 1)
  151. let line += 1
  152. endwhile
  153. if tablemode#table#IsBorder(line) | let line -= 1 | endif
  154. return line
  155. endif
  156. endfunction
  157. function! tablemode#spreadsheet#MoveToLastRow() "{{{2
  158. if tablemode#table#IsRow('.')
  159. call tablemode#utils#MoveToLine(tablemode#spreadsheet#GetLastRow('.'))
  160. endif
  161. endfunction
  162. function! tablemode#spreadsheet#LineNr(line, row) "{{{2
  163. if tablemode#table#IsRow(a:line)
  164. let line = tablemode#spreadsheet#GetFirstRow(a:line)
  165. let row_nr = 0
  166. while tablemode#table#IsTable(line + 1)
  167. if tablemode#table#IsRow(line)
  168. let row_nr += 1
  169. if a:row ==# row_nr | break | endif
  170. endif
  171. let line += 1
  172. endwhile
  173. return line
  174. endif
  175. endfunction
  176. function! tablemode#spreadsheet#RowNr(line) "{{{2
  177. let line = tablemode#utils#line(a:line)
  178. let rowNr = 0
  179. while !tablemode#table#IsHeader(line) && tablemode#table#IsTable(line)
  180. if tablemode#table#IsRow(line) | let rowNr += 1 | endif
  181. let line -= 1
  182. endwhile
  183. return rowNr
  184. endfunction
  185. function! tablemode#spreadsheet#RowCount(line) "{{{2
  186. let line = tablemode#utils#line(a:line)
  187. let [tline, totalRowCount] = [line, 0]
  188. while !tablemode#table#IsHeader(tline) && tablemode#table#IsTable(tline)
  189. if tablemode#table#IsRow(tline) | let totalRowCount += 1 | endif
  190. let tline -= 1
  191. endwhile
  192. let tline = line + 1
  193. while !tablemode#table#IsHeader(tline) && tablemode#table#IsTable(tline)
  194. if tablemode#table#IsRow(tline) | let totalRowCount += 1 | endif
  195. let tline += 1
  196. endwhile
  197. return totalRowCount
  198. endfunction
  199. function! tablemode#spreadsheet#ColumnNr(pos) "{{{2
  200. let pos = []
  201. if type(a:pos) == type('')
  202. let pos = [line(a:pos), col(a:pos)]
  203. elseif type(a:pos) == type([])
  204. let pos = a:pos
  205. else
  206. return 0
  207. endif
  208. let row_start = stridx(getline(pos[0]), g:table_mode_separator)
  209. return tablemode#utils#SeparatorCount(getline(pos[0])[row_start:pos[1]-2])
  210. endfunction
  211. function! tablemode#spreadsheet#ColumnCount(line) "{{{2
  212. return tablemode#utils#SeparatorCount(getline(tablemode#utils#line(a:line))) - 1
  213. endfunction
  214. function! tablemode#spreadsheet#IsFirstCell() "{{{2
  215. return tablemode#spreadsheet#ColumnNr('.') ==# 1
  216. endfunction
  217. function! tablemode#spreadsheet#IsLastCell() "{{{2
  218. return tablemode#spreadsheet#ColumnNr('.') ==# tablemode#spreadsheet#ColumnCount('.')
  219. endfunction
  220. function! tablemode#spreadsheet#MoveToStartOfCell() "{{{2
  221. if getline('.')[col('.')-1] !=# g:table_mode_separator || tablemode#spreadsheet#IsLastCell()
  222. call search(g:table_mode_escaped_separator_regex, 'b', line('.'))
  223. endif
  224. normal! 2l
  225. endfunction
  226. function! tablemode#spreadsheet#MoveToEndOfCell() "{{{2
  227. call search(g:table_mode_escaped_separator_regex, 'z', line('.'))
  228. normal! 2h
  229. endfunction
  230. function! tablemode#spreadsheet#DeleteColumn() "{{{2
  231. if tablemode#table#IsRow('.')
  232. for i in range(v:count1)
  233. call tablemode#spreadsheet#MoveToStartOfCell()
  234. call tablemode#spreadsheet#MoveToFirstRowOrHeader()
  235. silent! execute "normal! h\<C-V>"
  236. call tablemode#spreadsheet#MoveToEndOfCell()
  237. normal! 2l
  238. call tablemode#spreadsheet#MoveToLastRow()
  239. normal! d
  240. endfor
  241. call tablemode#table#Realign('.')
  242. endif
  243. endfunction
  244. function! tablemode#spreadsheet#DeleteRow() "{{{2
  245. if tablemode#table#IsRow('.')
  246. for i in range(v:count1)
  247. if tablemode#table#IsRow('.')
  248. normal! dd
  249. endif
  250. if !tablemode#table#IsRow('.')
  251. normal! k
  252. endif
  253. endfor
  254. call tablemode#table#Realign('.')
  255. endif
  256. endfunction
  257. function! tablemode#spreadsheet#InsertColumn(after) "{{{2
  258. if tablemode#table#IsRow('.')
  259. let quantity = v:count1
  260. call tablemode#spreadsheet#MoveToFirstRowOrHeader()
  261. call tablemode#spreadsheet#MoveToStartOfCell()
  262. if a:after
  263. call tablemode#spreadsheet#MoveToEndOfCell()
  264. normal! 3l
  265. endif
  266. execute "normal! h\<C-V>"
  267. call tablemode#spreadsheet#MoveToLastRow()
  268. normal! y
  269. let corner = tablemode#utils#get_buffer_or_global_option('table_mode_corner')
  270. if a:after
  271. let cell_line = g:table_mode_separator.' '
  272. let header_line = corner.g:table_mode_fillchar.g:table_mode_fillchar
  273. else
  274. let cell_line = ' '.g:table_mode_separator
  275. let header_line = g:table_mode_fillchar.g:table_mode_fillchar.corner
  276. endif
  277. let cell_line = escape(cell_line, '\&')
  278. let header_line = escape(header_line, '\&')
  279. " This transforms the character column before or after the column separator
  280. " into a new column with separator.
  281. " This requires, that
  282. " g:table_mode_separator != g:table_mode_fillchar
  283. " && g:table_mode_separator != g:table_mode_header_fillchar
  284. " && g:table_mode_separator != g:table_mode_align_char
  285. call setreg(
  286. \ '"',
  287. \ substitute(
  288. \ substitute(@", ' ', cell_line, 'g'),
  289. \ '\V\C'.escape(g:table_mode_fillchar, '\')
  290. \ .'\|'.escape(g:table_mode_header_fillchar, '\')
  291. \ .'\|'.escape(g:table_mode_align_char, '\'),
  292. \ header_line,
  293. \ 'g'),
  294. \ 'b')
  295. if a:after
  296. execute "normal! ".quantity."pl"
  297. else
  298. execute "normal! ".quantity."P"
  299. endif
  300. call tablemode#table#Realign('.')
  301. startinsert
  302. endif
  303. endfunction
  304. function! tablemode#spreadsheet#Min(range, ...) abort "{{{2
  305. let args = copy(a:000)
  306. call insert(args, a:range)
  307. return s:Min(call('tablemode#spreadsheet#cell#GetCellRange', args))
  308. endfunction
  309. function! tablemode#spreadsheet#Max(range, ...) abort "{{{2
  310. let args = copy(a:000)
  311. call insert(args, a:range)
  312. return s:Max(call('tablemode#spreadsheet#cell#GetCellRange', args))
  313. endfunction
  314. function! tablemode#spreadsheet#CountE(range, ...) abort "{{{2
  315. let args = copy(a:000)
  316. call insert(args, a:range)
  317. return s:CountE(call('tablemode#spreadsheet#cell#GetCellRange', args))
  318. endfunction
  319. function! tablemode#spreadsheet#CountNE(range, ...) abort "{{{2
  320. let args = copy(a:000)
  321. call insert(args, a:range)
  322. return s:CountNE(call('tablemode#spreadsheet#cell#GetCellRange', args))
  323. endfunction
  324. function! tablemode#spreadsheet#PercentE(range, ...) abort "{{{2
  325. let args = copy(a:000)
  326. call insert(args, a:range)
  327. return s:PercentE(call('tablemode#spreadsheet#cell#GetCellRange', args))
  328. endfunction
  329. function! tablemode#spreadsheet#PercentNE(range, ...) abort "{{{2
  330. let args = copy(a:000)
  331. call insert(args, a:range)
  332. return s:PercentNE(call('tablemode#spreadsheet#cell#GetCellRange', args))
  333. endfunction
  334. function! tablemode#spreadsheet#Sum(range, ...) abort "{{{2
  335. let args = copy(a:000)
  336. call insert(args, a:range)
  337. return s:Sum(call('tablemode#spreadsheet#cell#GetCellRange', args))
  338. endfunction
  339. function! tablemode#spreadsheet#Average(range, ...) abort "{{{2
  340. let args = copy(a:000)
  341. call insert(args, a:range)
  342. return s:Average(call('tablemode#spreadsheet#cell#GetCellRange', args))
  343. endfunction
  344. function! tablemode#spreadsheet#AverageNE(range, ...) abort "{{{2
  345. let args = copy(a:000)
  346. call insert(args, a:range)
  347. return s:AverageNE(call('tablemode#spreadsheet#cell#GetCellRange', args))
  348. endfunction
  349. function! tablemode#spreadsheet#Sort(bang, ...) range "{{{2
  350. if exists('*getcurpos')
  351. let col = getcurpos()[4] " curswant
  352. else
  353. let col = col('.')
  354. endif
  355. let opts = a:0 ? a:1 : ''
  356. let bang = a:bang ? '!' : ''
  357. if a:firstline == a:lastline
  358. let [firstRow, lastRow] = [tablemode#spreadsheet#GetFirstRow('.'), tablemode#spreadsheet#GetLastRow('.')]
  359. else
  360. let [firstRow, lastRow] = [a:firstline, a:lastline]
  361. endif
  362. call tablemode#spreadsheet#MoveToStartOfCell()
  363. exec ':undojoin | '.firstRow.','.lastRow . 'sort'.bang opts '/.*\%'.col.'v/'
  364. endfunction
  365. function! tablemode#spreadsheet#EchoCell()
  366. if tablemode#table#IsRow('.')
  367. echomsg '$' . tablemode#spreadsheet#RowNr('.') . ',' . tablemode#spreadsheet#ColumnNr('.')
  368. endif
  369. endfunction