Commands¶
VisiData is command-driven, which means that it only does something when you tell it to. Otherwise, it just sits there, waiting for your next command.
Every command is a discrete unit of behavior that does a defined task and runs to completion. Functions that could take longer than a couple hundred milliseconds should run in their own thread (see Threads).
Every command should be reproducible: given the same sheet, cursor position, and input string (if relevant), a command should yield identical output (with a few obvious exceptions, like :kbd:random-rows).
Any command which makes changes to a saveable sheet is appended to that sheet’s Command Log. Since all state changes must be initiated by a reproducible command, this command log can be replayed.
Adding new commands is a natural way to extend VisiData’s functionality.
Command Overview¶
Commands and Keybindings are managed in a similar way to options. The same precedence hierarchy is used, so that commands can be created or overridden for a specific type of sheet, or even a specific sheet itself.
Since all Sheets ultimately inherit from BaseSheet
, a command on BaseSheet
is effectively a global command.
Command Context¶
The execstr is a string of Python code passed to exec()
when the command is run.
exec()
looks up symbols in this order:
the current
sheet
the
vd
objectthe
visidata
module (seeaddGlobals()
andgetGlobals()
below)
The vd
and sheet
symbols are available to specify explicitly.
Note
Unqualified options
in a command execstr will use the sheet-specific options context for the current sheet.
Warning
In an execstr, while you can get an attribute on vd
or sheet
without specifying the object, to set an attribute does require an explicit object. e.g. instead of cursorRowIndex=2
, it must be sheet.cursorRowIndex=2
.
Commands API¶
- visidata.BaseSheet.addCommand(keystrokes, longname, execstr, helpstr='', replay=True, **kwargs)¶
Add a new command to cls sheet type.
keystrokes: default keybinding, including prefixes.
longname: name of the command.
execstr: Python statement to pass to exec()’ed when the command is executed.
helpstr: help string shown in the Commands Sheet.
Keybindings¶
Use “
^X
” for Ctrl+X.Primarily, plugin authors and users should use
0-9
, “KEY_F(1)
”,ALT+
for custom keybindings; these are purposefully left available for user keybindings.Consider not providing a default at all, for infrequently used commands.
Instead give it an easy and memorable longname, and/or a unique helpstr which can be searched for in the Command Help (g Ctrl+H) with g/.
Many other keycodes can be returned from the curses library as strings.
To discover what to use for some unknown key, press that key in VisiData and use the keystroke shown in the status bar.
- vd.allPrefixes = ['g', 'z', 'gz', 'Alt+', 'Alt+[']¶
vd.allPrefixes
is a list of prefixes (keystrokes that don’t trigger the end of a command sequence).
New prefixes can be added to this list, and then they can also be used as prefixes in keybindings.
Note
Combinations of prefixes are allowed, but only in the specified order: g
must come before z
, which must come before ALT
.
Note
ALT
is a just a handy constant for “^[
”, which represents Ctrl+[, which maps to Esc in the terminal.
Curses represents Alt+X (Meta+X on some keyboards) as Esc x. So to bind a command to Alt+X, use ALT+'x'
or '^[x'
.
Other helpful functions¶
- visidata.vd.bindkey(keystrokes, longname, obj='BaseSheet')¶
Bind keystrokes to longname on BaseSheet and unbind more-specific bindings of keystrokes.
- visidata.BaseSheet.bindkey(keystrokes, longname)¶
Bind keystrokes to longname on the cls sheet type.
- visidata.BaseSheet.execCommand(self, longname, vdglobals=None, keystrokes=None)¶
- visidata.addGlobals(*args, **kwargs)[source]¶
Update the VisiData globals dict with items from args and kwargs; to add symbols available to command execstrings and eval strings like command expr.’
Dunder methods are ignored, to prevent accidentally overwriting housekeeping methods.
Rules for command longnames¶
3 words max, 2 words if possible. A longname should be short and fit on a keymap.
Command classes should be unique in their first 3 chars and ideally mostly in their first 2.
Command longnames should be intuitively understandable, or at least not jargony.
Longnames should evoke interface, when possible.
Use existing verb-object-input structure if possible:
Verbs:
open
: push new sheetjump
: push existing sheetdup
: push copy of sheetshow
: display on statusgo
: move the cursorscroll
: change the visible screen area without changing the cursoraddcol
: add new column to this sheetsetcol
: set selected cells in this columnsearch
: search one or more columnssearchr
: search reverseselect/unselect/stoggle
: add/remove rows from selected rowssyscopy/syspaste
: copy/paste to system clipboardsysopen
: open with $EDITOR or other external program
Objects:
-all
: all sheets or all visible columns-col
: cursorCol-cols
: all visible columns-cells
: this column, selected rows-selected
: selected rows
Inputs:
-expr
: python expression-regex
: python regex
Many others are used, see the full command list for inspiration.
Examples¶
@Sheet.api
def show_hello(sheet):
vd.status(sheet.options.disp_hello)
# `sheet` members and `vd` members are available in the execstr scope
BaseSheet.addCommand(None, 'show-hello', 'show_hello()', 'show a warm greeting')
# bind Shift+H, Ctrl+H, and Alt+H to this command
BaseSheet.bindkey('H', 'show-hello')
BaseSheet.bindkey('^H', 'show-hello')
BaseSheet.bindkey(ALT+'h', 'show-hello')