more beetag refactoring
authorIan Kelling <ian@iankelling.org>
Sat, 1 Mar 2025 19:52:40 +0000 (14:52 -0500)
committerIan Kelling <ian@iankelling.org>
Sat, 1 Mar 2025 19:52:40 +0000 (14:52 -0500)
beet-data
beetag
brc
brc2
fsf-script-lib

index cccc6550051467fdea3bc9881870edf33343072e..8af190b4e2e82627876505ec7494cda6de935d46 100644 (file)
--- a/beet-data
+++ b/beet-data
@@ -121,6 +121,16 @@ tags=(
   sad
 )
 
+declare -A bpla # beet playlist associative array
+beetapl() { # beet add playlist
+  local name
+  name="$1"
+  shift
+  # shellcheck disable=SC2034 # unused from beetag, don't care for now.
+  bpla[$name]="${*@Q}"
+}
+
+
 # this function is just so we can have some local vars
 # and not mess with the global var namespace.
 beet-gen-global-vars() {
diff --git a/beetag b/beetag
index 84d7f52907ea9034d0d1f4038f2079ae38381e26..e786bc19491e6ee0fcbdeccbbb570fc5f50b9aff 100755 (executable)
--- a/beetag
+++ b/beetag
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Uncomment this when developing this file for quick shellcheck results,
+# otherwise it is redundant.
 . /a/c/fsf-script-lib
 
-
 # Must be called from beetag for variables to be setup
 beetag-help() {
   source /a/bin/ds/beet-data
@@ -65,6 +66,80 @@ EOF
   fi
 }
 
+# beet modify quietly
+beetmq() {
+  local tmpf
+  tmpf="$(mktemp)"
+  # a bunch of effort to ignore output we dont care about...
+  sed 's/^format_item:.*/format_item: ignore_this/' ~/.config/beets/config.yaml >$tmpf
+  beet -c $tmpf modify -y "$@" > >(grep -vFx -e 'ignore_this' -e 'Modifying 1 items.' ||:)
+  rm "$tmpf"
+  beetag-nostatus 1
+}
+
+kill-bg-quiet() {
+  # https://stackoverflow.com/a/5722874
+  kill %% 2>/dev/null ||:; wait %% 2>/dev/null ||:
+}
+
+
+# run if not running.
+#
+# Note: this does not work with shell scripts as they are normally
+# invoked, because the ps output has the interpreter at the start.
+# A workaround is to invoke the command in that format, or we could
+# do various other workarounds.
+#
+# background, this relies on how ps converts newlines in arguments to spaces, and
+# assumes we won't be searching for a command with spaces in its arguments
+rinr() {
+  # shellcheck disable=SC2009 # pgrep has no fixed string option, plus see above.
+  if ps h -o args -C "${1##*/}" | grep -Fxqv "$*" &>/dev/null || [[ $? == 141 ]]; then
+    "$@"
+  fi
+}
+# variation of above: run or wait if running
+rowir() {
+  local pid
+  pid=$(ps h -o 'pid,args' -C "${1##*/}" | sed -r 's/^[[:space:]]*([0-9]+)[[:space:]](.*)/\1\n\2/' | grep -B1 -Fx "$*" | head -n1 ||: )
+  if [[ $pid ]]; then
+    # https://unix.stackexchange.com/questions/427115/listen-for-exit-of-process-given-pid
+    tail --pid="$pid" -f /dev/null
+  else
+    "$@"
+  fi
+}
+
+
+mpvrpc-loadfile() {
+  local path nextpath cachedir finalpath nextpath count
+  cachedir=$HOME/.iank-music-cache
+  path="$1"
+  nextpath="$2"
+
+  # note: logic duplicated in beetpull
+  local remote_p=true
+  source /p/c/domain-info
+  if [[ $HOSTNAME == "$d_host" ]]; then
+    remote_p=false
+  fi
+
+  if $remote_p; then
+    finalpath="$cachedir${path#/i/m}"
+    rowir rsync --partial -a --inplace --mkpath "b8.nz:$path" "$finalpath"
+    finalnextpath="$cachedir${nextpath#/i/m}"
+    count=$(pgrep -a -f "^rsync --partial -a --inplace --mkpath $cachedir" || [[ $? == 1 ]] )
+    # allow us to start 2 rsyncs in the background
+    if [[ $count == [01] ]]; then
+      rinr rsync --partial -a --inplace --mkpath "b8.nz:$nextpath" "$finalnextpath" &
+    fi
+  else
+    finalpath="$path"
+  fi
+  mpvrpc '{ "command": ["loadfile", "'"$finalpath"'"] }'
+}
+
+
 # Must be called from beetag for variables to be setup
 beetag-nostatus() {
   if (( $# )); then
@@ -108,8 +183,10 @@ mpvrpc-percent-pos() {
 #
 # Sets variables: pl_state_path pl_seed_path. Does mkdir of their directory.
 #
+# Creates/recreates $pl_seed_path if needed.
+#
 # Input vars: random
-beetag-pl-state-init() {
+pl-state-init() {
   local seed_num seed_file pl_state_dir pl_state_file
   # note: this structure of files is rather haphazard.
   seed_num=1 # later we might want a few
@@ -131,8 +208,74 @@ beetag-pl-state-init() {
   pl_state_path=$pl_state_dir/$pl_state_file
   pl_seed_path=$pl_state_dir/$seed_file
 
+  if $new_random || [[ ! -r $pl_seed_path ]]; then
+    { base64 < /dev/urandom | head -c 200 ||:; echo; } > $pl_seed_path
+  fi
+
 }
 
+# Call from beetag.
+#
+# Sets do_rare_genres, button_map, last_genre_i, button_i. Toggles those
+# between rare and common genres.
+#
+# Input vars: buttons, common_genres, pl_tags
+toggle-rare-genres() {
+
+  # starts as off if not yet set.
+  if $do_rare_genres || [[ ! $do_rare_genres ]]; then
+    do_rare_genres=false
+    button_map=(${common_genres[@]} ${pl_tags[@]})
+    last_genre_i=$(( ${#rare_genres[@]} - 1 ))
+  else
+    do_rare_genres=true
+    button_map=(${rare_genres[@]} ${pl_tags[@]})
+    last_genre_i=$(( ${#rare_genres[@]} - 1 ))
+  fi
+  for (( i=0; i<${#buttons[@]}; i++ )); do
+    button_i[${buttons[i]}]=$i
+  done
+
+  }
+
+# Call from beetag. Queries our songlist and parses it into variables.
+#
+# Sets ls_lines, id_count, paths, ids
+#
+# Input vars: pl_tags, pl_seed_path, random, beet_query
+beetag-ls-setup() {
+  local fmt tag_query tmpstr line tag ls_line line_no_path right_pad
+  local -a ls_out
+
+  # note: PijokVipiotOzeph is just a random string for a delimiter
+  # shellcheck disable=SC2016 # false positive
+  fmt='%ifdef{rating,$rating }'"$tag_query"'$genre | $title - $artist - $album   $length  $id PijokVipiotOzeph $path'
+
+
+  for tag in "${pl_tags[@]}"; do
+    tag_query+="%ifdef{$tag,$tag }"
+  done
+
+  # shellcheck disable=SC2016 # obvious reason
+  tmpstr=$(beet ls -f "$fmt" "${beet_query[@]}" | { if $random; then sort -R --random-source=$pl_seed_path; else cat; fi; } )
+  mapfile -t ls_out <<<"$tmpstr"
+  if [[ ! ${ls_out[0]} ]]; then
+    echo "beetag: error: no result from beet ls ${beet_query[*]}"
+    return 1
+  fi
+  id_count=${#ls_out[@]}
+
+  for line in "${ls_out[@]}"; do
+    paths+=("${line#*PijokVipiotOzeph }")
+    line_no_path="${line% PijokVipiotOzeph*}"
+    ids+=("${line_no_path##* }")
+    right_pad="${line_no_path%% |*}"
+    ls_line="$(printf %-11s "$right_pad")${line_no_path#"$right_pad"}"
+    ls_lines+=("$ls_line")
+  done
+
+  }
+
 # tag with beets.
 # usage: beetag [-r] [-s] QUERY
 # it lists the query, reads an input char for tagging one by one.
@@ -155,12 +298,11 @@ beetag-pl-state-init() {
 # todo: enter should also unpause
 beetag()  {
   source /a/bin/ds/beet-data
-  local last_genre_i tag_query tag id char new_item char_i tag remove doplay i j random path
-  local do_rare_genres read_wait line lsout ls_line skip_lookback
-  local escape_char escaped_input expected_input skip_input_regex right_pad erasable_line seek_sec
-  local pl_state_path tmpstr
-  local new_random pl_seed_path fmt first_play repeat1
-  local -a buttons button_map ids tags tmp_tags initial_ls ls_lines paths
+  local last_genre_i tag id char new_item char_i tag remove doplay i j random path
+  local read_wait line lsout ls_line skip_lookback do_rare_genres pl_state_path
+  local escape_char escaped_input expected_input skip_input_regex erasable_line seek_sec
+  local new_random pl_seed_path first_play repeat1
+  local -a buttons button_map ids tags tmp_tags ls_lines paths beet_query
   local -A button_i
   local -i i j volume scrolled id_count line_int skip_start pre_j_count head_count skip_lookback
   local -i overflow_lines overflow
@@ -191,60 +333,20 @@ beetag()  {
     echo beetag: error expected a query arg >&2
     return 1
   fi
+  beet_query=("$@")
   ### end arg processing ###
 
   readonly -a buttons=( {a..p} {r..w} {6..8} , . / - "=")
 
-  # note: I used to do beetpull here, but mpv + ssfs on slowish
-  # connection leads to bad/buggy result.
-
-  do_rare_genres=false
+  ### begin control knob vars ###
   volume=70
-  read_wait=2
   doplay=true
+  ### end control knob vars ###
 
-  last_genre_i=$(( ${#common_genres[@]} - 1 ))
-
-  button_map=(${common_genres[@]} ${pl_tags[@]})
-
-  for (( i=0; i<${#buttons[@]}; i++ )); do
-    button_i[${buttons[i]}]=$i
-  done
-
-  beetag-pl-state-init
-
-  if $new_random || [[ ! -r $pl_seed_path ]]; then
-    { base64 < /dev/urandom | head -c 200 ||:; echo; } > $pl_seed_path
-  fi
-
-  tag_query=
-  for tag in "${pl_tags[@]}"; do
-    tag_query+="%ifdef{$tag,$tag }"
-  done
-  # note: PijokVipiotOzeph is just a random string for a delimiter
-  # shellcheck disable=SC2016 # false positive
-  fmt='%ifdef{rating,$rating }'"$tag_query"'$genre | $title - $artist - $album   $length  $id PijokVipiotOzeph $path'
-  # shellcheck disable=SC2016 # obvious reason
-  tmpstr=$(beet ls -f "$fmt" "$@" | { if $random; then sort -R --random-source=$pl_seed_path; else cat; fi; } )
-  mapfile -t initial_ls <<<"$tmpstr"
-  if [[ ! ${initial_ls[0]} ]]; then
-    echo "beetag: error: no result from beet ls $*"
-    return 1
-  fi
-  id_count=${#initial_ls[@]}
-  for line in "${initial_ls[@]}"; do
-    path="${line#*PijokVipiotOzeph }"
-    # https://github.com/koalaman/shellcheck/issues/2171
-    # shellcheck disable=SC2190 # bug in shellcheck, looking at paths from an earlier function
-    paths+=("$path")
-    line_no_path="${line% PijokVipiotOzeph*}"
-    id="${line_no_path##* }"
-    ids+=("$id")
-    right_pad="${line_no_path%% |*}"
-    ls_line="$(printf %-11s "$right_pad")${line_no_path#"$right_pad"}"
-    ls_lines+=("$ls_line")
-    i=$(( i+1 ))
-  done
+  read_wait=2
+  toggle-rare-genres
+  pl-state-init
+  beetag-ls-setup
 
   j=0
   if [[ $playlist ]]; then
@@ -396,19 +498,7 @@ beetag()  {
           return
           ;;
         y)
-          if $do_rare_genres; then
-            do_rare_genres=false
-            button_map=(${common_genres[@]} ${pl_tags[@]})
-            last_genre_i=$(( ${#rare_genres[@]} - 1 ))
-          else
-            do_rare_genres=true
-            button_map=(${rare_genres[@]} ${pl_tags[@]})
-            last_genre_i=$(( ${#rare_genres[@]} - 1 ))
-          fi
-          local -A button_i
-          for (( i=0; i<${#buttons[@]}; i++ )); do
-            button_i[${buttons[i]}]=$i
-          done
+          toggle-rare-genres
           for (( i=0; i<${#button_map[@]}; i++ )); do
             echo ${buttons[i]} ${button_map[i]}
           done
@@ -571,5 +661,3 @@ beetag()  {
     fi
   done
 }
-
-beetag "$@"
diff --git a/brc b/brc
index 0685d986e73a877b6941abaa16691a7b3a52b7ec..1c42e799f124f1a97cf2fa390a226c2eb1c15232 100644 (file)
--- a/brc
+++ b/brc
@@ -1925,25 +1925,6 @@ re() {
   grr -m 5 "$@"
 }
 
-# horizontal row. used to break up output
-hr() {
-  local start end end_count arg
-  # 180 is long enough. 5 for start.
-  start=█████ end=█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
-  end_count=$(( ${COLUMNS:-180} - 5 ))
-  arg="$*"
-  if [[ $arg ]]; then
-    end_count=$(( end_count - 2 - ${#arg} ))
-    start="$start $arg "
-  fi
-  if (( end_count >= 1 )); then
-    end=${end:0:$end_count}
-  else
-
-    end=
-  fi
-  printf "%s\n" "$(tput setaf 5 2>/dev/null ||:)$start$end$(tput sgr0 2>/dev/null||:)"
-}
 # highlighted echo.
 hl() {
   local col input_len=0
@@ -1958,6 +1939,7 @@ hl() {
   fi
   echo
 }
+
 # hl, then run.
 hlm() { hl "$*";  "$@"; }
 
diff --git a/brc2 b/brc2
index 82fb271a3c13a6e63a1c3ba5ded90efe40d2110b..5639e0edb85fcf10a4cfe434d2207064c9e64f0e 100644 (file)
--- a/brc2
+++ b/brc2
@@ -670,15 +670,6 @@ beetconvert-rm-extras() {
   rm "$tmpf"
 }
 
-declare -A bpla # beet playlist associative array
-beetapl() { # beet add playlist
-  local name
-  name="$1"
-  shift
-  bpla[$name]="${*@Q}"
-}
-
-
 beets-gen-playlists() {
   local i str
   local -a query_array query_str
@@ -719,21 +710,6 @@ bpl() {
 complete -W "${!bpla[*]}" bpl
 
 
-# beet modify quietly
-beetmq() {
-  local tmpf
-  tmpf="$(mktemp)"
-  # a bunch of effort to ignore output we dont care about...
-  sed 's/^format_item:.*/format_item: ignore_this/' ~/.config/beets/config.yaml >$tmpf
-  beet -c $tmpf modify -y "$@" > >(grep -vFx -e 'ignore_this' -e 'Modifying 1 items.' ||:)
-  rm "$tmpf"
-  beetag-nostatus 1
-}
-
-kill-bg-quiet() {
-  # https://stackoverflow.com/a/5722874
-  kill %% 2>/dev/null ||:; wait %% 2>/dev/null ||:
-}
 
 # debug variables
 dv() {
@@ -743,61 +719,10 @@ dv() {
   echo
 }
 
-
-# run if not running.
-#
-# Note: this does not work with shell scripts as they are normally
-# invoked, because the ps output has the interpreter at the start.
-# A workaround is to invoke the command in that format, or we could
-# do various other workarounds.
-#
-# background, this relies on how ps converts newlines in arguments to spaces, and
-# assumes we won't be searching for a command with spaces in its arguments
-rinr() {
-  # shellcheck disable=SC2009 # pgrep has no fixed string option, plus see above.
-  if ps h -o args -C "${1##*/}" | grep -Fxqv "$*" &>/dev/null || [[ $? == 141 ]]; then
-    "$@"
-  fi
-}
-# variation of above: run or wait if running
-rowir() {
-  local pid
-  pid=$(ps h -o 'pid,args' -C "${1##*/}" | sed -r 's/^[[:space:]]*([0-9]+)[[:space:]](.*)/\1\n\2/' | grep -B1 -Fx "$*" | head -n1 ||: )
-  if [[ $pid ]]; then
-    # https://unix.stackexchange.com/questions/427115/listen-for-exit-of-process-given-pid
-    tail --pid="$pid" -f /dev/null
-  else
-    "$@"
-  fi
-}
-
-mpvrpc-loadfile() {
-  local path nextpath cachedir finalpath nextpath count
-  cachedir=$HOME/.iank-music-cache
-  path="$1"
-  nextpath="$2"
-
-  # note: logic duplicated in beetpull
-  local remote_p=true
-  source /p/c/domain-info
-  if [[ $HOSTNAME == "$d_host" ]]; then
-    remote_p=false
-  fi
-
-  if $remote_p; then
-    finalpath="$cachedir${path#/i/m}"
-    rowir rsync --partial -a --inplace --mkpath "b8.nz:$path" "$finalpath"
-    finalnextpath="$cachedir${nextpath#/i/m}"
-    count=$(pgrep -a -f "^rsync --partial -a --inplace --mkpath $cachedir" || [[ $? == 1 ]] )
-    # allow us to start 2 rsyncs in the background
-    if [[ $count == [01] ]]; then
-      rinr rsync --partial -a --inplace --mkpath "b8.nz:$nextpath" "$finalnextpath" &
-    fi
-  else
-    finalpath="$path"
-  fi
-  mpvrpc '{ "command": ["loadfile", "'"$finalpath"'"] }'
-}
+# I tried making it a separate script, but the background process
+# management stuff doesn't work that way. There might be a fix, but I
+# didn't try to find one.
+. /a/c/beetag
 
 # usage: FILE|ALBUM_DIR [GENRE]
 beetadd() {
index ddcfce96d55acc27744836c9447e0f315b87c3ba..32dcdfbdef57329fc8c4780d9afba66ea4076127 100644 (file)
@@ -52,6 +52,26 @@ int_regex='^-?[0-9]+$'
 uint_regex='^[0-9]+$'
 
 
+# horizontal row. used to break up output
+hr() {
+  local start end end_count arg
+  # 180 is long enough. 5 for start.
+  start=█████ end=█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
+  end_count=$(( ${COLUMNS:-180} - 5 ))
+  arg="$*"
+  if [[ $arg ]]; then
+    end_count=$(( end_count - 2 - ${#arg} ))
+    start="$start $arg "
+  fi
+  if (( end_count >= 1 )); then
+    end=${end:0:$end_count}
+  else
+
+    end=
+  fi
+  printf "%s\n" "$(tput setaf 5 2>/dev/null ||:)$start$end$(tput sgr0 2>/dev/null||:)"
+}
+
 rm-maybe() {
   if (( $# )); then
     rm -f "$@"