usql icon indicating copy to clipboard operation
usql copied to clipboard

Add wrapper for C's readline library

Open kenshaw opened this issue 3 years ago • 5 comments

Add a standalone package that works on Linux, macOS, and Windows that wraps the C readline library. Ideally, it'll have more or less the same interface as the existing rline package, and would ideally be configurable by tags at build time.

kenshaw avatar Jan 18 '21 10:01 kenshaw

After I looked into this further, this seems to be much easier than I had originally thought. Just giving a heads up that I'm already working on this, and will probably have it done in the next few days. Only mentioning it in the very off chance that someone saw this issue and had decided to take it up.

kenshaw avatar Jan 21 '21 09:01 kenshaw

I wrote a wrapper around readline, replxx and editline, and have the ability to build each using an appropriate build tag, it leads to some undesirable issues that are preventing me (in a philosophical sense, not a technical sense) from merging it to usql. For any other ambitious developers out there who are interested in working on this, let me summarize the issues:

  1. readline and editline do not seem to have any clear or easy way to do syntax highlighting
  2. editline would not have inputrc support
  3. replxx does have syntax highlighting, tab completion, and other aspects, however it only allows a limited set of colors. As such, the chroma based highlighting would no longer be possible. It would be possible to try to match a chroma theme's styles to the colors that replxx supports, but this would of course be limited or a half-measure at best as the colors would be "clamped" to only those provided by the replxx library. replxx would also not have inputrc support. Overhauling the replxx package would be difficult, and no guarantee it'd get accepted into the upstream repo
  4. Adding replxx or a static build of readline would break go get (unless the .a and other platform's static build equivalents were included in the source repo, which would make the dependent repo grow extremely large over time)
  5. Having readline as a dynamic dependency as default would require the readline library to be installed somewhere on the system. While not an issue for Linux, BSDs, and others, macOS and Windows do not have these out of the box
  6. Ideally, for this project to continue being "universal" (ala the 'u' in usql), the default configuration/build should be the same out of the box on all platforms, including downloading binaries, building via brew, building from source, or from go get should be identical (with the exception of which drivers are enabled by default, which I find to a fair trade off, as it's easy to add additional build tags for brew, source, or go get)
  7. As a minor positive though, it does appear that readline and replxx can be built into the same project, and that they do not stomp on each other by implementing the same API. As such, it should be possible to allow the user to change which readline library they would like to use at runtime

Based on the above, even though I have not wanted to do it, my next great endeavor will be to do a clean, new implementation of a rline package that supports chroma out-of-the-box, works on all platforms, and hopefully fixes issues. inputrc (or some kind of equivalent) support will follow, but the first task will be to just do a clean implementation. Additionally, since it is possible to support both readline and replxx at the same time, I will make it possible to build those. My plan is that there will be a new usql only setting that allows the user to choose their readline library, and the Go implementation, readline and replxx implementations will all be built by default into usql releases or dynamically enabled with the appropriate build tag.

The new package will be called xo/rline.

Once completed, my expectation is that usql will have the additional tags for go build like the following:

rline_all - enable readline and replxx statically
rline_all_dynamic - include readline dynamically, replxx statically
rline_readline - include readline statically
rline_readline_dynamic
rline_replxx - include replxx statically

The rline package itself, while the API is not finalized, will end up looking something like the following:

import "github.com/xo/rline"
r, err := rline.New(opts...)
r.Prompt("a prompt string")
r.SetPrompter(rline.Readline) // sets it to the readline library
r.SetPrompter(rline.Replxx) // to replxx
r.SetPrompter(rline.Default) // to the Go based implementation

In the above the Readline Replxx and Default will likely be a uint const following the constant strategy pattern common in the Go standard library (see the crypto package for an example, if not familiar with the pattern).

kenshaw avatar Jan 22 '21 23:01 kenshaw

This is probably answered in other issues but what are the issues with the current readline lib? Have you considered using other Go based replacements, like https://github.com/peterh/liner/?

nineinchnick avatar Jan 23 '21 00:01 nineinchnick

@nineinchnick Yes, I've seen that package before. It might be a better jumping off point than "nothing" to implement a pure Go version, rather than trying to adopt the chyzer/readline or gohxs/readline packages. I haven't looked at it much. Based off a quick reading of of liner's API documentation, I don't see that it supports syntax highlighting out of the box, or otherwise will be able to support all the specific requirements.

At this point, I've more-or-less decided to just bite the bullet and write a from the ground-up implementation in idiomatic Go, that's designed to do efficient syntax highlighting out of the box, and to additionally provide a wrapper around with C's readline and replxx libraries. At least then the user will be able to decide which to use.

kenshaw avatar Jan 23 '21 01:01 kenshaw

I just pushed the initial commit to the aforementioned rline package that builds both readline and replxx into the repository. None of the Go implementation has been started yet, as I just wanted to put this together to see what the effect would be on usql and to work out the various build tags, dependencies, etc. Will start authoring a ground-up Go prompt implementation shortly.

kenshaw avatar Jan 24 '21 05:01 kenshaw