Hi Bruce, Chet

On Thu, 11 Dec 2025 at 18:27, Bruce Jerrick <[email protected]> wrote:
>
>> It would be nice if there were an option to the 'read' builtin to echo
>> dots rather that nothing at all
>
>
I thought I'd take a swing at this.

Try this patch: https://github.com/kurahaupo/bash/tree/patch-echosubst

This defines a new bind option "echo-substitution", which is consulted when
read is passed both the '-s' (echo-suppression) and the '-e' (use readline)
options, like:

bind "set echo-substitution $SUBSTITUTION"
read -es VAR

where SUBSTITUTION can be:

   1. “:none” (or empty) - the current behaviour, showing nothing;
   2. “:random” (randomly chosen ASCII chars);
   3. “:auto” - selects “•” when in a UTF-8 locale, or “*” otherwise;
   4. one multi-byte or single-byte character, either literally or as
   U+xxxx;
   5. any string of printable ASCII characters (not starting with a colon).

Examples:

The existing behaviour is available (and is the default):

$ bind "set echo-substitution :none"
$ read -esp 'Quiet> ' VAR       *# now type "Hello World"*
Quiet>
$ echo "$VAR"
Hello World

This is how I interpreted the original feature request:

$ bind "set echo-substitution ."
$ read -esp 'PlainDots> ' VAR   *# now type "Hello World"*
PlainDots> ...........
$ echo "$VAR"
Hello World

In hindsight perhaps it meant this:

$ bind "set echo-substitution U+2027"
$ read -esp 'SmallDots> ' VAR   *# now type "Hello World"*
SmallDots> ‧‧‧‧‧‧‧‧‧‧‧
$ echo "$VAR"
Hello World

Or this:

$ bind "set echo-substitution U+2022"
$ read -esp 'BigDots> ' VAR     *# now type "Hello World"*
BigDots> •••••••••••
$ echo "$VAR"
Hello World

Old-school folk might prefer this:

$ bind "set echo-substitution U+002a"
$ read -esp 'Stars> ' VAR       *# now type "Hello World"*
Stars> ***********
$ echo "$VAR"
Hello World

More fanciful options include:

$ bind 'set echo-substitution U+ff0a'
$ read -esp 'FatStars> ' VAR    *# now type "Hello World"*
FatStars> ***********
echo "$VAR"
Hello World

$ bind "set echo-substitution YabbaDabbaDoo"
$ read -esp 'Fred> ' VAR        *# now type "Hello World"*
Fred> YabbaDabbaD
$ echo "$VAR"
Hello World

$ bind $'set echo-substitution .\u2027\u2022 *\uff0a'
$ read -esp 'Hybrid> ' VAR      *# now type "Hello World"*
Hybrid> .‧• **.‧• *
$ echo "$VAR"
Hello World

$ bind "set echo-substitution :random"
$ read -esp 'Gibberish> ' VAR   *# now type "Hello World"*
Gibberish> 9H($Yto`~<.
$ echo "$VAR"

Hello World

For now, multi-byte characters are disabled unless in a UTF-8 locale.

Some attempts are made to prevent using non-printable characters as
substitutes, but this isn't fully implemented. (I note that readline
already seems to recognise double-width characters, so it must already be
linked with libunicode or have some equivalent mechanism, so this might not
actually be much more work.)

-Martin

PS: while testing this patch, I discovered that UTF-8 locale detection is
only done when readline starts up.
This means that “LC_ALL=C bind 'set echo-substitution :auto'” won't
necessarily pick “*”.

PPS: it's not just "read"; it works in any readline instance whenever "stty
-echo" is in effect, including the shell prompt.

Reply via email to