Leave TODO to bring back tmux session listings
[khome.git] / home / lib / login_functions.sh
index 0ff4e86..335f6fd 100644 (file)
@@ -1,31 +1,99 @@
 #
 
+## open : string -> unit
+##
+## Fork xdg-open so we don't block current terminal session when opening
+## things like pdf files. For example:
+##
+##    open book.pdf
+##
+open() {
+    (xdg-open "$1" &) &
+}
+
+## notify_done : unit -> unit
+notify_done() {
+    local -r _status_code="$?"
+    local -r _program="$1"
+    local _timestamp
+    _timestamp="$(timestamp)"
+    local -r _msg="$_timestamp [$_program] done "
+    if [[ "$_status_code" -eq 0 ]]
+    then
+        notify-send -u normal "$_msg OK: $_status_code"
+    else
+        notify-send -u critical "$_msg ERROR: $_status_code"
+    fi
+}
+
 ## p : string -> unit
 p() {
+    local -r usage='Usage: p [FILE] NAME'
+    local name
+    local file
+
+    case "$#" in
+        0)
+            echo "$usage" >&2
+            return 1;;
+        1)
+            file=~/._p/p
+            name="$1";;
+        2)
+            file="$1"
+            name="$2";;
+        *)
+            echo "$usage" >&2
+            return 1;;
+    esac
+
     awk \
-       -v _s="$1" \
-       '
-           BEGIN {_s = tolower(_s)}
-
-           /^[a-zA-Z]/ && tolower($1) ~ _s && NF >= 2 {
-               s = $1
-               p = $NF
-               if (NF == 2) {
-                   e = ""
-                   u = ""
-               } else if (NF == 3) {
-                   e = $2
-                   u = ""
-               } else {
-                   e = $2
-                   u = $3
-               } # TODO What would NF > 4 mean?
-               printf("s:\"%s\", e:\"%s\", u:\"%s\"\n", s, e, u) > "/dev/stderr"
-               printf "%s", p # XXX Intentionally avoiding newline in the result.
-           }
-       ' \
-       ~/._p/p \
-       | xsel -i -b -t 30000
+        -v _s="$name" \
+        '
+            BEGIN {_s = tolower(_s)}
+
+            # TODO fzf/dmenu select instead of searching:
+            /^[a-zA-Z]/ && tolower($1) ~ _s && NF >= 2 {
+                n++
+                s = $1
+                p = $NF
+                if (NF == 2) {
+                    e = ""
+                    u = ""
+                } else if (NF == 3) {
+                    e = $2
+                    u = ""
+                } else {
+                    e = $2
+                    u = $3
+                } # TODO What would NF > 4 mean?
+
+                printf("%d [O] s:\"%s\", e:\"%s\", u:\"%s\"\n", n, s, e, u) > "/dev/stderr"
+                if (match(u, "@")) {
+                    tmp = e
+                    e = u
+                    u = tmp
+                    printf("%d [C] s:\"%s\", e:\"%s\", u:\"%s\"\n", n, s, e, u) > "/dev/stderr"
+                }
+                ps[n] = p
+            }
+
+            END {
+                printf "%s", ps[n]  # XXX Intentionally avoiding newline in the result.
+                if (n == 1) {
+                    exit 0
+                } else if (n == 0) {
+                    printf "[ERROR] Found nothing.\n" > "/dev/stderr"
+                    exit 1
+                } else if (n > 1) {
+                    # TODO fzf-select which of the records the user (ahem, me) wants.
+                    printf "[WARNING] Found more than one record. Selecting the last one.\n" > "/dev/stderr"
+                    exit 0
+                }
+            }
+        ' \
+        "$file" \
+        | xsel -i -b -t 30000
 }
 
 ## web search
@@ -319,14 +387,15 @@ _yt() {
     local -r uri="$2"
     local -r opts="$3"
 
-    local -r id=$(youtube-dlc --get-id "$uri")
-    local -r title=$(youtube-dlc --get-title "$uri" | sed 's/[^А-Яа-яA-Za-z0-9._-]/_/g')
+    local -r yt=youtube-dl
+    local -r id=$("$yt" --get-id "$uri")
+    local -r title=$("$yt" --get-title "$uri" | sed 's/[^А-Яа-яA-Za-z0-9._-]/_/g')
     local -r dir="${base_dir}/${title}--${id}"
 
     mkdir -p "$dir"
     cd "$dir" || kill -INT $$
     echo "$uri" > 'uri'
-    youtube-dlc $opts -c --write-description --write-info-json "$uri"
+    "$yt" $opts -c --write-all-thumbnails --write-description --write-info-json "$uri"
 }
 
 yt_audio() {
@@ -354,7 +423,7 @@ gh_clone() {
     mkdir -p "$gh_dir"
     cd "$gh_dir" || kill -INT $$
     gh_fetch_repos "$gh_user_type" "$gh_user_name" \
-    | jq --raw-output '.[] | select(.fork | not) | .git_url' \
+    | jq --raw-output '.[] | select(.fork | not) | .clone_url' \
     | parallel -j 25 \
     git clone {}
 }
@@ -375,6 +444,59 @@ gh_clone_repo() {
     git clone "$1"
 }
 
+bar() {
+    local -r len="${1:-79}" # 1st arg or 79.
+    local -r char="${2:--}" # 2nd arg or a dash.
+    for _ in {1.."$len"}; do
+        printf '%c' "$char";
+    done
+}
+
+daily_todo_file_template() {
+cat << EOF
+===============================================================================
+$(date '+%F %A')
+===============================================================================
+
+-------------------------------------------------------------------------------
+TODAY
+-------------------------------------------------------------------------------
+
+
+-------------------------------------------------------------------------------
+CURRENT
+-------------------------------------------------------------------------------
+
+
+-------------------------------------------------------------------------------
+BLOCKED
+-------------------------------------------------------------------------------
+
+
+-------------------------------------------------------------------------------
+BACKLOG
+-------------------------------------------------------------------------------
+EOF
+}
+
+today() {
+    local date
+    date="$(date +%F)"
+    local -r dir="$DIR_TODO/daily"
+    local -r file="$dir/$date.txt"
+
+    mkdir -p "$dir"
+    if [ ! -f "$file" ]
+    then
+        daily_todo_file_template > "$file"
+    fi
+    cd "$DIR_TODO" && "$EDITOR" $EDITOR_ARGS "$file"
+}
+
+todo() {
+    cd "$DIR_TODO" && "$EDITOR" TODO
+}
+
 work_log_template() {
 cat << EOF
 $(date '+%F %A')
@@ -552,11 +674,54 @@ status() {
 
     echo 'accounting'
 
-    printf '%stmux\n%ssessions %d, clients %d\n' \
-        "$indent_unit" \
-        "${indent_unit}${indent_unit}" \
-        "$(tmux list-sessions 2> /dev/null | wc -l)" \
-        "$(tmux list-clients  2> /dev/null | wc -l)"
+    # TODO Bring back seesion and client listing, but per server/socket.
+    printf '%stmux\n' "$indent_unit"
+    ps -eo comm,cmd \
+    | awk '
+        # Expecting lines like:
+        #     "tmux: server    tmux -L pistactl new-session -d -s pistactl"
+        #     "tmux: client    tmux -L foo"
+        #     "tmux: client    tmux -Lbar"
+        #     "tmux: client    tmux"
+        #     "tmux: server    tmux -L foo -S bar" <-- -S takes precedence
+        /^tmux:/ {
+            # XXX This of course assumes pervasive usage of -L
+            # TODO Handle -S
+            role=$2
+
+            split($0, sides_of_S, "-S")
+            split(sides_of_S[2], words_right_of_S, FS)
+
+            split($0, sides_of_L, "-L")
+            split(sides_of_L[2], words_right_of_L, FS)
+
+            if (words_right_of_S[1]) {
+                sock = "path." words_right_of_S[1]
+            } else if (words_right_of_L[1]) {
+                sock = "name." words_right_of_L[1]
+            } else {
+                sock = "default"
+            }
+
+            roles[role]++
+            socks[sock]++
+            count[role, sock]++
+        }
+
+        END {
+            for (sock in socks) {
+                clients = count["client", sock]
+                printf "%s ", sock
+                if (clients) {
+                    printf "<-> %d", clients
+                }
+                printf "\n"
+            }
+            printf "\n"
+        }' \
+    | sort \
+    | column -t \
+    | indent "${indent_unit}${indent_unit}"
 
     echo
 
@@ -690,33 +855,33 @@ status() {
     sudo -n netstat -tulnp \
     | awk -v indent="${indent_unit}${indent_unit}" '
         NR > 2 && ((/^tcp/ && proc = $7) || (/^udp/ && proc = $6)) {
-           protocol = $1
-           addr = $4
-           port = a[split(addr, a, ":")]
-           name = p[split(proc, p, "/")]
-           names[name] = 1
-           protocols[protocol] = 1
-           if (!seen[protocol, name, port]++)
-               ports[protocol, name, ++seen[protocol, name]] = port
-       }
-
-       END {
-           for (protocol in protocols) {
-               printf "%s%s\t", indent, toupper(protocol)
-               for (name in names) {
-                   if (n = seen[protocol, name]) {
-                       sep = ""
-                       printf "%s:", name
-                       for (i = 1; i <= n; i++) {
-                           printf "%s%d", sep, ports[protocol, name, i]
-                           sep = ","
-                       }
-                       printf "  "
-                   }
-               }
-               printf "\n"
-           }
-       }'
+            protocol = $1
+            addr = $4
+            port = a[split(addr, a, ":")]
+            name = p[split(proc, p, "/")]
+            names[name] = 1
+            protocols[protocol] = 1
+            if (!seen[protocol, name, port]++)
+                ports[protocol, name, ++seen[protocol, name]] = port
+        }
+
+        END {
+            for (protocol in protocols) {
+                printf "%s%s\t", indent, toupper(protocol)
+                for (name in names) {
+                    if (n = seen[protocol, name]) {
+                        sep = ""
+                        printf "%s:", name
+                        for (i = 1; i <= n; i++) {
+                            printf "%s%d", sep, ports[protocol, name, i]
+                            sep = ","
+                        }
+                        printf "  "
+                    }
+                }
+                printf "\n"
+            }
+        }'
 
     echo "${indent_unit}<->"
 
@@ -754,32 +919,32 @@ ssh_invalid_by_addr() {
 
 ssh_invalid_by_day() {
     awk '
-       BEGIN {
-           m["Jan"] = "01"
-           m["Feb"] = "02"
-           m["Mar"] = "03"
-           m["Apr"] = "04"
-           m["May"] = "05"
-           m["Jun"] = "06"
-           m["Jul"] = "07"
-           m["Aug"] = "08"
-           m["Sep"] = "09"
-           m["Oct"] = "10"
-           m["Nov"] = "11"
-           m["Dec"] = "12"
-       }
-
-       /: Invalid user/ && $5 ~ /^sshd/ {
-           day = m[$1] "-" $2
-           max++
-           by_day[day]++
-       }
-
-       END {
-           for (day in by_day)
-               if ((c = by_day[day]) > 1)
-                   printf "%d %d %s\n", c, max, day
-       }
+        BEGIN {
+            m["Jan"] = "01"
+            m["Feb"] = "02"
+            m["Mar"] = "03"
+            m["Apr"] = "04"
+            m["May"] = "05"
+            m["Jun"] = "06"
+            m["Jul"] = "07"
+            m["Aug"] = "08"
+            m["Sep"] = "09"
+            m["Oct"] = "10"
+            m["Nov"] = "11"
+            m["Dec"] = "12"
+        }
+
+        /: Invalid user/ && $5 ~ /^sshd/ {
+            day = m[$1] "-" $2
+            max++
+            by_day[day]++
+        }
+
+        END {
+            for (day in by_day)
+                if ((c = by_day[day]) > 1)
+                    printf "%d %d %s\n", c, max, day
+        }
         ' \
         /var/log/auth.log \
         /var/log/auth.log.1 \
This page took 0.038201 seconds and 4 git commands to generate.