From: John Stone (johns_at_ks.uiuc.edu)
Date: Wed May 20 2020 - 11:45:03 CDT

Giacomo,
  Based on your feedback, I have been thinking of doing the following:

Since we don't ship rlwrap itself with VMD (and I'd rather not start),
my thought would be to continue to detect it when it's available, using
it by default, unless the user specifically disables it via environment
variable. In the case that we cannot find 'rlwrap' on the system, we
would use built-in linenoise-based command editing as the default
fallback, enabled when 'rlwrap' isn't found, unless the user has
disabled it via environment variable, or in one of the special
cases I mentioned (console is not a TTY, MPI runs of VMD, etc).

I spent some time looking at a couple of other line editing packages,
they're all fairly similar in terms of the APIs that VMD would need
to call to implement line editing with tab completion, history, etc.
The differences that remain largely seem to boil down to implementation
completeness/feature details. Some implement a more complete
set of editing features (e.g. your examples of word-left word-right
navigation being a prime example), some like linenoise only implement
the basics.

To provide a more featureful built-in command line editor for
those that want it, and/or on platforms that provide it by default
as part of the system libraries (*BSD, MacOS X, etc), I could also
see about adding support for libedit, which is a much more complete
line editing implementation than linenoise (20 times the size),
but is also BSD-licensed. That might eventually provide a superior
alternative to both linenoise and rlwrap with some work and
user testing mileage. Since it would require largely the same
modifications that I'm making for linenoise, I'm inclined to wait
until I finish the missing pieces we've already discussed for linenoise
and look at implementing libedit support later on.

For the time being, based on your feedback, I'm inclined to go ahead
with adding linenoise as a built-in fallback for rlwrap, adding
in implementation of tab completion callbacks, etc. I would leave
rlwrap as the default and only enable the built-in linenoise when
rlwrap isn't found, or has been disabled by the user. And as we
have discussed, I would make it possible to disable both of them
via environment variables, leaving VMD running with classic
console/terminal handling behavior.

BTW, since linenoise is a small piece of code, the specific key bindings
you were looking for a listing of can be found in the switch block that
begins at line 840 and ends at 973:
  https://github.com/antirez/linenoise/blob/master/linenoise.c

It's pretty minimalistic!
 ctrl-[t b f p n u k a e l w]
 esc-[0-9,A B C D H F]

Best,
  John

On Wed, May 20, 2020 at 12:09:16PM -0400, Giacomo Fiorin wrote:
> Hi John, thanks for the clarification. For a proof of concept, yes, I
> think that this implementation serves that initial purpose.
>
> "info commands" returns standard Tcl commands, VMD-specific commands and
> user-defined procs. Particularly the latter includes significant freedom,
> so it should be sufficient to cover the vast majority of cases. In this
> respect it may also be cleaner than rlwrap, which requires adding commands
> explicitly via external files.
>
> If you go ahead with it, it would be very helpful to have environment
> variables for both linenoise and rlwrap, with some minimal documentation in
> the User's Guide.
>
> Giacomo
>
> On Wed, May 20, 2020 at 11:33 AM John Stone <johns_at_ks.uiuc.edu> wrote:
>
> > Giacomo,
> > I realized I missed addressing your comment about there not
> > being a persistent history:
> > linenoise supports this, but I did not bother implementing the
> > calls to commit commands to the the linenoise persisent history
> > since Tcl has always had that built-in itself, albeit via "history".
> > If people think that is important, it isn't difficult to add
> > the calls to add to and commit the persistent history to disk.
> >
> > Best,
> > John
> >
> > On Wed, May 20, 2020 at 10:26:21AM -0500, John Stone wrote:
> > > Giacomo,
> > > Thanks for the concrete feedback.
> > > The tab completion feature for linenoise requires that the caller
> > > (VMD) register a callback to be triggered any time the user presses
> > > the completion key (tab, in this case). I haven't implemented
> > > tab completion in the version of the code I sent you.
> > >
> > > To implement tab completion, I would likely use the Tcl command
> > > "info commands" to get a list of all global Tcl commands, which would
> > > include Tcl-intrinsic commands, VMD-internal commands, and VMD plugin
> > > commands added to the global namespace. I could use that to provide
> > > a large fraction of the completion candidates in an automatic way
> > > without hard-coding a bunch of Tcl-specific stuff there.
> > >
> > > As with tab completion, I also didn't yet implement the "hint" callback
> > > described in the linenoise README doc.
> > >
> > > The linenoise code appeals to me because of the BSD license
> > > and minimalist implementation (3% of the size of GNU readline).
> > >
> > > Another more full-featured option would be the BSD libedit
> > > library, which is apparently what Apple uses (along with a shim)
> > > to emulate GNU readline (since they can't ship the real readline
> > > lib due to GPL). I haven't looked at how clean/portable libedit is
> > > outside of BSD OSes, but that might be another option for those
> > > that expect a more featureful line editing implementation.
> > >
> > > The implementation I made for linenoise should serve as a proof of
> > > concept for implementing support for any of the other line editing libs

-- 
NIH Center for Macromolecular Modeling and Bioinformatics
Beckman Institute for Advanced Science and Technology
University of Illinois, 405 N. Mathews Ave, Urbana, IL 61801
http://www.ks.uiuc.edu/~johns/           Phone: 217-244-3349
http://www.ks.uiuc.edu/Research/vmd/