ZenMaster
ZenMaster

Reputation: 12746

Execute a bash function without actually typing the comand to do so, and print out its output instead

I have a function:

function create-file {
  touch some-file
}

I want to press a key(s) or type an alias to execute this function on a terminal, without pasting the create-file in.

I want the function to execute, and display the output on the terminal, in the same prompt line replacing the alias (perhaps alias can be invisible) which I then can execute, or have it executed by pressing Enter.

Can this be achieved?

Context: creating a demo with many commands... that I don't want to actually type, but do want to show in the demo being typed at a certain speed and then get executed.

I would type, or send without typing, the following command/alias:

> create-file

Press "Enter", and have the "expanded" version of the create-file alias to be executed in the same prompt, replacing create-file

> touch some-file

As a compromise it might also be ok with the following sequence:

> create-file        # (hit "Enter")
> touch some-file    # this line, which is the output/expand of the above is printed
> ...                # result of the `touch some-file` command (in this case) is printed

To clarify, I am not looking for a solution to record/replay or progressively type out commands, that's solved. I am looking to take the result of slow type/record, as a string, push into the prompt and execute, without having to type something like replay last command.

Upvotes: -4

Views: 114

Answers (2)

Philippe
Philippe

Reputation: 26727

You can define this key binding in bash:

bind -x '"'$(tput kf4)'":  create-file'

Pressing F4 will run the function.

Update

zsh equivalent :

zle -N create-file
bindkey "${terminfo[kf4]}" create-file

Upvotes: 2

ruakh
ruakh

Reputation: 183514

I think you're overthinking this a bit. Instead of having create-file just print touch some-file (which then leaves you looking for the easiest way to take a printed-out command and run it), you can have create-file print touch some-file, then wait for the demo operator to hit Enter, then run touch some-file.

For example:

# slow-print prints its arguments, one character at
# a time, sleeping 10ms between characters. It does
# *not* add a trailing newline.
function slow-print() {
    local char
    while IFS= read -n 1 -r char ; do
        sleep 0.01
        printf %s "$char"
    done <<<"$*"
}

# wait-for-enter waits for the operator to type a
# character (which theoretically should be 'Enter',
# but if they type a different character that's OK,
# we'll just hide that character and make it look
# like they hit 'Enter').
function wait-for-enter() {
    local enter
    read -n 1 -r -s enter
    echo
}

function create-file() {
    slow-print 'touch some-file'

    wait-for-enter

    touch some-file
}

Upvotes: 2

Related Questions