Skip to content

Commit

Permalink
feat: add inc method for incrementing pbar value
Browse files Browse the repository at this point in the history
  • Loading branch information
Thanga-Ganapathy committed Apr 5, 2024
1 parent d73f626 commit 91c6883
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 94 deletions.
5 changes: 5 additions & 0 deletions .changeset/pink-chefs-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@opentf/cli-pbar': minor
---

Added inc method to increment the progress bar value.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ build
built
lib

play.js
play.js
test.[tj]s
126 changes: 97 additions & 29 deletions README.md

Large diffs are not rendered by default.

Binary file added assets/count-demo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@opentf/cli-pbar",
"version": "0.4.0",
"description": "CLI progress bar.",
"description": "The Customizable CLI Progress Bars.",
"keywords": [
"cli",
"progress",
Expand Down Expand Up @@ -80,7 +80,7 @@
},
"dependencies": {
"@opentf/cli-styles": "^0.15.0",
"@opentf/std": "^0.4.0"
"@opentf/std": "^0.5.0"
},
"publishConfig": {
"access": "public",
Expand Down
8 changes: 4 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

106 changes: 69 additions & 37 deletions src/ProgressBar.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,55 @@
import { EOL } from 'node:os';
import { style } from '@opentf/cli-styles';
import {
compact,
intersperse,
isObj,
percentage,
percentageOf,
shallowMerge,
} from '@opentf/std';
import { type Bar, type BarSize, type Options } from './types';
import { DEFAULT_BAR_CHAR, MEDIUM_BAR_CHAR, SMALL_BAR_CHAR } from './constants';

class ProgressBar {
private _stream: NodeJS.WriteStream;
private _width: number;
private _color: string;
private _bgColor: string;
private _autoClear: boolean;
private _options: Options = {
stream: process.stderr,
width: 30,
color: 'g',
bgColor: 'gr',
autoClear: false,
size: 'DEFAULT',
prefix: '',
suffix: '',
showPercent: true,
showCount: false,
};
private _bars: Bar[];
private _size: BarSize;

constructor(options?: Options) {
this._stream = options?.stream || process.stderr;
this._width = options?.width || 30;
this._color = options?.color || 'g';
this._bgColor = options?.bgColor || 'gr';
this._autoClear = options?.autoClear || false;

constructor(options?: Partial<Options>) {
this._options = shallowMerge(this._options, options as object) as Options;
this._bars = [];
this._size = options?.size || 'DEFAULT';
}

private _getBarCharBySize(size: BarSize | undefined) {
const s = size || this._size;
if (s === 'DEFAULT') {
return DEFAULT_BAR_CHAR;
const s = size || this._options.size;
if (s === 'SMALL') {
return SMALL_BAR_CHAR;
} else if (s === 'MEDIUM') {
return MEDIUM_BAR_CHAR;
}

return SMALL_BAR_CHAR;
return DEFAULT_BAR_CHAR;
}

private _getBars(bar: Bar, percent: number): string {
const barChar = this._getBarCharBySize(bar.size);
const color = bar.color || this._color;
const bgColor = bar.bgColor || this._bgColor;
const percentVal = Math.trunc(percentageOf(percent, this._width));
const color = bar.color || this._options.color;
const bgColor = bar.bgColor || this._options.bgColor;
const percentVal = Math.trunc(percentageOf(percent, this._options.width));
const doneBars = style(`$${color}.bol{${barChar}}`).repeat(percentVal);
const bgBars = style(`$${bgColor}.dim{${barChar}}`).repeat(
this._width - percentVal
this._options.width - percentVal
);
return doneBars + bgBars;
}
Expand All @@ -56,11 +59,21 @@ class ProgressBar {
let str = '';

if (i > 0) {
this._stream.write('\n');
this._options.stream.write(EOL);
}

const prefix = b.prefix || '';
const suffix = b.suffix || '';
const prefix = Object.hasOwn(b, 'prefix')
? b.prefix
: this._options.prefix;
const suffix = Object.hasOwn(b, 'suffix')
? b.suffix
: this._options.suffix;
const showPercent = Object.hasOwn(b, 'showPercent')
? b.showPercent
: this._options.showPercent;
const showCount = Object.hasOwn(b, 'showCount')
? b.showCount
: this._options.showCount;

if (b.progress) {
const percent = b.total
Expand All @@ -69,62 +82,75 @@ class ProgressBar {
const bar = this._getBars(b, percent);
str += (
intersperse(
compact([prefix, bar, percent + '%', suffix]),
compact([
prefix,
bar,
showPercent ? percent + '%' : null,
showCount ? `[${b.value || 0}/${b.total || 0}]` : null,
suffix,
]),
' '
) as string[]
).join('');
} else {
str += prefix + ' ' + suffix;
}

if (this._stream.cursorTo(0) && this._stream.clearLine(0)) {
this._stream.write(str);
if (
this._options.stream.cursorTo(0) &&
this._options.stream.clearLine(0)
) {
this._options.stream.write(str);
}
});
}

/** Starts rendering of the progress bars. */
start(obj?: Partial<Bar>) {
if (typeof obj === 'object') {
this._bars.push({ ...obj, progress: true } as Bar);
}
this._render();
}

_clear() {
this._stream.moveCursor(0, -(this._bars.length - 1));
this._stream.cursorTo(0);
this._stream.clearScreenDown();
private _clear() {
this._options.stream.moveCursor(0, -(this._bars.length - 1));
this._options.stream.cursorTo(0);
this._options.stream.clearScreenDown();
}

/** Stops the current progress bar with optional message to display. */
stop(msg?: string) {
if (this._autoClear) {
if (this._options.autoClear) {
this._clear();
if (msg) {
this._stream.write(msg + '\n');
this._options.stream.write(msg + EOL);
}
return;
}
this._stream.write('\n');
this._options.stream.write(EOL);
}

/** Update the current progress bar */
update(obj: Partial<Bar>, id?: number) {
if (!id) {
this._bars[0] = { ...(this._bars[0] as Bar), ...obj } as Bar;
} else {
const index = this._bars.findIndex((b) => isObj(b) && b.id === id);
this._bars[index] = { ...(this._bars[index] as Bar), ...obj } as Bar;
}
this._stream.moveCursor(0, -(this._bars.length - 1));
this._options.stream.moveCursor(0, -(this._bars.length - 1));
this._render();
}

/** Adds a new progress bar to the rendering stack. */
add(obj: Partial<Bar>) {
if (isObj(obj)) {
const id = this._bars.length + 1;
const barInstance = { progress: true, ...obj, id } as Bar;
this._bars.push(barInstance);
if (this._bars.length > 2) {
this._stream.moveCursor(0, -(this._bars.length - 2));
this._options.stream.moveCursor(0, -(this._bars.length - 2));
}
this._render();
return {
Expand All @@ -136,6 +162,12 @@ class ProgressBar {

return null;
}

/** Increment the value + 1, optionally with the provided value. */
inc(bar?: Partial<Bar>, val = 1) {
const n = this._bars[0]?.value || 0;
this.update({ ...bar, value: n + val });
}
}

export default ProgressBar;
45 changes: 24 additions & 21 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
import type { WriteStream } from 'node:tty';

export type BarSize = 'SMALL' | 'MEDIUM' | 'DEFAULT';

export type Options = {
stream?: NodeJS.WriteStream;
width?: number;
color?: string;
bgColor?: string;
autoClear?: boolean;
size?: BarSize;
/** The wriatable stream to use, default is stderr. */
stream: WriteStream;
/** The width of the rendered progress bar. */
width: number;
/** The foreground color of completed bars. */
color: string;
/** The background color of bars. */
bgColor: string;
/** Set true to remove the progress bar after it completed. */
autoClear: boolean;
/** The size of the progress bar to render, default is 30. */
size: BarSize;
/** The string to be prefixed progress bar */
prefix: string;
/** The string to be suffixed progress bar */
suffix: string;
/** Show hide progress bar percent */
showPercent: boolean;
/** Show hide progress bar count */
showCount: boolean;
};

// export interface IRunOptions {
// total: number;
// value: number;
// prefix?: string;
// suffix?: string;
// color?: string;
// }

export type Bar = {
export type Bar = Omit<Options, 'stream' | 'width' | 'autoClear'> & {
id?: number;
total: number;
value: number;
id?: number;
prefix?: string;
suffix?: string;
color?: string;
bgColor?: string;
size?: BarSize;
progress?: boolean;
};

0 comments on commit 91c6883

Please sign in to comment.