feat(jobrunner): add named background job manager backed by GNU screen
Adds jobrunner (short alias jr) for running, listing, inspecting, re-attaching to, and terminating detached background tasks. Unlike bkg and detach, which discard output, a jobrunner job keeps a live terminal that survives closing the shell and can be restored later with attach. Includes the __jobrunner_sessions parser shared by the function and its completions, dynamic job-name completions, and screen in the fish-deps catalog.
This commit is contained in:
@@ -30,6 +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
|
||||
- **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,57 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# Completions for the `jobrunner` background job manager.
|
||||
# `jr` inherits these via `function jr --wraps jobrunner`.
|
||||
|
||||
# Offer running jobs as name<TAB>description pairs.
|
||||
function __jobrunner_complete_jobs
|
||||
for row in (__jobrunner_sessions)
|
||||
set -l f (string split \t -- $row)
|
||||
printf '%s\t%s job (PID %s)\n' $f[1] $f[3] $f[2]
|
||||
end
|
||||
end
|
||||
|
||||
set -l subcmds run list attach kill logs help
|
||||
set -l needs_job "__fish_seen_subcommand_from attach kill logs -a --attach -k --kill -o --output"
|
||||
|
||||
# No file completions; jobs are named, not paths.
|
||||
complete -c jobrunner -f
|
||||
|
||||
# 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'
|
||||
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||
-a list -d 'List all managed background jobs'
|
||||
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||
-a attach -d 'Re-attach interactively to a job'
|
||||
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||
-a kill -d 'Terminate a running background job'
|
||||
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||
-a logs -d "Print a job's output without attaching"
|
||||
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||
-a help -d 'Show usage help'
|
||||
|
||||
# Flag forms.
|
||||
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||
-s r -l run -d 'Start a named job in the background'
|
||||
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||
-s l -l list -d 'List all managed background jobs'
|
||||
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||
-s a -l attach -d 'Re-attach interactively to a job'
|
||||
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||
-s k -l kill -d 'Terminate a running background job'
|
||||
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||
-s o -l output -d "Print a job's output without attaching"
|
||||
complete -c jobrunner -s h -l help -d 'Show usage help'
|
||||
|
||||
# Running jobs, for the subcommands that take one.
|
||||
complete -c jobrunner -n "$needs_job" -a '(__jobrunner_complete_jobs)'
|
||||
|
||||
# A bare job name attaches to it, so offer jobs in first position too.
|
||||
complete -c jobrunner -n "not __fish_seen_subcommand_from $subcmds" \
|
||||
-a '(__jobrunner_complete_jobs)'
|
||||
|
||||
# After `run <name>`, complete the command to execute.
|
||||
complete -c jobrunner -n "__fish_seen_subcommand_from run -r --run; and test (count (commandline -opc)) -ge 3" \
|
||||
-a '(__fish_complete_subcommand)'
|
||||
@@ -125,6 +125,8 @@ split=### split
|
||||
spwin=### spwin
|
||||
detach=### detach
|
||||
bkg=### bkg
|
||||
jobrunner=### jobrunner
|
||||
jr=### jr
|
||||
ssh=### ssh
|
||||
clipboard=## 5.9 Clipboard
|
||||
copy-fn=### y
|
||||
|
||||
@@ -1482,6 +1482,71 @@ Add -i (interactive confirmation) to destructive commands:
|
||||
Example:
|
||||
# Rendered automatically by fish; not called directly.
|
||||
|
||||
### jobrunner
|
||||
|
||||
Synopsis: jobrunner [<subcommand>] [<name>] [<command>...]
|
||||
jr [<subcommand>] [<name>] [<command>...]
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
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
|
||||
kill, -k, --kill <name> Terminate a running background job
|
||||
logs, -o, --output <name> Print a job's current output, no attach
|
||||
help, -h, --help Show usage help
|
||||
|
||||
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
|
||||
|
||||
Notes:
|
||||
Detach from an attached job with Ctrl-A then D; the job keeps running.
|
||||
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'`.
|
||||
|
||||
Example:
|
||||
jobrunner run build make -j8
|
||||
jobrunner backup rsync -a ./data remote:/backup/
|
||||
jobrunner list
|
||||
jobrunner logs build
|
||||
jobrunner build
|
||||
jobrunner kill build
|
||||
|
||||
**Dependencies:** `screen`, `__jobrunner_sessions`
|
||||
|
||||
**Used by:** `jr`
|
||||
|
||||
### jr
|
||||
|
||||
Synopsis: jr [<subcommand>] [<name>] [<command>...]
|
||||
|
||||
Shorthand for jobrunner. Accepts the same subcommands, flags, and
|
||||
shorthands, and inherits its completions.
|
||||
|
||||
Arguments:
|
||||
See jobrunner --help for the full argument reference.
|
||||
|
||||
Exit Status:
|
||||
Same as jobrunner.
|
||||
|
||||
Example:
|
||||
jr run build make -j8
|
||||
jr list
|
||||
|
||||
**Dependencies:** `jobrunner`
|
||||
|
||||
### split
|
||||
|
||||
Synopsis: split [-h | -v] [command...]
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# SYNOPSIS
|
||||
# __jobrunner_sessions
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# EXIT STATUS
|
||||
# 0 Parsed successfully (including the zero-session case)
|
||||
# 1 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])
|
||||
end
|
||||
|
||||
printf '%s\t%s\t%s\t%s\n' $m[3] $m[2] $state $started
|
||||
end
|
||||
end
|
||||
@@ -16,27 +16,27 @@ function _fish_deps_catalog
|
||||
set -g _fdc_bins \
|
||||
uv cargo fish starship fzf zoxide direnv paru yay \
|
||||
wakatime tailscale \
|
||||
eza lsd bat btop dust duf prettyping ov rg lazygit lazydocker trash kitty wezterm python3 yt-dlp
|
||||
eza lsd bat btop dust duf prettyping ov rg lazygit lazydocker trash kitty wezterm python3 yt-dlp screen
|
||||
|
||||
set -g _fdc_tiers \
|
||||
rec rec req rec req rec rec rec rec \
|
||||
int int \
|
||||
rec rec rec rec rec rec rec rec rec rec rec rec rec rec rec rec
|
||||
rec rec rec rec rec rec rec rec rec rec rec rec rec rec rec rec rec
|
||||
|
||||
set -g _fdc_cargo \
|
||||
"" "" "" starship "" zoxide "" "" "" \
|
||||
"" "" \
|
||||
eza lsd bat "" du-dust "" "" ov ripgrep "" "" trashy "" "" "" ""
|
||||
eza lsd bat "" du-dust "" "" ov ripgrep "" "" trashy "" "" "" "" ""
|
||||
|
||||
set -g _fdc_pm \
|
||||
uv cargo fish starship fzf zoxide direnv "" yay \
|
||||
wakatime tailscale \
|
||||
eza lsd bat btop dust duf prettyping ov ripgrep lazygit lazydocker trash kitty wezterm python yt-dlp
|
||||
eza lsd bat btop dust duf prettyping ov ripgrep lazygit lazydocker trash kitty wezterm python yt-dlp screen
|
||||
|
||||
set -g _fdc_special \
|
||||
curl-uv rustup-installer git-cargo-fish curl-installer fzf-update "" "" paru-build yay-build \
|
||||
wakatime-binary "" \
|
||||
"" "" "" "" "" "" "" "" "" "" curl-lazydocker "" "" "" "" ""
|
||||
"" "" "" "" "" "" "" "" "" "" curl-lazydocker "" "" "" "" "" ""
|
||||
end
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CATEGORY
|
||||
# 08-terminal-management
|
||||
#
|
||||
# DEPENDENCIES
|
||||
# screen, __jobrunner_sessions
|
||||
#
|
||||
# SYNOPSIS
|
||||
# jobrunner [<subcommand>] [<name>] [<command>...]
|
||||
# jr [<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.
|
||||
#
|
||||
# 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
|
||||
# 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
|
||||
# kill, -k, --kill <name> Terminate a running background job
|
||||
# logs, -o, --output <name> Print a job's current output, no attach
|
||||
# help, -h, --help Show usage help
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# EXAMPLE
|
||||
# jobrunner run build make -j8
|
||||
# jobrunner backup rsync -a ./data remote:/backup/
|
||||
# jobrunner list
|
||||
# jobrunner logs build
|
||||
# jobrunner build
|
||||
# jobrunner kill build
|
||||
#
|
||||
# NOTES
|
||||
# Detach from an attached job with Ctrl-A then D; the job keeps running.
|
||||
# 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'
|
||||
set -l c_head (set_color --bold cyan)
|
||||
set -l c_cmd (set_color --bold white)
|
||||
set -l c_arg (set_color cyan)
|
||||
set -l c_flag (set_color yellow)
|
||||
set -l c_ok (set_color green)
|
||||
set -l c_err (set_color red)
|
||||
set -l c_dim (set_color brblack)
|
||||
set -l c_rst (set_color normal)
|
||||
|
||||
set -l subcmds run list attach kill logs help \
|
||||
-r --run -l --list -a --attach -k --kill -o --output -h --help
|
||||
|
||||
# ╭──────────────────────────────────────────────────────────╮
|
||||
# │ Help │
|
||||
# ╰──────────────────────────────────────────────────────────╯
|
||||
# Answered before the dependency check so usage is readable anywhere.
|
||||
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
|
||||
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"
|
||||
echo " $c_cmd""list$c_rst List all managed background jobs"
|
||||
echo " $c_cmd""attach$c_rst $c_arg""<name>$c_rst Re-attach interactively to a job"
|
||||
echo " $c_cmd""kill$c_rst $c_arg""<name>$c_rst Terminate a running background job"
|
||||
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-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"
|
||||
echo " $c_flag-k$c_rst, $c_flag--kill$c_rst Same as $c_cmd""kill$c_rst"
|
||||
echo " $c_flag-o$c_rst, $c_flag--output$c_rst Same as $c_cmd""logs$c_rst"
|
||||
echo " $c_flag-h$c_rst, $c_flag--help$c_rst Show this help message"
|
||||
echo
|
||||
echo "$c_head""Shorthands:$c_rst"
|
||||
echo " $c_cmd""jobrunner$c_rst $c_dim""list$c_rst"
|
||||
echo " $c_cmd""jobrunner$c_rst $c_arg""<name>$c_rst $c_dim""attach <name>$c_rst"
|
||||
echo " $c_cmd""jobrunner$c_rst $c_arg""<name> <cmd>...$c_rst $c_dim""run <name> <cmd>...$c_rst"
|
||||
echo
|
||||
echo "$c_head""Examples:$c_rst"
|
||||
echo " $c_cmd""jobrunner$c_rst $c_arg""run build$c_rst""$c_dim"" make -j8$c_rst"
|
||||
echo " $c_cmd""jobrunner$c_rst $c_arg""logs build$c_rst"
|
||||
echo " $c_cmd""jobrunner$c_rst $c_arg""kill build$c_rst"
|
||||
echo
|
||||
echo "$c_dim""Detach from an attached job with Ctrl-A then D.$c_rst"
|
||||
return 0
|
||||
end
|
||||
|
||||
# ╭──────────────────────────────────────────────────────────╮
|
||||
# │ 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
|
||||
end
|
||||
|
||||
# ╭──────────────────────────────────────────────────────────╮
|
||||
# │ Argument pre-processing │
|
||||
# ╰──────────────────────────────────────────────────────────╯
|
||||
set -q argv[1]; or set argv list
|
||||
set -l cmd $argv[1]
|
||||
|
||||
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.*$' '')
|
||||
set argv attach $argv
|
||||
set cmd attach
|
||||
else
|
||||
echo "$c_err""jobrunner:$c_rst unknown subcommand or job '$c_arg$cmd$c_rst'." >&2
|
||||
echo "Run $c_cmd""jobrunner --help$c_rst for usage." >&2
|
||||
return 1
|
||||
end
|
||||
else
|
||||
# A name plus a command line is an implicit run.
|
||||
set argv run $argv
|
||||
set cmd run
|
||||
end
|
||||
end
|
||||
|
||||
# ╭──────────────────────────────────────────────────────────╮
|
||||
# │ Dispatch │
|
||||
# ╰──────────────────────────────────────────────────────────╯
|
||||
switch $cmd
|
||||
case run -r --run
|
||||
if test (count $argv) -lt 3
|
||||
echo "$c_head""Usage:$c_rst $c_cmd""jobrunner run$c_rst $c_arg""<name> <command>...$c_rst" >&2
|
||||
return 1
|
||||
end
|
||||
set -l name $argv[2]
|
||||
set -l task $argv[3..-1]
|
||||
|
||||
# screen stores each session as a socket file named after it.
|
||||
if string match -q '*/*' -- $name
|
||||
echo "$c_err""jobrunner:$c_rst job name may not contain '/'." >&2
|
||||
return 1
|
||||
end
|
||||
if contains -- $name (__jobrunner_sessions | 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
|
||||
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)
|
||||
set -l f (string split \t -- $row)
|
||||
test "$f[1]" = "$name"; and set pid $f[2]; and break
|
||||
end
|
||||
|
||||
if set -q pid[1]
|
||||
echo "$c_ok""✔$c_rst Started job $c_arg$name$c_rst $c_dim(PID $pid)$c_rst"
|
||||
else
|
||||
# The job may have finished (or failed) before we looked.
|
||||
echo "$c_ok""✔$c_rst Started job $c_arg$name$c_rst $c_dim(already exited)$c_rst"
|
||||
end
|
||||
|
||||
case list -l --list
|
||||
set -l rows (__jobrunner_sessions)
|
||||
if test (count $rows) -eq 0
|
||||
echo "No background jobs running."
|
||||
return 0
|
||||
end
|
||||
|
||||
printf '%s%-20s %-8s %-10s %s%s\n' "$c_head" JOB PID STATE STARTED "$c_rst"
|
||||
for row in $rows
|
||||
set -l f (string split \t -- $row)
|
||||
printf '%s%-20s%s %-8s %-10s %s%s%s\n' \
|
||||
"$c_arg" $f[1] "$c_rst" $f[2] $f[3] "$c_dim" $f[4] "$c_rst"
|
||||
end
|
||||
|
||||
case attach -a --attach
|
||||
if test (count $argv) -ne 2
|
||||
echo "$c_head""Usage:$c_rst $c_cmd""jobrunner attach$c_rst $c_arg""<name>$c_rst" >&2
|
||||
return 1
|
||||
end
|
||||
set -l name $argv[2]
|
||||
if not contains -- $name (__jobrunner_sessions | 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
|
||||
|
||||
case kill -k --kill
|
||||
if test (count $argv) -ne 2
|
||||
echo "$c_head""Usage:$c_rst $c_cmd""jobrunner kill$c_rst $c_arg""<name>$c_rst" >&2
|
||||
return 1
|
||||
end
|
||||
set -l name $argv[2]
|
||||
if not contains -- $name (__jobrunner_sessions | 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
|
||||
or begin
|
||||
echo "$c_err""jobrunner:$c_rst failed to terminate job '$c_arg$name$c_rst'." >&2
|
||||
return 1
|
||||
end
|
||||
echo "$c_ok""✔$c_rst Terminated job $c_arg$name$c_rst"
|
||||
|
||||
case logs -o --output
|
||||
if test (count $argv) -ne 2
|
||||
echo "$c_head""Usage:$c_rst $c_cmd""jobrunner logs$c_rst $c_arg""<name>$c_rst" >&2
|
||||
return 1
|
||||
end
|
||||
set -l name $argv[2]
|
||||
if not contains -- $name (__jobrunner_sessions | 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
|
||||
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.
|
||||
while set -q out[1]; and test -z "$out[-1]"
|
||||
set -e out[-1]
|
||||
end
|
||||
if set -q out[1]
|
||||
printf '%s\n' $out
|
||||
else
|
||||
echo "$c_dim(no output yet)$c_rst"
|
||||
end
|
||||
|
||||
case '*'
|
||||
echo "$c_err""jobrunner:$c_rst invalid subcommand '$c_arg$cmd$c_rst'." >&2
|
||||
echo "Run $c_cmd""jobrunner --help$c_rst for usage." >&2
|
||||
return 1
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,28 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CATEGORY
|
||||
# 08-terminal-management
|
||||
#
|
||||
# DEPENDENCIES
|
||||
# jobrunner
|
||||
#
|
||||
# SYNOPSIS
|
||||
# jr [<subcommand>] [<name>] [<command>...]
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Shorthand for jobrunner. Accepts the same subcommands, flags, and
|
||||
# shorthands, and inherits its completions.
|
||||
#
|
||||
# ARGUMENTS
|
||||
# See jobrunner --help for the full argument reference.
|
||||
#
|
||||
# EXIT STATUS
|
||||
# Same as jobrunner.
|
||||
#
|
||||
# EXAMPLE
|
||||
# jr run build make -j8
|
||||
# jr list
|
||||
function jr --wraps jobrunner --description 'Shorthand for jobrunner'
|
||||
jobrunner $argv
|
||||
end
|
||||
Reference in New Issue
Block a user