├── Default (Linux).sublime-keymap
├── Default (OSX).sublime-keymap
├── Default (Windows).sublime-keymap
├── .gitignore
├── LICENSE
├── MiniPy.py
└── README.md
/Default (Linux).sublime-keymap:
--------------------------------------------------------------------------------
1 | [
2 | { "keys": ["ctrl+shift+x"], "command": "minipy_eval" }
3 | ]
--------------------------------------------------------------------------------
/Default (OSX).sublime-keymap:
--------------------------------------------------------------------------------
1 | [
2 | { "keys": ["super+shift+x"], "command": "minipy_eval" }
3 | ]
--------------------------------------------------------------------------------
/Default (Windows).sublime-keymap:
--------------------------------------------------------------------------------
1 | [
2 | { "keys": ["ctrl+shift+x"], "command": "minipy_eval" }
3 | ]
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.py[cod]
2 |
3 | # C extensions
4 | *.so
5 |
6 | # Packages
7 | *.egg
8 | *.egg-info
9 | dist
10 | build
11 | eggs
12 | parts
13 | bin
14 | var
15 | sdist
16 | develop-eggs
17 | .installed.cfg
18 | lib
19 | lib64
20 |
21 | # Installer logs
22 | pip-log.txt
23 |
24 | # Unit test / coverage reports
25 | .coverage
26 | .tox
27 | nosetests.xml
28 |
29 | # Translations
30 | *.mo
31 |
32 | # Mr Developer
33 | .mr.developer.cfg
34 | .project
35 | .pydevproject
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Ofer Affias
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/MiniPy.py:
--------------------------------------------------------------------------------
1 | from math import *
2 | from random import *
3 | from hashlib import md5 as _md5
4 | from hashlib import sha1 as _sha1
5 | from collections import Counter
6 | import datetime
7 | import re
8 | import sublime
9 | import sublime_plugin
10 |
11 |
12 | def cumsum(lst):
13 | return [sum(lst[:i]) for i in range(1, len(lst)+1)]
14 |
15 |
16 | def cumprod(lst, use_logsum=False):
17 | def do_cumprod(lst):
18 | tmp = 1
19 | toReturn = list()
20 | for el in lst:
21 | tmp *= el
22 | toReturn.append(tmp)
23 | return toReturn
24 |
25 | if use_logsum:
26 | return [exp(el_log) for el_log in cumsum([log(el) for el in lst])]
27 | else:
28 | return do_cumprod(lst)
29 |
30 |
31 | def dnow():
32 | return datetime.datetime.strftime(datetime.datetime.now(), '%d/%m/%Y')
33 |
34 |
35 | def tnow():
36 | return datetime.datetime.strftime(datetime.datetime.now(), '%H:%M:%S')
37 |
38 |
39 | def dtnow():
40 | return datetime.datetime.strftime(datetime.datetime.now(), '%d/%m/%Y %H:%M:%S')
41 |
42 |
43 | def _hashfunc(hashfunc, obj):
44 | s = str(obj)
45 | h = hashfunc(s.encode('utf-8'))
46 | return h.hexdigest()
47 |
48 |
49 | def md5(obj):
50 | return _hashfunc(_md5, obj)
51 |
52 |
53 | def sha1(obj):
54 | return _hashfunc(_sha1, obj)
55 |
56 |
57 | def set_intersect(itr0, itr1):
58 | s0, s1 = set(itr0), set(itr1)
59 | return s0.intersection(s1)
60 |
61 |
62 | def set_difference(itr0, itr1):
63 | s0, s1 = set(itr0), set(itr1)
64 | return s0 - s1
65 |
66 |
67 | def set_symdiff(itr0, itr1):
68 | s0, s1 = set(itr0), set(itr1)
69 | return s0.symmetric_difference(s1)
70 |
71 |
72 | def formatnum(num, digits=8, scientificNotation=None):
73 |
74 | def normalFormatting(num, digits):
75 | return ('{:.%df}' % digits).format(num)
76 |
77 | def scientificFormatting(num, digits):
78 | return ('{:.%de}' % digits).format(num)
79 |
80 | if scientificNotation is False:
81 | return normalFormatting(num, digits)
82 |
83 | if scientificNotation is True:
84 | return scientificFormatting(num, digits)
85 |
86 | if scientificNotation is None:
87 | scientificNotation = 8
88 |
89 | if isinstance(scientificNotation, int):
90 | if len(normalFormatting(num, digits)) > scientificNotation:
91 | return scientificFormatting(num, digits)
92 | return normalFormatting(num, digits)
93 |
94 |
95 | # reverse() in python3
96 | def rev(s):
97 | return s[::-1]
98 |
99 |
100 | # timestamp (unix time since epoch) to string
101 | def ts(timestamp_sec, fmt='%Y-%m-%dT%H:%M:%S.%f%z'):
102 | return datetime.datetime.utcfromtimestamp( timestamp_sec ).strftime( fmt )
103 |
104 |
105 | class Minipy_evalCommand(sublime_plugin.TextCommand):
106 | def run(self, edit, user_input=None):
107 | self.edit = edit
108 | view = self.view
109 | script = ""
110 |
111 | # sum the total number of special char $
112 | total = 0
113 | for region in view.sel():
114 | total += view.substr(region).count("$")
115 |
116 | print("total = ", total)
117 | # build a list from 1 to the number of special chars
118 | serial_number = list(range(1, total + 1))
119 | # serial_number.reverse()
120 | serial_number = rev(serial_number)
121 | print(repr(serial_number))
122 |
123 | # replace each special char $ with the next index from serial_number list
124 | # and eval the expression
125 | for region in view.sel():
126 | if region.begin() != region.end():
127 | script = view.substr(region)
128 | for n in range(script.count("$")):
129 | script = re.sub(r"\$", str(serial_number.pop()), script, 1)
130 | # print(eval(script))
131 | view.replace(edit, region, str(eval(script)))
132 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MiniPy
2 |
3 | Sublime Text 3 plugin - inline python evaluation.
4 |
5 | ## Functionality
6 |
7 | ### As a calculator
8 |
9 | For example you can write `3.14*0.6` and get the result `1.884` in your text.
10 | It also supports multiple selection.
11 |
12 | ### Incremnt counter at cursor positions
13 |
14 | Another feature is the use of $ as accumolation variable, e.g. having the following multipe selection:
15 |
16 | arr[$]
17 | arr[$]
18 | arr[$]
19 |
20 | will result with
21 |
22 | arr[1]
23 | arr[2]
24 | arr[3]
25 |
26 | similarly:
27 |
28 | arr[0 ] arr[0]
29 | arr[$+2] -> arr[3]
30 | arr[$*3] arr[6]
31 |
32 | ### General Python evalueator
33 |
34 | Besides that, you have the following imports avaiable:
35 |
36 | from math import *
37 | from random import *
38 | from collections import Counter
39 | import datetime
40 | import re # though you should probably use the build in regex features of ST instead.
41 |
42 | So you can do:
43 |
44 | Counter(('Ann', 'Bob', 'Bob', 'Michael')) -> Counter({'Bob': 2, 'Ann': 1, 'Michael': 1})
45 | Counter(('Ann', 'Bob', 'Bob', 'Michael', 'michael')) -> Counter({'Bob': 2, 'Ann': 1, 'michael': 1, 'Michael': 1})
46 | Counter(name.title() for name in ('Ann', 'Bob', 'Bob', 'Michael', 'michael')) -> Counter({'Bob': 2, 'Michael': 2, 'Ann': 1})
47 |
48 | ### Computing checksums
49 |
50 | And the functions `md5` and `sha1` returns the correspondingly hex-digest of the stringified version of the inputs, e.g. `md5(['foo', 'bar', 'baz']) = dbb432a3f0ac1a2687911715dfbf7502`. Notice that it's possible to hash the list _because it's the string-representation of the list which are being hashed!_
51 |
52 | The python `hashlib.md5` and `hashlib.sha1` functions are avaiable under the names `_md5` and `_sha1`.
53 |
54 | ### Inserting datatimes
55 |
56 | The functions `dnow`, `tnow` and `dtnow` return respectively the current string-formatted date, time and datetime:
57 |
58 | dnow() -> 03/05/2017
59 | tnow() -> 09:36:03
60 | dtnow() -> 03/05/2017 09:36:03
61 |
62 | Notice that you need to have parenthesis after the function name to invoke the function call.
63 |
64 |
65 | ### Computing with sets
66 |
67 | While you can just use the regular python to do set computations, there's a few functions included for convinience: `set_intersect`, `set_difference` and `set_symdiff`.
68 |
69 | The functions takes two iterable arguments, which are turned into sets, and the computations are performed:
70 |
71 | set_intersect('foo bar', 'foo baz') -> {'b', ' ', 'a', 'f', 'o'}
72 | set_intersect('foo baz', 'foo bar') -> {'b', 'a', ' ', 'o', 'f'}
73 | set_difference('foo baz', 'foo bar') -> {'z'}
74 | set_difference('foo bar', 'foo baz') -> {'r'}
75 | set_symdiff('foo baz', 'foo bar') -> {'z', 'r'}
76 | set_symdiff('foo bar', 'foo baz') -> {'z', 'r'}
77 |
78 |
79 | ### Computing cumulative sums and products
80 |
81 | Compute the cumulative sum of an iterable:
82 |
83 | cumsum([1,2,3,4,5]) -> [1, 3, 6, 10, 15]
84 | cumsum([0.02809, 0.05619, 0.08646, 0.11919, 0.15192, 0.18465, 1.31694]) -> [0.02809, 0.08428, 0.17074, 0.28993, 0.44185, 0.6265000000000001, 1.94344]
85 |
86 | And a cumulative product
87 |
88 | cumprod([1, 2, 3, 4, 5]) -> [1, 2, 6, 24, 120]
89 | cumprod([0.02809, 0.05619, 0.08646, 0.11919, 0.15192, 0.18465, 1.31694]) -> [0.02809, 0.0015783771, 0.000136466484066, 1.626544023582654e-05, 2.471045680626768e-06, 4.5627858492773275e-07, 6.008915196347284e-07]
90 |
91 | But doing products of a lot of small numbers are prone to errors, so we can use a math trick:
92 |
, where _A_ is the iterable. This will increase the numerical stability, as seen in this example:
93 |
94 | cumprod([1e-8, 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14]) -> [1e-08, 1e-17, 1e-27, 1e-38, 9.999999999999999e-51, 9.999999999999999e-64, 1e-77]
95 | cumprod([1e-8, 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14], use_logsum=True) -> [9.999999999999982e-09, 9.99999999999999e-18, 1.0000000000000022e-27, 9.999999999999936e-39, 9.999999999999944e-51, 1.0000000000000049e-63, 9.999999999999967e-78]
96 | cumprod([1e-8, 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14], use_logsum=True) -> # same result as above.
97 |
98 |
99 | ### Formatting numbers
100 |
101 | The function `formatnum` formats numbers, and takes two mandatory and an optional argument:
102 |
103 | num
104 | : The number bieng formatted.
105 |
106 | digits
107 | : The number of desired digits in the formatted number.
108 |
109 | scientificNotation
110 | : Wether of not to use scientific notation.
111 | : Can be True, False or int, where int is the threshold for how many characters the number may contain when formatted un-scientifically, before switching to scientific notation.
112 | : This is the default behaviour, and it's set to 8.
113 |
114 | Example usage:
115 |
116 | formatnum(0.123456789, 4) -> 0.1235
117 | formatnum(0.123456789, 9) -> 1.234567890e-01
118 | formatnum(123456789.0, 9) -> 1.234567890e+08
119 | formatnum(123456789.0, 2) -> 1.23e+08
120 | formatnum(123.456789, 12) -> 1.234567890000e+02
121 | formatnum(123.456789, 12, False) -> 123.456789000000
122 | formatnum(123.456789, 3) -> 123.457
123 | formatnum(3.14159, 4) -> 3.1416
124 | formatnum(3.14159, 3) -> 3.142
125 | formatnum(3.14159, 2) -> 3.14
126 | formatnum(3.14159, 2, True) -> 3.14e+00
127 | formatnum(3.141592653589793238462643, 3) -> 3.142
128 |
129 | ### Convert Timestamp to human readable time
130 |
131 | The function `ts` transform timestamp as unix time, which is seconds since epoch to string using supplied format
132 |
133 | ts(1478002058.368) -> 2016-11-01T12:07:38.368000+0000
134 | ts(1478002058.368, '%Y%m%d') -> 20161101
135 |
136 | ## Usage
137 |
138 | To evaluate term, highlight and:
139 |
140 | Super + Shift + X for Mac OS X
141 | Ctrl + Shift + X for Windows/Linux
142 |
--------------------------------------------------------------------------------