Skip to content

BREAKING(cli/unstable): make ProgressBar value and max properties public #6430

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 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 46 additions & 33 deletions cli/unstable_progress_bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ const UNIT_RATE_MAP = new Map<Unit, number>([

/**
* `ProgressBar` is a customisable class that reports updates to a
* {@link WritableStream} on a 1s interval. Progress is communicated by calling
* the `ProgressBar.add(x: number)` method.
* {@link WritableStream} on a 1s interval. Progress is communicated by using
* the `ProgressBar.value` property.
*
* @experimental **UNSTABLE**: New API, yet to be vetted.
*
Expand All @@ -130,7 +130,7 @@ const UNIT_RATE_MAP = new Map<Unit, number>([
* const bar = new ProgressBar(Deno.stdout.writable, { max: 100_000 });
*
* for await (const buffer of gen) {
* bar.add(buffer.length);
* bar.value += buffer.length;
* await writer.write(buffer);
* }
*
Expand All @@ -151,23 +151,51 @@ const UNIT_RATE_MAP = new Map<Unit, number>([
* });
*
* for (const x of Array(100)) {
* bar.add(1);
* bar.value += 1;
* await delay(Math.random() * 500);
* }
*
* bar.end();
* await bar.end();
*/
export class ProgressBar {
/**
* The current progress that has been completed.
* @example Usage
* ```ts no-assert
* import { ProgressBar } from "@std/cli/unstable-progress-bar";
*
* const progressBar = new ProgressBar(Deno.stdout.writable, { max : 10 });
* progressBar.value += 1
*
* // do stuff
*
* await progressBar.end()
* ```
*/
value: number;
/**
* The maximum progress that is expected.
* @example Usage
* ```ts no-assert
* import { ProgressBar } from "@std/cli/unstable-progress-bar";
*
* const progressBar = new ProgressBar(Deno.stdout.writable, { max : 1 });
* progressBar.max = 100
*
* // do stuff
*
* await progressBar.end()
* ```
*/
max: number;

#unit: Unit;
#rate: number;
#writer: WritableStreamDefaultWriter;
#id: number;
#startTime: number;
#lastTime: number;
#lastValue: number;

#value: number;
#max: number;
#barLength: number;
#fillChar: string;
#emptyChar: string;
Expand All @@ -186,15 +214,16 @@ export class ProgressBar {
) {
const {
value = 0,
max,
barLength = 50,
fillChar = "#",
emptyChar = "-",
clear = false,
fmt = (x) => `${x.styledTime()} ${x.progressBar} ${x.styledData()} `,
keepOpen = true,
} = options;
this.#value = value;
this.#max = options.max;
this.value = value;
this.max = max;
this.#barLength = barLength;
this.#fillChar = fillChar;
this.#emptyChar = emptyChar;
Expand All @@ -213,13 +242,13 @@ export class ProgressBar {
this.#id = setInterval(() => this.#print(), 1000);
this.#startTime = performance.now();
this.#lastTime = this.#startTime;
this.#lastValue = this.#value;
this.#lastValue = this.value;
}

async #print(): Promise<void> {
const currentTime = performance.now();

const size = this.#value / this.#max * this.#barLength | 0;
const size = this.value / this.max * this.#barLength | 0;
const fillChars = this.#fillChar.repeat(size);
const emptyChars = this.#emptyChar.repeat(this.#barLength - size);

Expand All @@ -230,39 +259,23 @@ export class ProgressBar {
return `[${minutes}:${seconds}]`;
},
styledData: (fractions = 2): string => {
const currentValue = (this.#value / this.#rate).toFixed(fractions);
const maxValue = (this.#max / this.#rate).toFixed(fractions);
const currentValue = (this.value / this.#rate).toFixed(fractions);
const maxValue = (this.max / this.#rate).toFixed(fractions);
return `[${currentValue}/${maxValue} ${this.#unit}]`;
},
progressBar: `[${fillChars}${emptyChars}]`,
time: currentTime - this.#startTime,
previousTime: this.#lastTime - this.#startTime,
value: this.#value,
value: this.value,
previousValue: this.#lastValue,
max: this.#max,
max: this.max,
};
this.#lastTime = currentTime;
this.#lastValue = this.#value;
this.#lastValue = this.value;
await this.#writer.write("\r\u001b[K" + this.#fmt(formatter))
.catch(() => {});
}

/**
* Increments the progress by `x`.
*
* @example Usage
* ```ts ignore
* import { ProgressBar } from "@std/cli/unstable-progress-bar";
*
* const progressBar = new ProgressBar(Deno.stdout.writable, { max: 100 });
* progressBar.add(10);
* ```
* @param x The amount of progress that has been made.
*/
add(x: number): void {
this.#value += x;
}

/**
* Ends the progress bar and cleans up any lose ends.
*
Expand Down
2 changes: 1 addition & 1 deletion cli/unstable_progress_bar_stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export class ProgressBarStream extends TransformStream<Uint8Array, Uint8Array> {
bar = new ProgressBar(writable, options);
},
transform(chunk, controller) {
bar?.add(chunk.length);
if (bar) bar.value += chunk.length;
controller.enqueue(chunk);
},
flush(_controller) {
Expand Down
8 changes: 4 additions & 4 deletions cli/unstable_progress_bar_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Deno.test("ProgressBar() outputs default result", async () => {
const { readable, writable } = new TransformStream();
const bar = new ProgressBar(writable, { max: 10 * 1000 });

for await (const a of getData(10, 1000)) bar.add(a.length);
for await (const a of getData(10, 1000)) bar.value += a.length;
bar.end().then(() => writable.close());

for await (const buffer of readable) {
Expand Down Expand Up @@ -66,7 +66,7 @@ Deno.test("ProgressBar() can handle a readable.cancel() correctly", async () =>
const { readable, writable } = new TransformStream();
const bar = new ProgressBar(writable, { max: 10 * 1000 });

for await (const a of getData(10, 1000)) bar.add(a.length);
for await (const a of getData(10, 1000)) bar.value += a.length;
bar.end();

await readable.cancel();
Expand All @@ -79,7 +79,7 @@ Deno.test("ProgressBar() can remove itself when finished", async () => {
clear: true,
});

for await (const a of getData(10, 1000)) bar.add(a.length);
for await (const a of getData(10, 1000)) bar.value += a.length;
bar.end()
.then(() => writable.close());

Expand All @@ -104,7 +104,7 @@ Deno.test("ProgressBar() passes correct values to formatter", async () => {
},
});

for await (const a of getData(10, 1000)) bar.add(a.length);
for await (const a of getData(10, 1000)) bar.value += a.length;
bar.end();

await new Response(readable).bytes();
Expand Down
Loading