Skip to content

Conversation

midichef
Copy link
Contributor

This PR is for the situation when bindkey names a command that does not exist, like from this .visidatarc line: Sheet.bindkey('2', 'not-a-command')
When the user presses 2, visidata immediately exits with status -1, with no other output.

That's because fail() in execCommand() raises ExpectedException which bubbles up past run() and main_vd() to vd_cli():

if not cmd:
vd.fail('no command for %s' % (longname or keystrokes))

visidata/visidata/main.py

Lines 386 to 394 in d499914

def vd_cli():
rc = -1
try:
rc = main_vd()
except BrokenPipeError:
os.dup2(os.open(os.devnull, os.O_WRONLY), sys.stdout.fileno()) # handle broken pipe gracefully
except visidata.ExpectedException as e:
if vd.options.debug:
raise

This PR prevents the abrupt exit and shows the fail message: no command for not-a-command

@midichef
Copy link
Contributor Author

The commit message records why I catch Exception instead of the more specific ExpectedException. I tried for about 20 minutes to import ExpectedException in mainloop.py, but I could not figure out a way to untangle the resulting circular imports. Using Exception with exceptionCaught gets the job done, and matches the error handling elsewhere in the same function:

try:
if vd.replayOne(cmd):
vd.replay_cancel()
except Exception as e:
vd.exceptionCaught(e)

The intent is purely to catch ExpectedException raised by fail().
But catching that specific exception is complicated, due to
circular import problems when importing the ExpectedException
symbol. Using the more general Exception, with exceptionCaught(),
works around that difficulty.
like from addCommand('a', 'a', 'pass', 'looping command')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants