1

How do I take the key/values from an associative array and display them in a Zenity list dialog?

Example:

#!/bin/bash

get_final_bookmarks_choice(){
    if [ ${#matched_bookmarks[@]} -eq 1 ]; then
        # open_bookmarks_command
        return
    fi
    # guard clause.  If no bm found.
    if [ -${#matched_bookmarks[@]} -eq 0 ]; then 
        msg='No bookmarks match found.'
        notify-send "$msg"; echo "$msg"
        return
    fi

    bm_url=$(zenity --entry --title="Multi matches found" \
    --text="Choose bookmark" \
    --column="Name" --column="URL" \

    # Key/value dictionary here.
    )
    # Return the key.
    echo "$key returned here."
}


declare -A matched_bookmarks
matched_bookmarks=(
    ['match 1']='http://match1.com'
    ['match 2']='http://match2.com'
    ['match 3']='http://match3.com'
)

bm_name="$(get_final_bookmarks_choice)"

bm_url="${matched_bookmarks[$bm_name]}"

echo "Bookmarks URL:$bm_url"
Emily
  • 1,979
  • 3
  • 16
  • 39

1 Answers1

1

You have to use array, not associative array, as argument to zenity command:

dialogarray=()
for idx in "${!matched_bookmarks[@]}";do
    dialogarray+=("$idx" "${matched_bookmarks[$idx]}")
done

zenity --list --title="Multi matches found" --text="Choose bookmark" \
     --column="Name" --column="URL" "${dialogarray[@]}"

Here is my version of your script:

#!/bin/bash

get_final_bookmarks_choice(){
    local -n Assoc=$1 Result=$2
    case ${#Assoc[@]}  in
        1 ) # open_bookmarks_command
            Result=${!Assoc[*]}
            return
            ;;
        0 ) # guard clause.  If no bm found.
            msg='No bookmarks match found.'
            notify-send "$msg"
            echo "$msg"
            exit 1
            ;;
        * )
            local -a zenDialog=()
            local idx
            for idx in "${!Assoc[@]}";do
                zenDialog+=("$idx" "${Assoc[$idx]}")
            done
            read -r Result < <(
                zenity --list --title="Multi matches found" \
                       --text="Choose bookmark" \
                       --column="Name" --column="URL" "${zenDialog[@]}" )
    esac
}


declare -A matched_bookmarks
matched_bookmarks=(
    ['match 1']='http://match1.com'
    ['match 2']='http://match2.com'
    ['match 3']='http://match3.com'
)

get_final_bookmarks_choice matched_bookmarks bm_name

bm_url="${matched_bookmarks[$bm_name]}"

echo "Bookmarks URL:$bm_url"

For fun, a SE based version:

#!/bin/bash
shopt -s extglob
get_final_bookmarks_choice(){ local -n Assoc=$1 Result=$2
    case ${#Assoc[@]}  in
        1 ) # open_bookmarks_command
            Result=${!Assoc[*]}
            return  ;;
        0 ) # guard clause.  If no bm found.
            msg='No bookmarks match found.'
            notify-send "$msg"
            echo "$msg"
            return 1  ;;
        * )
            local -a zArgs=(); local idx
            for idx in "${!Assoc[@]}";do
                zArgs+=("$idx" "${Assoc[$idx]}")
                while IFS=$'\r\n' read -r idx;do
                    [ "$idx" ]&&[ -z "${idx//*title*}" ]&&break;done< <(
                    wget -qO - "${Assoc[$idx]}")
                idx=${idx//<*([^>])>}  idx=${idx//&amp;/&} 
                zArgs+=("$idx")
            done
            read -r Result < <( zenity --list --width 860 --height 200 \
                --title="Multi matches found" --text="Choose bookmark" \
                --column="Name" --column="URL" --column="Title" "${zArgs[@]}");;
    esac
}
declare -A matched_bookmarks
matched_bookmarks=( ['Stack Overflow']='https://stackoverflow.com/'
                    ['Code Golf']='https://codegolf.stackexchange.com/'
                    ['Unix & Linux']='https://unix.stackexchange.com/'   )
get_final_bookmarks_choice matched_bookmarks bm_name &&
    echo "Bookmarks URL:${matched_bookmarks[$bm_name]}"

should produce something like:

enter image description here

F. Hauri
  • 58,205
  • 15
  • 105
  • 122
  • No. There is no *direct* way to transforme `key, value, key, value` into an array. And note that [tag:shell] commandline are ALWAYS an *array* containing *command* and *arguments*. – F. Hauri Jan 28 '22 at 13:10
  • Perfect. Thanks. – Emily Jan 28 '22 at 13:10
  • Anyway, using `nameref` (`local -n`) in your function let you able to do a lot of cleaning like this. – F. Hauri Jan 28 '22 at 13:11
  • @Emily Added three columns demo – F. Hauri Jan 28 '22 at 14:30
  • Thanks. Drilling down on shopt and wget -q0 now. First time I've seen them, in my short bash dabbling career. – Emily Jan 28 '22 at 18:19
  • @Emily If you like this, maybe would you appreciate [How do I prompt for Yes/No/Cancel input in a Linux shell script?](https://stackoverflow.com/questions/226703/how-do-i-prompt-for-yes-no-cancel-input-in-a-linux-shell-script/27875395#27875395)! ;-) – F. Hauri Jan 29 '22 at 10:01
  • Thanks. I've added it to my notes. I'm sure I'll be using it later. – Emily Jan 29 '22 at 17:26