mirror of
https://github.com/dhruvasagar/vim-table-mode.git
synced 2025-11-08 11:03:47 -05:00
Merge pull request #175 from insanum/formulas
added some new formula functions
This commit is contained in:
@@ -1,4 +1,106 @@
|
||||
" Private Functions {{{1
|
||||
function! s:TotalCells(list) "{{{2
|
||||
let result = 0
|
||||
for item in a:list
|
||||
if type(item) == type([])
|
||||
let result += s:TotalCells(item)
|
||||
else
|
||||
let result += 1
|
||||
endif
|
||||
endfor
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! s:Min(list) "{{{2
|
||||
let found = v:false
|
||||
let result = 0
|
||||
for item in a:list
|
||||
if empty(item)
|
||||
continue
|
||||
endif
|
||||
if type(item) == type(1) || type(item) == type(1.0)
|
||||
if found == v:false || item < result
|
||||
let found = v:true
|
||||
let result = item
|
||||
endif
|
||||
elseif type(item) == type('')
|
||||
let val = str2float(item)
|
||||
if found == v:false || val < result
|
||||
let found = v:true
|
||||
let result = val
|
||||
endif
|
||||
elseif type(item) == type([])
|
||||
let val = s:Min(item)
|
||||
if found == v:false || val < result
|
||||
let found = v:true
|
||||
let result = val
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! s:Max(list) "{{{2
|
||||
let found = v:false
|
||||
let result = 0
|
||||
for item in a:list
|
||||
if empty(item)
|
||||
continue
|
||||
endif
|
||||
if type(item) == type(1) || type(item) == type(1.0)
|
||||
if found == v:false || item > result
|
||||
let found = v:true
|
||||
let result = item
|
||||
endif
|
||||
elseif type(item) == type('')
|
||||
let val = str2float(item)
|
||||
if found == v:false || val > result
|
||||
let found = v:true
|
||||
let result = val
|
||||
endif
|
||||
elseif type(item) == type([])
|
||||
let val = s:Max(item)
|
||||
if found == v:false || val > result
|
||||
let found = v:true
|
||||
let result = val
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! s:CountE(list) "{{{2
|
||||
let result = 0
|
||||
for item in a:list
|
||||
if empty(item)
|
||||
let result += 1
|
||||
elseif type(item) == type([])
|
||||
let result += s:CountE(item)
|
||||
endif
|
||||
endfor
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! s:CountNE(list) "{{{2
|
||||
let result = 0
|
||||
for item in a:list
|
||||
if type(item) == type([])
|
||||
let result += s:CountNE(item)
|
||||
elseif !empty(item)
|
||||
let result += 1
|
||||
endif
|
||||
endfor
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! s:PercentE(list) "{{{2
|
||||
return (s:CountE(a:list)*100)/s:TotalCells(a:list)
|
||||
endfunction
|
||||
|
||||
function! s:PercentNE(list) "{{{2
|
||||
return (s:CountNE(a:list)*100)/s:TotalCells(a:list)
|
||||
endfunction
|
||||
|
||||
function! s:Sum(list) "{{{2
|
||||
let result = 0.0
|
||||
for item in a:list
|
||||
@@ -14,7 +116,11 @@ function! s:Sum(list) "{{{2
|
||||
endfunction
|
||||
|
||||
function! s:Average(list) "{{{2
|
||||
return s:Sum(a:list)/len(a:list)
|
||||
return s:Sum(a:list)/s:TotalCells(a:list)
|
||||
endfunction
|
||||
|
||||
function! s:AverageNE(list) "{{{2
|
||||
return s:Sum(a:list)/s:CountNE(a:list)
|
||||
endfunction
|
||||
|
||||
" Public Functions {{{1
|
||||
@@ -244,6 +350,42 @@ function! tablemode#spreadsheet#InsertColumn(after) "{{{2
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! tablemode#spreadsheet#Min(range, ...) abort "{{{2
|
||||
let args = copy(a:000)
|
||||
call insert(args, a:range)
|
||||
return s:Min(call('tablemode#spreadsheet#cell#GetCellRange', args))
|
||||
endfunction
|
||||
|
||||
function! tablemode#spreadsheet#Max(range, ...) abort "{{{2
|
||||
let args = copy(a:000)
|
||||
call insert(args, a:range)
|
||||
return s:Max(call('tablemode#spreadsheet#cell#GetCellRange', args))
|
||||
endfunction
|
||||
|
||||
function! tablemode#spreadsheet#CountE(range, ...) abort "{{{2
|
||||
let args = copy(a:000)
|
||||
call insert(args, a:range)
|
||||
return s:CountE(call('tablemode#spreadsheet#cell#GetCellRange', args))
|
||||
endfunction
|
||||
|
||||
function! tablemode#spreadsheet#CountNE(range, ...) abort "{{{2
|
||||
let args = copy(a:000)
|
||||
call insert(args, a:range)
|
||||
return s:CountNE(call('tablemode#spreadsheet#cell#GetCellRange', args))
|
||||
endfunction
|
||||
|
||||
function! tablemode#spreadsheet#PercentE(range, ...) abort "{{{2
|
||||
let args = copy(a:000)
|
||||
call insert(args, a:range)
|
||||
return s:PercentE(call('tablemode#spreadsheet#cell#GetCellRange', args))
|
||||
endfunction
|
||||
|
||||
function! tablemode#spreadsheet#PercentNE(range, ...) abort "{{{2
|
||||
let args = copy(a:000)
|
||||
call insert(args, a:range)
|
||||
return s:PercentNE(call('tablemode#spreadsheet#cell#GetCellRange', args))
|
||||
endfunction
|
||||
|
||||
function! tablemode#spreadsheet#Sum(range, ...) abort "{{{2
|
||||
let args = copy(a:000)
|
||||
call insert(args, a:range)
|
||||
@@ -256,6 +398,12 @@ function! tablemode#spreadsheet#Average(range, ...) abort "{{{2
|
||||
return s:Average(call('tablemode#spreadsheet#cell#GetCellRange', args))
|
||||
endfunction
|
||||
|
||||
function! tablemode#spreadsheet#AverageNE(range, ...) abort "{{{2
|
||||
let args = copy(a:000)
|
||||
call insert(args, a:range)
|
||||
return s:AverageNE(call('tablemode#spreadsheet#cell#GetCellRange', args))
|
||||
endfunction
|
||||
|
||||
function! tablemode#spreadsheet#Sort(bang, ...) range "{{{2
|
||||
if exists('*getcurpos')
|
||||
let col = getcurpos()[4] " curswant
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
" Private Functions {{{1
|
||||
function! s:IsHTMLComment(line) "{{{2
|
||||
return getline(a:line) =~# '^\s*<!--'
|
||||
endfunction
|
||||
|
||||
function! s:IsFormulaLine(line) "{{{2
|
||||
return getline(a:line) =~# 'tmf: '
|
||||
endfunction
|
||||
@@ -15,6 +19,7 @@ function! tablemode#spreadsheet#formula#Add(...) "{{{2
|
||||
let fr = '$' . row . ',' . colm . '=' . fr
|
||||
let fline = tablemode#spreadsheet#GetLastRow('.') + 1
|
||||
if tablemode#table#IsBorder(fline) | let fline += 1 | endif
|
||||
if s:IsHTMLComment(fline) | let fline += 1 | endif
|
||||
let cursor_pos = [line('.'), col('.')]
|
||||
if getline(fline) =~# 'tmf: '
|
||||
" Comment line correctly
|
||||
@@ -55,6 +60,30 @@ function! tablemode#spreadsheet#formula#EvaluateExpr(expr, line) abort "{{{2
|
||||
let [row, colm] = [0, str2nr(cell)]
|
||||
endif
|
||||
|
||||
if expr =~# 'Min(.*)'
|
||||
let expr = substitute(expr, 'Min(\([^)]*\))', 'tablemode#spreadsheet#Min("\1",'.line.','.colm.')', 'g')
|
||||
endif
|
||||
|
||||
if expr =~# 'Max(.*)'
|
||||
let expr = substitute(expr, 'Max(\([^)]*\))', 'tablemode#spreadsheet#Max("\1",'.line.','.colm.')', 'g')
|
||||
endif
|
||||
|
||||
if expr =~# 'CountE(.*)'
|
||||
let expr = substitute(expr, 'CountE(\([^)]*\))', 'tablemode#spreadsheet#CountE("\1",'.line.','.colm.')', 'g')
|
||||
endif
|
||||
|
||||
if expr =~# 'CountNE(.*)'
|
||||
let expr = substitute(expr, 'CountNE(\([^)]*\))', 'tablemode#spreadsheet#CountNE("\1",'.line.','.colm.')', 'g')
|
||||
endif
|
||||
|
||||
if expr =~# 'PercentE(.*)'
|
||||
let expr = substitute(expr, 'PercentE(\([^)]*\))', 'tablemode#spreadsheet#PercentE("\1",'.line.','.colm.')', 'g')
|
||||
endif
|
||||
|
||||
if expr =~# 'PercentNE(.*)'
|
||||
let expr = substitute(expr, 'PercentNE(\([^)]*\))', 'tablemode#spreadsheet#PercentNE("\1",'.line.','.colm.')', 'g')
|
||||
endif
|
||||
|
||||
if expr =~# 'Sum(.*)'
|
||||
let expr = substitute(expr, 'Sum(\([^)]*\))', 'tablemode#spreadsheet#Sum("\1",'.line.','.colm.')', 'g')
|
||||
endif
|
||||
@@ -63,6 +92,10 @@ function! tablemode#spreadsheet#formula#EvaluateExpr(expr, line) abort "{{{2
|
||||
let expr = substitute(expr, 'Average(\([^)]*\))', 'tablemode#spreadsheet#Average("\1",'.line.','.colm.')', 'g')
|
||||
endif
|
||||
|
||||
if expr =~# 'AverageNE(.*)'
|
||||
let expr = substitute(expr, 'AverageNE(\([^)]*\))', 'tablemode#spreadsheet#AverageNE("\1",'.line.','.colm.')', 'g')
|
||||
endif
|
||||
|
||||
if expr =~# '\$\-\?\d\+,\-\?\d\+'
|
||||
let expr = substitute(expr, '\$\(\-\?\d\+\),\(\-\?\d\+\)',
|
||||
\ '\=str2float(tablemode#spreadsheet#cell#GetCells(line, submatch(1), submatch(2)))', 'g')
|
||||
@@ -107,6 +140,7 @@ function! tablemode#spreadsheet#formula#EvaluateFormulaLine() abort "{{{2
|
||||
if tablemode#table#IsRow('.') " We're inside the table
|
||||
let line = tablemode#spreadsheet#GetLastRow('.')
|
||||
let fline = line + 1
|
||||
if s:IsHTMLComment(fline) | let fline += 1 | endif
|
||||
if tablemode#table#IsBorder(fline) | let fline += 1 | endif
|
||||
while s:IsFormulaLine(fline)
|
||||
let exprs += split(matchstr(getline(fline), matchexpr), ';')
|
||||
@@ -116,6 +150,7 @@ function! tablemode#spreadsheet#formula#EvaluateFormulaLine() abort "{{{2
|
||||
let fline = line('.')
|
||||
let line = line('.') - 1
|
||||
while s:IsFormulaLine(line) | let fline = line | let line -= 1 | endwhile
|
||||
if s:IsHTMLComment(line) | let line -= 1 | endif
|
||||
if tablemode#table#IsBorder(line) | let line -= 1 | endif
|
||||
if tablemode#table#IsRow(line)
|
||||
" let exprs = split(matchstr(getline('.'), matchexpr), ';')
|
||||
|
||||
@@ -120,8 +120,11 @@ Formula Expressions :
|
||||
The formula can be a simple mathematical expression involving cells
|
||||
which are also defined by the same format as that of the target cell.
|
||||
Apart from basic mathematical expressions, table mode also provides
|
||||
special functions 'Sum' and 'Average'. Both these functions take a
|
||||
range as input. A range can be of two forms :
|
||||
special functions 'Min', 'Max', 'CountE' (number of empty cells),
|
||||
'CountNE' (number of non-empty cells), 'PercentE' (percent of empty
|
||||
cells), 'PercentNE' (percent of non-empty cells), 'Sum', 'Average',
|
||||
and 'AverageNE' (average over non-empty cells). All these functions
|
||||
take a range as input. A range can be of two forms :
|
||||
|
||||
'n:m': This represents cells in the current column from row
|
||||
'n' through 'm'. If 'm' is negative it represents 'm' row
|
||||
|
||||
3
t/fixtures/cell/counts.txt
Normal file
3
t/fixtures/cell/counts.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
| 1 | 2 | 3 |
|
||||
| | 0 | |
|
||||
| 4 | 5 | 6 |
|
||||
@@ -74,11 +74,93 @@ describe 'spreadsheet'
|
||||
call cursor(1,3)
|
||||
Expect tablemode#spreadsheet#Average('1:2') == 2.0
|
||||
Expect tablemode#spreadsheet#Average('1,1:1,2') == 1.5
|
||||
Expect tablemode#spreadsheet#Average('1,1:2,2') == 5.0
|
||||
Expect tablemode#spreadsheet#Average('1,1:2,2') == 2.5
|
||||
call cursor(2,7)
|
||||
Expect tablemode#spreadsheet#Average('1:2') == 3.0
|
||||
Expect tablemode#spreadsheet#Average('2,1:2,2') == 3.5
|
||||
end
|
||||
|
||||
it 'should return the min of cell range'
|
||||
call cursor(1,3)
|
||||
Expect tablemode#spreadsheet#Min('1:2') == 1.0
|
||||
Expect tablemode#spreadsheet#Min('1,1:1,2') == 1.0
|
||||
Expect tablemode#spreadsheet#Min('1,1:2,2') == 1.0
|
||||
call cursor(2,7)
|
||||
Expect tablemode#spreadsheet#Min('1:2') == 2.0
|
||||
Expect tablemode#spreadsheet#Min('2,1:2,2') == 3.0
|
||||
end
|
||||
|
||||
it 'should return the max of cell range'
|
||||
call cursor(1,3)
|
||||
Expect tablemode#spreadsheet#Max('1:2') == 3.0
|
||||
Expect tablemode#spreadsheet#Max('1,1:1,2') == 2.0
|
||||
Expect tablemode#spreadsheet#Max('1,1:2,2') == 4.0
|
||||
call cursor(2,7)
|
||||
Expect tablemode#spreadsheet#Max('1:2') == 4.0
|
||||
Expect tablemode#spreadsheet#Max('2,1:2,2') == 4.0
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Count'
|
||||
before
|
||||
new
|
||||
read t/fixtures/cell/counts.txt
|
||||
end
|
||||
|
||||
it 'should return the count of empty cell range'
|
||||
call cursor(1,3)
|
||||
Expect tablemode#spreadsheet#CountE('1:3') == 1
|
||||
Expect tablemode#spreadsheet#CountE('1,1:1,3') == 0
|
||||
Expect tablemode#spreadsheet#CountE('2,1:2,3') == 2
|
||||
Expect tablemode#spreadsheet#CountE('1,1:3,3') == 2
|
||||
call cursor(3,11)
|
||||
Expect tablemode#spreadsheet#CountE('1:3') == 1
|
||||
Expect tablemode#spreadsheet#CountE('3,1:3,3') == 0
|
||||
end
|
||||
|
||||
it 'should return the count of not-empty cell range'
|
||||
call cursor(1,3)
|
||||
Expect tablemode#spreadsheet#CountNE('1:3') == 2
|
||||
Expect tablemode#spreadsheet#CountNE('1,1:1,3') == 3
|
||||
Expect tablemode#spreadsheet#CountNE('2,1:2,3') == 1
|
||||
Expect tablemode#spreadsheet#CountNE('1,1:3,3') == 7
|
||||
call cursor(3,11)
|
||||
Expect tablemode#spreadsheet#CountNE('1:3') == 2
|
||||
Expect tablemode#spreadsheet#CountNE('3,1:3,3') == 3
|
||||
end
|
||||
|
||||
it 'should return the percent count of empty cell range'
|
||||
call cursor(1,3)
|
||||
Expect tablemode#spreadsheet#PercentE('1:3') == 33
|
||||
Expect tablemode#spreadsheet#PercentE('1,1:1,3') == 0
|
||||
Expect tablemode#spreadsheet#PercentE('2,1:2,3') == 66
|
||||
Expect tablemode#spreadsheet#PercentE('1,1:3,3') == 22
|
||||
call cursor(3,11)
|
||||
Expect tablemode#spreadsheet#PercentE('1:3') == 33
|
||||
Expect tablemode#spreadsheet#PercentE('3,1:3,3') == 0
|
||||
end
|
||||
|
||||
it 'should return the percent count of not-empty cell range'
|
||||
call cursor(1,3)
|
||||
Expect tablemode#spreadsheet#PercentNE('1:3') == 66
|
||||
Expect tablemode#spreadsheet#PercentNE('1,1:1,3') == 100
|
||||
Expect tablemode#spreadsheet#PercentNE('2,1:2,3') == 33
|
||||
Expect tablemode#spreadsheet#PercentNE('1,1:3,3') == 77
|
||||
call cursor(3,11)
|
||||
Expect tablemode#spreadsheet#PercentNE('1:3') == 66
|
||||
Expect tablemode#spreadsheet#PercentNE('3,1:3,3') == 100
|
||||
end
|
||||
|
||||
it 'should return the average of not-empty cell range'
|
||||
call cursor(1,3)
|
||||
Expect tablemode#spreadsheet#AverageNE('1:3') == 2.5
|
||||
Expect tablemode#spreadsheet#AverageNE('1,1:1,3') == 2.0
|
||||
Expect tablemode#spreadsheet#AverageNE('2,1:2,3') == 0.0
|
||||
Expect tablemode#spreadsheet#AverageNE('1,1:3,3') == 3.0
|
||||
call cursor(3,11)
|
||||
Expect tablemode#spreadsheet#AverageNE('1:3') == 4.5
|
||||
Expect tablemode#spreadsheet#AverageNE('3,1:3,3') == 5.0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user