Mercurial > dotfiles.old
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 |