forked from colinta/SublimeCalculate
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcalculate.py
More file actions
145 lines (117 loc) · 4.95 KB
/
calculate.py
File metadata and controls
145 lines (117 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import sublime
import sublime_plugin
import math
import re
class CalculateCommand(sublime_plugin.TextCommand):
def run(self, edit, **kwargs):
calculate_e = self.view.begin_edit('calculate')
regions = [region for region in self.view.sel()]
# any edits that are performed will happen in reverse; this makes it
# easy to keep region.a and region.b pointing to the correct locations
def compare(region_a, region_b):
return cmp(region_b.end(), region_a.end())
regions.sort(compare)
for region in regions:
try:
error = self.run_each(edit, region, **kwargs)
except Exception as exception:
error = exception.message
if error:
sublime.status_message(error)
self.view.end_edit(calculate_e)
def calculate(self, formula):
dict = {}
for key in dir(math):
dict[key] = getattr(math, key)
def average(nums):
return sum(nums) / len(nums)
dict['avg'] = average
dict['average'] = average
return unicode(eval(formula, dict, {}))
def run_each(self, edit, region, replace=False):
if region.empty() and len(self.view.sel()):
def on_done(formula):
value = self.calculate(formula)
self.view.insert(edit, region.begin(), value)
self.view.window().show_input_panel('Formula', '', on_done, None, None)
elif not region.empty():
formula = self.view.substr(region)
value = self.calculate(formula)
if not replace:
value = "%s = %s" % (formula, value)
self.view.replace(edit, region, value)
class CalculateCountCommand(sublime_plugin.TextCommand):
def run(self, edit, index=1):
regions = [region for region in self.view.sel()]
def generate_integer_counter(initial):
def count():
offset = initial
while True:
yield unicode(offset)
offset += 1
return iter(count()).next
def generate_hexadecimal_counter(initial, length):
def count():
offset = initial
while True:
yield u"0x%x" % offset
offset += 1
return iter(count()).next
def generate_octal_counter(initial, length):
def count():
offset = initial
while True:
yield u"0%o" % offset
offset += 1
return iter(count()).next
def generate_string_counter(initial):
def count():
offset = initial
while True:
yield offset
up = 1 # increase last character
while True:
o = ord(offset[-up])
o += 1
tail = ''
if up > 1:
tail = offset[-up + 1:]
if o > ord('z'):
offset = offset[:-up] + u'a' + tail
up += 1
if len(offset) < up:
offset = u'a' + offset
break
else:
offset = offset[:-up] + unichr(o) + tail
break
return iter(count()).next
is_first = True
subs = []
for region in regions:
if is_first:
# see if the region is a number or alphanumerics
content = self.view.substr(region)
if re.match('0x[0-9a-fA-F]+$', content):
counter = generate_hexadecimal_counter(int(content[2:], 16), len(regions))
elif re.match('0[0-7]+$', content):
counter = generate_octal_counter(int(content[1:], 8), len(regions))
elif re.match('[0-9]+$', content):
counter = generate_integer_counter(int(content))
elif re.match('[a-z]+$', content):
counter = generate_string_counter(content)
else:
counter = generate_integer_counter(index)
subs.append((region, str(counter())))
is_first = False
# any edits that are performed will happen in reverse; this makes it
# easy to keep region.a and region.b pointing to the correct locations
def compare(sub_a, sub_b):
return cmp(sub_b[0].end(), sub_a[0].end())
subs.sort(compare)
calculate_e = self.view.begin_edit('calculate')
for sub in subs:
self.view.sel().subtract(sub[0])
self.view.replace(edit, sub[0], sub[1])
self.view.sel().add(sublime.Region(sub[0].begin() + len(sub[1]), sub[0].begin() + len(sub[1])))
self.view.end_edit(calculate_e)