oils-for-unix / oils

Oils is our upgrade path from bash to a better language and runtime. It's also for Python and JavaScript users who avoid shell!
http://www.oilshell.org/
Other
2.84k stars 156 forks source link

ShellAC protocol specification #909

Open roberth opened 3 years ago

roberth commented 3 years ago

Hi, First of all, thank you for writing ShellAC, which seems to be exactly what the command line shell ecosystem needs. I'm looking into supporting it in Haskell's de-facto standard library for option parsing, but I have some questions that aren't answered by the ShellAC pages on the wiki (https://github.com/oilshell/oil/wiki/Shellac-Protocol-Proposal-V2 and its links). Judging from those pages, I'd have to conclude that it doesn't satisfy my needs, but I hope that that's a premature conclusion. So I'd like to know, are those pages the only documentation of the ShellAC protocol? Does the ShellAC protocol have forward compatibility when it comes to extensions? If not, do you think it is feasible to change the protocol? (How widely has it been implemented?)

For completeness, here's my initial evaluation. I'd be happy to update it. https://github.com/pcapriotti/optparse-applicative/pull/414#issuecomment-799278891

HuwCampbell commented 3 years ago

A little background on what we do in optparse-applicative might help here.

All optparse-applicative programs contain context sensitive completions automatically. This works by equiping them with a few hidden extra options which enable completion mode.

Using ghcup (which is an installer like rustup for haskell) as an example, after installing the common zsh completion script, we get this without any extra effort by the builder of the ghcup tool.

Screen Shot 2021-03-16 at 12 01 42 pm

On the command line, we can see how this works by running:

# Simple completion of the first argument to ghcup, having typed `ghcup li`
> ghcup --bash-completion-index 1 --bash-completion-word ghcup --bash-completion-word li --
list

# Rich completion of the first argument to ghcup, having typed `ghcup li`
> ghcup --bash-completion-index 1 --bash-completion-word ghcup --bash-completion-word li --bash-completion-enriched
list    Show available GHCs and other tools

# Rich completion of the arguments to list, having typed `ghcup list `
> ghcup --bash-completion-index 2 --bash-completion-word ghcup --bash-completion-word list --bash-completion-enriched
--tool  Tool to list versions for. Default is...
-t  Tool to list versions for. Default is...
--show-criteria Show only installed or set tool versions
-c  Show only installed or set tool versions
--raw-format    More machine-parsable format
-r  More machine-parsable format
-h  Show this help text
--help  Show this help text

How this works is relatively orthogonal, but it actually runs the program and its command line parser proper, but interpreting the parser with a different monad. The benefits are that the options presented are always the ones available (that is, it's always correct) and that we can write custom actions like looking up which versions of GHC are already installed in haskell as well, sharing code with the application itself.

Our protocol is essentially:

We will then send back:

We then have bash, zsh, and fish completion scripts which are able to communicate in this protocol. These are autogenerated with --bash-completion-scipt, or their zsh and fish equivalents. All programs get the same scripts (changing only the function names and the program to invoke with the magic arguments).

Now aside from the fact that the names of these options include the word bash; this works very, very well. @roberth is however interested in adding to the protocol to iron out a few niggles; and I'm keen to see more languages and libraries adopt a system like this, and any improvements would be great.

So this is an invitation for collaboration. I'm comfortable with optparse-applicative to continue to go it alone; but it would be nice for a unified protocol to emerge.

andychu commented 3 years ago

Hi, thanks for the message and I'm glad to see work on this.

So Shellac was basically a discussion, not something ever implemented. Most of the discussions are here:

https://oilshell.zulipchat.com/#narrow/stream/146045-shell-autocompletion

And actually the most significant work was done separately under Redox OS (there's a Zulip thread, and links at the end of https://github.com/oilshell/oil/wiki/Shellac-Protocol-Proposal-V2)

So Shellac was basically "cut" from the Oil project sometime in 2020. I think there was a tension between designing a "good" protocol (for correctness, generality), and designing one that could actually be implemented in bash, fish, and zsh! So I'm curious to see how you've done that.


Oil emulates bash, which gives it a lot of completions "for free". On the other hand, supporting a brand new protocol that wasn't implemented by shells wouldn't be all that useful.

I think there has to be an upgrade path from bash or zsh completions to general shellac completions -- basically some wrappers. A binary with a flag parser can act as a shellac plugin / "server", but a shell running a program should also be a valid plugin / server.

So it's great that you have actually implemented something in bash zsh and fish! That's the kind of thing I was looking for. (I know all about bash completion, but little about zsh or fish completion.)


Comments:

More:

Oil uses QSN but I think it's too hard to implement in other shells: http://www.oilshell.org/release/latest/doc/qsn.html

i.e. you could have a completion format like:

'completion \n with \n newlines' 'description \n for \n it'
andychu commented 3 years ago

@AdminXVII may be interested in this, having done prior work on Ion / Redox

And refreshing my memory from a couple years ago