-
|
I am trying to use visidata as a GUI for catagorizing my account data. However, I wonder whether one can programmatically pose a restriction on column I found that in Can someone give me an idea how to tackle this problem or give me some hint? Maybe there is already a similar feature? Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments
-
|
I am getting closer to a solution... Here is what I did: # Install sample data
$ mkdir sample_data
$ wget -P sample_data/ https://raw.githubusercontent.com/saulpw/visidata/refs/heads/develop/sample_data/benchmark.csv
$ wget -P sample_data/ https://raw.githubusercontent.com/saulpw/visidata/refs/heads/develop/sample_data/sample.tsv
# Create config file
$ mkdir -p config/visidata
$ touch config/visidata/config.pyNow, in @Sheet.api
def editCell(self, vcolidx=None, rowidx=None, value=None, **kwargs):
'''Call vd.editText for the cell at (*rowidx*, *vcolidx*). Return the new value, properly typed.
- *vcolidx*: numeric index into ``self.availCols``. When None, use current column.
- *rowidx*: numeric index into ``self.rows``. If negative, indicates the column name in the header.
- *value*: if given, the starting input; otherwise the starting input is the cell value or column name as appropriate.
- *kwargs*: passthrough args to ``vd.editText``.
'''
reslist = ["apple", "banana", "cherry"]
res = reslist[random.randint(0,2)]
self.vd.status(f'gave you a random fruit')
return resI can now edit the sample data: If the user now presses What I would like to have: This is where I am stuck now. Does somebody have any ideas, e.g. how I can call the version of |
Beta Was this translation helpful? Give feedback.
-
|
Finally, I found some kind of solution. Below is my
@Sheet.api
def pickeditCell(self, vcolidx=None, rowidx=None, value=None, **kwargs):
'''Call vd.editText for the cell at (*rowidx*, *vcolidx*). Return the new value, properly typed.
- *vcolidx*: numeric index into ``self.availCols``. When None, use current column.
- *rowidx*: numeric index into ``self.rows``. If negative, indicates the column name in the header.
- *value*: if given, the starting input; otherwise the starting input is the cell value or column name as appropriate.
- *kwargs*: passthrough args to ``vd.editText``.
'''
# -------------------- lines taken from original _input.py -> editCell(...)
if vcolidx is None:
vcolidx = self.cursorVisibleColIndex
x, w = self._visibleColLayout.get(vcolidx, (0, 0))
col = self.availCols[vcolidx]
if rowidx is None:
rowidx = self.cursorRowIndex
if rowidx < 0: # header
vd.fail(f"Header can't be fuzzy-edited")
else:
y, h = self._rowLayout.get(rowidx, (0, 0))
value = value or col.getDisplayValue(self.rows[self.cursorRowIndex])
# update local bindings with kwargs.bindings instead of the inverse, to preserve kwargs.bindings for caller
# end----------------- lines taken from original _input.py -> editCell(...) ------------------------
# uniq_colvalues, value, col
uniq_colvalues = set(["apple", "banana", "cherry"])
choices = [AttrDict(key=v) for v in sorted(uniq_colvalues)]
preset = value if value in uniq_colvalues else ''
pick = self.inputPalette(
prompt=f'{col.name}: ',
items=choices,
value_key='key',
value=preset,
formatter=lambda m, item, trig: f'{trig} {item.key}' if item else ' ',
)
return pick # VisiData will write this value into the cell
@Sheet.api
def pickeditCellRepeat(sheet):
'Edit chosen column; after commit, move down and re-run until Esc.'
col = sheet.cursorCol
vcolidx = sheet.cursorVisibleColIndex
try:
val = sheet.pickeditCell(vcolidx)
except EscapeException:
return
# If user cancels, skip; otherwise set value and queue next iteration.
if val is not None:
col.setValues([sheet.cursorRow], val)
vd.queueCommand('go-down')
vd.queueCommand('pickedit-cell-repeat')
Sheet.addCommand('E', 'pickedit-cell-repeat', 'pickeditCellRepeat()', 'edit cell and, on Enter, move down and continue editing')However, after pressing |
Beta Was this translation helpful? Give feedback.
-
|
With @saulpw commit de57f34 there is now a lightweight implementation of multiselection:
I put this into my # To push and wait for the sheet to finish loading synchronously:
def myOpenSheet(filename):
vs = vd.openSource(filename)
vd.push(vs) # will call vs.ensureLoaded()
vd.sync(vs.ensureLoaded()) # wait for loader threads to finish (if needed)
myOpenSheet("../sample_data/sample.tsv")
@Sheet.api
def pickeditCell(self, vcolidx=None, rowidx=None, value=None, **kwargs):
'''Call vd.editText for the cell at (*rowidx*, *vcolidx*). Return the new value, properly typed.
- *vcolidx*: numeric index into ``self.availCols``. When None, use current column.
- *rowidx*: numeric index into ``self.rows``. If negative, indicates the column name in the header.
- *value*: if given, the starting input; otherwise the starting input is the cell value or column name as appropriate.
- *kwargs*: passthrough args to ``vd.editText``.
'''
# -------------------- lines taken from original _input.py -> editCell(...)
if vcolidx is None:
vcolidx = self.cursorVisibleColIndex
x, w = self._visibleColLayout.get(vcolidx, (0, 0))
col = self.availCols[vcolidx]
if rowidx is None:
rowidx = self.cursorRowIndex
if rowidx < 0: # header
vd.fail(f"Header can't be fuzzy-edited")
else:
y, h = self._rowLayout.get(rowidx, (0, 0))
value = value or col.getDisplayValue(self.rows[self.cursorRowIndex])
# update local bindings with kwargs.bindings instead of the inverse, to preserve kwargs.bindings for caller
# end----------------- lines taken from original _input.py -> editCell(...) ------------------------
# uniq_colvalues, value, col
uniq_colvalues = set(["apple", "banana", "cherry", "elderberry", "fig", "grape", "honeydew"])
choices = [AttrDict(key=v) for v in sorted(uniq_colvalues)]
preset = value if value in uniq_colvalues else ''
#vd.status(f'{uniq_colvalues}')
palette_height = min(5, len(uniq_colvalues)+2)
palette_y = y + 1 # default: draw just under the edited row
if palette_y + palette_height - 1 > self.windowHeight:
palette_y = max(0, y - palette_height + 1) # move above when there's no space below
pick = self.inputPalette(
prompt=f'{col.name}: ',
items=choices,
value_key='key',
value=preset,
x=x+2, y=palette_y, w=w, h=palette_height,
formatter=lambda m, item, trig: f'{trig} {item.key}' if item else ' ',
)
return pick # VisiData will write this value into the cell
@Sheet.api
def pickeditCellRepeat(sheet):
'Edit chosen column; after commit, move down and re-run until Esc.'
col = sheet.cursorCol
vcolidx = sheet.cursorVisibleColIndex
try:
val = sheet.pickeditCell(vcolidx)
except EscapeException:
return
# If user cancels, skip; otherwise set value and queue next iteration.
if val is not None:
col.setValues([sheet.cursorRow], val)
vd.queueCommand('go-down')
vd.queueCommand('pickedit-cell-repeat')
Sheet.addCommand('E', 'pickedit-cell-repeat', 'pickeditCellRepeat()', 'edit cell and, on Enter, move down and continue editing') |
Beta Was this translation helpful? Give feedback.


With @saulpw commit de57f34 there is now a lightweight implementation of multiselection:
I put this into my
config.pyand if pressingEI can repeatedly edit cell values: