Add progression reporting.
This commit is contained in:
parent
feaef5a448
commit
e94d8a0c50
4 changed files with 58 additions and 9 deletions
6
examples/run_wait
Executable file
6
examples/run_wait
Executable file
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/bash
|
||||
set -e
|
||||
cd "$(dirname "$(realpath "$0")")"
|
||||
|
||||
|
||||
../src/regar.ts --hard --progress 'sleep 2s' wdir
|
0
examples/wdir/work.txt
Normal file
0
examples/wdir/work.txt
Normal file
6
package/deploy
Normal file
6
package/deploy
Normal file
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/bash
|
||||
set -e
|
||||
cd "$(dirname "$(realpath "$0")")"
|
||||
|
||||
./release/package
|
||||
./aur/package
|
55
src/regar.ts
55
src/regar.ts
|
@ -5,13 +5,13 @@ import { Command } from "https://deno.land/x/cliffy@v1.0.0-rc.4/command/mod.ts"
|
|||
import { Channel, Constructible, InstanceOf } from "https://git.barnulf.net/mb/barnulf_ts/raw/branch/master/mod.ts"
|
||||
import { wait } from "https://git.barnulf.net/mb/barnulf_ts/raw/branch/master/src/lib/utils.ts"
|
||||
|
||||
const version = "1.0.0"
|
||||
const version = "1.1.0"
|
||||
|
||||
async function main() {
|
||||
const { do_clear, command, extensions, files, strategy, go_up } = await parse_args()
|
||||
const { do_clear, command, extensions, files, strategy, go_up, show_progress } = await parse_args()
|
||||
const channel = new Channel<Event>()
|
||||
files.map((path) => new Watcher(path, extensions).spin(channel))
|
||||
new Runner(command, strategy, do_clear, go_up).spin(channel)
|
||||
new Runner(command, strategy, do_clear, go_up, show_progress).spin(channel)
|
||||
}
|
||||
|
||||
async function parse_args() {
|
||||
|
@ -26,6 +26,7 @@ async function parse_args() {
|
|||
.option("-e, --extensions <extentions>", "Comma separated whitelist of extensions to whatch.")
|
||||
.option("-c, --clear", "Clear the terminal on restart.", { default: false })
|
||||
.option("-u, --up", "Scroll the terminal to the start of the command at each run.", { default: false })
|
||||
.option("-p, --progress", "Show estimated progress on subsequent runs.", { default: false })
|
||||
.help({ colors: false })
|
||||
const { args, options } = await cmd.parse()
|
||||
const [command, ...files] = args
|
||||
|
@ -36,7 +37,8 @@ async function parse_args() {
|
|||
const extensions = options.extensions?.split(",")
|
||||
const do_clear = options.clear
|
||||
const go_up = options.up
|
||||
return { command, files, strategy, extensions, do_clear, go_up }
|
||||
const show_progress = options.progress
|
||||
return { command, files, strategy, extensions, do_clear, go_up, show_progress }
|
||||
}
|
||||
|
||||
class Watcher {
|
||||
|
@ -67,6 +69,7 @@ class Runner {
|
|||
private strategy: ShutdownStrategy,
|
||||
private do_clear: boolean,
|
||||
private go_up: boolean,
|
||||
private show_progress: boolean,
|
||||
) {}
|
||||
|
||||
public async spin(channel: Channel<Event>) {
|
||||
|
@ -89,7 +92,9 @@ class Runner {
|
|||
log("running", this.command)
|
||||
console.log()
|
||||
const process = new Deno.Command("sh", { args }).spawn()
|
||||
process.status.then(this.on_end())
|
||||
let stop: Stop | undefined = undefined
|
||||
if (this.show_progress) stop = this.start_progress()
|
||||
process.status.then(this.on_end(stop))
|
||||
return process
|
||||
}
|
||||
|
||||
|
@ -101,20 +106,22 @@ class Runner {
|
|||
private last_event_date_ms = 0
|
||||
private debouncing(event: Event) {
|
||||
const delay_ms = event.date_ms - this.last_event_date_ms
|
||||
const threshold_ms = 100
|
||||
const threshold_ms = 150
|
||||
if (delay_ms < threshold_ms) return true
|
||||
this.last_event_date_ms = event.date_ms
|
||||
return false
|
||||
}
|
||||
|
||||
private on_end() {
|
||||
private on_end(stop: Stop | undefined) {
|
||||
if (this.go_up) this.save_cursor()
|
||||
const start_ms = Date.now()
|
||||
return () => {
|
||||
return (status: Deno.CommandStatus) => {
|
||||
const end_ms = Date.now()
|
||||
const time_ms = end_ms - start_ms
|
||||
if (status.success) this.time_estimation_ms = time_ms
|
||||
const secs = time_ms / 1000
|
||||
if (this.go_up) this.restore_cursor()
|
||||
if (stop !== undefined) stop.stop = true
|
||||
log("terminated", `${secs} s`)
|
||||
}
|
||||
}
|
||||
|
@ -126,8 +133,26 @@ class Runner {
|
|||
private restore_cursor() {
|
||||
console.log("\x1b[u")
|
||||
}
|
||||
|
||||
time_estimation_ms = 0
|
||||
private start_progress() {
|
||||
const stop = { stop: false }
|
||||
;(async () => {
|
||||
for await (const step of progress(this.time_estimation_ms)) {
|
||||
if (stop.stop) break
|
||||
const secs = (Math.floor(step.ms / 100) / 10).toString().padStart(3)
|
||||
const total = Math.floor(this.time_estimation_ms / 1_000).toString().padStart(3)
|
||||
const perc = (Math.floor(step.relative * 1_000) / 10).toString().padStart(5)
|
||||
log("progress", `${secs} s / ${total} s (${perc} %)\x1bM`)
|
||||
}
|
||||
})()
|
||||
|
||||
return stop
|
||||
}
|
||||
}
|
||||
|
||||
type Stop = { stop: boolean }
|
||||
|
||||
interface ShutdownStrategy {
|
||||
/** Returns wether the child has been shutdown. */
|
||||
shutdown(process_: Deno.ChildProcess): Promise<boolean>
|
||||
|
@ -173,6 +198,18 @@ function try_signal(pid: number, sig: Deno.Signal) {
|
|||
)
|
||||
}
|
||||
|
||||
async function* progress(time_ms: number, step_ms = 100) {
|
||||
const start = Date.now()
|
||||
yield { ms: 0., relative: 0. }
|
||||
while (true) {
|
||||
const ellapsed = Date.now() - start
|
||||
if (ellapsed > time_ms) break
|
||||
yield { ms: ellapsed, relative: ellapsed / time_ms }
|
||||
await wait(step_ms)
|
||||
}
|
||||
yield { ms: time_ms, relative: 1. }
|
||||
}
|
||||
|
||||
// deno-lint-ignore no-explicit-any
|
||||
type Catching<C extends Constructible<C, any>, R = void> = [
|
||||
exception: C,
|
||||
|
@ -199,7 +236,7 @@ function log(verb: string, value: unknown) {
|
|||
const bold = "\x1b[1m"
|
||||
const reset = "\x1b[0m"
|
||||
console.log(
|
||||
`` +
|
||||
`\x1b[2K` +
|
||||
`${yellow}${bold}${verb.padStart(12)}${reset}` +
|
||||
` ` +
|
||||
`${yellow}${value}${reset}`,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue