mainly beets fixes
authorIan Kelling <ian@iankelling.org>
Mon, 3 Mar 2025 04:08:09 +0000 (23:08 -0500)
committerIan Kelling <ian@iankelling.org>
Mon, 3 Mar 2025 04:08:09 +0000 (23:08 -0500)
beet-data
beetag
brc
brc2
distro-end
pkgs

index f1e9823f08dda14309b5688f3f5ce7aa28fff36e..19acc31e01cb0effa261a60efe2ba87653ac9ccd 100644 (file)
--- a/beet-data
+++ b/beet-data
@@ -28,7 +28,6 @@ nav_tags=(
   gimicky
   # anything sad which i sometimes like or avoid.
   sad
-
   ## playlists
   # intimate, love
   love
@@ -40,6 +39,11 @@ nav_tags=(
   rend
   # for running
   run
+  # songs I used to like more, but are now rated 1-2
+  tiredof
+  # songs i've been really into very recently. I expect this to change a
+  # lot, and push old songs out and perhaps into other playlists.
+  worm
 )
 
 # playlist tags
@@ -52,14 +56,12 @@ pl_tags=(
 nav_convert_query="^genre:spoken-w ^genre:skit ^lesser_version:t rating:3..5"
 
 common_genres=(
-  ambient
   # gangsta rap / angry rap. something like g-rap would make beet queries for genre:rap include it
   arp
   avant
   blues
   # slow instrumental. todo: reclassify some ambient into this.
   chill
-  classical
   country
   # lyrical edm. todo: some pop needs reclassification to this
   dance
@@ -84,6 +86,8 @@ common_genres=(
 
 # because we were destined to run out of single key buttons.
 rare_genres=(
+  ambient
+  classical
   jazz
   musical
   noise
diff --git a/beetag b/beetag
index 392efa63e36c0df700f7fb5eaa19cbf233d7a639..92c238038e639c6c43996504dfd4a371a6b91144 100755 (executable)
--- a/beetag
+++ b/beetag
@@ -272,10 +272,6 @@ beetag-ls-setup() {
   # 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
@@ -433,11 +429,15 @@ beetag()  {
   escape_char=$(printf "\u1b")
   readonly escape_char
 
-
   toggle-rare-genres
   pl-state-init
   beetag-ls-setup
 
+  if (( ! id_count )); then
+    echo "beetag: no result from beet ls ${beet_query[*]}. nothing to do."
+    return
+  fi
+
   if [[ $playlist && -r $pl_state_path ]]; then
     j=$(cat $pl_state_path) # playlist position.
   fi
diff --git a/brc b/brc
index 214102f4c81da745deb5e02cf36be9858373b572..aa451e8f62ea9e163a054f22612a6e7bd206e919 100644 (file)
--- a/brc
+++ b/brc
@@ -1970,7 +1970,7 @@ github-release-dl() {
   fi
   version="${latest_prefix##*/}"
   version="${version#v}"
-  m wget -- "$latest_prefix/$file_prefix$version$file_suffix"
+  m wget -q -- "$latest_prefix/$file_prefix$version$file_suffix"
 }
 
 ## Given a url to a github repo written in go, install its binary
@@ -1979,9 +1979,13 @@ github-release-dl() {
 # go-github-install restic/restic restic_ _linux_amd64.bz2
 # go-github-install restic/rest-server rest-server_ _linux_amd64.tar.gz
 go-github-install() {
-  local tmpd targetf tmp files src
+  local tmpd targetf tmp files src sudo_maybe
+  if [[ $EUID != 0 ]]; then
+    sudo_maybe=sudo
+  fi
+
   tmpd=$(mktemp -d)
-  cd $tmpd
+  cd $tmpd
   file_prefix=$2
   file_suffix=$3
   tmp="${file_prefix##*[[:alnum:]]}"
@@ -1991,20 +1995,20 @@ go-github-install() {
   files=(./*)
   case $file_suffix in
     *.bz2)
-      bunzip2 -- ./*
+      bunzip2 -- ./*
       ;;
     *.tar.gz|*.tgz)
-      tar -vxzf ./*
+      tar -vxzf ./*
       ;;
   esac
-  rm -f -- "${files[@]}"
+  rm -f -- "${files[@]}"
   files=(./*)
   # Here we detect and handle 2 cases: either we extracted a single
   # binary which we have to rename or a folder with a binary named
   # $targetf in it which is all we care about.
   if (( ${#files[@]} == 1 )) && [[ -f ${files[0]} ]]; then
-    chmod +x ./*
-    mv -- ./* /usr/local/bin/$targetf
+    chmod +x ./*
+    m $sudo_maybe mv -- ./* /usr/local/bin/$targetf
   else
     files=(./*/$targetf)
     if [[ -f $targetf ]]; then
@@ -2012,13 +2016,14 @@ go-github-install() {
     elif [[ -f ${files[0]} ]]; then
       src="${files[0]}"
     fi
-    chmod +x "$src"
-    mv -- "$src" /usr/local/bin
+    chmod +x "$src"
+    m $sudo_maybe mv -- "$src" /usr/local/bin
   fi
   cd - >/dev/null
   rm -rf $tmpd
 }
 
+
 ## 2024: I'm using gh instead of hub, but leaving this just in case.
 ## I tried the github cli tool (gh) and it seems easier than
 ## I remember hub.
diff --git a/brc2 b/brc2
index bdbe6dbb4f159c4d7b5a3d0136faa448beb62aed..08fb32dbef249e4300deae5b2e11bc11c6b40e8a 100644 (file)
--- a/brc2
+++ b/brc2
@@ -561,115 +561,26 @@ _iki-convert() {
   esac
 }
 
-source /a/bin/ds/beet-data
-
-
-# Generate beet smartplaylists for navidrome.
-# for going in the reverse direction, run
-# /b/ds/navidrome-playlist-export
-beetsmartplaylists() {
-  install -m 0700 -d /tmp/ianbeetstmp
-  beet splupdate
-  # kill off any playlists we deleted. they will still need manual
-  # killing from a navidrome client.
-  rm -rf /i/converted/beetsmartplaylists
-  mkdir -p /i/converted/beetsmartplaylists
-  for f in /tmp/ianbeetstmp/*; do
-    sed 's,^/i/m,/i/converted,;s,\.flac$,.mp3,' "$f" >"/i/converted/beetsmartplaylists/${f##*/}"
-    rm "$f"
-  done
-  rmdir /tmp/ianbeetstmp
-}
 
-# internal function for beetrating, in case we need to ssh
-beetrating-stdin() {
-  local tmp rating path cpath sqlpath userid
-  # plucked this from the db. im the only user.
-  userid=23cc2eb9-e35e-4811-a0f0-d5f0dd6eb634
-  while read -r rating path; do
-    cpath="/i/converted${path#/i/m}" # converted path
-    case $cpath in
-      *.flac)
-        cpath="${cpath%.*}.mp3"
-        ;;
-    esac
-    if [[ ! -e $cpath ]]; then
-      echo "beetraing: error: this should not happen, path does not exist: $cpath"
-      return 1
-    fi
-    sqlpath="${cpath//\'/\'\'}"
-    old_rating=$(sqlite3 /i/navidrome/navidrome.db "select rating from annotation inner join media_file on item_id = id where path = '$sqlpath' and item_type = 'media_file';")
-    if [[ $old_rating ]]; then
-      if [[ $old_rating != "$rating" ]]; then
-        echo "setting rating $old_rating -> $rating $cpath"
-        # https://stackoverflow.com/a/50317320
-        # we got a timeout error once. arbitrarily chose 15 seconds.
-        sqlite3 /i/navidrome/navidrome.db ".timeout 15000" "
-update annotation set rating = $rating
- where item_id in (
- select media_file.id from annotation inner join media_file on annotation.item_id = media_file.id
-   where media_file.path = '$sqlpath' and annotation.item_type = 'media_file' );"
-      fi
-    else
-      echo "setting rating $rating $cpath"
-      # /a/opt/navidrome/persistence/sql_annotations.go v0.48.0
-      # https://www.sqlite.org/lang_insert.html
-      sqlite3 /i/navidrome/navidrome.db ".timeout 15000" "insert into annotation select '$(uuidgen)', '$userid', id, 'media_file', 0, NULL, $rating, 0, NULL from media_file where path = '$sqlpath';"
-    fi
+# debug variables
+dv() {
+  for arg; do
+    printf "%s=%s " "$arg" "${!arg}"
   done
+  echo
 }
 
-nav_convert_query="^genre:spoken-w ^genre:skit ^lesser_version:t rating:3..5"
-
-# Export beets ratings into navidrome
-beetrating() {
-  local ssh_prefix
-  source /p/c/domain-info
-  if [[ $HOSTNAME != "$d_host" ]]; then
-    ssh_prefix="ssh b8.nz"
-  fi
-  # shellcheck disable=SC2016 # obvious reason
-  beet ls -f '$rating $path' $nav_convert_query | $ssh_prefix beetrating-stdin
-}
-
-# Do transcoding and hardlinking of audio files for navidrome.
-beetconvert() {
-  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 convert -y $nav_convert_query > >(grep -vFx 'ignore_this' ||:) 2> >(grep -v '^convert: Skipping' ||:)
-  rm "$tmpf"
-}
 
-# This deletes files in the converted directory which should no longer
-# be there due to a rename of the unconverted file.
-beetconvert-rm-extras() {
-  local l tmpf
-  local -A paths
-  tmpf="$(mktemp)"
-  # shellcheck disable=SC2016 # obvious reason
-  beet ls -f '$path' $nav_convert_query >"$tmpf"
-  ## begin removal of files that are leftover from previous conversion,
-  # eg, previously rated > 1, now rated 1.
-  while read -r l; do
-    convertedpath="/i/converted${l#/i/m}"
-    case $convertedpath in
-      *.flac) convertedpath="${convertedpath%.flac}.mp3" ;;
-    esac
-    paths[$convertedpath]=t
-  done <"$tmpf"
+#### begin beet related functions ####
+source /a/bin/ds/beet-data
 
-  find /i/converted -path /i/converted/beetsmartplaylists -prune -o \( -type f -print \) -name '*.mp3' -o -name '*.m4a' >"$tmpf"
-  while read -r l; do
-    if [[ ! ${paths[$l]} ]]; then
-      rm -v "$l"
-    fi
-    # note: the pruning is duplicative of filtering on name, but whatever.
-  done <"$tmpf"
-  rm "$tmpf"
-}
+# 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.
+source /a/c/beetag
 
+# For adding or removing a smart playlist, copy output to
+# /p/c/subdir_files/.config/beets/config.yaml
 beets-gen-playlists() {
   local i str
   local -a query_array query_str
@@ -710,23 +621,9 @@ bpl() {
 complete -W "${!bpla[*]}" bpl
 
 
-
-# debug variables
-dv() {
-  for arg; do
-    printf "%s=%s " "$arg" "${!arg}"
-  done
-  echo
-}
-
-# 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]
+# usage: FILE|ALBUM_DIR [GENRE] [RATING]
 beetadd() {
-  local import_path genre_arg single_track_arg
+  local import_path genre_arg single_track_arg rating_arg
   import_path="$1"
   if [[ ! -e $import_path ]]; then
     echo "beetadd error: path does not exist"
@@ -734,14 +631,48 @@ beetadd() {
   if [[ $2 ]]; then
     genre_arg="--set genre=$2"
   fi
+  if [[ $3 ]]; then
+    rating_arg="--set rating=$3"
+  fi
   if [[ -f $import_path ]]; then
     single_track_arg=-s
   fi
-  beet import --set totag=t $single_track_arg $genre_arg "$import_path"
+  beet import --set totag=t $single_track_arg $genre_arg $rating_arg "$import_path"
+  function err-cleanup() {
+    if beet ls -a totag:t | grep -q .; then
+      beet modify -ay totag:t 'totag!'
+    fi
+    if beet ls totag:t | grep -q .; then
+      beet modify -y totag:t 'totag!'
+    fi
+  }
   beetag totag:t
-  beet modify -y totag:t "totag!"
-}
-
+  err-cleanup
+  unset -f err-cleanup
+}
+
+# beetag: error: no result from beet ls totag:t
+# [1] 711197
+# █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
+# a arp            i nv             s sleep          8 pump1
+# b avant          l latin          t techno         , pumprap
+# c blues          m metal          u world          . rend
+# d chill          n mq             v expl           / run
+# e country        o pop            w gimicky        - tiredof
+# f dance          p rap            6 sad            = worm
+# g darkwave       r rock           7 love           \ lesser_version
+# h hardcore
+
+# y other genres   z fg player      ' = toggle play  1-5 rate    ] repeat1
+# ; previous       _ delete         j/k skip         mpv_keys vol,pause,seek
+# █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
+# ██
+# [file] Cannot open file '': No such file or directory
+# Failed to open .
+# bash: ( j + 1 ) % id_count : division by 0 (error token is "id_count ")
+
+
+##### begin beet2nav functions #####
 # update navidrome music data after doing beets tagging
 beet2nav() {
   m beetpull
@@ -772,6 +703,114 @@ beetpull() {
   fi
 }
 
+# Do transcoding and hardlinking of audio files for navidrome.
+beetconvert() {
+  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 convert -y $nav_convert_query > >(grep -vFx 'ignore_this' ||:) 2> >(grep -v '^convert: Skipping' ||:)
+  rm "$tmpf"
+}
+
+nav_convert_query="^genre:spoken-w ^genre:skit ^lesser_version:t rating:3..5"
+
+# Export beets ratings into navidrome
+beetrating() {
+  local ssh_prefix
+  source /p/c/domain-info
+  if [[ $HOSTNAME != "$d_host" ]]; then
+    ssh_prefix="ssh b8.nz"
+  fi
+  # shellcheck disable=SC2016 # obvious reason
+  beet ls -f '$rating $path' $nav_convert_query | $ssh_prefix beetrating-stdin
+}
+
+
+# This deletes files in the converted directory which should no longer
+# be there due to a rename of the unconverted file.
+beetconvert-rm-extras() {
+  local l tmpf
+  local -A paths
+  tmpf="$(mktemp)"
+  # shellcheck disable=SC2016 # obvious reason
+  beet ls -f '$path' $nav_convert_query >"$tmpf"
+  ## begin removal of files that are leftover from previous conversion,
+  # eg, previously rated > 1, now rated 1.
+  while read -r l; do
+    convertedpath="/i/converted${l#/i/m}"
+    case $convertedpath in
+      *.flac) convertedpath="${convertedpath%.flac}.mp3" ;;
+    esac
+    paths[$convertedpath]=t
+  done <"$tmpf"
+
+  find /i/converted -path /i/converted/beetsmartplaylists -prune -o \( -type f -print \) -name '*.mp3' -o -name '*.m4a' >"$tmpf"
+  while read -r l; do
+    if [[ ! ${paths[$l]} ]]; then
+      rm -v "$l"
+    fi
+    # note: the pruning is duplicative of filtering on name, but whatever.
+  done <"$tmpf"
+  rm "$tmpf"
+}
+
+# Generate beet smartplaylists for navidrome.
+# for going in the reverse direction, run
+# /b/ds/navidrome-playlist-export
+beetsmartplaylists() {
+  install -m 0700 -d /tmp/ianbeetstmp
+  beet splupdate
+  # kill off any playlists we deleted. they will still need manual
+  # killing from a navidrome client.
+  rm -rf /i/converted/beetsmartplaylists
+  mkdir -p /i/converted/beetsmartplaylists
+  for f in /tmp/ianbeetstmp/*; do
+    sed 's,^/i/m,/i/converted,;s,\.flac$,.mp3,' "$f" >"/i/converted/beetsmartplaylists/${f##*/}"
+    rm "$f"
+  done
+  rmdir /tmp/ianbeetstmp
+}
+
+# internal function for beetrating, in case we need to ssh
+beetrating-stdin() {
+  local tmp rating path cpath sqlpath userid
+  # plucked this from the db. im the only user.
+  userid=23cc2eb9-e35e-4811-a0f0-d5f0dd6eb634
+  while read -r rating path; do
+    cpath="/i/converted${path#/i/m}" # converted path
+    case $cpath in
+      *.flac)
+        cpath="${cpath%.*}.mp3"
+        ;;
+    esac
+    if [[ ! -e $cpath ]]; then
+      echo "beetraing: error: this should not happen, path does not exist: $cpath"
+      return 1
+    fi
+    sqlpath="${cpath//\'/\'\'}"
+    old_rating=$(sqlite3 /i/navidrome/navidrome.db "select rating from annotation inner join media_file on item_id = id where path = '$sqlpath' and item_type = 'media_file';")
+    if [[ $old_rating ]]; then
+      if [[ $old_rating != "$rating" ]]; then
+        echo "setting rating $old_rating -> $rating $cpath"
+        # https://stackoverflow.com/a/50317320
+        # we got a timeout error once. arbitrarily chose 15 seconds.
+        sqlite3 /i/navidrome/navidrome.db ".timeout 15000" "
+update annotation set rating = $rating
+ where item_id in (
+ select media_file.id from annotation inner join media_file on annotation.item_id = media_file.id
+   where media_file.path = '$sqlpath' and annotation.item_type = 'media_file' );"
+      fi
+    else
+      echo "setting rating $rating $cpath"
+      # /a/opt/navidrome/persistence/sql_annotations.go v0.48.0
+      # https://www.sqlite.org/lang_insert.html
+      sqlite3 /i/navidrome/navidrome.db ".timeout 15000" "insert into annotation select '$(uuidgen)', '$userid', id, 'media_file', 0, NULL, $rating, 0, NULL from media_file where path = '$sqlpath';"
+    fi
+  done
+}
+##### end beet2nav functions #####
+
 # remove all playlists in navidrome, for when I make big
 # playlist name changes and just want to scrap everything.
 nav-rm-plists() {
@@ -849,6 +888,9 @@ beegenre() {
   rm $tmpf
 }
 
+#### end beet related functions ####
+
+
 # prettify the date
 btrbk-date() {
   local indate
@@ -1332,7 +1374,7 @@ apache-header() {
 # programs. If a small program grows beyond 300 lines, I plan to change
 # to a recommended GPL license.
 
-# Copyright 2024 Ian Kelling
+# Copyright 2025 Ian Kelling
 
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -4042,11 +4084,24 @@ reml() { # rem with limit to 5 matches per file
 
 rep() {
   local paths
-  paths="/p/c /p/profanity-config"
+  local -a opts
+  if [[ ! $1 ]]; then
+    echo rem: missing argument >&2
+    return 1
+  fi
+  for arg; do
+    if [[ $arg == -* ]]; then
+      opts+=("$1")
+      shift
+    else
+      break
+    fi
+  done
+  paths="/p/c /p/profanity-config /b/bash_unpublished"
   find $paths -not \( -name .svn -prune -o -name .git -prune \
        -o -name .hg -prune -o -name .editor-backups -prune \
        -o -name .undo-tree-history -prune \) 2>/dev/null | grep -iP --color=auto -- "$*" ||:
-  rgv $local_rgv_args -- "$*" $paths /a/t.org /p/w.org ||:
+  rgv $local_rgv_args "${opts[@]}" -- "$*" $paths /a/t.org /p/w.org ||:
 }
 repl() { # rem with limit to 5 matches per file
   local local_rgv_args="-m 5"
index 92bfa881f4123136231d5cc9195d421b636063c4..4ea6549ad9c3c7e393770c96f64e5e58a9acf906 100755 (executable)
@@ -1693,52 +1693,61 @@ case $(debian-codename) in
 esac
 
 
-## begin beets
-# soo, apt install beets fails due to wanting a pip package,
-# we find out why it wants this through
-# apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances beets | less
-# python-mediafile requires tox, which requires virtualenv, which requires pip.
-# but, python-mediafile doesn't really require tox, it is specified in
-# ./usr/lib/python3/dist-packages/mediafile-0.9.0.dist-info/METADATA
-# as being required only for testing, but the debian package
-# included it anyways, due to a mistake or bad tooling or something.
-# I don't plan to use tox, so, according to https://serverfault.com/a/251091,
-# we can create and install a dummy package by:
-#
-# "equivs-control <name>, edit the file produced to provide the right
-# dependency and have a nice name, then run equivs-build <name> and
-# finally dpkg -i the resulting .deb file"
-# as of 2023-02, the tox dependency was removed in debian unstable, so
-# this hack will probably go away in t12.
+##### begin beets #####
+
+# ## apt install method, disabled because it is 2025 & packaged version is 2021.
+# # apt install beets fails due to wanting a pip package,
+# # we find out why it wants this through
+# # apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances beets | less
+# # python-mediafile requires tox, which requires virtualenv, which requires pip.
+# # but, python-mediafile doesn't really require tox, it is specified in
+# # ./usr/lib/python3/dist-packages/mediafile-0.9.0.dist-info/METADATA
+# # as being required only for testing, but the debian package
+# # included it anyways, due to a mistake or bad tooling or something.
+# # I don't plan to use tox, so, according to https://serverfault.com/a/251091,
+# # we can create and install a dummy package by:
+# #
+# # "equivs-control <name>, edit the file produced to provide the right
+# # dependency and have a nice name, then run equivs-build <name> and
+# # finally dpkg -i the resulting .deb file"
+# # as of 2023-02, the tox dependency was removed in debian unstable, so
+# # this hack will probably go away in t12.
+
+# case $(debian-codename) in
+#   aramo)
+#     if pcheck tox; then
+#       tmpdir="$(mktemp -d)"
+#       cd "$tmpdir"
+#       # edited from output of equivs-control tox
+#       cat >tox <<'EOF'
+# Section: python
+# Priority: optional
+# Standards-Version: 3.9.2
+# Package: tox
+# Description: tox-dummy
+# EOF
+#       equivs-build tox
+#       sudo dpkg -i tox_1.0_all.deb
+#       rm -rf ./tox*
+#       cd
+#       rm -r "$tmpdir"
+#     fi
+#     ;;
+# esac
+# pi beets beets-doc
+# # get rid of annoying message
+# s sed -ri "s/^([[:space:]]*ui.print_\('Playing)/#\1/" /usr/share/beets/beetsplug/play.py
 
-case $(debian-codename) in
-  aramo)
-    if pcheck tox; then
-      tmpdir="$(mktemp -d)"
-      cd "$tmpdir"
-      # edited from output of equivs-control tox
-      cat >tox <<'EOF'
-Section: python
-Priority: optional
-Standards-Version: 3.9.2
-Package: tox
-Description: tox-dummy
-EOF
-      equivs-build tox
-      sudo dpkg -i tox_1.0_all.deb
-      rm -rf ./tox*
-      cd
-      rm -r "$tmpdir"
-    fi
-    ;;
-esac
-pi beets beets-doc
 
+pipx ensurepath -v
+# in brackets are nondefault plugins
+pipx install 'beets[lyrics,discogs,mbsync]'
 
-# get rid of annoying message
-s sed -ri "s/^([[:space:]]*ui.print_\('Playing)/#\1/" /usr/share/beets/beetsplug/play.py
+# note: when i first setup beets, i found installing some plugins
+# useful, but now it is bundled with enough good ones that i found no
+# urgent need.
 
-## end beets
+##### end beets #####
 
 
 # notes about barrier
@@ -2010,13 +2019,20 @@ esac
 
 # from https://raw.githubusercontent.com/cli/cli/trunk/docs/install_linux.md
 # One time setup afterwards:
+# pass github-gh-token | gh auth login --with-token
+#
+# Originally,
 # gh auth login
 #
 # When it gets to the page where it asks to authorize github, the button
 # is grayed out. You can just open browser dev tools, inspect the
 # button, remove disabled="", then click it and it works.
 #
-# Auth token gets saved into /p/c/subdir_files/.local/share/keyrings/
+# Auth token gets saved into /p/c/subdir_files/.local/share/keyrings/ ,
+# but I found a solution for backing it up and importing it to other
+# comps: I saved the output of `gh auth token` to pass, and it can be
+# imported with the above command.
+#
 #
 # initial config goes to /home/iank/.config/gh
 curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
diff --git a/pkgs b/pkgs
index d088afef9d648aa78c19c78d0d708a91bd39841a..55f4d41d3c4533d4bd008f43824e76688888dc3e 100644 (file)
--- a/pkgs
+++ b/pkgs
@@ -263,6 +263,7 @@ p3=(
   pinentry-gtk2
   pidgin
   pidgin-otr
+  pipx
   pixz
   # unattended-upgrades.log: Please install powermgmt-base package to check power status
   powermgmt-base