vxgmichel/aioconsole

Support readline or equivalent alternatives

achimnol opened this issue ยท 9 comments

Googling leads me to this SO question but there is no reply yet.

Python already provides a binding module to GNU readline or libedit, but this does not work together with aioconsole since it does not have coroutine-based interfaces. Maybe we need a new lower-level wrapper for the readline library.

This issue is both question and feature request:

  • Is there any plan to support readline or readline-style interactive prompts?
  • Are there any known/fundamental technical issues related to supporting readline (except that the stdlib readline does not have coroutines)?
    • Could we just make the user prompt to be synchronous while leaving user codes running between prompts asynchronous?

I don't know much about readline, but will supporting it allow us to use left/right arrow keys in the prompts?

@achimnol Thank you for creating an issue, this is very interesting.

I'm not knowledgeable enough about readline to answer all your questions, I'll have to start an investigation. What I can tell you though is that aioconsole aims at providing an asynchronous interface to arbitrary stdin/stdout, with methods similar to the Stream API.

Meaning those streams can either come from:

  • the console (standard unix streams)
  • an application like IDLE (or Windows, FWIW)
  • a TCP socket (for serving python prompts over the network)

As @dufferzafar pointed out, it would nice to have support of left/right arrow keys for all those use cases, but I have no idea whether this is doable yet. It would also be worth looking into prompt_toolkit as well, since it has asyncio support.

Any help is more than welcome by the way ๐Ÿ˜‰

Yeah, I recently had to build an asyncio based CLI and found out that prompt_toolkit has support for it. I think that is our best bet to create an awesome async-cli.

Haven't looked into the specifics yet, but will definitely post anything I learn here.

I tried to add support for readline with low-level, callback-based readline API, but it segfaults mysteriously in the callback. I might investigate further, but this will surely only support read from terminal.

If you connect via TCP, you can just use socat readline tcp:host:port to have basic readline support.

@lilydjwg How does the socat option work? I ran the echo example and I can connect fine w/ nc but when I try to say socat readline anything, I just get an error (using the latest version of socat):

socat readline tcp:127.0.0.1:9999 
2017/10/27 11:21:45 socat[603] E unknown device/address "readline"

@TD22057 There seems to be a problem with socat and readline.

Instead you can use rlwrap:

# Works with local apython console
$ rlwrap apython

# Also works with a remote console
$ apython --serve locahost:8888
The console is being served on 127.0.0.1:8888

# with both netcat and socat
$ rlwrap nc localhost 8888
$ rlwrap socat - tcp:localhost 8888

I actually didn't know about rlwrap and it seems to be a valid solution for remote consoles, and an acceptable workaround for local consoles. I'll update the documentation.

Thanks for your post.

rlwrap works perfectly and is exactly what I need for my application. Thanks for this very cool project.

Hi all,

I just implemented readline support (PR #9) for local console through the apython script. It seems to work fine and it even provides some level of auto-completion (only for the built-ins).

The implementation is hackish but contained, and can even be disabled using the --no-readline argument. It works by starting the actual program in a subprocess and controlling the standard streams in order to take advantage of the readline support provided by the input built-in.

Feel free to review the PR if you're interested. Otherwise, I'll probably merge it next week (or not, if I change my mind and finally consider it's too hackish :) ).

Thanks for your inputs!

PR #9 is merged, readline support for linux is now available with version 0.1.4.