feat: implement __rand_string generator and update jobrunner to use tmux
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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'
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user