Optimize process management and add terminal scrolling functionality

Improved process handling, added go_up option for scrolling the terminal to the
start of the command at each run.
This commit is contained in:
Matthieu Jolimaitre 2025-06-26 15:03:27 +02:00
parent 4375958642
commit 019c576f1d
2 changed files with 24 additions and 7 deletions

View file

@ -1,3 +1,3 @@
{ {
"fmt": { "useTabs": true, "lineWidth": 120 } "fmt": { "useTabs": true, "lineWidth": 120 }
} }

View file

@ -5,10 +5,10 @@ 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 { Channel, Constructible, InstanceOf } from "https://git.barnulf.net/mb/barnulf_ts/raw/branch/master/mod.ts";
async function main() { async function main() {
const { do_clear, command, extensions, files, strategy } = await parse_args(); const { do_clear, command, extensions, files, strategy, go_up } = await parse_args();
const channel = new Channel<Event>(); const channel = new Channel<Event>();
files.map((path) => new Watcher(path, extensions).spin(channel)); files.map((path) => new Watcher(path, extensions).spin(channel));
new Runner(command, strategy, do_clear).spin(channel); new Runner(command, strategy, do_clear, go_up).spin(channel);
} }
async function parse_args() { async function parse_args() {
@ -20,15 +20,18 @@ async function parse_args() {
.option("-s, --soft", "Ends the child process by sending an interuption and waiting for it to shut down.") .option("-s, --soft", "Ends the child process by sending an interuption and waiting for it to shut down.")
.option("-w, --wait", "Wait for the child process to complete without terminating it. (default)") .option("-w, --wait", "Wait for the child process to complete without terminating it. (default)")
.option("-e, --extensions <extentions>", "Comma separated whitelist of extensions to whatch.") .option("-e, --extensions <extentions>", "Comma separated whitelist of extensions to whatch.")
.option("-c, --clear", "Clear the terminal on restart").parse(); .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 })
.parse();
const [command, ...files] = args; const [command, ...files] = args;
let strategy: ShutdownStrategy = new WaitStrategy(); let strategy: ShutdownStrategy = new WaitStrategy();
if (options.soft) strategy = new SoftStrategy(); if (options.soft) strategy = new SoftStrategy();
if (options.hard) strategy = new HardStrategy(); if (options.hard) strategy = new HardStrategy();
if (options.wait) strategy = new WaitStrategy(); if (options.wait) strategy = new WaitStrategy();
const extensions = options.extensions?.split(","); const extensions = options.extensions?.split(",");
const do_clear = options.clear ?? false; const do_clear = options.clear;
return { command, files, strategy, extensions, do_clear }; const go_up = options.up;
return { command, files, strategy, extensions, do_clear, go_up };
} }
class Watcher { class Watcher {
@ -58,6 +61,7 @@ class Runner {
private command: string, private command: string,
private strategy: ShutdownStrategy, private strategy: ShutdownStrategy,
private do_clear: boolean, private do_clear: boolean,
private go_up: boolean,
) {} ) {}
public async spin(channel: Channel<Event>) { public async spin(channel: Channel<Event>) {
@ -77,6 +81,8 @@ class Runner {
private launch() { private launch() {
const args = ["-c", this.command]; const args = ["-c", this.command];
log("running", this.command); log("running", this.command);
if (this.go_up) this.save_cursor();
console.log();
const process = new Deno.Command("sh", { args }).spawn(); const process = new Deno.Command("sh", { args }).spawn();
process.status.then(this.on_end()); process.status.then(this.on_end());
return process; return process;
@ -102,9 +108,18 @@ class Runner {
const end_ms = Date.now(); const end_ms = Date.now();
const time_ms = end_ms - start_ms; const time_ms = end_ms - start_ms;
const secs = time_ms / 1000; const secs = time_ms / 1000;
if (this.go_up) this.restore_cursor();
log("terminated", `${secs} s`); log("terminated", `${secs} s`);
}; };
} }
private save_cursor() {
console.log("\x1bs");
}
private restore_cursor() {
console.log("\x1b[u");
}
} }
interface ShutdownStrategy { interface ShutdownStrategy {
@ -166,7 +181,9 @@ function catch_<T, R, Cs extends Catching<any, R>[]>(op: () => T, ...catchings:
for (const [kind, strategy] of catchings) { for (const [kind, strategy] of catchings) {
if (!(exception instanceof kind)) continue; if (!(exception instanceof kind)) continue;
if (strategy === "ignore") return; if (strategy === "ignore") return;
return strategy(exception); // trust
// deno-lint-ignore no-explicit-any
return strategy(exception as any);
} }
} }
} }