4

Is there any way in the shell script by which I can set the input line programmatically? Consider the following scenario.

Let's say I make a script to create a git branch, and right after it is done making a branch, I don't want to switch to new branch programmatically, but just give user the command displayed on the prompt, so user don't have to type the command to switch to new branch but only just press enter key if he wants to run the displayed command.

read -p "Enter your branch name: " N
git branch $N
render-text-on-prompt "git checkout $N"

Execution:

$ ./mkbranch
$ Enter your branch name: change-93
$ git checkout change-93 _
melpomene
  • 84,125
  • 8
  • 85
  • 148
arxoft
  • 1,385
  • 3
  • 17
  • 34
  • Related: https://unix.stackexchange.com/questions/82630/put-text-in-the-bash-command-line-buffer and https://superuser.com/questions/1462995/how-to-create-a-bash-function-that-return-to-the-current-prompt – melpomene Jul 30 '19 at 15:30
  • 1
    I usually do this sort of thing with `tmux paste-buffer`. The script loads the command into the buffer and then pastes it. The user can then either hit return, or cancel (or edit) the command interactively. – William Pursell Jul 30 '19 at 15:31

3 Answers3

1

bash doesn't have a way to "preload" the next input buffer (unlike zsh, in which you can simply use print -z "git checkout $N"). You would need to have mkbranch handle the input (and subsequently execute the entered command) itself.

read -p "Enter your branch name: " N
git branch "$N"
read -e -i "git checkout $N" cmd
eval "$cmd"

-e informs read to use the Readline library for entering the line of text; the -i option preloads the input buffer. (Without the -e the -i doesn't do anything.)

Note that read -e does not itself know anything about bash syntax, so there are no implicit line continuations; this makes it distinctly different from the ordinary bash prompt.

An alternative would be to simply ask the user if they would like to checkout the newly created branch:

read -p "Enter your branch name: " N
git branch "$N"
read -e -i Y -p "Checkout branch $N? (Y/n)"
[[ $REPLY == Y ]] && git checkout "$N"

Hitting enter accepts the pre-loaded Y to trigger the hard-coded `checkout command; any other command skips it. Either way, the script ends and returns to the regular command prompt.

agc
  • 7,973
  • 2
  • 29
  • 50
chepner
  • 497,756
  • 71
  • 530
  • 681
  • You could set `READLINE_LINE`, but the documentation says it only works in `bind -x`. – melpomene Jul 30 '19 at 15:32
  • I'm not sure assigning to it is useful even there; I think it's just a way for the code bound to a key by `bind -x` to access the current command-line buffer. – chepner Jul 30 '19 at 15:38
0

You could just use a switch to check what the user input is.

function render_text_on_prompt {
    if [[ -z ${1} ]]; then # The argument passed into the function is empty/not set
        echo "Wrong usage!"
        return 1
    fi

    # Print the argument
    echo "${1} - Hit the enter key to run this command or anything else to abort"

    read INPUT_STRING
    case ${INPUT_STRING} in # Check what the user entered
        "") # User entered <enter>
            ${1}
            break
            ;;
        *) # User entered anything but enter
            echo "Nothing changed"
            break
            ;;
    esac
    return 0
}

I hope this helped.

Laurent
  • 39
  • 1
  • 5
0

Here's a stub, which can be adapted as needed:

c="echo foo bar" ; read -p "Run '$c' [Y/n]? " n ; \
[ ! "$n" ] || [ "$n" = Y ] || [ "$n" = y ] && $c

The last line will run command $c if the user types Enter, y or Y. Example run:

Run 'echo foo bar' [Y/n]? 

User hits Enter:

foo bar
agc
  • 7,973
  • 2
  • 29
  • 50
  • D'oh, this is a *POSIX* shell version... a `bash` version would be more succinct. Pending... – agc Jul 30 '19 at 15:26
  • The `bash` tag was added by Jonathan Leffler, not OP. – melpomene Jul 30 '19 at 15:28
  • 2
    @melpomene: The use of `-p` on the `read` command made it 'not POSIX' — POSIX `read` (command) only supports the `-r` option. – Jonathan Leffler Jul 30 '19 at 17:46
  • 1
    @JonathanLeffler, Odd, the code above runs in `dash` and `bash --posix`. Aha, but not `posh`! Evidently some *POSIX* shells are more *POSIX* than others... – agc Jul 30 '19 at 17:58