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

Merged
merged 23 commits into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
88dc9f9
initial commit
timreichen Feb 19, 2025
07bf344
update
timreichen Feb 22, 2025
4718c7c
Merge branch 'main' into cli-ProgressBar-public-value-property
timreichen Feb 22, 2025
62f2d1a
Merge branch 'main' into cli-ProgressBar-public-value-property
kt3k Mar 21, 2025
6daf4ec
clean up
kt3k Mar 21, 2025
8aab2f7
fix conflict resolution error
kt3k Mar 21, 2025
84cc65b
Merge branch 'main' into cli-ProgressBar-public-value-property
timreichen Mar 22, 2025
0afcc64
initial commit
timreichen Mar 30, 2025
2af1eba
Merge branch 'main' into cli-ProgressBar-public-value-property
timreichen Apr 1, 2025
fbe4087
add jsdoc
timreichen Apr 1, 2025
5442288
Merge branch 'main' into cli-ProgressBar-public-value-property
timreichen Apr 1, 2025
8f181f4
update jsdoc
timreichen Apr 1, 2025
7f6472d
Merge branch 'main' into cli-ProgressBar-public-value-property
timreichen Apr 2, 2025
415282a
update
timreichen Apr 2, 2025
ba780aa
Merge branch 'main' into cli-ProgressBar-public-value-property
timreichen Apr 10, 2025
4c304f8
Merge branch 'main' into cli-ProgressBar-public-value-property
timreichen Apr 10, 2025
97b331f
Merge branch 'main' into cli-ProgressBar-public-value-property
timreichen Apr 16, 2025
53e4687
Merge branch 'main' into cli-ProgressBar-public-value-property
timreichen Apr 18, 2025
399b294
Merge branch 'main' into cli-ProgressBar-public-value-property
timreichen Apr 25, 2025
69bf849
update
timreichen Apr 25, 2025
4727556
Merge branch 'main' into cli-ProgressBar-public-value-property
kt3k May 20, 2025
d1fe717
Merge branch 'main' into cli-ProgressBar-public-value-property
timreichen May 20, 2025
53c02cf
update
timreichen May 20, 2025
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
85 changes: 49 additions & 36 deletions cli/unstable_progress_bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,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 @@ -134,11 +134,11 @@ const UNIT_RATE_MAP = new Map<Unit, number>([
* const bar = new ProgressBar({ max: 100_000 });
*
* for await (const buffer of gen) {
* bar.add(buffer.length);
* bar.value += buffer.length;
* await writer.write(buffer);
* }
*
* await bar.end();
* await bar.stop();
* await writer.close();
* ```
*
Expand All @@ -155,23 +155,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.stop();
*/
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({ max : 10 });
* progressBar.value += 1;
*
* // do stuff
*
* await progressBar.stop();
* ```
*/
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({ max : 1 });
* progressBar.max = 100;
*
* // do stuff
*
* await progressBar.stop();
* ```
*/
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 @@ -189,15 +217,16 @@ export class ProgressBar {
const {
writable = Deno.stderr.writable,
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 @@ -216,13 +245,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 @@ -233,48 +262,32 @@ 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.
*
* @example Usage
* ```ts ignore
* import { ProgressBar } from "@std/cli/unstable-progress-bar";
*
* const progressBar = new ProgressBar(Deno.stdout.writable, { max: 100 });
* await progressBar.end()
* const progressBar = new ProgressBar({ max: 100 });
* await progressBar.stop()
* ```
*/
async stop(): Promise<void> {
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 @@ -53,7 +53,7 @@ export class ProgressBarStream extends TransformStream<Uint8Array, Uint8Array> {
bar = new ProgressBar(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.stop().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.stop();

await readable.cancel();
Expand All @@ -76,7 +76,7 @@ Deno.test("ProgressBar() can remove itself when finished", async () => {
const { readable, writable } = new TransformStream();
const bar = new ProgressBar({ writable, max: 10 * 1000, 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.stop()
.then(() => writable.close());

Expand All @@ -102,7 +102,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.stop();

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