Skip to content

Commit

Permalink
feat: allow to configure the writer to stderr (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangfuxing committed Oct 30, 2024
1 parent bcc5d0d commit 32cd98a
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 57 deletions.
54 changes: 29 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,32 @@ ProgressBar in terminal for deno

![logo](screenshots/logo.png)

## Changelog

[changelog](./changelog.md)

## Usage

### Multiple progress bars

#### example

```ts
import { MultiProgressBar } from "https://deno.land/x/[email protected]/mod.ts";
import { delay } from "https://deno.land/[email protected]/async/delay.ts";

// or JSR
// import { MultiProgressBar } from "jsr:@deno-library/progress";
// import { delay } from "jsr:@std/async";
import { MultiProgressBar } from "jsr:@deno-library/progress";
import { delay } from "jsr:@std/async";

// or JSR (with version)
// import { MultiProgressBar } from "jsr:@deno-library/progress@1.4.9";
// import { MultiProgressBar } from "jsr:@deno-library/progress@1.5.0";
// import { delay } from "jsr:@std/[email protected]";

// or JSR (no prefix, run `deno add @deno-library/progress` and `deno add @std/async`)
// import { MultiProgressBar } from "@deno-library/progress";
// import { delay } from "@std/async";

// or
// import { MultiProgressBar } from "https://deno.land/x/[email protected]/mod.ts";
// import { delay } from "https://deno.land/[email protected]/async/delay.ts";

const title = "download files";
const total = 100;

Expand Down Expand Up @@ -74,6 +78,7 @@ interface constructorOptions {
interval?: number;
display?: string;
prettyTime?: boolean;
output?: typeof Deno.stdout | typeof Deno.stderr;
}

interface renderOptions {
Expand Down Expand Up @@ -109,6 +114,7 @@ class MultiProgressBar {
* @param interval minimum time between updates in milliseconds, default: 16
* @param display What is displayed and display order, default: ':bar :text :percent :time :completed/:total'
* @param prettyTime Whether to pretty print time and eta
* @param output Output stream, can be Deno.stdout or Deno.stderr, default is Deno.stdout
*/
constructor(options: ConstructorOptions);

Expand Down Expand Up @@ -158,21 +164,21 @@ What is displayed and display order, default: ':bar :text :percent :time
#### simple example

```ts
import ProgressBar from "https://deno.land/x/[email protected]/mod.ts";
import { delay } from "https://deno.land/[email protected]/async/delay.ts";

// or JSR
// import ProgressBar from "jsr:@deno-library/progress";
// import { delay } from "jsr:@std/async";
import ProgressBar from "jsr:@deno-library/progress";
import { delay } from "jsr:@std/async";

// or JSR (with version)
// import ProgressBar from "jsr:@deno-library/progress@1.4.9";
// import ProgressBar from "jsr:@deno-library/progress@1.5.0";
// import { delay } from "jsr:@std/[email protected]";

// or JSR (no prefix, run `deno add @deno-library/progress` and `deno add @std/async`)
// import ProgressBar from "@deno-library/progress";
// import { delay } from "@std/async";

// or
// import ProgressBar from "https://deno.land/x/[email protected]/mod.ts";
// import { delay } from "@std/async/delay";

const title = "downloading:";
const total = 100;
const progress = new ProgressBar({
Expand All @@ -193,21 +199,21 @@ await download();
#### complex example

```ts
import ProgressBar from "https://deno.land/x/[email protected]/mod.ts";
import { delay } from "https://deno.land/[email protected]/async/delay.ts";

// or JSR
// import ProgressBar from "jsr:@deno-library/progress";
// import { delay } from "jsr:@std/async";
import ProgressBar from "jsr:@deno-library/progress";
import { delay } from "jsr:@std/async";

// or JSR (with version)
// import ProgressBar from "jsr:@deno-library/progress@1.4.9";
// import ProgressBar from "jsr:@deno-library/progress@1.5.0";
// import { delay } from "jsr:@std/[email protected]";

// or JSR (no prefix, run `deno add @deno-library/progress` and `deno add @std/async`)
// import ProgressBar from "@deno-library/progress";
// import { delay } from "@std/async";

// or
// import ProgressBar from "https://deno.land/x/[email protected]/mod.ts";
// import { delay } from "@std/async/delay";

const total = 100;
const progress = new ProgressBar({
total,
Expand Down Expand Up @@ -248,6 +254,7 @@ interface ConstructorOptions {
interval?: number,
display?: string
prettyTime?: boolean;
output?: typeof Deno.stdout | typeof Deno.stderr;
}

interface renderOptions {
Expand Down Expand Up @@ -286,6 +293,7 @@ class ProgressBar {
* @param interval minimum time between updates in milliseconds, default: 16
* @param display What is displayed and display order, default: ':title :percent :bar :time :completed/:total'
* @param prettyTime Whether to pretty print time and eta
* @param output Output stream, can be Deno.stdout or Deno.stderr, default is Deno.stdout
*/
constructor(options: ConstructorOptions): void;

Expand Down Expand Up @@ -382,7 +390,3 @@ Log some messages next to the bar
![console](./screenshots/info.gif)

More screenshots in the `screenshots` folder.

## Changelog

[changelog](./changelog.md)
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## Changelog

### v1.5.0 - 2024.04.02
[Allow to configure the writer to something other than stdout](https://github.com/deno-library/progress/issues/30)

### v1.4.9 - 2024.04.02

[Both JSR and HTTPS are supported](https://github.com/deno-library/progress/issues/29)
Expand Down
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@deno-library/progress",
"version": "1.4.9",
"version": "1.5.0",
"exports": {
".": "./mod.ts",
"./time": "./time.ts"
Expand Down
23 changes: 23 additions & 0 deletions examples/stderr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import ProgressBar from "../mod.ts";
import { delay } from "../deps.example.ts";

const total = 100;

const progress = new ProgressBar({
total,
// ==> here
output: Deno.stderr,
// <== here
});

let completed = 0;

async function download() {
while (completed <= total) {
await progress.render(completed++);

await delay(50);
}
}

await download();
24 changes: 7 additions & 17 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { bgGreen, bgWhite, stripAnsiCode } from "./deps.ts";
import { prettyTime, type prettyTimeOptions } from "./time.ts";
export { MultiProgressBar } from "./multi.ts";

const hasStdout = Deno.stdout;
const isTerminal = Deno.stdout.isTerminal;

const enum Direction {
left,
Expand All @@ -21,6 +21,7 @@ interface constructorOptions {
interval?: number;
display?: string;
prettyTime?: boolean;
output?: typeof Deno.stdout | typeof Deno.stderr;
}

interface renderOptions {
Expand Down Expand Up @@ -54,16 +55,7 @@ export default class ProgressBar {
private start = Date.now();
private lastRenderTime = 0;
private encoder = new TextEncoder();
private writer = Deno.stdout.writable.getWriter();

// Deno Version 1.39.1 no longer reports errors
// Note from @bjesuiter: This MUST be a Lamda function compared to a class member function,
// otherwise it will leak async ops in `deno test`
// Deno Version: 1.27.1
// private signalListener = () => {
// this.end();
// Deno.exit();
// };
private writer: WritableStreamDefaultWriter<Uint8Array>;

/**
* Title, total, complete, incomplete, can also be set or changed in the render method
Expand All @@ -77,6 +69,7 @@ export default class ProgressBar {
* - interval minimum time between updates in milliseconds, default: 16
* - display What is displayed and display order, default: ':title :percent :bar :time :completed/:total'
* - prettyTime Whether to pretty print time and eta
* - output Output stream, can be Deno.stdout or Deno.stderr, default is Deno.stdout
*/
constructor({
title = "",
Expand All @@ -89,6 +82,7 @@ export default class ProgressBar {
interval = 16,
display,
prettyTime = false,
output = Deno.stdout,
}: constructorOptions = {}) {
this.title = title;
this.total = total;
Expand All @@ -101,7 +95,7 @@ export default class ProgressBar {
this.display = display ??
":title :percent :bar :time :completed/:total :text";
this.prettyTime = prettyTime;
// Deno.addSignalListener("SIGINT", this.signalListener);
this.writer = output.writable.getWriter();
}

/**
Expand All @@ -117,7 +111,7 @@ export default class ProgressBar {
* - `prettyTimeOptions` prettyTime options
*/
async render(completed: number, options: renderOptions = {}): Promise<void> {
if (this.#end || !hasStdout) return;
if (this.#end || !isTerminal) return;

if (completed < 0) {
throw new Error(`completed must greater than or equal to 0`);
Expand Down Expand Up @@ -206,7 +200,6 @@ export default class ProgressBar {
* No need to call in most cases, unless you want to end before 100%
*/
async end(): Promise<void> {
// Deno.removeSignalListener("SIGINT", this.signalListener);
if (this.#end) return;
this.#end = true;
if (this.clear) {
Expand Down Expand Up @@ -252,13 +245,10 @@ export default class ProgressBar {
switch (direction) {
case Direction.all:
return this.stdoutWrite("\x1b[2K");
// break;
case Direction.left:
return this.stdoutWrite("\x1b[1K");
// break;
case Direction.right:
return this.stdoutWrite("\x1b[0K");
// break;
}
}

Expand Down
21 changes: 7 additions & 14 deletions multi.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { bgGreen, bgWhite, stripAnsiCode } from "./deps.ts";
import { prettyTime, type prettyTimeOptions } from "./time.ts";

const hasStdout = Deno.stdout;
const isTerminal = Deno.stdout.isTerminal;

interface constructorOptions {
title?: string;
Expand All @@ -12,6 +12,7 @@ interface constructorOptions {
interval?: number;
display?: string;
prettyTime?: boolean;
output?: typeof Deno.stdout | typeof Deno.stderr;
}

interface renderOptions {
Expand Down Expand Up @@ -49,16 +50,7 @@ export class MultiProgressBar {
private start = Date.now();
private lastRenderTime = 0;
private encoder = new TextEncoder();
private writer = Deno.stdout.writable.getWriter();

// Deno Version 1.39.1 no longer reports errors
// Note from @bjesuiter: This MUST be a Lamda function compared to a class member function,
// otherwise it will leak async ops in `deno test`
// Deno Version: 1.27.1
// private signalListener = () => {
// this.end();
// Deno.exit();
// };
private writer: WritableStreamDefaultWriter<Uint8Array>;

/**
* Title, total, complete, incomplete, can also be set or changed in the render method
Expand All @@ -71,6 +63,7 @@ export class MultiProgressBar {
* - interval minimum time between updates in milliseconds, default: 16
* - display What is displayed and display order, default: ':bar :text :percent :time :completed/:total'
* - prettyTime Whether to pretty print time and eta
* - output Output stream, can be Deno.stdout or Deno.stderr, default is Deno.stdout
*/
constructor({
title = "",
Expand All @@ -81,6 +74,7 @@ export class MultiProgressBar {
interval,
display,
prettyTime = false,
output = Deno.stdout,
}: constructorOptions = {}) {
if (title != "") {
this.#bars.push({ str: title });
Expand All @@ -93,7 +87,7 @@ export class MultiProgressBar {
this.interval = interval ?? 16;
this.display = display ?? ":bar :text :percent :time :completed/:total";
this.prettyTime = prettyTime;
// Deno.addSignalListener("SIGINT", this.signalListener);
this.writer = output.writable.getWriter();
}

/**
Expand All @@ -108,7 +102,7 @@ export class MultiProgressBar {
* - `prettyTimeOptions` - prettyTime options
*/
async render(bars: Array<renderOptions>): Promise<void> {
if (this.#end || !hasStdout) return;
if (this.#end || !isTerminal) return;

const now = Date.now();
const ms = now - this.lastRenderTime;
Expand Down Expand Up @@ -197,7 +191,6 @@ export class MultiProgressBar {
* No need to call in most cases, unless you want to end before 100%
*/
async end(): Promise<void> {
// Deno.removeSignalListener("SIGINT", this.signalListener);
if (this.#end) return;
this.#end = true;
if (this.clear) {
Expand Down

0 comments on commit 32cd98a

Please sign in to comment.