├── 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 | --------------------------------------------------------------------------------