formula.vim 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. " Private Functions {{{1
  2. function! s:IsFormulaLine(line) "{{{2
  3. return getline(a:line) =~# 'tmf: '
  4. endfunction
  5. function! s:IsHTMLComment(line) "{{{2
  6. return !s:IsFormulaLine(a:line) && getline(a:line) =~# '^\s*<!--'
  7. endfunction
  8. " Public Functions {{{1
  9. function! tablemode#spreadsheet#formula#Add(...) "{{{2
  10. let fr = a:0 ? a:1 : input('f=')
  11. let row = tablemode#spreadsheet#RowNr('.')
  12. let colm = tablemode#spreadsheet#ColumnNr('.')
  13. let indent = indent('.')
  14. let indent_str = repeat(' ', indent)
  15. if fr !=# ''
  16. let fr = '$' . row . ',' . colm . '=' . fr
  17. let fline = tablemode#spreadsheet#GetLastRow('.') + 1
  18. if tablemode#table#IsBorder(fline) | let fline += 1 | endif
  19. if s:IsHTMLComment(fline) | let fline += 1 | endif
  20. let cursor_pos = [line('.'), col('.')]
  21. if getline(fline) =~# 'tmf: '
  22. " Comment line correctly
  23. let line_val = getline(fline)
  24. let start_pos = match(line_val, tablemode#table#StartCommentExpr())
  25. let end_pos = match(line_val, tablemode#table#EndCommentExpr())
  26. if empty(end_pos) | let end_pos = len(line_val) | endif
  27. let line_expr = strpart(line_val, start_pos, end_pos)
  28. let sce = matchstr(line_val, tablemode#table#StartCommentExpr() . '\zs')
  29. let ece = matchstr(line_val, tablemode#table#EndCommentExpr())
  30. call setline(fline, sce . line_expr . '; ' . fr . ece)
  31. else
  32. let cstring = &commentstring
  33. let [cmss, cmse] = ['', '']
  34. if len(cstring) > 0
  35. let cms = split(cstring, '%s')
  36. if len(cms) == 2
  37. let [cmss, cmse] = cms
  38. else
  39. let [cmss, cmse] = [cms[0], '']
  40. endif
  41. endif
  42. let fr = indent_str . cmss . ' tmf: ' . fr . ' ' . cmse
  43. call append(fline-1, fr)
  44. call cursor(cursor_pos)
  45. endif
  46. call tablemode#spreadsheet#formula#EvaluateFormulaLine()
  47. endif
  48. endfunction
  49. function! tablemode#spreadsheet#formula#EvaluateExpr(expr, line) "{{{2
  50. let line = tablemode#utils#line(a:line)
  51. let [target, expr] = map(split(a:expr, '='), 'tablemode#utils#strip(v:val)')
  52. let cell = substitute(target, '\$', '', '')
  53. if cell =~# ','
  54. let [row, colm] = map(split(cell, ','), 'str2nr(v:val)')
  55. else
  56. let [row, colm] = [0, str2nr(cell)]
  57. endif
  58. if expr =~# 'Min(.*)'
  59. let expr = substitute(expr, 'Min(\([^)]*\))', 'tablemode#spreadsheet#Min("\1",'.line.','.colm.')', 'g')
  60. endif
  61. if expr =~# 'Max(.*)'
  62. let expr = substitute(expr, 'Max(\([^)]*\))', 'tablemode#spreadsheet#Max("\1",'.line.','.colm.')', 'g')
  63. endif
  64. if expr =~# 'CountE(.*)'
  65. let expr = substitute(expr, 'CountE(\([^)]*\))', 'tablemode#spreadsheet#CountE("\1",'.line.','.colm.')', 'g')
  66. endif
  67. if expr =~# 'CountNE(.*)'
  68. let expr = substitute(expr, 'CountNE(\([^)]*\))', 'tablemode#spreadsheet#CountNE("\1",'.line.','.colm.')', 'g')
  69. endif
  70. if expr =~# 'PercentE(.*)'
  71. let expr = substitute(expr, 'PercentE(\([^)]*\))', 'tablemode#spreadsheet#PercentE("\1",'.line.','.colm.')', 'g')
  72. endif
  73. if expr =~# 'PercentNE(.*)'
  74. let expr = substitute(expr, 'PercentNE(\([^)]*\))', 'tablemode#spreadsheet#PercentNE("\1",'.line.','.colm.')', 'g')
  75. endif
  76. if expr =~# 'Sum(.*)'
  77. let expr = substitute(expr, 'Sum(\([^)]*\))', 'tablemode#spreadsheet#Sum("\1",'.line.','.colm.')', 'g')
  78. endif
  79. if expr =~# 'Average(.*)'
  80. let expr = substitute(expr, 'Average(\([^)]*\))', 'tablemode#spreadsheet#Average("\1",'.line.','.colm.')', 'g')
  81. endif
  82. if expr =~# 'AverageNE(.*)'
  83. let expr = substitute(expr, 'AverageNE(\([^)]*\))', 'tablemode#spreadsheet#AverageNE("\1",'.line.','.colm.')', 'g')
  84. endif
  85. if expr =~# '\$\-\?\d\+,\-\?\d\+'
  86. let expr = substitute(expr, '\$\(\-\?\d\+\),\(\-\?\d\+\)',
  87. \ '\=tablemode#spreadsheet#cell#GetCells(line, submatch(1), submatch(2))', 'g')
  88. endif
  89. if cell =~# ','
  90. if expr =~# '\$'
  91. let expr = substitute(expr, '\$\(\d\+\)',
  92. \ '\=tablemode#spreadsheet#cell#GetCells(line, row, submatch(1))', 'g')
  93. endif
  94. silent! call tablemode#spreadsheet#cell#SetCell(eval(expr), line, row, colm)
  95. else
  96. let [row, line] = [1, tablemode#spreadsheet#GetFirstRow(line)]
  97. while !s:IsFormulaLine(line)
  98. if !tablemode#table#IsBorder(line)
  99. let texpr = expr
  100. if expr =~# '\$'
  101. let texpr = substitute(texpr, '\$\(\d\+\)',
  102. \ '\=tablemode#spreadsheet#cell#GetCells(line, row, submatch(1))', 'g')
  103. endif
  104. silent! call tablemode#spreadsheet#cell#SetCell(eval(texpr), line, row, colm)
  105. let row += 1
  106. endif
  107. let line += 1
  108. endwhile
  109. endif
  110. endfunction
  111. function! tablemode#spreadsheet#formula#EvaluateFormulaLine() "{{{2
  112. let exprs = []
  113. let cstring = &commentstring
  114. let matchexpr = ''
  115. if len(cstring) > 0
  116. let cms = split(cstring, '%s')
  117. if len(cms) == 2
  118. let matchexpr = '^\s*' . escape(cms[0], '/*') . '\s*tmf: \zs.*\ze' . escape(cms[1], '/*') . '\s*$'
  119. else
  120. let matchexpr = '^\s*' . escape(cms[0], '/*') . '\s*tmf: \zs.*$'
  121. endif
  122. else
  123. let matchexpr = '^\s* tmf: \zs.*$'
  124. endif
  125. if tablemode#table#IsRow('.') " We're inside the table
  126. let line = tablemode#spreadsheet#GetLastRow('.')
  127. let fline = line + 1
  128. if s:IsHTMLComment(fline) | let fline += 1 | endif
  129. if tablemode#table#IsBorder(fline) | let fline += 1 | endif
  130. while s:IsFormulaLine(fline)
  131. let exprs += split(matchstr(getline(fline), matchexpr), ';')
  132. let fline += 1
  133. endwhile
  134. elseif s:IsFormulaLine('.')
  135. let fline = line('.')
  136. let line = line('.') - 1
  137. while s:IsFormulaLine(line) | let fline = line | let line -= 1 | endwhile
  138. if s:IsHTMLComment(line) | let line -= 1 | endif
  139. if tablemode#table#IsBorder(line) | let line -= 1 | endif
  140. if tablemode#table#IsRow(line)
  141. " let exprs = split(matchstr(getline('.'), matchexpr), ';')
  142. while s:IsFormulaLine(fline)
  143. let exprs += split(matchstr(getline(fline), matchexpr), ';')
  144. let fline += 1
  145. endwhile
  146. endif
  147. endif
  148. for expr in exprs
  149. call tablemode#spreadsheet#formula#EvaluateExpr(expr, line)
  150. endfor
  151. endfunction