Add overlay for tasks

main
Julius Riegel 8 months ago
parent b49a7b7c5e
commit 39635bfef8

@ -16,19 +16,4 @@ alias `shx` = sudo -E helix -c '{{dirs.config}}/helix/config.toml'
alias devshell = nix develop -c $env.SHELL alias devshell = nix develop -c $env.SHELL
{{/if-installed}} {{/if-installed}}
{{#if-installed git}}
alias gc = git commit
alias gp = git push
alias ga = git add
alias ga. = git add .
alias gu = git pull
def `git yeet` [] {
git add .
git commit -m (http get https://whatthecommit.com/index.txt)
git push
}
alias gy = git yeet
{{/if-installed}}
def --env `silo cd` [] { silo repo | cd $in } def --env `silo cd` [] { silo repo | cd $in }

@ -454,3 +454,11 @@ source {{dirs.config}}/broot/launcher/nushell/br
{{#if-installed zoxide}} {{#if-installed zoxide}}
source ~/.zoxide.nu source ~/.zoxide.nu
{{/if-installed}} {{/if-installed}}
{{#if-installed pueued}}
use task.nu
{{/if-installed}}
{{#if-installed git}}
source git.nu
{{/if-installed}}

@ -0,0 +1,127 @@
export def get-sign [cmd] {
let x = (scope commands | where name == $cmd).signatures?.0?.any?
mut s = []
mut n = {}
mut p = []
mut pr = []
mut r = []
for it in $x {
if $it.parameter_type == 'switch' {
if ($it.short_flag | is-not-empty) {
$s ++= $it.short_flag
}
if ($it.parameter_name | is-not-empty) {
$s ++= $it.parameter_name
}
} else if $it.parameter_type == 'named' {
if ($it.parameter_name | is-empty) {
$n = ($n | upsert $it.short_flag $it.short_flag)
} else if ($it.short_flag | is-empty) {
$n = ($n | upsert $it.parameter_name $it.parameter_name)
} else {
$n = ($n | upsert $it.short_flag $it.parameter_name)
}
} else if $it.parameter_type == 'positional' {
if $it.is_optional == false {
$p ++= $it.parameter_name
} else {
$pr ++= $it.parameter_name
}
} else if $it.parameter_type == 'rest' {
$r ++= $it.parameter_name
}
}
{ switch: $s, name: $n, positional: ($p ++ $pr), rest: $r }
}
# "test -h [123 (3213 3)] 123 `a sdf` --cd --ef sadf -g" | token
export def token [] {
let s = ($in | split row '' | range 1..-2)
let s = if ($s | last) == ' ' { $s } else { $s | append ' ' }
mut par = []
mut res = []
mut cur = ''
mut esc = false
for c in $s {
if $c == '\' {
$esc = true
} else {
if $esc {
$cur ++= $c
$esc = false
} else {
if $c == ' ' and ($par | length) == 0 {
$res ++= [$cur]
$cur = ''
} else {
if $c in ['{' '[' '('] {
$par ++= $c
}
if $c in ['}' ']' ')'] {
$par = ($par | range ..-2)
}
if $c in ['"' "'" '`'] {
if ($par | length) > 0 and ($par | last) == $c {
$par = ($par | range ..-2)
} else {
$par ++= $c
}
}
$cur ++= $c
}
}
}
}
return $res
}
export def parse [] {
let token = ($in | token)
let sign = (get-sign $token.0)
mut sw = ''
mut pos = []
mut opt = {}
for c in $token {
if ($sw | is-empty) {
if ($c | str starts-with '-') {
let c = if ($c | str substring 1..2) != '-' {
let k = ($c | str substring 1..)
if $k in $sign.name {
$'($sign.name | get $k)'
} else {
$k
}
} else {
$c | str substring 2..
}
if $c in $sign.switch {
$opt = ($opt | upsert $c true)
} else {
$sw = $c
}
} else {
$pos ++= [$c]
}
} else {
$opt = ($opt | upsert $sw $c)
$sw = ''
}
}
$opt._args = $pos
let p = $pos | range 1..($sign.positional | length)
let rest = $pos | range (($sign.positional | length) + 1)..-1
$opt._pos = ( $p | enumerate
| reduce -f {} {|it, acc|
$acc | upsert ($sign.positional | get $it.index) $it.item
} )
if ($sign.rest | length) > 0 {
$opt._pos = ($opt._pos | upsert $sign.rest.0 $rest)
}
$opt
}
# def test [a b x? ...y --cd(-c) --ef(-e):string -g -h:int --ij --lm:bool] {}
# (scope commands | where name == test).signatures?.0?.any?
# get-sign test | to yaml
# "test -h 111 123 'asdf' --cd --ef sadf -g -h 222" | cmd parse | to yaml

@ -0,0 +1,697 @@
use argx.nu
def agree [
prompt
--default-not (-n)
] {
let prompt = if ($prompt | str ends-with '!') {
$'(ansi red)($prompt)(ansi reset)'
} else {
$'($prompt)'
}
(if $default_not { [no yes] } else { [yes no] } | input list $prompt) == 'yes'
}
def tips [ msg ] {
print -e $"(ansi light_gray)($msg)(ansi reset)"
}
def --wrapped with-flag [...flag] {
if ($in | is-empty) { [] } else { [...$flag $in] }
}
export def `git yeet` [] {
git add .
git commit -m (http get https://whatthecommit.com/index.txt)
git push
}
export alias gy = git yeet
# git status
export def gs [] {
git status
}
# git stash
export def gst [
--apply (-a)
--clear (-c)
--drop (-d)
--list (-l)
--pop (-p)
--show (-s)
--all (-A)
--include-untracked (-i)
] {
if $apply {
git stash apply
} else if $clear {
git stash clear
} else if $drop {
git stash drop
} else if $list {
git stash list
} else if $pop {
git stash pop
} else if $show {
git stash show --text
} else if $all {
git stash --all ...(if $include_untracked {[--include-untracked]} else {[]})
} else {
git stash
}
}
# git log
export def gl [
commit?: string@"nu-complete git log"
--verbose(-v)
--num(-n):int=32
] {
if ($commit|is-empty) {
_git_log $verbose $num
} else {
git log --stat -p -n 1 $commit
}
}
# git branch
export def gb [
branch?: string@"nu-complete git branches"
--remote (-r)='origin': string@"nu-complete git remotes"
--delete (-d)
--no-merged (-n)
] {
let bs = git branch | lines | each {|x| $x | str substring 2..}
if $delete {
let remote_branches = (remote_branches)
if ($branch | is-empty) {
let dels = if $no_merged { gb } else {
gb
| where { $in.merged | is-not-empty }
}
| where { ($in.remote | is-empty) and ($in.current | is-empty) }
| each {|x|
let pf = if ($x.current | is-empty) { " " } else { $"(ansi cyan)* " }
let nm = if ($x.merged | is-not-empty ) { $"(ansi green)☑ " } else { " " }
$x | insert display $"($nm)($pf)(ansi reset)($x.branch)"
}
if ($dels | is-empty) {
tips "no branches to delete"
return
}
let $dels = $dels
| input list -d display --multi
| get branch
for b in $dels {
tips $"delete (ansi yellow)($b)"
git branch -D $b
}
if ($dels | is-not-empty) and (agree 'delete remote branch?!') {
for b in ($dels | filter { $"($remote)/($in)" in $remote_branches }) {
tips $"delete (ansi yellow)($remote)/($b)"
git branch -D -r $'($remote)/($b)'
git push $remote -d $b
}
}
} else {
if $branch in $bs and (agree 'branch will be delete!') {
git branch -D $branch
}
if $"($remote)/($branch)" in $remote_branches and (agree 'delete remote branch?!') {
git branch -D -r $'($remote)/($branch)'
git push $remote -d $branch
}
}
} else if ($branch | is-empty) {
let merged = git branch --merged
| lines
| each { $in | parse -r '\s*\*?\s*(?<b>[^\s]+)' | get 0.b }
{
local: (git branch)
remote: (git branch --remote)
}
| transpose k v
| each {|x|
$x.v | lines
| each {|n|
let n = $n | parse -r '\s*(?<c>\*)?\s*(?<b>[^\s]+)( -> )?(?<r>[^\s]+)?' | get 0
let c = if ($n.c | is-empty) { null } else { true }
let r = if ($n.r | is-empty) { null } else { $n.r }
let m = if $n.b in $merged { true } else { null }
let rm = if $x.k == 'remote' { true } else { null }
{ current: $c, remote: $rm, branch: $n.b, ref: $r, merged: $m }
}
}
| flatten
} else if $branch in $bs {
git checkout $branch
} else {
if (agree 'create new branch?') {
git checkout -b $branch
}
}
}
# git clone, init
export def --env gn [
repo?: string@"nu-complete git branches"
local?: path
--submodule (-s) # git submodule
--init (-i) # git init
] {
if $init {
if ($repo | is-empty) {
git init --initial-branch main
} else {
git init $repo --initial-branch main
cd $repo
}
if $submodule {
git submodule init
}
} else {
let local = if ($local | is-empty) {
$repo | path basename | split row '.' | get 0
} else {
$local
}
git clone ...(if $submodule {[--recurse-submodules]} else {[]}) $repo $local
cd $local
}
}
# edit .gitignore
export def gig [--empty-dir] {
if $empty_dir {
[
'# Ignore everything in this directory'
'*'
'# Except this file'
'!.gitignore'
] | str join (char newline) | save .gitignore
} else {
^$env.EDITOR $"(git rev-parse --show-toplevel)/.gitignore"
}
}
# git pull, push and switch
export def gp [
branch?: string@"nu-complete git branches"
--remote (-r)='origin': string@"nu-complete git remotes"
--force (-f) # git push -f
--override
--submodule (-s) # git submodule
--init (-i) # git init
--merge (-m) # git pull (no)--rebase
--autostash (-a) # git pull --autostash
--back-to-prev (-b) # back to branch
] {
if $submodule {
git submodule update
} else if $override {
git pull --rebase
git add --all
git commit -v -a --no-edit --amend
git push --force
} else {
let m = if $merge { [] } else { [--rebase] }
let a = if $autostash {[--autostash]} else {[]}
let branch = if ($branch | is-empty) { (_git_status).branch } else { $branch }
let branch_repr = $'(ansi yellow)($branch)(ansi light_gray)'
let lbs = git branch | lines | each { $in | str substring 2..}
let rbs = (remote_branches)
let prev = (_git_status).branch
if $"($remote)/($branch)" in $rbs {
if $branch in $lbs {
let bmsg = $'both local and remote have ($branch_repr) branch'
if $force {
tips $'($bmsg), with `--force`, push'
git branch -u $'($remote)/($branch)' $branch
git push --force
} else {
tips $'($bmsg), pull'
if $prev != $branch {
tips $'switch to ($branch_repr)'
git checkout $branch
}
git pull ...$m ...$a
}
} else {
tips $"local doesn't have ($branch_repr) branch, fetch"
git checkout -b $branch
git fetch $remote $branch
git branch -u $'($remote)/($branch)' $branch
git pull ...$m ...$a -v
}
} else {
let bmsg = $"remote doesn't have ($branch_repr) branch"
let force = if $force {[--force]} else {[]}
if $branch in $lbs {
tips $'($bmsg), set upstream and push'
git checkout $branch
} else {
tips $'($bmsg), create and push'
git checkout -b $branch
}
git push ...$force --set-upstream $remote $branch
}
if $back_to_prev {
git checkout $prev
}
let s = (_git_status)
if $s.ahead > 0 {
tips 'remote is behind, push'
git push
}
}
}
# git add, rm and restore
export def ga [
file?: path
--all (-A)
--patch (-p)
--update (-u)
--verbose (-v)
--delete (-d) # git rm
--cached (-c)
--force (-f)
--restore (-r) # git restore
--staged (-s)
--source (-o): string
] {
if $delete {
let c = if $cached {[--cached]} else {[]}
let f = if $force {[--force]} else {[]}
git rm ...$c ...$f -r $file
} else if $restore {
let o = $source | with-flag --source
let s = if $staged {[--staged]} else {[]}
let file = if ($file | is-empty) { [.] } else { [$file] }
git restore ...$o ...$s ...$file
} else {
let a = if $all {[--all]} else {[]}
let p = if $patch {[--patch]} else {[]}
let u = if $update {[--update]} else {[]}
let v = if $verbose {[--verbose]} else {[]}
let f = if $force {[--force]} else {[]}
let file = if ($file | is-empty) { [.] } else { [$file] }
git add ...([$a $p $u $v $f $file] | flatten)
}
}
# git commit
export def gc [
message?: string
--all (-A)
--amend (-a)
--keep (-k)
] {
let m = $message | with-flag -m
let a = if $all {[--all]} else {[]}
let n = if $amend {[--amend]} else {[]}
let k = if $keep {[--no-edit]} else {[]}
git commit -v ...$m ...$a ...$n ...$k
}
# git diff
export def gd [
file?: path
--cached (-c) # cached
--word-diff (-w) # word-diff
--staged (-s) # staged
] {
let w = if $word_diff {[--word-diff]} else {[]}
let c = if $cached {[--cached]} else {[]}
let s = if $staged {[--staged]} else {[]}
git diff ...$c ...$s ...$w ...($file | with-flag)
}
# git merge
export def gm [
branch?: string@"nu-complete git branches"
--abort (-a)
--continue (-c)
--quit (-q)
--no-squash (-n) # git merge (no)--squash
] {
let x = if $no_squash { [] } else { [--squash] }
if ($branch | is-empty) {
git merge ...$x $"origin/(git_main_branch)"
} else {
git merge ...$x $branch
}
if not $no_squash {
git commit -v
}
}
# git rebase
# TODO: --onto: (commit_id)
export def gr [
branch?: string@"nu-complete git branches"
--interactive (-i)
--onto (-o): string
--abort (-a)
--continue (-c)
--skip (-s)
--quit (-q)
] {
if $abort {
git rebase --abort
} else if $continue {
git rebase --continue
} else if $skip {
git rebase --skip
} else if $quit {
git rebase --quit
} else if ($onto | is-not-empty) {
git rebase --onto $branch
} else {
let i = if $interactive {[--interactive]} else {[]}
if ($branch | is-empty) {
git rebase ...$i (git_main_branch)
} else {
git rebase ...$i $branch
}
}
}
# git cherry-pick
export def gcp [
commit?: string@"nu-complete git log all"
--abort (-a)
--continue (-c)
--skip (-s)
--quit (-q)
] {
if $abort {
git cherry-pick --abort
} else if $continue {
git cherry-pick --continue
} else if $skip {
git cherry-pick --skip
} else if $quit {
git cherry-pick --quit
} else {
git cherry-pick $commit
}
}
# copy file from other branch
export def gcf [
branch: string@"nu-complete git branches"
...file: string@"nu-complete git branch files"
] {
^git checkout $branch $file
}
# git reset
export def grs [
commit?: string@"nu-complete git log"
--hard (-h)
--clean (-c)
] {
let h = if $hard {[--hard]} else {[]}
let cm = $commit | with-flag
git reset ...$h ...$cm
if $clean {
git clean -fd
}
}
# git remote
export def grm [
remote?: string@"nu-complete git remotes"
uri?: string
--add (-a)
--rename (-r)
--delete (-d)
--update (-u)
--set (-s)
] {
if ($remote | is-empty) {
git remote -v
} else if $add {
git remote add $remote $uri
} else if $set {
git remote set-url $remote $uri
} else if $rename {
let old = $remote
let new = $uri
git remote rename $old $new
} else if $delete {
git remote remove $remote
} else if $update {
git remote update $remote
} else {
git remote show $remote
}
}
# git bisect
export def gbs [
--bad (-b)
--good (-g)
--reset (-r)
--start (-s)
] {
if $good {
git bisect good
} else if $bad {
git bisect bad
} else if $reset {
git bisect reset
} else if $start {
git bisect start
} else {
git bisect
}
}
export def gha [] {
git log --pretty=%h»¦«%aN»¦«%s»¦«%aD
| lines
| split column "»¦«" sha1 committer desc merged_at
| histogram committer merger
| sort-by merger
| reverse
}
export def ggc [] {
git reflog expire --all --expire=now
git gc --prune=now --aggressive
}
export alias gcl = git config --list
export alias gsw = git switch
export alias gswc = git switch -c
export alias gts = git tag -s
export def _git_status [] {
# TODO: show-stash
let raw_status = do -i { git --no-optional-locks status --porcelain=2 --branch | lines }
let stashes = do -i { git stash list | lines | length }
mut status = {
idx_added_staged : 0
idx_modified_staged : 0
idx_deleted_staged : 0
idx_renamed : 0
idx_type_changed : 0
wt_untracked : 0
wt_modified : 0
wt_deleted : 0
wt_type_changed : 0
wt_renamed : 0
ignored : 0
conflicts : 0
ahead : 0
behind : 0
stashes : $stashes
repo_name : no_repository
tag : no_tag
branch : no_branch
remote : ''
}
if ($raw_status | is-empty) { return $status }
for s in $raw_status {
let r = $s | split row ' '
match $r.0 {
'#' => {
match ($r.1 | str substring 7..) {
'oid' => {
$status.commit_hash = ($r.2 | str substring 0..8)
}
'head' => {
$status.branch = $r.2
}
'upstream' => {
$status.remote = $r.2
}
'ab' => {
$status.ahead = ($r.2 | into int)
$status.behind = ($r.3 | into int | math abs)
}
}
}
'1'|'2' => {
match ($r.1 | str substring 0..1) {
'A' => {
$status.idx_added_staged += 1
}
'M' => {
$status.idx_modified_staged += 1
}
'R' => {
$status.idx_renamed += 1
}
'D' => {
$status.idx_deleted_staged += 1
}
'T' => {
$status.idx_type_changed += 1
}
}
match ($r.1 | str substring 1..2) {
'M' => {
$status.wt_modified += 1
}
'R' => {
$status.wt_renamed += 1
}
'D' => {
$status.wt_deleted += 1
}
'T' => {
$status.wt_type_changed += 1
}
}
}
'?' => {
$status.wt_untracked += 1
}
'u' => {
$status.conflicts += 1
}
}
}
$status
}
export def _git_log_stat [n] {
do -i {
git log --reverse -n $n --pretty=»¦«%h --stat
| lines
| reduce -f { c: '', r: [] } {|it, acc|
if ($it | str starts-with '»¦«') {
$acc | upsert c ($it | str substring 6.. )
} else if ($it | find -r '[0-9]+ file.+change' | is-empty) {
$acc
} else {
let x = $it
| split row ','
| each {|x| $x
| str trim
| parse -r "(?<num>[0-9]+) (?<col>.+)"
| get 0
}
| reduce -f {sha: $acc.c file:0 ins:0 del:0} {|i,a|
let col = if ($i.col | str starts-with 'file') {
'file'
} else {
$i.col | str substring ..3
}
let num = $i.num | into int
$a | upsert $col $num
}
$acc | upsert r ($acc.r | append $x)
}
}
| get r
}
}
export def _git_log [verbose num] {
let r = do -i {
git log --reverse -n $num --pretty=%h»¦«%s»¦«%aN»¦«%aE»¦«%aD»¦«%D
| lines
| split column "»¦«" sha message author email date refs
| each {|x|
let refs = if ($x.refs | is-empty) {
$x.refs
} else {
$x.refs | split row ", "
}
$x
| update date { $x.date | into datetime }
| update refs $refs
}
}
if $verbose {
$r | merge ( _git_log_stat $num )
} else {
$r
}
}
def "nu-complete git log" [] {
git log -n 32 --pretty=%h»¦«%s
| lines
| split column "»¦«" value description
| each {|x| $x | update value $"($x.value)"}
}
def "nu-complete git log all" [] {
git log --all -n 32 --pretty=%h»¦«%d»¦«%s
| lines
| split column "»¦«" value branch description
| each {|x| $x | update description $"($x.branch) ($x.description)" }
}
def "nu-complete git branch files" [context: string, offset:int] {
let token = $context | split row ' '
let branch = $token | get 1
let files = $token | skip 2
git ls-tree -r --name-only $branch
| lines
| filter {|x| not ($x in $files)}
}
def "nu-complete git branches" [] {
git branch
| lines
| filter {|x| not ($x | str starts-with '*')}
| each {|x| $"($x|str trim)"}
}
export def remote_branches [] {
git branch -r
| lines
| str trim
| filter {|x| not ($x | str starts-with 'origin/HEAD') }
}
def "nu-complete git remotes" [] {
^git remote | lines | each { |line| $line | str trim }
}
def git_main_branch [] {
git remote show origin
| lines
| str trim
| find --regex 'HEAD .*?[: ].+'
| first
| str replace --regex 'HEAD .*?[: ](.+)' '$1'
}

@ -0,0 +1,434 @@
# Spawn a task to run in the background, even when the shell is closed.
#
# Note that a fresh Nushell interpreter is spawned to execute the
# given task, so it won't inherit the current scope's variables,
# custom commands and alias definitions.
#
# It will only inherit environment variables which can be converted to a string.
#
# Note that the closure can't take arguments.
#
# Example usage: task spawn { echo "Hello, World!" }
export def spawn [
command: closure # The closure to run.
--working-directory (-w): directory # Specify the working directory the task will be run in.
--immediate (-i) # Immediately start the task.
--stashed (-s) # Create the task in Stashed state. Useful to avoid immediate execution if the queue is empty
--delay (-d): duration # Queue the task for execution only after the duration.
--group (-g): string # The group to spawn the task under.
--after (-a): int # Start the task once all specified tasks have successfully finished. As soon as one of the dependencies fails, this task will fail as well.
--priority (-o): string # Start this task with a higher priority. The higher the number, the faster it will be processed.
--label (-l): string # Label the task. This string will be shown in the `status` column of `task status`.
] -> int {
mut args = []
if $working_directory != null {
$args = ($args | prepend ["--working-directory", $working_directory])
}
if $immediate {
$args = ($args | prepend "--immediate")
}
if $stashed {
$args = ($args | prepend "--stashed")
}
if $delay != null {
$args = ($args | prepend ["--delay" ($delay | format duration sec | parse "{secs} {_}" | get 0.secs)])
}
if $group != null {
$args = ($args | prepend ["--group" $group])
}
if $after != null {
$args = ($args | prepend ["--after" $after])
}
if $priority != null {
$args = ($args | prepend ["--priority" $priority])
}
if $label != null {
$args = ($args | prepend ["--label" $label])
}
let source_path = mktemp --tmpdir --suffix "-nu-task"
(
view source $command
| str trim --left --char "{"
| str trim --right --char "}"
)
| save --force $source_path
(pueue add --print-task-id ...$args $"nu --config '($nu.config-path)' --env-config '($nu.env-path)' ($source_path)")
}
# Remove tasks from the queue.
# Running or paused tasks need to be killed first.
export def remove [
...ids: int # IDs of the tasks to remove from the status list.
] {
pueue remove ...$ids
}
# Switches the queue position of two tasks.
# Only works for queued or stashed tasks.
export def switch [
task_id_1: int # The first task ID.
task_id_2: int # The second task ID.
] {
pueue switch $task_id_1 $task_id_2
}
# Stash a task that is not currently running.
#
# Stashed tasks won't be automatically started.
# You will have to queue them or start them by hand.
export def stash [
...ids: int # IDs of the tasks to stash.
] {
pueue stash ...$ids
}
# Queue stashed tasks for execution.
export def queue [
...ids: int # IDs of the tasks to queue.
--delay (-d): duration # Queue only after the specified delay.
] {
let args = if $delay != null {
["--delay" ($delay | format duration sec | parse '{secs} {_}' | get 0.secs)]
} else {
[]
}
pueue enqueue ...$args ...$ids
}
# Resume operation of specific tasks or groups of tasks.
#
# By default, this resumes the default group and all its tasks.
# It can also be used force-start specific tasks or start whole groups.
export def start [
...ids: int # IDs of the tasks to start. By default all the tasks in the default group will be started.
--group (-g): string # Resume a specific group and all paused tasks in it. The group will be set to running and its paused tasks will be resumed.
--all (-a) # Resume all groups. All groups will be set to running and paused tasks will be resumed.
] {
mut args = []
if $group != null {
$args = ($args | prepend ["--group" $group])
}
if $all {
$args = ($args | prepend "--all")
}
pueue start ...$args
}
# Restart failed or successful task(s).
#
# By default, identical tasks will be created and
# enqueued, but it's possible to restart in-place.
#
# You can also edit a few properties, such as
# the path and the command of the task, before restarting.
export def restart [
...ids: int # IDs of the tasks to restart.
--all-failed (-a) # Restart all failed tasks across all groups. Nice to use in combination with `--in-place/i`.
--failed-in-group (-g): string # Like `--all-failed`, but only restart tasks failed tasks of a specific group. The group will be set to running and its paused tasks will be resumed.
--start-immediately (-k) # Immediately start the tasks, no matter how many open slots there are. This will ignore any dependencies tasks may have.
--stashed (-s) # Set the restarted task to a "Stashed" state. Useful to avoid immediate execution.
--in-place (-i) # Restart the tasks by reusing the already existing tasks.
--not-in-place (-n) # Opposite of `--in-place`. This is already the default unless you have `restart_in_place` set to true.
--edit (-e) # Edit the tasks' commands before restarting
--edit-path (-p) # Edit the tasks' paths before restarting
--edit-label (-l) # Edit the tasks' labels before restarting
] {
mut args = []
if $all_failed {
$args = ($args | prepend "--all-failed")
}
if $failed_in_group != null {
$args = ($args | prepend "--failed-in-group")
}
if $start_immediately {
$args = ($args | prepend "--start-immediately")
}
if $stashed {
$args = ($args | prepend "--stashed")
}
if $in_place {
$args = ($args | prepend "--in-place")
}
if $not_in_place {
$args = ($args | prepend "--not-in-place")
}
if $edit {
$args = ($args | prepend "--edit")
}
if $edit_path {
$args = ($args | prepend "--edit-path")
}
if $edit_label {
$args = ($args | prepend "--edit-label")
}
pueue restart ...$args ...$ids
}
# Either pause a running tasks or a specific groups of tasks.
#
# By default, pauses the default group and all its tasks.
#
# A paused group won't start any new tasks automatically.
export def pause [
...ids: int # IDs of the tasks to pause.
--group (-g) # Pause a specific group
--all (-a) # Pause all groups.
--wait (-w) # Only pause the specified group and let already running tasks finish by themselves
] {
mut args = []
if $group != null {
$args = ($args | prepend "--group")
}
if $all != null {
$args = ($args | prepend "--all")
}
if $wait != null {
$args = ($args | prepend "--wait")
}
pueue pause ...$args ...$ids
}
# Kill specific running tasks or whole task groups.
#
# Kills all tasks of the default group when no ids or a specific group are provided.
export def kill [
...ids: int # IDs of the tasks to kill.
--group (-g): string # Kill all running tasks in a group. This also pauses the group.
--all (-a) # Kill all running tasks across ALL groups. This also pauses all groups.
--signal (-s): string # Send a UNIX signal instead of simply killing the process. DISCLAIMER: This bypasses Pueue's process handling logic! You might enter weird invalid states, use at your own descretion.
] {
mut args = []
if $group != null {
$args = ($args | prepend ["--group" $group])
}
if $all {
$args = ($args | prepend "--all")
}
if $signal != null {
$args = ($args | prepend ["--signal" $signal])
}
pueue kill ...$args ...$ids
}
# Send something to a task. Useful for sending confirmations such as "y\n".
export def send [
id: int # ID of the task to send something to.
input: string # The input that should be sent to the process.
] {
pueue send $id $input
}
# Edit the command, path or label of a stashed or queued task.
#
# By default only the command is edited.
#
# Multiple properties can be added in one go.
export def edit [
id: int # ID of the task to edit.
--command (-c) # Edit the task's command
--path (-p) # Edit the task's path
--label (-l) # Edit the task's label
] {
mut args = []
if $command {
$args = ($args | prepend "--command")
}
if $path {
$args = ($args | prepend "--path")
}
if $label {
$args = ($args | prepend "--label")
}
pueue edit ...$args $id
}
# Use this to add or remove groups.
#
# By default, this will simply display all known groups.
export def group [] {
pueue group --json | from json
}
# Create a new group with a name.
export def "group add" [
name: string # The name of the new group.
--parallel (-p): int # The amount of parallel tasks the group can run at one time.
] {
let args = if $parallel != null {
["--parallel" $parallel]
} else {
[]
}
pueue group add ...$args $name
}
# Remove a group with a name.
export def "group remove" [
name: string # The name of the group to be removed.
] {
pueue group remove $name
}
# Display the current status of all tasks.
export def status [
--detailed (-d) # Return a table with more detailed information.
] {
let output = (
pueue status --json
| from json
| get tasks
| transpose --ignore-titles status
| flatten
)
# TODO: Rename the Done column to done.
if not $detailed {
$output | select id label group Done? status? start? end?
} else {
$output
}
}
# Display the output of tasks.
#
# Only the last few lines will be shown by default for multiple tasks.
# If you want to follow the output, use `--tail/-t`.
export def log [
...ids: int # The tasks to check the outputs of.
--last (-l): int # Only print the last N lines of each task's output. This is done by default if you're looking at multiple tasks.
--tail (-t) # Follow the output as it is printing. Only works with 1 task. When used in conjunction with `--last`, the last N lines will be printed before starting to wait for output.
--detailed (-d) # Include all fields, don't simplify output.
] {
def process_raw [raw: string] {
let full = (
$raw
| from json
| transpose -i info
| flatten --all
| flatten --all
)
if $detailed {
$full
} else {
$full | select id label group Done? status? start? end?
}
}
if (($ids | length) == 1) {
if $tail {
let args = if $last != null {
["--lines" $last]
} else {
[]
}
pueue follow ...$ids
} else {
let args = if $last != null {
["--lines" $last]
} else {
[]
}
process_raw (pueue log --full --json ...$args ...$ids)
| first
}
} else {
if $tail {
echo $"(ansi red)--tail can only be used with one task.(ansi reset)"
return
}
let args = if $last != null {
["--lines" $last]
} else {
[]
}
process_raw (pueue log --full --json ...$args ...$ids)
}
}
# Wait until the provided tasks are finished.
#
# This is like join() or await in many languages.
export def wait [
...ids: int # IDs of the tasks to wait for.
--group (-g): string # Wait for all tasks in a specific group.
--all (-a) # Wait for all tasks across all groups and the default group.
--quiet (-q) # Don't show any log output while waiting.
--status (-s): string # Wait for tasks to reach a specific task status.
] {
mut args = []
if $group != null {
$args = ($args | prepend ["--group" $group])
}
if $all {
$args = ($args | prepend $all)
}
if $quiet {
$args = ($args | prepend $quiet)
}
if $status != null {
$args = ($args | prepend ["--status" $status])
}
pueue wait ...$args ...$ids
}
# Remove tasks from the status list.
export def clean [
--successful-only (-s) # Only clean tasks that finished successfully
--group (-g): string # Only clean tasks of a specific group
] {
mut args = []
if $successful_only {
$args = ($args | prepend "--successful-only")
}
if $group != null {
$args = ($args | prepend ["--group" $group])
}
pueue clean ...$args
}
# Shutdown pueue and thus this module.
export def shutdown [] {
pueue shutdown
}
# Set the maximum parallel tasks for a group.
#
# Note that no tasks will be stopped if the number is lowered.
# The limit only applies when schelduing.
export def set-parallel-limit [
max: int # The maximum parallel tasks allowed for a group when schelduing.
--group (-g): string # The group to set the limit for. By default this is `default`.
] {
let args = if $group != null {
["--group" $group]
} else {
[]
}
pueue parallel ...$args $max
}

@ -20,5 +20,9 @@ config:needs("wezterm", "wezterm")
config:needs("zellij", "zellij") config:needs("zellij", "zellij")
config:needs("starship", "starship") config:needs("starship", "starship")
config:needs("lvim", "lvim") config:needs("lvim", "lvim")
config:needs("lvim", "lvim")
config:needs("git", "nushell/scripts/git.nu")
config:needs("pueue", "nushell/scripts/task.nu")
config:needs("pueue", "systemd/user/pueued.service")
return config return config

@ -0,0 +1,13 @@
# This is the service file for the pueue daemon
# To enable the daemon type `systemctl --user enable pueued.service`
# To start the daemon type `systemctl --user start pueued.service`
[Unit]
Description=Pueue Daemon - CLI process scheduler and manager
[Service]
Restart=no
ExecStart=/home/jri/.nix-profile/bin/pueued -vv
[Install]
WantedBy=default.target

@ -63,6 +63,8 @@ layout {
pane { pane {
name "Terminal" name "Terminal"
size "30%" size "30%"
command "nu"
args "-e" "clear; onefetch --no-art --no-color-palette --text-colors 7 10 11 12 7 15"
} }
} }
} }
@ -71,5 +73,6 @@ layout {
keybinds { keybinds {
normal { normal {
bind "Ctrl f" { ToggleFocusFullscreen; } bind "Ctrl f" { ToggleFocusFullscreen; }
bind "Alt p" { Run "nu" "{{dirs.data}}/scripts/ide.nu" "floating-prompt"; }
} }
} }

@ -1,5 +1,7 @@
#!/bin/env nu #!/bin/env nu
use task.nu
def --env main [] { def --env main [] {
if $env.ZELLIJ? == null { if $env.ZELLIJ? == null {
let tmpdir = init let tmpdir = init
@ -11,7 +13,7 @@ def --env main [] {
} }
def `main open-file` [path: string] { export def `main open-file` [path: string] {
if ($path | str starts-with "http") { if ($path | str starts-with "http") {
/usr/bin/xdg-open $path /usr/bin/xdg-open $path
return return
@ -25,6 +27,13 @@ def `main open-file` [path: string] {
} }
} }
export def `main floating-prompt` [] {
task spawn -i {
zellij action new-pane --floating -- nu -c 'nu -e clear; zellij action close-pane';
}
zellij action close-pane
}
def open-editor [path: string] { def open-editor [path: string] {
zellij ac move-focus right zellij ac move-focus right
zellij ac write-chars $":open ($path)\r" zellij ac write-chars $":open ($path)\r"

@ -52,6 +52,8 @@ config.modules = {
'topgrade', 'topgrade',
'skim', 'skim',
'pastel', 'pastel',
'pueue',
'onefetch',
}, },
gui = mod { gui = mod {
'kdePackages.breeze-icons', 'kdePackages.breeze-icons',

Loading…
Cancel
Save