feat: implement __rand_string generator and update jobrunner to use tmux

This commit is contained in:
2026-08-02 05:21:21 -04:00
parent 674a50ea05
commit ffff95f3b9
12 changed files with 2283 additions and 63 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ This config layers on top of the CachyOS base Fish configuration and adds:
- **Smart CLI wrappers** that prefer modern tools (`eza`, `bat`, `btop`, `dust`, `prettyping`) with graceful fallbacks
- **Auto Python venv** activation on directory change (direnv-aware)
- **Kitty terminal** deep integration for splits, tabs, and SSH
- **Named background jobs** — `jobrunner` (short: `jr`) starts, lists, inspects, re-attaches to, and kills detached tasks via GNU `screen`, so long-running work survives closing the shell
- **Named background jobs** — `jobrunner` (short: `jr`) starts, lists, inspects, re-attaches to, and kills detached tasks via `tmux` or GNU `screen`, so long-running work survives closing the shell
- **Optional session logging** — terminal scrollback, multiplexer panes (tmux/zellij), and AUR-helper output can be captured to `~/.terminal_history`; **off by default**, opt in when you want it (see the caution below and [Session Logging](#session-logging))
- **AI workflow** helpers for Claude and Antigravity session management
- **WakaTime** shell activity tracking
+20
View File
@@ -0,0 +1,20 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
complete -c __rand_string -f
complete -c __rand_string -s s -l separator -x -a 'dash underscore dot none' -d 'Set separator for following words'
complete -c __rand_string -s c -l case -x -a 'lower upper title' -d 'Set casing for following words'
# List of all available lists in data/words
set -l categories
if set -q __fish_config_dir
set categories (string replace -r '\.txt$' '' (command ls $__fish_config_dir/data/words/*.txt 2>/dev/null | command xargs -n 1 basename 2>/dev/null))
end
for cat in $categories
complete -c __rand_string -a "$cat" -d "Pick a random word from the $cat list"
end
complete -c __rand_string -a 'digits=' -d 'Generate N random digits (e.g. digits=3)'
complete -c __rand_string -a 'literal=' -d 'Insert a literal string exactly as provided'
+23 -1
View File
@@ -6,7 +6,25 @@
# Offer running jobs as name<TAB>description pairs.
function __jobrunner_complete_jobs
for row in (__jobrunner_sessions)
set -l tool ""
set -l tokens (commandline -opc)
set -l idx 1
while test $idx -le (count $tokens)
switch $tokens[$idx]
case -t --tool
set idx (math $idx + 1)
if test $idx -le (count $tokens)
set tool $tokens[$idx]
end
case '--tool=*'
set tool (string replace -- "--tool=" "" $tokens[$idx])
case '-t*'
set tool (string replace -r "^-t" "" $tokens[$idx])
end
set idx (math $idx + 1)
end
for row in (__jobrunner_sessions $tool)
set -l f (string split \t -- $row)
printf '%s\t%s job (PID %s)\n' $f[1] $f[3] $f[2]
end
@@ -18,6 +36,10 @@ set -l needs_job "__fish_seen_subcommand_from attach kill logs -a --attach -k --
# No file completions; jobs are named, not paths.
complete -c jobrunner -f
# Backend tool selection flag.
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
-s t -l tool -x -a "tmux screen" -d 'Force specific backend'
# Subcommands (only as the first argument).
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
-a run -d 'Start a named job in the background'
+108
View File
@@ -0,0 +1,108 @@
admiring
adoring
affectionate
agitated
amazing
angry
awesome
beautiful
blissful
bold
boring
brave
busy
charming
clever
compassionate
competent
condescending
confident
cool
cranky
crazy
dazzling
determined
distracted
dreamy
eager
ecstatic
elastic
elated
elegant
eloquent
epic
exciting
fervent
festive
flamboyant
focused
friendly
frosty
funny
gallant
gifted
goofy
gracious
great
happy
hardcore
heuristic
hopeful
hungry
infallible
inspiring
intelligent
interesting
jolly
jovial
keen
kind
laughing
loving
lucid
magical
modest
musing
mystifying
naughty
nervous
nice
nifty
nostalgic
objective
optimistic
peaceful
pedantic
pensive
practical
priceless
quirky
quizzical
recursing
relaxed
reverent
romantic
sad
serene
sharp
silly
sleepy
stoic
strange
stupefied
suspicious
sweet
tender
thirsty
trusting
unruffled
upbeat
vibrant
vigilant
vigorous
wizardly
wonderful
xenodochial
youthful
zealous
zen
+223
View File
@@ -0,0 +1,223 @@
aardvark
albatross
alligator
alpaca
ant
anteater
antelope
ape
armadillo
baboon
badger
barracuda
bat
bear
beaver
bee
bison
boar
buffalo
butterfly
camel
capybara
caribou
cat
caterpillar
cattle
chamois
cheetah
chicken
chimpanzee
chinchilla
chough
clam
cobra
cockroach
cod
cormorant
coyote
crab
crane
crocodile
crow
curlew
deer
dinosaur
dog
dogfish
dolphin
donkey
dotterel
dove
dragonfly
duck
dugong
dunlin
eagle
echidna
eel
eland
elephant
elk
emu
falcon
ferret
finch
fish
flamingo
fly
fox
frog
gaur
gazelle
gerbil
giraffe
gnat
gnu
goat
goldfinch
goldfish
goose
gorilla
goshawk
grasshopper
grouse
guanaco
gull
hamster
hare
hawk
hedgehog
heron
herring
hippopotamus
hornet
horse
human
hummingbird
hyena
ibex
ibis
jackal
jaguar
jay
jellyfish
kangaroo
kingfisher
koala
kookabura
kouprey
kudu
lapwing
lark
lemur
leopard
lion
llama
lobster
locust
loris
louse
lyrebird
magpie
mallard
manatee
mandrill
mantis
marten
meerkat
mink
mole
mongoose
monkey
moose
mosquito
mouse
mule
narwhal
newt
nightingale
octopus
okapi
opossum
oryx
ostrich
otter
owl
oyster
panther
parrot
partridge
peafowl
pelican
penguin
pheasant
pig
pigeon
pony
porcupine
porpoise
quail
quelea
quetzal
rabbit
raccoon
rail
ram
rat
raven
red-deer
red-panda
reindeer
rhinoceros
rook
salamander
salmon
sand-dollar
sandpiper
sardine
scorpion
seahorse
seal
shark
sheep
shrew
skunk
snail
snake
sparrow
spider
spoonbill
squid
squirrel
starling
stingray
stinkbug
stork
swallow
swan
tapir
tarsier
termite
tiger
toad
trout
turkey
turtle
viper
vulture
wallaby
walrus
wasp
weasel
whale
wildcat
wolf
wolverine
wombat
woodcock
woodpecker
worm
wren
yak
zebra
+81
View File
@@ -0,0 +1,81 @@
amber
amethyst
apricot
aqua
aquamarine
auburn
azure
beige
black
blue
bronze
brown
buff
carmine
celadon
cerise
cerulean
charcoal
chartreuse
chocolate
cinnamon
copper
coral
cream
crimson
cyan
denim
emerald
fuchsia
gold
goldenrod
gray
green
grey
indigo
ivory
jade
khaki
lavender
lemon
lilac
lime
magenta
mahogany
maroon
mauve
mustard
navy
ochre
olive
orange
orchid
peach
pear
periwinkle
pink
plum
puce
purple
quartz
red
rose
ruby
rust
salmon
sapphire
scarlet
silver
slate
tan
taupe
teal
tomato
topaz
turquoise
ultramarine
umber
vanilla
violet
white
yellow
+236
View File
@@ -0,0 +1,236 @@
agnesi
albattani
allen
almeida
antonelli
archimedes
ardinghelli
aryabhata
austin
babbage
banach
banzai
bardeen
bartik
bassi
beaver
bell
benz
bhabha
bhaskara
black
blackburn
blackwell
bohr
booth
borg
bose
bouman
boyd
brahmagupta
brattain
brown
buck
burnell
cannon
carson
cartwright
carver
cerf
chandrasekhar
chaplygin
chatelet
chatterjee
chaum
chebyshev
clarke
cohen
colden
cori
cray
curie
curran
darwin
davinci
dewdney
dhawan
diffie
dijkstra
dirac
driscoll
dubinsky
easley
edison
einstein
elbakyan
elgamal
elion
ellis
engelbart
euclid
euler
faraday
feistel
fermat
fermi
feynman
franklin
gagarin
galileo
galois
ganguly
gates
gauss
germain
goldberg
goldstine
goldwasser
golick
goodall
gould
greider
grothendieck
haibt
hamilton
haslett
hawking
heisenberg
hellman
hermann
herschel
hertz
heyrovsky
hodgkin
hofstadter
hoover
hopper
hugle
hypatia
ishizaka
jackson
jang
jemison
jennings
jepsen
johnson
joliot
jones
kalam
kapitsa
kare
keldysh
keller
kepler
khayyam
khorana
kilby
kirch
knuth
kowalevski
lalande
lamarr
lamport
leakey
leavitt
lederberg
lehmann
lewin
lichterman
liskov
lovelace
lumiere
mahavira
margulis
matsumoto
maxwell
mayer
mccarthy
mcclintock
mclaren
mclean
mcnulty
meitner
mendel
mendeleev
meninsky
merkle
mestorf
mirzakhani
montalcini
moore
morse
moser
murdock
napier
nash
neumann
newton
nightingale
nobel
noether
northcutt
noyce
panini
pare
pascal
pasteur
payne
perlman
pike
poincare
poitras
proskuriakova
ptolemy
raman
ramanujan
rhodes
ride
ritchie
robinson
roentgen
rosalind
rubin
saha
sammet
sanderson
satoshi
shamir
shannon
shaw
shirley
shockley
shtern
sinoussi
snyder
solomon
spence
stonebraker
sutherland
swanson
swartz
swirles
taussig
tesla
tharp
thompson
torvalds
tu
turing
varahamihira
vaughan
villani
visvesvaraya
volhard
wescoff
wilbur
wiles
williams
williamson
wilson
wing
wozniak
wright
wu
yalow
yonath
zhukovsky
+1296
View File
File diff suppressed because it is too large Load Diff
+45 -24
View File
@@ -2,42 +2,63 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __jobrunner_sessions
# __jobrunner_sessions [<tool>]
#
# DESCRIPTION
# Parses `screen -ls` into machine-readable rows, one per active session:
# name, PID, state, and start time separated by tabs. Shared by jobrunner
# and its completions so both agree on what a session is named. Prints
# nothing when no sessions exist.
# Parses `tmux list-sessions` or `screen -ls` into machine-readable rows,
# one per active session: name, PID, state, and start time separated by tabs.
# Shared by jobrunner and its completions so both agree on what a session is
# named. Prints nothing when no sessions exist.
#
# EXIT STATUS
# 0 Parsed successfully (including the zero-session case)
# 1 screen is not installed
# 1 tool (tmux or screen) is not installed
#
# RETURNS
# One line per session: <name>\t<pid>\t<state>\t<started>
#
# EXAMPLE
# __jobrunner_sessions
# __jobrunner_sessions | string replace -r '\t.*$' ''
function __jobrunner_sessions --description 'List active screen sessions as name/pid/state/started rows'
command -q screen; or return 1
# screen -ls exits 1 when nothing is running; the parse handles that.
for line in (command screen -ls 2>/dev/null)
# Session rows are tab-indented and start with "<pid>.<name>".
set -l m (string match -r '^\s+(\d+)\.([^\t]+)\t(.*)$' -- $line)
or continue
# Trailing fields are parenthesized: "(<date>)\t(<state>)", and some
# screen builds omit the date, so read the state off the end.
set -l fields (string split \t -- $m[4])
set -l state (string trim -c '()' -- $fields[-1])
set -l started ""
if test (count $fields) -gt 1
set started (string trim -c '()' -- $fields[1])
# __jobrunner_sessions tmux | string replace -r '\t.*$' ''
function __jobrunner_sessions --description 'List active jobrunner sessions as name/pid/state/started rows'
set -l tool $argv[1]
if test -z "$tool"
if command -q tmux
set tool tmux
else if command -q screen
set tool screen
else
return 1
end
end
printf '%s\t%s\t%s\t%s\n' $m[3] $m[2] $state $started
if test "$tool" = tmux
command -q tmux; or return 1
set -l tab (printf '\t')
for line in (command tmux list-sessions -F "#{session_name}$tab#{pid}$tab#{?session_attached,Attached,Detached}$tab#{t:session_created}" 2>/dev/null)
# tmux output is natively tab-separated.
printf '%s\n' $line
end
else if test "$tool" = screen
command -q screen; or return 1
# screen -ls exits 1 when nothing is running; the parse handles that.
for line in (command screen -ls 2>/dev/null)
# Session rows are tab-indented and start with "<pid>.<name>".
set -l m (string match -r '^\s+(\d+)\.([^\t]+)\t(.*)$' -- $line)
or continue
# Trailing fields are parenthesized: "(<date>)\t(<state>)", and some
# screen builds omit the date, so read the state off the end.
set -l fields (string split \t -- $m[4])
set -l state (string trim -c '()' -- $fields[-1])
set -l started ""
if test (count $fields) -gt 1
set started (string trim -c '()' -- $fields[1])
end
printf '%s\t%s\t%s\t%s\n' $m[3] $m[2] $state $started
end
else
return 1
end
end
+150
View File
@@ -0,0 +1,150 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __rand_string [COMPONENTS/MODIFIERS]...
#
# DESCRIPTION
# Generates a random, memorable string using a sequence of specified word
# categories and formatting modifiers. Words are pulled from curated
# plain-text databases bundled in `data/words/`.
#
# Modifiers like `--separator` and `--case` are evaluated sequentially and
# apply only to the components that follow them.
#
# Supported Components:
# <category> A bundled word list (e.g. adjective, animal, color, name, noun)
# digits=<N> N random digits (e.g. digits=3 -> 842)
# literal=<text> A literal string component
#
# ARGUMENTS
# -s, --separator=<sep> Delimiter for subsequent words (dash, underscore, dot, none, or literal chars)
# -c, --case=<casing> Casing for subsequent words (lower, upper, title)
#
# EXIT STATUS
# 0 String generated successfully
# 1 Unknown category or missing word list file
#
# EXAMPLE
# __rand_string adjective animal
# __rand_string --case=title color animal --separator=dot digits=4
#
# NOTES
# Falls back to `random choice` if GNU `shuf` is missing, but `shuf` is
# much faster for files with >1000 lines.
function __rand_string --description 'Generate random, memorable strings from curated word databases'
set -l sep "dash"
set -l casing "lower"
# Locate the words directory relative to this function
set -l words_dir ""
if set -q __fish_config_dir
set words_dir "$__fish_config_dir/data/words"
else
# Fallback if __fish_config_dir isn't available
set words_dir "$HOME/.config/fish/data/words"
end
set -l result ""
set -l i 1
while test $i -le (count $argv)
set -l arg $argv[$i]
set -l handled 0
# 1. Parse inline modifiers
switch $arg
case -s --separator
set i (math $i + 1)
set sep $argv[$i]
set handled 1
case '--separator=*'
set sep (string replace -- "--separator=" "" $arg)
set handled 1
case '-s*'
set sep (string replace -r "^-s" "" $arg)
set handled 1
case -c --case
set i (math $i + 1)
set casing $argv[$i]
set handled 1
case '--case=*'
set casing (string replace -- "--case=" "" $arg)
set handled 1
case '-c*'
set casing (string replace -r "^-c" "" $arg)
set handled 1
end
if test $handled -eq 1
set i (math $i + 1)
continue
end
# 2. Resolve separator alias
set -l actual_sep $sep
switch $sep
case dash
set actual_sep "-"
case underscore
set actual_sep "_"
case dot
set actual_sep "."
case none empty
set actual_sep ""
end
# 3. Generate the component part
set -l part ""
switch $arg
case 'digits=*'
set -l n (string replace -- "digits=" "" $arg)
if not string match -qr '^\d+$' -- $n
set n 1
end
for idx in (seq $n)
set part "$part"(random 0 9)
end
case 'literal=*'
set part (string replace -- "literal=" "" $arg)
case 'string=*'
set part (string replace -- "string=" "" $arg)
case '*'
set -l db "$words_dir/$arg.txt"
if not test -f "$db"
echo "__rand_string: unknown category or file missing for '$arg'" >&2
return 1
end
# Fetch random line (shuf is fastest, random choice is portable fallback)
if command -q shuf
set part (command shuf -n 1 "$db")
else
set part (random choice (command cat "$db"))
end
end
# 4. Apply casing
switch $casing
case upper
set part (string upper $part)
case lower
set part (string lower $part)
case title
set part (string replace -r '^(.)' '\U$1' (string lower $part))
end
# 5. Append to result
if test -n "$result"
set result "$result$actual_sep$part"
else
set result "$part"
end
set i (math $i + 1)
end
if test -n "$result"
echo $result
end
end
+99 -36
View File
@@ -5,24 +5,25 @@
# 08-terminal-management
#
# DEPENDENCIES
# screen, __jobrunner_sessions
# tmux, screen, __jobrunner_sessions
#
# SYNOPSIS
# jobrunner [<subcommand>] [<name>] [<command>...]
# jr [<subcommand>] [<name>] [<command>...]
# jobrunner [-t <tool>] [<subcommand>] [<name>] [<command>...]
# jr [-t <tool>] [<subcommand>] [<name>] [<command>...]
#
# DESCRIPTION
# Runs, lists, inspects, re-attaches to, and terminates named background
# jobs using GNU screen as the process engine. Unlike bkg and detach,
# which discard output, a jobrunner job keeps a live terminal you can
# return to later — it survives closing the shell, and `attach` restores
# it in any subsequent session.
# jobs using tmux or GNU screen as the process engine. Unlike bkg and
# detach, which discard output, a jobrunner job keeps a live terminal you
# can return to later — it survives closing the shell, and `attach`
# restores it in any subsequent session.
#
# Every subcommand has a matching flag form, and the common cases are
# inferred: no arguments lists jobs, a lone name attaches to it, and a
# name followed by a command runs it.
#
# ARGUMENTS
# -t, --tool <name> Force specific backend (tmux or screen)
# run, -r, --run <name> <cmd>... Start a named job in the background
# list, -l, --list List all managed background jobs
# attach, -a, --attach <name> Re-attach interactively to a job
@@ -33,11 +34,11 @@
# EXIT STATUS
# 0 Command succeeded, or no jobs are running
# 1 Invalid arguments, or the named job does not exist
# 127 screen is not installed
# 127 neither tmux nor screen is installed
#
# EXAMPLE
# jobrunner run build make -j8
# jobrunner backup rsync -a ./data remote:/backup/
# jobrunner -t screen run backup rsync -a ./data remote:/backup/
# jobrunner list
# jobrunner logs build
# jobrunner build
@@ -48,7 +49,7 @@
# Commands are executed directly rather than through a shell, so pipes and
# redirections must be wrapped explicitly, e.g.
# `jobrunner run sync fish -c 'a | b'`.
function jobrunner --description 'Manage detached background jobs with GNU screen'
function jobrunner --description 'Manage detached background jobs with tmux or GNU screen'
set -l c_head (set_color --bold cyan)
set -l c_cmd (set_color --bold white)
set -l c_arg (set_color cyan)
@@ -61,6 +62,29 @@ function jobrunner --description 'Manage detached background jobs with GNU scree
set -l subcmds run list attach kill logs help \
-r --run -l --list -a --attach -k --kill -o --output -h --help
# ╭──────────────────────────────────────────────────────────╮
# │ Tool Extraction │
# ╰──────────────────────────────────────────────────────────╯
set -l tool ""
while test (count $argv) -gt 0
switch $argv[1]
case -t
set tool $argv[2]
set -e argv[1..2]
case --tool
set tool $argv[2]
set -e argv[1..2]
case '--tool=*'
set tool (string replace -- "--tool=" "" $argv[1])
set -e argv[1]
case '-t*'
set tool (string replace -r "^-t" "" $argv[1])
set -e argv[1]
case '*'
break
end
end
# ╭──────────────────────────────────────────────────────────╮
# │ Help │
# ╰──────────────────────────────────────────────────────────╯
@@ -68,7 +92,7 @@ function jobrunner --description 'Manage detached background jobs with GNU scree
if set -q argv[1]; and contains -- $argv[1] help -h --help
echo "$c_head""Usage:$c_rst $c_cmd""jobrunner$c_rst $c_arg""[<subcommand>] [<name>] [<command>...]$c_rst"
echo
echo " Run and manage named background jobs backed by GNU screen."
echo " Run and manage named background jobs backed by tmux or GNU screen."
echo
echo "$c_head""Subcommands:$c_rst"
echo " $c_cmd""run$c_rst $c_arg""<name> <cmd>...$c_rst Start a named job in the background"
@@ -78,6 +102,7 @@ function jobrunner --description 'Manage detached background jobs with GNU scree
echo " $c_cmd""logs$c_rst $c_arg""<name>$c_rst Print a job's output without attaching"
echo
echo "$c_head""Flags:$c_rst"
echo " $c_flag-t$c_rst, $c_flag--tool$c_rst $c_arg<name>$c_rst Force specific backend (tmux or screen)"
echo " $c_flag-r$c_rst, $c_flag--run$c_rst Same as $c_cmd""run$c_rst"
echo " $c_flag-l$c_rst, $c_flag--list$c_rst Same as $c_cmd""list$c_rst"
echo " $c_flag-a$c_rst, $c_flag--attach$c_rst Same as $c_cmd""attach$c_rst"
@@ -102,9 +127,24 @@ function jobrunner --description 'Manage detached background jobs with GNU scree
# ╭──────────────────────────────────────────────────────────╮
# │ Dependency check │
# ╰──────────────────────────────────────────────────────────╯
if not command -q screen
echo "$c_err""jobrunner:$c_rst 'screen' is required but was not found in PATH." >&2
return 127
if test -n "$tool"
if not contains -- $tool tmux screen
echo "$c_err""jobrunner:$c_rst invalid tool '$c_arg$tool$c_rst', must be 'tmux' or 'screen'." >&2
return 1
end
if not command -q $tool
echo "$c_err""jobrunner:$c_rst '$tool' is required but was not found in PATH." >&2
return 127
end
else
if command -q tmux
set tool tmux
else if command -q screen
set tool screen
else
echo "$c_err""jobrunner:$c_rst neither 'tmux' nor 'screen' was found in PATH." >&2
return 127
end
end
# ╭──────────────────────────────────────────────────────────╮
@@ -116,7 +156,7 @@ function jobrunner --description 'Manage detached background jobs with GNU scree
if not contains -- $cmd $subcmds
if test (count $argv) -eq 1
# A lone name attaches, but only if that job actually exists.
if contains -- $cmd (__jobrunner_sessions | string replace -r '\t.*$' '')
if contains -- $cmd (__jobrunner_sessions $tool | string replace -r '\t.*$' '')
set argv attach $argv
set cmd attach
else
@@ -148,19 +188,23 @@ function jobrunner --description 'Manage detached background jobs with GNU scree
echo "$c_err""jobrunner:$c_rst job name may not contain '/'." >&2
return 1
end
if contains -- $name (__jobrunner_sessions | string replace -r '\t.*$' '')
if contains -- $name (__jobrunner_sessions $tool | string replace -r '\t.*$' '')
echo "$c_err""jobrunner:$c_rst job '$c_arg$name$c_rst' is already running." >&2
return 1
end
command screen -d -m -S $name $task
if test "$tool" = tmux
command tmux new-session -d -s $name $task
else
command screen -d -m -S $name $task
end
or begin
echo "$c_err""jobrunner:$c_rst failed to start job '$c_arg$name$c_rst'." >&2
return 1
end
set -l pid
for row in (__jobrunner_sessions)
for row in (__jobrunner_sessions $tool)
set -l f (string split \t -- $row)
test "$f[1]" = "$name"; and set pid $f[2]; and break
end
@@ -173,7 +217,7 @@ function jobrunner --description 'Manage detached background jobs with GNU scree
end
case list -l --list
set -l rows (__jobrunner_sessions)
set -l rows (__jobrunner_sessions $tool)
if test (count $rows) -eq 0
echo "No background jobs running."
return 0
@@ -192,12 +236,16 @@ function jobrunner --description 'Manage detached background jobs with GNU scree
return 1
end
set -l name $argv[2]
if not contains -- $name (__jobrunner_sessions | string replace -r '\t.*$' '')
if not contains -- $name (__jobrunner_sessions $tool | string replace -r '\t.*$' '')
echo "$c_err""jobrunner:$c_rst no such job '$c_arg$name$c_rst'." >&2
return 1
end
# -x attaches to an already-attached session instead of failing.
command screen -x $name
if test "$tool" = tmux
command tmux attach-session -t $name
else
# -x attaches to an already-attached session instead of failing.
command screen -x $name
end
case kill -k --kill
if test (count $argv) -ne 2
@@ -205,11 +253,15 @@ function jobrunner --description 'Manage detached background jobs with GNU scree
return 1
end
set -l name $argv[2]
if not contains -- $name (__jobrunner_sessions | string replace -r '\t.*$' '')
if not contains -- $name (__jobrunner_sessions $tool | string replace -r '\t.*$' '')
echo "$c_err""jobrunner:$c_rst no such job '$c_arg$name$c_rst'." >&2
return 1
end
command screen -X -S $name quit
if test "$tool" = tmux
command tmux kill-session -t $name
else
command screen -X -S $name quit
end
or begin
echo "$c_err""jobrunner:$c_rst failed to terminate job '$c_arg$name$c_rst'." >&2
return 1
@@ -222,25 +274,36 @@ function jobrunner --description 'Manage detached background jobs with GNU scree
return 1
end
set -l name $argv[2]
if not contains -- $name (__jobrunner_sessions | string replace -r '\t.*$' '')
if not contains -- $name (__jobrunner_sessions $tool | string replace -r '\t.*$' '')
echo "$c_err""jobrunner:$c_rst no such job '$c_arg$name$c_rst'." >&2
return 1
end
# hardcopy -h dumps scrollback plus the visible screen to a file.
# ponytail: snapshot only; add `screen -L` logging if full
# since-start history is ever needed.
set -l dump (command mktemp)
command screen -X -S $name hardcopy -h $dump
or begin
set -l out
if test "$tool" = tmux
# capture-pane -S - -p outputs the scrollback and current pane directly to stdout.
set out (command tmux capture-pane -t $name -S - -p)
or begin
echo "$c_err""jobrunner:$c_rst could not read output of '$c_arg$name$c_rst'." >&2
return 1
end
else
# hardcopy -h dumps scrollback plus the visible screen to a file.
# ponytail: snapshot only; add `screen -L` logging if full
# since-start history is ever needed.
set -l dump (command mktemp)
command screen -X -S $name hardcopy -h $dump
or begin
command rm -f $dump
echo "$c_err""jobrunner:$c_rst could not read output of '$c_arg$name$c_rst'." >&2
return 1
end
set out (command cat $dump)
command rm -f $dump
echo "$c_err""jobrunner:$c_rst could not read output of '$c_arg$name$c_rst'." >&2
return 1
end
set -l out (command cat $dump)
command rm -f $dump
# hardcopy pads the dump out to the full window height.
# hardcopy (and sometimes tmux) pad the dump with empty lines.
while set -q out[1]; and test -z "$out[-1]"
set -e out[-1]
end
+1 -1
View File
@@ -18,7 +18,7 @@
# lstree ~/projects/myapp
function lstree --description 'Full recursive tree listing'
if which eza >/dev/null 2>&1
eza --tree --icons --color=auto --hyperlink $argv
eza --tree --icons --color=auto --hyperlink=auto $argv
else if which lsd >/dev/null 2>&1
lsd --tree --hyperlink=auto $argv
else