Compare commits

...

2 commits

3 changed files with 41 additions and 33 deletions

View file

@ -516,8 +516,13 @@ func pasrseCliAlias(cfg: var CliCfg, node: NimNode) =
func propagate(c: var CliCfg) = func propagate(c: var CliCfg) =
for child in c.subcommands.mitems: for child in c.subcommands.mitems:
child.pre = c.preSub # push the preSub to the lowest subcommand
child.post = c.postSub if child.subcommands.len != 0 and child.preSub == nil:
child.preSub = c.preSub
child.postSub = c.postSub
else:
child.pre = c.preSub
child.post = c.postSub
child.inheritFrom(c) child.inheritFrom(c)
propagate(child) propagate(child)

View file

@ -5,47 +5,50 @@ type
Spinny = ref object Spinny = ref object
t: Thread[Spinny] t: Thread[Spinny]
lock: Lock lock: Lock
text: string text: BbString
running: bool running: bool
frames: seq[string] frames: seq[string]
frame: string bbFrames: seq[BbString]
frame: BbString
interval: int interval: int
customSymbol: bool customSymbol: bool
style: string style: string
file: File
EventKind = enum EventKind = enum
Stop Stop
SymbolChange SymbolChange
TextChange TextChange
SpinnyEvent = object SpinnyEvent = object
kind: EventKind kind: EventKind
payload: string payload: BbString
var spinnyChannel: Channel[SpinnyEvent] var spinnyChannel: Channel[SpinnyEvent]
proc newSpinny*(text: string, s: Spinner): Spinny = proc newSpinny*(text: string | Bbstring, s: Spinner): Spinny =
let style = "bold blue" let style = "bold blue"
Spinny( Spinny(
text: text, text: bb(text),
running: true, running: true,
frames: mapIt(s.frames, $bb(bbEscape(it), style)), frames: s.frames,
bbFrames: mapIt(s.frames, bb(bbEscape(it), style)),
customSymbol: false, customSymbol: false,
interval: s.interval, interval: s.interval,
style: "bold blue", style: "bold blue",
file: stderr,
) )
proc newSpinny*(text: string, spinType: SpinnerKind): Spinny = proc newSpinny*(text: string | Bbstring, spinType: SpinnerKind): Spinny =
newSpinny(text, Spinners[spinType]) newSpinny(text, Spinners[spinType])
proc setSymbolColor*(spinny: Spinny, style: string) = proc setSymbolColor*(spinny: Spinny, style: string) =
spinny.frames = mapIt(spinny.frames, $bb(it, style)) spinny.bbFrames = mapIt(spinny.frames, bb(bbEscape(it), style))
proc setSymbol*(spinny: Spinny, symbol: string) = proc setSymbol*(spinny: Spinny, symbol: string) =
spinnyChannel.send(SpinnyEvent(kind: SymbolChange, payload: symbol)) spinnyChannel.send(SpinnyEvent(kind: SymbolChange, payload: bb(symbol)))
proc setText*(spinny: Spinny, text: string) = proc setText*(spinny: Spinny, text: string | BbString) =
spinnyChannel.send(SpinnyEvent(kind: TextChange, payload: text)) spinnyChannel.send(SpinnyEvent(kind: TextChange, payload: bb(text)))
proc handleEvent(spinny: Spinny, eventData: SpinnyEvent): bool = proc handleEvent(spinny: Spinny, eventData: SpinnyEvent): bool =
result = true result = true
@ -74,14 +77,15 @@ proc spinnyLoop(spinny: Spinny) {.thread.} =
spinny.running = false spinny.running = false
break break
stdout.flushFile() flushFile spinny.file
if not spinny.customSymbol: if not spinny.customSymbol:
spinny.frame = spinny.frames[frameCounter] spinny.frame = spinny.bbFrames[frameCounter]
# TODO: instead of truncating support multiline text, need custom wrapping and cleanup then
withLock spinny.lock: withLock spinny.lock:
eraseLine() eraseLine spinny.file
stdout.write(spinny.frame & " " & spinny.text) spinny.file.write $((spinny.frame & " " & spinny.text).truncate(terminalWidth())) # needs to be truncated
stdout.flushFile() flushFile spinny.file
sleep spinny.interval sleep spinny.interval
@ -96,37 +100,35 @@ proc start*(spinny: Spinny) =
createThread(spinny.t, spinnyLoop, spinny) createThread(spinny.t, spinnyLoop, spinny)
proc stop(spinny: Spinny, kind: EventKind, payload = "") = proc stop(spinny: Spinny, kind: EventKind, payload = "") =
spinnyChannel.send(SpinnyEvent(kind: kind, payload: payload)) spinnyChannel.send(SpinnyEvent(kind: kind, payload: bb(payload)))
spinnyChannel.send(SpinnyEvent(kind: Stop)) spinnyChannel.send(SpinnyEvent(kind: Stop))
joinThread spinny.t joinThread spinny.t
eraseLine stdout eraseLine spinny.file
flushFile stdout flushFile spinny.file
proc stop*(spinny: Spinny) = proc stop*(spinny: Spinny) =
spinny.stop(Stop) spinny.stop(Stop)
template withSpinner*(msg: string = "", body: untyped): untyped = template withSpinner*(msg: string = "", body: untyped): untyped =
var spinner {.inject.} = newSpinny(msg, Dots) var spinner {.inject.} = newSpinny(msg, Dots)
if isatty(stdout): # don't spin if it's not a tty if isatty(spinner.file): # don't spin if it's not a tty
start spinner start spinner
body
body
if isatty(stdout):
stop spinner stop spinner
else:
body
template withSpinner*(body: untyped): untyped = template withSpinner*(body: untyped): untyped =
withSpinner("", body) withSpinner("", body)
template with*(kind: SpinnerKind, msg: string, body: untyped): untyped = template with*(kind: SpinnerKind, msg: string, body: untyped): untyped =
var spinner {.inject.} = newSpinny(msg, kind) var spinner {.inject.} = newSpinny(msg, kind)
if isatty(stdout): # don't spin if it's not a tty if isatty(spinner.file): # don't spin if it's not a tty
start spinner start spinner
body
body
if isatty(stdout):
stop spinner stop spinner
else:
body
when isMainModule: when isMainModule:
for kind, _ in Spinners: for kind, _ in Spinners:

View file

@ -25,7 +25,7 @@ hwylCli:
? "path to config file" ? "path to config file"
* @["config.yml"] * @["config.yml"]
preSub: preSub:
echo "this is run after subcommand parsing but before its run block" echo "this is run after subcommand parsing but before final run block"
echo fmt"{yes=}, {color=}" echo fmt"{yes=}, {color=}"
run: run:
echo "this is always run prior to subcommand parsing" echo "this is always run prior to subcommand parsing"
@ -53,6 +53,7 @@ hwylCli:
flags: flags:
^config ^config
run: run:
echo "hello from `example one subsub` command"
echo fmt"{color=}" echo fmt"{color=}"
run: run: