bashzsh

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.


Solution

  • 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
    }