Search code examples
bashyad

Can a YAD button invoke a function within a script?


I am playing around with YAD dialogs in BASH and am having trouble with the button construction. I can't get a YAD button to call a function in the same script. Is there a way to do this?

My understanding is the if I use the following construction, pressing the button will call the command that follows the colon This example (which works) will open an instance of Firefox if a user clicks the Open Browser button:

yad --button="Open browser":firefox

I have a script with several BASH functions. I'd like a button press to call one of the functions. It doesn't. The following is a simple script that, when run, demonstrates the disappointing behavior:

#!/bin/bash,

click_one()
{
   yad --center --text="Clicked the one"
}

click_two()
{
   yad --center --text="Clicked the two"
}

cmd="yad --center --text=\"Click a button to see what happens\" \
      --button=\"One\":click_one \
      --button=\"Two\":2 \
      --button=\"Date\":date \
      --button=\"Exit\":99"

proceed=true

while $proceed; do
    eval "$cmd"
    exval=$?

    case $exval in
        2) click_two;;
        99) proceed=false;;
    esac
done

In the code above, button Date works as expected, calling the date command. Buttons Two and Exit work because I'm checking the exit value of the command and branching on its value. Sadly (for me), button One does nothing. I had hoped that clicking on button One would call the local function click_one. I would like to know if there's a way to format the YAD command so that the click_one function is called.

While the above code suggests a workaround using the exit value, my real goal is to apply a successful answer to a form button that, as far as I can figure out so far, doesn't return an exit value. In other words, the following also fails silently, but I'd like it to invoke function click_one:

yad --form --field="One":fbtn click_one

Solution

  • Apparently not, it needs to be an actual command.

    You could: put your functions in a separate file and as the command, launch bash, source that file, and call the function.

    Here, I'm also restructuring your code to store the yad command in an array. This will make your script more robust:

    # using an array makes the quoting a whole lot easier
    cmd=(
        yad --center --text="Click a button to see what happens" 
          --button="One":"bash -c 'source /path/to/functions.sh; click_one'"
          --button="Two":2 
          --button="Date":date 
          --button="Exit":99
    )
    
    while true; do
        "${cmd[@]}"      # this is how to invoke the command from the array
        exval=$?
        case $exval in
            2) click_two;;
            99) break;;
        esac
    done