Tobia
Tobia

Reputation: 18811

Handle EOF in RLWrap

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:

Upvotes: 2

Views: 290

Answers (2)

Hans Lub
Hans Lub

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

James Madison
James Madison

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

Related Questions