Description
The Problem
When spinning up raku
for the first time, users are presented with a list of modules they should install in order to have such niceties as:
- backspaces
- left/right cursor movement
- up/down for scrolling through previous incantations
Note that there are no instrucitons for how to install these modules. No link to a package manager, let alone a package manager being provided.
This might not bother others but I find it to be deeply un-user-friendly and more than a little embarrassing for a language that bills itself as -- and generally lives up to -- "batteries included".
Beyond that pain point, by punting the responsibilities of parsing user input to userspace we also lose the ability to provide meaningful hooks into the REPL experience itself.
And it goes deeper still: Even our getc
implementation requires a third-party module to be able to read a character of user input without an enter key being pressed.
Poterntial Remediations
Ship releases with zef
This would at least allow users to swiftly install one of the recommended options.
Pros
IMO this is long overdue. It likely deserves its own problem-solving ticket if it doesn't already have one.
Also, we apparently already do this for Windows. Aligning what we ship across platforms makes a lot of sense to me.
Cons
Doesn't do anything to address REPL extensibility / getc
.
Ship releases with Terminal::LineEditor
Pros
Terminal::LineEditor
is a very comprehensive line editor that is implemented almost entirely in Raku.
It supports significantly more than what I would consider the table stakes required for a usable REPL (my essentials are: backspaces, left/right cursor movement, and up/down with session history).
Cons
No direct cons except that poor getc
is still incapable of collecting raw input.
Oh, and the fact that there are four dependencies for this module. More on that next.
Provide all the necessary pieces that are required to write Terminal::LineEditor
in core
Shipping Terminal::LineEditor
in core begs the question of why we don't just provide the functionalities provided by it's dependencies in core:
- Why don't we provide a way to switch on the terminal's raw mode, so that for example
getc(:raw)
would work? (This is provided byTerminal::MakeRaw
in 55 LoC) - Why don't we provide the ability for all Raku programs to easily interpret user input from terminal emulators that support ANSI sequences (eg, more or less all of them)? (
Terminal::ANSIParser
, ~300 LoC) - To round out these offerings (and the dependencies required to ship
Terminal::LineEditor
anyway), why would we not offer a mechanism for modeling terminal capabilities, objects of which are constructed with the lowest common denominator and which could be used to standardize the handling of user expectations with Raku programs in their favorite terminal emulator (Terminal::Capabilities
, ~50 LoC)
The only thing missing from a REPL usability standpoint is Terminal::ANSI
(380 LoC, though some would be omitted because of overlap with Terminal::ANSIParser
). This provides all the ANSI-standard pieces related to text output.
Pros
getc
can finally do a thing that users likely assume it is/should be capable of.
Every terminal-specific Raku program can benefit. All libraries related to terminal interaction can drop up to 5 dependencies. Terminal::LineEditor
can live in rakudo/lib
.
We can design a basic, functional REPL around which many layers of interaction can be added *without requiring any third party libraries at all.
Cons
The main objection I have heard is related to maintanability. I'd like to note that the update frequencies of each module I have mentioned is very low, meaning that there seems to have been very few causes to modify any of these modules over a matter of years (Terminal::MakeRaw
is working on Windows support, but it is unique here in that it is the only one that relies on native libraries.)
Terminal::MakeRaw
is easy to implement because of NativeCall
and requires more effort to bring into NQP where it would need to live in order to provide any benefit to getc
.