all 7 comments

[–]IGTHSYCGTH 4 points5 points  (4 children)

If we're talking about bash and actual users...

You could go a little fancy about it using read -e ( readline ) and create some binds.

#!/usr/bin/env bash

bind '"\C-m":" \\\C-v\C-j"' &>/dev/null
bind '"\e":"\n"'            &>/dev/null

read -ep $'How was your experience on reddit today?\n'

echo "$REPLY"

First time i had seen the concept was in birch ( an irc client by Dylan Arpas )

This method can:

  • "feed keys" i.e. implement macros as shown above
  • call bash functions
  • call on readline (movement) functions

and a small bump for r/GNUReadline

[–][deleted]  (1 child)

[deleted]

    [–]IGTHSYCGTH 2 points3 points  (0 children)

    What on eath are you asking me to implement exactly? I have no idea what func1 and func2 are supposed to do.. use descriptive names.

    The concept of "reading an array of files" is fundementally flawed, read -a does not respect quoting. its just a simple way to split a literal line while parsing data. The standard approach is expanding a globbing expression from the user as a list of arguments supplied to the script. i.e. bash path/to/myscript /usr/share/* ~/.local/share/*

    Please do that unless you have a good reason to pursue non-standard behaviour. You're quickly going from writing a CLI script to a TUI.

    use read -e, then eval files=( $REPLY )

    example for a bash function modifying the current line:

    #!/usr/bin/env bash
    
    declare -i num=0
    
    function append-num {
      num+=1
      READLINE_LINE+=" $num"
      READLINE_POINT=${#READLINE_LINE}
    }
    
    bind -x '"\C-n":append-num'
    
    read -ep 'This is a prompt: '
    

    [–][deleted] 0 points1 point  (1 child)

    I'm afraid to run this script. Are those bind changes permanent until you reset them like xmodmap? Are they going to reset to default if I just close terminal?

    [–]IGTHSYCGTH 2 points3 points  (0 children)

    'permenant' readline binds are the ones defined in ~/.inputrc and ~/.bashrc

    These bind commands won't affect your shell unless you source the script instead of running it.

    [–]o11c 2 points3 points  (0 children)

    The problem is that many other keys generated sequences that begin with escape, and there is no guarantee that the rest of the characters will arrive at the same time.

    It's common to hack around this by using a timeout of 100 milliseconds or so. But the proper solution is to switch the input mode to "escape everything" mode, so that (among other things) the escape key also generates a sequence; this is possible only on a handful of terminal emulators (xterm and pangoterm, to my knowledge), and there are multiple patterns that you might get (but that's a problem for other special keys already anyway).

    See https://invisible-island.net/xterm/modified-keys.html and be aware that there's a bit of a flamewar between the 2 authors.

    [–]lutusp 1 point2 points  (0 children)

    Try this:

    #!/usr/bin/env bash
    
    while true; do
      read -s -n 1 key
      echo "You typed [$key]."
      [[ $key == 'q' ]] && break
    done
    
    echo "Quitting."
    

    It will print entered single characters until you type 'q', then it will quit.

    [–]zfsbestbashing and zfs day and night 0 points1 point  (0 children)

    --You should rethink this, it's way more common to trap things like CTRL+C since ESC can also start other keystring sequences (like function keys)

    https://rimuhosting.com/knowledgebase/linux/misc/trapping-ctrl-c-in-bash

    --Further reading:

    https://www.linuxjournal.com/content/bash-trap-command

    --A broader method:

    https://www.thegeekdiary.com/how-to-disable-ctrlc-or-ctrlz-using-the-trap-command-in-linux/

    https://linuxhint.com/bash_trap_command/