Skip to content

wdzeng/poopoobar

Repository files navigation

PooPooBar

A cool CLI progress bar.

demo

  • Simple: easy to use.
  • Lightweight: no dependency.
  • Informative: instant and precise progress, ETA, and speed
  • Smart: silent on non-tty.
  • TypeScript supported.
  • CommonJS/ESM supported.

Installation

npm install poopoobar

Usage

Import the package:

import { ProgressBar } from 'poopoobar'       // esm
const { ProgressBar } = require('poopoobar')  // cjs

Example:

const bar = new ProgressBar(100)
bar.start()

for (let i=0; i<100; i++) {
  // do_sync_task()      // bad: don't run synchornized task
  await do_async_task()  // good
  bar.tick()
}
bar.stop()

Another example:

const bar = new ProgressBar(100, { clearAfterStop: true, width: 80 })
bar.start()

try {
  for (let i=0; i<100; i+=2) {
    bar.log('Start task %d and %d', i, i+1)
    await do_two_tasks()
    bar.tick(2)
    bar.log('Task %d and %d finished', i, i+1)
  }
} finally {
  bar.stop()
}

API

  • class ProgressBar

    Property Type Description
    progress number current progress value; guaranteed to be a non-negative integer
    total number total progress value; guaranteed to be a positive integer
  • ProgressBar(total: number, options?: object)

    Creates a progress bar instance.

    Argument Type Description
    total number total progress; must be a positive integer
    options? object progress bar options; default to all default options
    options.width? number progress bar width; must be at least 16; default to terminal column count
    options.output? tty.WriteStream output stream; default to process.stderr
    options.bottom? boolean draw the bar at the terminal bottom; default to false
    options.clearAfterStop? boolean clear the bar on terminal after stopping; must be true if bottom is true; default to matching bottom
    options.tryNotToBlink? boolean take more actions to prevent the terminal frmo blinking; default to false

    You probably don't want to use two progress bars simultaneously, as this can break the drawing.

    If options.bottom is true, options.clearAfterStop must also be true. This is because if we do not erase the bottom bar after the progress bar stops, the future messages will eventually overwrite the bar.

    See When to tryNotToBlink at the bottom section.

  • progressBar.start()

    Start the progress bar. By this time the progress bar is drawn on the terminal and is refreshed periodically. This cannot be called twice.

  • progressBar.tick(value?: number)

    Increase the progress bar value. The new progress must not exceed total. This must be called only after start().

    Argument Type Description
    value? number progress increment value; must be a non-negative integer; default to 1
  • progressBar.stop()

    Stop the progress bar and any drawings. This clears the bar on the terminal if options.clearAfterStop is set to true. This must be called after start(). This acts as a no-op if called more than once.

    You cannot restart a progress bar after stopping. Use a new progress bar instance in this case.

  • progressBar.log(format: string, ...arguments: any[])

    Print a message. If the progress bar is not running or if this is a non-tty program, it acts as a trivial print.

    Argument Type Description
    format string see util.format
    ...arguments any[] see util.format

    Do not directly call process.stderr.write or console.error (or write to the bar stream) when the progress bar is running, as it can break the drawing.

When to tryNotToBlink

Some terminals may blink when the program frequently draw and erase texts. By enabling tryNotToBlink, the progress bar takes more action to deal with the drawing, which can reduce the possibility the terminal blinks.

Some terminals (e.g. VS Code integrated terminal) has great rendering techniques. In this case you do not need to enable this option.

Enabling tryNotToBlink has a very critical prerequisite that every message must be one-line only. Note that a long message which occupies more than on rows on the terminal is not a one-line message.

Follow the following questions if you are not sure whether to enable it:

  1. Will you call log() method when the progress bar is running?
    • no -> false
    • maybe/yes -> goto next question
  2. Do you care about terminal blinking?
    • no -> false
    • yes -> goto next question
  3. Try to set this to false and run your program. Does the terminal blink?
    • no -> false
    • yes -> goto next question
  4. Will there be any long or multiline message?
    • maybe/yes -> false
    • no -> true