Reputation: 18811
I'm using RLWrap to "tame" a really good REPL, Dyalog APL, that unfortunately had its origins in Windows land and therefore does not comply with UNIX conventions. Moreover, being a closed source product, it cannot be modified to do so.
I managed to achieve most of my goals, but Ctrl-D still causes it to barf an error and keep running, while I would like it to cause a graceful exit, like any other REPL.
I looked into rlwrap options, as well as its filter API, for a way to intercept EOF coming from the user and translate it into a custom exit command, which would be )off
in my case, but I couldn't find a way to do it.
My current alias:
alias dyalog='rlwrap -a -H ~/.dyalog_history /opt/mdyalog/17.0/64/unicode/dyalog -b -s'
Relevant options are:
-s
tells Dyalog to start in a simple REPL mode, without taking control of the screen;-a
tells RLWrap to always remain in readline mode, ignoring Dyalog's attempts to read the input character by character.Upvotes: 2
Views: 290
Reputation: 5678
Assuming that a "naked" dyalog
responds to CTRL+D by exiting gracefully, you can make rlwrap
pass this key directly to dyalog
by adding the next few lines to your ~/.inputrc
:
$if dyalog
"\C-d": rlwrap-direct-keypress
$endif
You may (or may not) have to issue
$ stty eof undef
beforehand in the terminal you're using (to prevent CTRL+D from closing your stdin
)
Upvotes: 1
Reputation: 943
The trick is to catch the return code from the read. Given how nested it is, I find it easiest to do this in a hidden file in the home directory.
To see how it works fully, I include a larger code block, but the core is on that line with the 'read' in it.
sCommand=""
while [ ! "$sCommand" == "exit" ]
do
sHistory=~/.promptHistory
sCommand=$(rlwrap -H $sHistory sh -c 'read -p "> " REPLY && echo $REPLY'; echo $? > ~/.hold)
if [[ "$(cat ~/.hold)" -eq 1 ]]; then sCommand="exit"; fi
if [ "$sCommand" == "exit" ]; then return; fi # Bail out if the user asked for exit.
case $sCommand in
# All useful commands intercepted here. Let 'exit' flow through.
esac
done
The magic is in getting the return code with $? and getting it into ~/.hold for safe keeping. From there, the rest is just code.
Upvotes: 0