Skip to content

feat(cli/unstable): add ProgressBar start() method #6408

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
35 changes: 28 additions & 7 deletions cli/unstable_progress_bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
* const writer = (await Deno.create("./_tmp/output.txt")).writable.getWriter();
*
* const bar = new ProgressBar(Deno.stdout.writable, { max: 100_000 });
* bar.start();
*
* for await (const buffer of gen) {
* bar.add(buffer.length);
Expand All @@ -131,6 +132,7 @@
* return `${x.styledTime()}${x.progressBar}[${x.value}/${x.max} files]`;
* },
* });
* bar.start();
*
* for (const x of Array(100)) {
* bar.add(1);
Expand All @@ -143,10 +145,10 @@
#unit: string;
#rate: number;
#writer: WritableStreamDefaultWriter;
#id: number;
#startTime: number;
#lastTime: number;
#lastValue: number;
#intervalId?: number;
#startTime: number = 0;
#lastTime: number = 0;
#lastValue: number = 0;

#value: number;
#max: number;
Expand Down Expand Up @@ -204,9 +206,9 @@
const stream = new TextEncoderStream();
stream.readable
.pipeTo(writable, { preventClose: this.#keepOpen })
.catch(() => clearInterval(this.#id));
.catch(() => clearInterval(this.#intervalId));
this.#writer = stream.writable.getWriter();
this.#id = setInterval(() => this.#print(), 1000);
this.#intervalId = setInterval(() => this.#print(), 1000);
this.#startTime = performance.now();
this.#lastTime = this.#startTime;
this.#lastValue = this.#value;
Expand Down Expand Up @@ -259,6 +261,25 @@
this.#value += x;
}

/**
* Starts the progress bar.
*
* @example Usage
* ```ts ignore
* import { ProgressBar } from "@std/cli/unstable-progress-bar";
*
* const bar = new ProgressBar(Deno.stdout.writable, { max: 1 });
* bar.start();
* ```
*/
start(): void {
if (this.#intervalId) return;
this.#intervalId = setInterval(() => this.#print(), 200);
this.#startTime = performance.now();
this.#lastTime = this.#startTime;
this.#lastValue = this.#value;
}

Check warning on line 281 in cli/unstable_progress_bar.ts

View check run for this annotation

Codecov / codecov/patch

cli/unstable_progress_bar.ts#L277-L281

Added lines #L277 - L281 were not covered by tests

/**
* Ends the progress bar and cleans up any lose ends.
*
Expand All @@ -271,7 +292,7 @@
* ```
*/
async end(): Promise<void> {
clearInterval(this.#id);
clearInterval(this.#intervalId);
await this.#print()
.then(() => this.#writer.write(this.#clear ? "\r\u001b[K" : "\n"))
.then(() => this.#writer.close())
Expand Down
1 change: 1 addition & 0 deletions cli/unstable_progress_bar_stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class ProgressBarStream extends TransformStream<Uint8Array, Uint8Array> {
super({
start(_controller) {
bar = new ProgressBar(writable, options);
bar.start();
},
transform(chunk, controller) {
bar?.add(chunk.length);
Expand Down
51 changes: 50 additions & 1 deletion cli/unstable_progress_bar_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ async function* getData(
Deno.test("ProgressBar() outputs default result", async () => {
const { readable, writable } = new TransformStream();
const bar = new ProgressBar(writable, { max: 10 * 1000 });
bar.start();

for await (const a of getData(10, 1000)) bar.add(a.length);
bar.end().then(() => writable.close());
Expand Down Expand Up @@ -65,6 +66,7 @@ Deno.test("ProgressBar() outputs default result", async () => {
Deno.test("ProgressBar() can handle a readable.cancel() correctly", async () => {
const { readable, writable } = new TransformStream();
const bar = new ProgressBar(writable, { max: 10 * 1000 });
bar.start();

for await (const a of getData(10, 1000)) bar.add(a.length);
bar.end();
Expand All @@ -78,6 +80,7 @@ Deno.test("ProgressBar() can remove itself when finished", async () => {
max: 10 * 1000,
clear: true,
});
bar.start();

for await (const a of getData(10, 1000)) bar.add(a.length);
bar.end()
Expand All @@ -103,6 +106,7 @@ Deno.test("ProgressBar() passes correct values to formatter", async () => {
return "";
},
});
bar.start();

for await (const a of getData(10, 1000)) bar.add(a.length);
bar.end();
Expand All @@ -119,7 +123,7 @@ Deno.test("ProgressBar() uses correct unit type", async () => {
max: 2 ** (10 * ++i),
keepOpen: false,
});

bar.start();
const decoder = new TextDecoder();
for await (const buffer of readable) {
assertEquals(decoder.decode(buffer.subarray(-5, -2)), unit);
Expand All @@ -128,3 +132,48 @@ Deno.test("ProgressBar() uses correct unit type", async () => {
bar.end();
}
});

Deno.test("ProgressBar() handles successive start() calls", () => {
const { writable } = new TransformStream();
const bar = new ProgressBar(writable, { max: 1 });
bar.start();
bar.start();
bar.end();
});

Deno.test("ProgressBar() handles successive end() calls", () => {
const { writable } = new TransformStream();
const bar = new ProgressBar(writable, { max: 1 });
bar.start();
bar.end();
bar.end();
});

Deno.test(
"ProgressBar() handles multiple start() and stop() calls",
async () => {
const { readable, writable } = new TransformStream();
const bar = new ProgressBar(writable, { max: 1 });
bar.start();
bar.add(0.5);
bar.end();
const decoder = new TextDecoder();
for await (const buffer of readable) {
assertEquals(
decoder.decode(buffer),
"\r\x1b[K[00:00] [#########################-------------------------] [0.00/0.00 KiB] ",
);
break;
}
bar.start();
bar.add(0.5);
bar.end();
for await (const buffer of readable) {
assertEquals(
decoder.decode(buffer),
"\r\x1b[K[00:00] [#########################-------------------------] [0.00/0.00 KiB] ",
);
break;
}
},
);
Loading