Operand

odyssey, u hear?

gram: nue

> ./gram.nu

Lenses
(coming soon!)


source ./grammar.nu
source ./nix.nu
source ./machine.nu

def "grammar norm" [base: path] { {
  base: ($base | path expand),
  name: ($base | path basename),
  machine: $m.baseboard,
} }

def "grammar gleam" [base: path] { {
  base: ($base | path expand),
  name: ($base | path basename),
  machine: null, #$m.base,
  shares: [ doc README.md ],
  command: { preshare: "nd gleam docs build" },
} }

def "grammar mix" [base: path] { {
  base: ($base | path expand),
  name: ($base | path basename),
  machine: $m.baseboard,
  shares: [ doc share ],
  command: {
    # basis: "nd mix deps.get",
    preshare: "nd mix docs",
  }
} }

let grams = {
  build: { base: ~/.build, name: build, machine: $m.baseboard }
  mech: { base: ~/.mech, name: mech, machine: $m.baseboard }
  nue: { base: ~/.nue, name: nue, machine: $m.baseboard } # , shares: [ guide ] }
  nux: { base: ~/.nux, name: nux, machine: $m.baseboard }

  ledge: { base: ~/ledge, name: ledge, machine: $m.baseboard }
  course: { base: ~/course, name: course, machine: $m.baseboard }

  # publish!
  gear: { base: ~/gear, name: gear, machine: $m.baseboard }
  # group: { base: ~/group, name: group, machine: null }
  # page:  { base: ~/space/gram/page, name: page, machine: null }

  page:  {
    base: ~/page, name: page, machine: $m.baseboard, shares: [share],
    command: { preshare: "
    (glob *.diagram) | each { diagram $in };
    rsync -av --filter='+ /*' --filter='+ /*/*.svg' --filter='- *' *.diagram share/
  "} }

  # scope:   (grammar norm ~/share/gram/scope)
  # gloss:   (grammar norm ~/space/gram/gloss)
  # nuer:    (grammar norm ~/space/gram/nuer)
  # min:     (grammar norm ~/space/gram/min)
  # qu:      (grammar norm ~/space/gram/qu)
  # aurora:  (grammar norm ~/space/gram/aurora)

  pool:    (grammar norm /pool)
  drop:    (grammar norm ~/share/gram/drop)
  relay:   (grammar norm ~/share/gram/relay)
  essay:   (grammar norm ~/share/gram/essay)
  op:      (grammar mix ~/share/gram/op),
  reps:    (grammar mix ~/share/gram/reps),
  dash:    (grammar mix ~/share/gram/dash),
  operable:(grammar mix ~/share/gram/operable | upsert command ({})),

  session: (grammar mix ~/base/mirror/asciinema-server | upsert name "session"),
  pain:    (grammar mix ~/space/gram/pain),
  gram:    (grammar gleam ~/space/gram/gram),
  lens:    (grammar gleam ~/space/gram/lens),
  panel:   (grammar gleam ~/space/gram/panel),
}; let g = $grams

def "gram recycle" [gram: record] {
  shell $machines.baseboard $"close-($gram.name); do-($gram.name) daemon;"
}

def "gram share" [...gs: record, --legacy] {
  $gs | each {|gram|
    let base = $gram.base | path expand
    let share = [ / home ($gram.machine.login) share gram $gram.name ] | path join
    let aim = [ (machine address $gram.machine) $share ] | str join ':'

    let branch = if ('base' in (code -C $base remote | lines)) {
      'base' } else {
        print "Danger! Add your repo to base.operand.online:"
        print $"> ssh base.operand.online \"repo create ($gram.name) -d 'some summary.'\""
        print $"> git remote add base base.operand.online:($gram.name)"
        print $"> gram share $g.($gram.base)"
        print ''
        print $"or add `--legacy` to proceed regardless."
        if not $legacy { return null }
        
      if ('share' in (code -C $base remote | lines)) {
        code -C $base remote set-url share $aim } else {
        code -C $base remote add share $aim }
     'share'
    }

    let prepare = if ($branch == 'base') {
      $"if not \('($share)' | path exists\) {
        git clone base.operand.online:($gram.name) ($share) }"
    } else {
    (['('
      $"mkdir '($share)';"
      $"cd '($share)';"
      $"nix-shell -p git --command 'git -C ($share) init';"
      $"nix-shell -p git --command 'git config --global --add safe.directory ($share)';"
      # $"nix-shell -p git --command 'git -C ($share) branch -m main';"
      $"nix-shell -p git --command 'git -C ($share) config --add receive.denyCurrentBranch warn';"
    ')'] | str join "\n")
    }

    print "Preparing codebase"; print $prepare
    shell $gram.machine $prepare
    # ssh (machine address $gram.machine) $prepare
    # ssh (machine address $gram.machine) $"ls ($share)" | print

    print (code -C $base remote -v)
    code -C $base push $branch
    print "pushed."

    if ($branch == base) {
      shell $gram.machine $"
        nix-shell -p git --command '
        git -C ($share) fetch origin;
        git -C ($share) checkout origin/main;
        git -C ($share) branch -D main
        git -C ($share) switch -c main
      '"
    } else {
      shell $gram.machine $"nix-shell -p git --command 'git -C ($share) reset --hard main'"
      shell $gram.machine $"nix-shell -p git --command 'git -C ($share) checkout main'"
    }

    if ($gram | get -o command.basis | is-not-empty) {
      cd $base; nu run -s [gram] $gram.command.basis
    } else { print "no command.basis; passing." }

    if ($gram | get -o command.preshare | is-not-empty) {
      cd $base; nu run -s [gram diagram] $gram.command.preshare | print
    } else { print "no command.preshare; passing." }

    if not ($gram | get -o shares | is-empty) {
      shell $gram.machine $"mkdir '(dirname $share)'"
      print $"time rsync -av --delete ...($gram.shares | | each {|s| ([$base $s] | path join | path expand) }) ($aim)"
      time rsync -av --delete ...($gram.shares | each {|s| [$base $s] | path join | path expand } | where { path exists }) $aim | print
    }
} }

def "gram ply" [...gs: record] {
# deploy gram images on machine, compiled and managed by colmena

  # $gs | group-by machine.name | transpose | get column1 | each {|machines|
  #   $machines | each {|mach| cd ~/.build/($gram.machine.login)
  #     nsh colmena colmena apply --on $mach.machine.name --build-on-target --impure switch } }

  $gs | each { |gram|
    gram share $gram
    let base = try { $gram.base | path basename } catch {  }
    let logs = "~/space/log" | path expand; mkdir $logs;
    let log = [ $logs ([ (clock | str trim) $base deploy log ] | str join '.') ] | path join
    try { shell $gram.machine $"run-($gram.name)" | tee { save $log } | print }
  }
}

def "gram cycle" [...gs: record] {
  $gs | par-each { |gram|
    let base = try { $gram.base | path basename } catch {  }
    let logs = "~/qu/log" | path expand; mkdir $logs;
    let log = [ $logs ([ (clock | str trim) $base cycle log ] | str join '.') ] | path join
    echo "running cycle"
    try { shell $gram.machine $"yes | cycle-($gram.name)" | tee { save $log } | print }
    gram share $gram
  }
}

def "gram clean" [...gs: record] {
  $gs | par-each {|gram|
    shell $gram.machine ("time rm -r ...(
      ls ($gram.name)/ | get name | path basename | filter {
       $in != run and $in != (
        '~/($gram.name)/run' | path expand | path dirname | path basename
      ) } | each { ([ ($gram.name) $in ] | path join | path expand) } | tee { print }
    )" | str replace -a '($gram.name)' $gram.name)
} }

# def "gram clean" [gram: record] {
# let running = shell $gram.machine $"(~/($gram.name)/run | path expand | path dirname | path basename)"
# time rm -r ...(ls $gram.name | get name | path basename | filter {
#   $in != run and $in != $running } | each { ([ $gram.name $in ] | path join | path expand) })
# }

def g [...name: any] { $g | get ($name | into cell-path) }

def "gram node" [gram: string, name: path] {
  [ ($grams | get $gram | get base)
    $name
  ] | path join
}