0

Context

I'm trying to build a dialog box feeded with my timewarrior data, so I can directly select what I'm going back to rather than timew s :ids filter_tag, then time cont @12.

So, first I created the data set that is attempted to populate the Dialog options:

timew s :ids $(date -I -d'8 days ago') - $(date -I -d'tomorrow') |
    # most recent first, only the top 30 (4 additional lines are decoration)
    tac | head -n 34 |
    # format the whole thing as '1 "some label "' and so on
    sed -ne 's:.*@::p' |
    sed -e 's|\s\+[0-9]\+:.*| |g' -e's:\s\+: ":' -e's:\s*$:":' -e's:^: :'

This generates reports like the following:

 1 "some_info, some_info"
 2 "some_info, some_info"
 3 "some_info, some_info"
 4 "some_info"
 5 "some_info, some_info"
 6 "some_info, some_info, some_info"
 7 "some_info, some_info"
 8 "some_info, some_info-some_info, some_info, some_info"
 9 "some_info, some_info"
 10 "some_info, some_info-some_info, some_info, some_info"
 11 "some_info, some_info"
 12 "some_info, some_info"
 13 "some_info"
 14 "some_info, some_info"
 14 "some_info, some_info"
 15 "some_info, some_info, some_info"
 16 "some_info, some_info, some_info, some_info, some_info, some_info"
 17 "some_info, some_info, some_info"
 18 "some_info"
 19 "some_info, some_info"
 20 "some_info"
 21 "some_info, some_info, some_info, some_info, some_info, some_info"
 22 "some_info, some_info"
 23 "some_info, some_info, some_info, some_info, some_info, some_info"
 24 "some_info, some_info45, some_info some_info some_info, some_info"
 25 "some_info"
 26 "some_info"
 27 "some_info, some_info, some_info"
 28 "some_info, some_info, some_info, some_info"
 29 "some_info, some_info, some_info"
 30 "some_info"

The Dialog scaffold

So I found this scaffold to

#!/bin/bash

HEIGHT=15
WIDTH=40
CHOICE_HEIGHT=4
BACKTITLE="Backtitle here"
TITLE="Title here"
MENU="Choose one of the following options:"

OPTIONS=(1 "Option 1"
         2 "Option 2"
         3 "Option 3")

CHOICE=$(dialog --clear \
                --backtitle "$BACKTITLE" \
                --title "$TITLE" \
                --menu "$MENU" \
                $HEIGHT $WIDTH $CHOICE_HEIGHT \
                "${OPTIONS[@]}" \
                2>&1 >/dev/tty)

clear
case $CHOICE in
        1)
            echo "You chose Option 1"
            ;;
        2)
            echo "You chose Option 2"
            ;;
        3)
            echo "You chose Option 3"
            ;;
esac

Issue

So I naively thought that using OPTIONS=( $(timew s :ids $(date -I -d'8 days ago') - $(date -I -d'tomorrow') | tac | head -n 34 | sed -ne 's:.*@::p' | sed -e 's|\s\+[0-9]\+:.*| |g' -e's:\s\+: ":' -e's:\s*$:":')) as a replacement in the previous code would do the trick. But it seems that quotes won't be taken into consideration so easily. I tried to hack that around in various ways, including in a while read loop and using Shell parameter expansion: ${variable@Q}, and other horrifying stuffs, but didn't found anything that would work.

Question

How do I populate correctly the Dialog options with the output of my Timewarrior output?

psychoslave
  • 2,783
  • 3
  • 27
  • 44

1 Answers1

1

This should achieve the effect you wanted :

#!/bin/bash

HEIGHT=15
WIDTH=40
CHOICE_HEIGHT=4
BACKTITLE="Backtitle here"
TITLE="Title here"
MENU="Choose one of the following options:"

generate_options(){
    cat << EOF
Option 1
Option 2
Option 3
EOF
}

declare -a OPTIONS
count=1
while IFS= read -r line; do
    OPTIONS+=( $((count++)) "$line" )
done < <(generate_options)

CHOICE=$(dialog --clear \
                --backtitle "$BACKTITLE" \
                --title "$TITLE" \
                --menu "$MENU" \
                $HEIGHT $WIDTH $CHOICE_HEIGHT \
                "${OPTIONS[@]}" \
                2>&1 >/dev/tty)

clear
case $CHOICE in
        1)
            echo "You chose Option 1"
            ;;
        2)
            echo "You chose Option 2"
            ;;
        3)
            echo "You chose Option 3"
            ;;
esac

You just need to replace cat command with your command (without the number at the beginning of the line).

So a full solution for this problem is:

#!/bin/bash

HEIGHT=40
WIDTH=80
CHOICE_HEIGHT=30
BACKTITLE="Timewarrior"
TITLE="Resume Selector"
MENU="Select task to resume"

generate_options(){
  # events of the last week, filtered by $@
  timew s :ids $(date -I -d'8 days ago') - $(date -I -d'tomorrow') "$@" |
    # most recent first, keep only a 60 entry buffer
    tac | head -n 60 |
    # format the whole thing as '1 some labels' and so on
    sed -ne 's:.*@::p' |
    sed -e 's|\s\+[0-9]\+:.*| |g' -e's:^: :' |
    # keep only 30 entries
    uniq | head -n 30
}

declare -a OPTIONS
while IFS= read -r line; do
  bid=$(echo "$line" | awk '{print $1}')
  peg=$(echo "$line" | sed 's:[0-9]\+\ \+::')
  # get ride of duplicates
  case "${OPTIONS[@]}" in  *"$peg"*) continue ;; esac
  OPTIONS+=( "$bid" "$peg" )
done < <(generate_options "$@")

CHOICE=$(dialog --clear \
                --backtitle "$BACKTITLE" \
                --title "$TITLE" \
                --menu "$MENU" \
                $HEIGHT $WIDTH $CHOICE_HEIGHT \
                "${OPTIONS[@]}" \
                2>&1 >/dev/tty)

clear
if [[ -z $CHOICE ]] ; then
  exit
fi
timew cont "@$CHOICE"
psychoslave
  • 2,783
  • 3
  • 27
  • 44
Philippe
  • 20,025
  • 2
  • 23
  • 32
  • Wonderful @philippe, thanks so much. I permitted myself to complete your answer with the solution that it enabled me to build. – psychoslave May 17 '20 at 06:22