-
-
Notifications
You must be signed in to change notification settings - Fork 287
/
Copy pathexpr.py
65 lines (50 loc) · 3.01 KB
/
expr.py
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
from visidata import Progress, Sheet, Column, asyncthread, vd, ExprColumn
class CompleteExpr:
def __init__(self, sheet=None):
self.sheet = sheet
def __call__(self, val, state):
i = len(val)-1
while val[i:].isidentifier() and i >= 0:
i -= 1
if i < 0:
base = ''
partial = val
elif val[i] == '.': # no completion of attributes
return None
else:
base = val[:i+1]
partial = val[i+1:]
varnames = []
varnames.extend(sorted((base+col.name) for col in self.sheet.columns if col.name.startswith(partial)))
varnames.extend(sorted((base+x) for x in vd.getGlobals() if x.startswith(partial)))
# Remove duplicate tabbing suggestions
varnames_dict = {var:None for var in varnames}
varnames = list(varnames_dict.keys())
return varnames[state%len(varnames)]
@Column.api
@asyncthread
def setValuesFromExpr(self, rows, expr):
'Set values in this column for *rows* to the result of the Python expression *expr* applied to each row.'
compiledExpr = compile(expr, '<expr>', 'eval')
vd.addUndoSetValues([self], rows)
for row in Progress(rows, 'setting'):
# Note: expressions that are only calculated once, do not need to pass column identity
# they can reference their "previous selves" once without causing a recursive problem
v = vd.callNoExceptions(self.sheet.evalExpr, compiledExpr, row)
vd.callNoExceptions(self.setValue, row, v)
self.recalc()
vd.status('set %d values = %s' % (len(rows), expr))
@Sheet.api
def inputExpr(self, prompt, *args, **kwargs):
return vd.input(prompt, "expr", *args, completer=CompleteExpr(self), **kwargs)
Sheet.addCommand('=', 'addcol-expr', 'addColumnAtCursor(ExprColumn(inputExpr("new column expr="), curcol=cursorCol))', 'create new column from Python expression, with column names as variables')
Sheet.addCommand('g=', 'setcol-expr', 'cursorCol.setValuesFromExpr(someSelectedRows, inputExpr("set selected="))', 'set current column for selected rows to result of Python expression')
Sheet.addCommand('z=', 'setcell-expr', 'cursorCol.setValues([cursorRow], evalExpr(inputExpr("set expr="), cursorRow,))', 'evaluate Python expression on current row and set current cell with result of Python expression')
Sheet.addCommand('gz=', 'setcol-iter', 'cursorCol.setValues(someSelectedRows, *list(itertools.islice(eval(input("set column= ", "expr", completer=CompleteExpr())), len(someSelectedRows))))', 'set current column for selected rows to the items in result of Python sequence expression')
Sheet.addCommand(None, 'show-expr', 'status(evalExpr(inputExpr("show expr="), cursorRow))', 'evaluate Python expression on current row and show result on status line')
vd.addGlobals({'CompleteExpr': CompleteExpr})
vd.addMenuItems('''
Edit > Modify > current cell > Python expression > setcell-expr
Edit > Modify > selected cells > Python sequence > setcol-expr
Column > Add column > Python expr > addcol-expr
''')