freq

    Offer to run a complex linux command from among those listed in a file in the current directory, .

    This facility makes it easy to package common actions in particular contexts. That can be a huge memory aid, preserving a record of the actions I have available in particular contexts, including intricate details of those actions.

    Last update: 2021-04-25

    #!/bin/bash
    
    # Offer to run a complex command from among those in `./.frequents`
    
    # - A command line parameter is taken as the chosen line's number or label.
    # - Otherwise, a consolidated list of comments and commands are presented,
    #   and a prompt is issued for a line number or label of command to run.
    # - In either case the choice is echoed and the command line is evalled.
    #   - Using eval means the command line can contain multiple commands in a
    #     pipeline, sequence, with backgrounded components, etc.
    # - Lines that begin with a "#" hash mark are taken as commentary and
    #   labels for the following lines.
    #   - The comments are presented in the listing but not included in the
    #     command-numbering count.
    #   - The comment lines can contain a ":" delimited word, which is used
    #     as a label for the succeeding command line.
    #     - The word may not contain any whitespace.
    
    # Copyright Ken Manheimer, ken.manheimer@gmail.com,  2007-2019
    # Licensed under Gnu Public License v3, 
    
    
    unset lines
    unset comments
    unset labels
    
    declare -A labels
    
    arg="$1"
    
    NEWLINE="
    "
    
    read_from () {
      carry=""
      if [ -r "$1" ]; then
        exec 3< "$1"
        while read curline <&3; do
          if [ -n "$carry" ]; then
            curline="$carry $curline"
            carry=""
          fi
          case $curline in
            *" "\\ ) cume="$curline"
                     carry="${curline:0:-2}";;
            * ) build "$curline";;
          esac
        done
        if [ -n "$carry" ]; then
          build "$carry"
        fi
        exec 3<&-
      fi
    }
    
    build () {
      curline="$1"
      if [ -n "$curline" ]; then
        case $curline in
          \#* ) if [ -n "${comments[${#lines[@]}]}" ]; then
                  comments[${#lines[@]}]+="${NEWLINE} $curline"
                else
                  comments[${#lines[@]}]="  $curline"
                fi;;
          * )
            label=$(echo "${comments[${#lines[@]}]}" | \
                    sed -n -e 's/.*:\([^: ]*\):.*/\1/p')
            if [ -n "$label" ]; then
              # XXX debug:
              #echo $label
              labels[${label}]="$curline"
            fi
            lines[${#lines[@]}]="$curline";;
        esac
      fi
    }
    
    if [ ! .frequents -ef ~/.frequents ]; then
      frequents=.frequents
    else
      frequents=~/.frequents
    fi
    if [ "$(tail -c 1 $frequents)" != "$(echo -e '\n')" ]; then
      echo "(NOTE: $frequents lacks a trailing newline)" 1>&2
    fi
    read_from $frequents
    
    size=${#lines[@]}
    
    if [ "$size" = 0 ]; then
      echo "no entries"
      exit
    fi
    
    which=""
    
    if [ -n "$arg" ]; then
      which="$arg"
    else
      echo
      incr=0
      for i in "${lines[@]}"; do
        if [ -n "${comments[$incr]}" ]; then
          echo "${comments[$incr]}"
        fi
        echo $((incr++)): $i
      done
      echo
      echo -n "execute command from line number[empty input to cancel]: "
      read which
    fi
    
    mode=""
    case "$which" in
      [0-9] | [0-9][0-9] | [0-9][0-9][0-9]) mode=number ;;
      * ) mode=alpha;;
    esac
    
    if [ "x$mode" = "xnumber" ]; then
      if [ -z "${lines[$which]}" ]; then
         echo no match
         exit 1
      else
         echo "$which: ${lines[$which]}"
         eval "${lines[$which]}"
      fi
    else
      if [ -z "$which" ]; then
         echo no match
         exit 1
      elif [ -z "${labels[$which]}" ]; then
         echo no match
         exit 1
      else
         echo "$which: ${labels[$which]}"
         eval "${labels[$which]}"
      fi
    fi