Package rlwrap not working correctly

I installed it, look:

# rlwrap tclsh
% seset a 1
1
% puput $a
1
%
Well, I typed set and put, not seset or puput.

Is the problem known?

I remember there is an alternative, I think with editline, but I do not remember the name. ...
 
Hello! Tcl is among the most elegant programming languages (on a similar level as Lisp/Scheme and in some respects perhaps even better) and Tk is among the easiest and fastest ways to create useful GUIs and so I decided to try to solve this today since I like it.

I spent several hours today trying and I was luckily able figure out a decent workaround after trying dozens of different approaches. The best overall workaround I found was actually quite simple.

Simply run the rlwrap command with the following parameters:

Code:
rlwrap --substitute-prompt '' tclsh

... where tclsh has been replaced by whatever the name of your tclsh or wish command is. I use tclsh9.0 and wish9.0 personally.

This unfortunately removes the % part of the Tcl command prompt REPL, but it does prevent any extra character noise from ever being generated.

I figured it out by observing that the amount of text gibberish generated by Tcl seemed to grow in proportion to the size of the prompt in use, which implied that reducing the size of the prompt to zero would therefore perhaps eliminate the problem and indeed it did. Thus, you can fix the issue that way at the cost of it becoming harder to distinguish interactive REPL commands from their output. However, that downside of this workaround can be easily worked around by periodically running history from your Tcl shell to see which parts were your command or not.

The result of the workaround makes working with the Tcl shell sufficiently pleasant again.

I recommend then creating a shell script or shell function that bundles this in a more concise form to make it much faster to use.

For example, I use Fish shell and have the following functions defined in my ~/.config/fish/functions directory as _tcl.fish and _wish.fish respectively:

Code:
function _tcl
  rlwrap --substitute-prompt '' tclsh9.0 $argv
end

Code:
function _wish
  rlwrap --substitute-prompt '' wish9.0 $argv
end

Subsequently, I can simply write just _tcl or _wish every time I want to use Tcl or Tk with line history active and the $argv passes any additional arguments.

Similar things can be done with Bourne shell or Bash by using $1 and such (numbered argument variable substitutions) in the script body to pull in arguments to shell scripts so that you can reuse Bourne shell scripts as functions, etc. Adding #!/bin/sh as the first line of the script and applying chmod +x script_name makes such scripts behave like executables, enabling you to use ./path/to/script to run them whenever you want to for Bourne shell or Bash.

I also tried to figure out a way to hack in bold face for prompts and regular text for result output by abusing the tput bold and tput sgr0 to try to weave them into the beginning and ending of each rlwrap cycle so that it would again be easy to distinguish results but I was unable to figure out a way to hack it in. There just needs to be a way to insert those two commands at the start and end respectively of each prompt line and that would resolve the problem of distinguishing prompts from output text. Oh well though.

There also exists an alternative to rlwrap called enhance, which is part of the libtecla package but it wasn't working on my system, though I didn't try installing the much larger full tecla package since it would have pulled in all of Gtk and a ton of other stuff onto my system just to potentially fix this tiny problem.
 
Later tonight I tried to create a more complete and more usable solution (one designed to use switching between bold and regular font to make distinguishing between interactive prompt text and result output text easier, like I alluded to earlier) but unfortunately I've not been able to get that additional trick truly working right because the Tcl shell seems to keep overwriting the bold font formatting after each prompt is entered (i.e. sent to be run by Tcl) and thereby causing the bold font to only show while each prompt is still being typed and unfortunately thereafter turning back into regular text upon pressing the enter key.

Nonetheless, I will provide the progress I made in that regard here so that future people trying to solve this issue may be able to make use of it.

The strategy is to use rlwrap's --filter system (see man RlwrapFilter) to write a Perl script that manipulates the input prompt and output results to insert the desired formatting and to also try to make the prompt empty too, so that the Tcl fix is all in once nice neat package (a rlwrap filter script). However, it doesn't work as expected, though it is close.

Here is the Perl script I have created in /usr/local/share/rlwrap/filters/ named fix_tcl (which I first copied from the built-in null filter to start with and then refined one step at a time):

Perl:
#!/usr/bin/env perl

use lib ($ENV{RLWRAP_FILTERDIR} or ".");
use RlwrapFilter;
use strict;


my $filter = new RlwrapFilter;

$filter -> help_text(
  "\n".
  "Usage: rlwrap --filter fix_tcl <tcl_interpreter_name>\n".
  "\n".
  "Provides a workaround for when Tcl emits\n".
  "erroneous characters after each prompt is entered."
);

$filter -> prompt_handler (
  sub {
    # Using `ncurses`:
    #system('tput', 'bold');
    #return '';
 
    # Manually:
    return "\033[1m";
  }
};

$filter -> output_handler (
  sub {
    # Using `ncurses`:
    #system('tput', 'sgr0');  #a.k.a. normal font
    #return $_;
 
    # Manually:
    return "\033[0m$_";
  }
);

$filter -> run

(PS: My VirtualBox clipboard support is not working right now and so I retyped all the above manually and so it may have typos potentially, but hopefully not. It should convey the idea adequately though, either way.)

Also, notice that I've provided two different implementations: a commented out ncurses one and one that uses cryptic terminal escape sequences manually. The former is easier to read, but the later requires that you install ncurses on your system so that you get access to tput (try pkg install ncurses if you want that).



Oh, and unexpectedly someone responded to me while I was still typing in this comment and almost finished with it, so I will respond to that too:

I downloaded & compiled the latest version of directly from https://github.com/hanslub42/rlwrap/releases and it seems to work fine.

Do you mean that a new release of rlwrap that you've tried fixes the erroneous text or do you mean that my suggestion works correctly in working around the issue with that version of rlwrap? I'm not sure which. It is ambiguous.

Anyway, that's good news if the issue is fully solved upstream. 🥳

Either way, it is good to share how these kinds of workarounds can be made and so it was still a good use of time anyway. :)

Whatever the case may be, I hope some of this info was helpful in some way and I am wishing you a good night/day, etc! 🌃
 
Fixes the original problem of echoing twice the first couple characters.

Technically, this response is also ambiguous, but no worries. It isn't that important, especially since I can just check on it myself whenever I want to later on.

I am guessing though that you probably mean to say that the upstream changes to rlwrap do indeed fix the problem fully without necessitating a workaround like the one I gave, and not (in the alternative interpretation) that the combination of the upstream current version and my workaround still work as intended as an ad-hoc fix.

In any case, have a wonderful day/night and have fun with Tcl/Tk! It is one of the best languages in terms of expressiveness, though I do wish it also had C's native performance! 😎👋
 
Back
Top