├── .gitignore
├── .npmignore
├── .travis.yml
├── LICENSE
├── README.md
├── example
├── example.js
├── example.sh
└── example.svg
├── index.js
├── package.json
└── test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | example
2 | .travis.yml
3 | test.js
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '9'
4 | - '8'
5 | - '7'
6 | - '6'
7 | - '5'
8 | - '4'
9 | - '0.12'
10 | - '0.10'
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016-2017 Thomas Watson Steen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # progress-string
2 |
3 | Generate a CLI progress bar as a string that you can then output in any
4 | way you like.
5 |
6 |
7 |
8 | [](https://travis-ci.org/watson/progress-string)
9 | [](https://github.com/feross/standard)
10 |
11 | ## Installation
12 |
13 | ```
14 | npm install progress-string --save
15 | ```
16 |
17 | ## Usage
18 |
19 | ```js
20 | var progress = require('progress-string')
21 | var diff = require('ansi-diff-stream')()
22 |
23 | var value = 0
24 | var total = 42
25 | var bar = progress({width: 50, total: total})
26 |
27 | setInterval(function () {
28 | diff.write(
29 | 'The progress of the program is:\n' +
30 | bar(++value)
31 | )
32 | if (value === total) process.exit()
33 | }, 250)
34 |
35 | diff.pipe(process.stdout)
36 | ```
37 |
38 | ## API
39 |
40 | ### `var bar = progress(options)`
41 |
42 | This module exposes a function that takes a single `options` argument
43 | and retuns a bar function.
44 |
45 | These are the options:
46 |
47 | - `total` - (integer) The max value of the progress bar
48 | - `width` - (integer, default: 42) The width of the progress bar in chars
49 | - `incomplete` - (string, default: `-`) The char used to indicate the
50 | incomplete part of the progress bar
51 | - `complete` - (string, default: `=`) The char used to indicate the
52 | completed part of the progress bar
53 | - `style` - (function, optional) See `options.style` below for details
54 |
55 | #### `options.style`
56 |
57 | You can provide a custom styling function to style the progress bar
58 | returned by the `bar` function.
59 |
60 | It will be called with two arguments: `complete` and `incomplete`. Each
61 | a string representing its part of the progress bar.
62 |
63 | Whatever the style function returns will be returned by the `bar`
64 | function.
65 |
66 | ```js
67 | var bar = progress({
68 | width: 10,
69 | total: 100,
70 | style: function (complete, incomplete) {
71 | // add an arrow at the head of the completed part
72 | return complete + '>' + incomplete
73 | }
74 | })
75 |
76 | console.log(bar(50)) // =====>-----
77 | ```
78 |
79 | ### `var str = bar(value)`
80 |
81 | Call the `bar` function with the `value` you want to the generated
82 | progress bar to have.
83 |
84 | The `bar` function will return a string representation of the progress
85 | bar.
86 |
87 | ## License
88 |
89 | MIT
90 |
--------------------------------------------------------------------------------
/example/example.js:
--------------------------------------------------------------------------------
1 | var progress = require('../')
2 | var diff = require('ansi-diff-stream')()
3 |
4 | var value = 0
5 | var total = 1024
6 | var bar = progress({width: 50, total: total})
7 | var arrow = progress({
8 | width: 50,
9 | total: total,
10 | style: function (complete, incomplete) {
11 | return complete.slice(0, complete.length - 1) + '>' + incomplete
12 | }
13 | })
14 |
15 | var custom = progress({
16 | width: 48,
17 | total: total,
18 | style: function (complete, incomplete) {
19 | return '#'.repeat(complete.length) + '' + ' '.repeat(incomplete.length)
20 | }
21 | })
22 |
23 | var int = setInterval(function () {
24 | value += 32
25 | diff.write(
26 | 'default progress bar: ' +
27 | bar(value) + '\n' +
28 | 'but you can style it: ' +
29 | arrow(value) + '\n' +
30 | 'in any way you want: ' +
31 | '[' + custom(value) + ']' + ' (' + value + '/' + total + ')'
32 | )
33 | if (value === total) {
34 | clearInterval(int)
35 | setTimeout(() => {
36 | process.exit()
37 | }, 1000)
38 | }
39 | }, 250)
40 |
41 | diff.pipe(process.stdout)
42 |
--------------------------------------------------------------------------------
/example/example.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -u
3 |
4 | svg-term --command="node example/example" \
5 | --out example/example.svg \
6 | --height=3 \
7 | --no-cursor \
8 | --padding=10 \
9 | --width=84 \
10 | --term=terminal \
11 | --profile=Pro
12 |
--------------------------------------------------------------------------------
/example/example.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | module.exports = function (opts) {
4 | if (!Number.isFinite(opts.total)) throw new Error('missing required opts.total')
5 |
6 | var width = opts.width || 42
7 | var total = opts.total
8 | var incomplete = Array(width + 1).join(opts.incomplete || '-')
9 | var complete = Array(width + 1).join(opts.complete || '=')
10 | var style = opts.style || defaultStyle
11 | var unit = total / width
12 |
13 | return function (value) {
14 | var chars = unit === 0 ? width : Math.floor(value / unit)
15 | if (value >= total) chars = complete.length
16 | return style(complete.slice(0, chars), incomplete.slice(chars))
17 | }
18 | }
19 |
20 | function defaultStyle (complete, incomplete) {
21 | return complete + incomplete
22 | }
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "progress-string",
3 | "version": "1.2.2",
4 | "description": "Get a progess bar as a string",
5 | "main": "index.js",
6 | "scripts": {
7 | "example": "sh example/example.sh",
8 | "test": "standard && node test.js"
9 | },
10 | "keywords": [
11 | "progress",
12 | "bar",
13 | "cli"
14 | ],
15 | "author": "Thomas Watson Steen (https://twitter.com/wa7son)",
16 | "license": "MIT",
17 | "dependencies": {},
18 | "devDependencies": {
19 | "ansi-diff-stream": "^1.2.0",
20 | "standard": "^8.5.0",
21 | "svg-term-cli": "^2.1.1",
22 | "tape": "^4.6.2"
23 | },
24 | "repository": {
25 | "type": "git",
26 | "url": "git+https://github.com/watson/progress-string.git"
27 | },
28 | "bugs": {
29 | "url": "https://github.com/watson/progress-string/issues"
30 | },
31 | "homepage": "https://github.com/watson/progress-string#readme",
32 | "coordinates": [
33 | 52.1630635,
34 | -7.1482208
35 | ]
36 | }
37 |
--------------------------------------------------------------------------------
/test.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | var test = require('tape')
4 | var progress = require('./')
5 |
6 | test('no options', function (t) {
7 | t.throws(function () {
8 | progress()
9 | })
10 | t.end()
11 | })
12 |
13 | test('empty options object', function (t) {
14 | t.throws(function () {
15 | progress({})
16 | })
17 | t.end()
18 | })
19 |
20 | test('opts.total === 0', function (t) {
21 | t.doesNotThrow(function () {
22 | progress({total: 0})
23 | })
24 | t.end()
25 | })
26 |
27 | test('0 of 0', function (t) {
28 | var bar = progress({width: 10, total: 0})
29 | t.equal(bar(1), '==========')
30 | t.end()
31 | })
32 |
33 | test('1 of 0', function (t) {
34 | var bar = progress({width: 10, total: 0})
35 | t.equal(bar(1), '==========')
36 | t.end()
37 | })
38 |
39 | test('0% of 100', function (t) {
40 | var bar = progress({width: 10, total: 100})
41 | t.equal(bar(0), '----------')
42 | t.end()
43 | })
44 |
45 | test('1% of 100', function (t) {
46 | var bar = progress({width: 10, total: 100})
47 | t.equal(bar(1), '----------')
48 | t.end()
49 | })
50 |
51 | test('50% of 100', function (t) {
52 | var bar = progress({width: 10, total: 100})
53 | t.equal(bar(50), '=====-----')
54 | t.end()
55 | })
56 |
57 | test('99% of 100', function (t) {
58 | var bar = progress({width: 10, total: 100})
59 | t.equal(bar(99), '=========-')
60 | t.end()
61 | })
62 |
63 | test('100% of 100', function (t) {
64 | var bar = progress({width: 10, total: 100})
65 | t.equal(bar(100), '==========')
66 | t.end()
67 | })
68 |
69 | test('custom chars', function (t) {
70 | var bar = progress({width: 10, total: 100, incomplete: '*', complete: '#'})
71 | t.equal(bar(50), '#####*****')
72 | t.end()
73 | })
74 |
75 | test('options.style', function (t) {
76 | var bar = progress({width: 10, total: 100, style: style})
77 | t.equal(bar(50), '=====>-----')
78 | t.end()
79 |
80 | function style (complete, incomplete) {
81 | return complete + '>' + incomplete
82 | }
83 | })
84 |
--------------------------------------------------------------------------------