comparison vim/bundle/math/plugin/vmath.vim @ 22:b2c16cd71d95

Add math plugin
author zegervdv <zegervdv@me.com>
date Sun, 23 Mar 2014 18:08:34 +0100
parents
children
comparison
equal deleted inserted replaced
21:bf5c5093bad9 22:b2c16cd71d95
1 " Vim global plugin for math on visual regions
2 " Maintainer: Damian Conway
3 " License: This file is placed in the public domain.
4
5 "######################################################################
6 "## ##
7 "## To use: ##
8 "## ##
9 "## vmap <expr> ++ VMATH_YankAndAnalyse() ##
10 "## nmap ++ vip++ ##
11 "## ##
12 "## (or whatever keys you prefer to remap these actions to) ##
13 "## ##
14 "######################################################################
15
16
17 " If already loaded, we're done...
18 if exists("loaded_vmath")
19 finish
20 endif
21 let loaded_vmath = 1
22
23 " Preserve external compatibility options, then enable full vim compatibility...
24 let s:save_cpo = &cpo
25 set cpo&vim
26
27 " Grab visual selection and do simple math on it...
28 function! VMATH_YankAndAnalyse ()
29 return "y:call VMATH_Analyse()\<CR>gv"
30 endfunction
31
32 " What to consider a number...
33 let s:NUM_PAT = '^[+-]\?\d\+\%([.]\d\+\)\?\([eE][+-]\?\d\+\)\?$'
34
35 " How widely to space the report components...
36 let s:REPORT_GAP = 5 "spaces between components
37
38 " Do simple math on current yank buffer...
39 function! VMATH_Analyse ()
40 " Extract data from selection...
41 let selection = getreg('')
42 let raw_numbers = filter(split(selection), 'v:val =~ s:NUM_PAT')
43 let numbers = map(copy(raw_numbers), 'str2float(v:val)')
44
45 " Results include a newline if original selection did...
46 let newline = selection =~ "\n" ? "\n" : ""
47
48 " Calculate and en-register various interesting metrics...
49 let summation = len(numbers) ? join( numbers, ' + ') : '0'
50 call setreg('s', s:tidy( eval( summation ) )) " Sum --> register s
51 call setreg('a', s:average(raw_numbers) ) " Average --> register a
52 call setreg('x', s:tidy( s:max(numbers) )) " Max --> register x
53 call setreg('n', s:tidy( s:min(numbers) )) " Min --> register n
54 call setreg('r', @n . ' to ' . @x ) " Range --> register r
55
56 " Default paste buffer should depend on original contents (TODO)
57 call setreg('', @s )
58
59 " Report...
60 let gap = repeat(" ", s:REPORT_GAP)
61 highlight NormalUnderlined term=underline cterm=underline gui=underline
62 echohl NormalUnderlined
63 echo 's'
64 echohl NONE
65 echon 'um: ' . @s . gap
66 echohl NormalUnderlined
67 echon 'a'
68 echohl NONE
69 echon 'vg: ' . @a . gap
70 echon 'mi'
71 echohl NormalUnderlined
72 echon 'n'
73 echohl NONE
74 echon ': ' . @n . gap
75 echon 'ma'
76 echohl NormalUnderlined
77 echon 'x'
78 echohl NONE
79 echon ': ' . @x . gap
80
81 endfunction
82
83 " Prettify numbers...
84 function! s:tidy (number)
85 let tidied = printf('%g', a:number)
86 return substitute(tidied, '[.]0\+$', '', '')
87 endfunction
88
89 " Compute average with meaningful number of decimal places...
90 function! s:average (numbers)
91 " Compute average...
92 let summation = eval( len(a:numbers) ? join( a:numbers, ' + ') : '0' )
93 let avg = 1.0 * summation / s:max([len(a:numbers), 1])
94
95 " Determine significant figures...
96 let min_decimals = 15
97 for num in a:numbers
98 let decimals = strlen(matchstr(num, '[.]\d\+$')) - 1
99 if decimals < min_decimals
100 let min_decimals = decimals
101 endif
102 endfor
103
104 " Adjust answer...
105 return min_decimals > 0 ? printf('%0.'.min_decimals.'f', avg)
106 \ : string(avg)
107 endfunction
108
109 " Reimplement these because the builtins don't handle floats (!!!)
110 function! s:max (numbers)
111 if !len(a:numbers)
112 return 0
113 endif
114 let numbers = copy(a:numbers)
115 let maxnum = numbers[0]
116 for nextnum in numbers[1:]
117 if nextnum > maxnum
118 let maxnum = nextnum
119 endif
120 endfor
121 return maxnum
122 endfunction
123
124 function! s:min (numbers)
125 if !len(a:numbers)
126 return 0
127 endif
128 let numbers = copy(a:numbers)
129 let minnum = numbers[0]
130 for nextnum in numbers[1:]
131 if nextnum < minnum
132 let minnum = nextnum
133 endif
134 endfor
135 return minnum
136 endfunction
137
138
139 " Restore previous external compatibility options
140 let &cpo = s:save_cpo