feat: 초기 프로젝트 설정 및 룰.md 파일 추가

This commit is contained in:
2025-07-28 09:53:31 +09:00
commit 09a4d38512
8165 changed files with 1021855 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
multimeter
==========
Control multiple ANSI progress bars on the terminal.
![multibar example output](http://substack.net/images/screenshots/multibar.png)
![multimeter](http://substack.net/images/multimeter.png)
example
=======
````javascript
var multimeter = require('multimeter');
var multi = multimeter(process);
multi.drop(function (bar) {
var iv = setInterval(function () {
var p = bar.percent();
bar.percent(p + 1);
if (p >= 100) clearInterval(iv);
}, 25);
});
````
methods
=======
var multimeter = require('multimeter');
var multi = multimeter(stream, ...)
-----------------------------------
Create a new multimeter handle on the supplied stream/process objects, which
will be passed directly to [charm](https://github.com/substack/node-charm).
If you pass in a charm object that will be used instead of creating a new one.
var bar = multi(x, y, params)
-----------------------------
Create a new progress bar at `(x,y)` with `params` which default to:
* width : 10
* before : '['
* after : '] '
* solid : { background : 'blue', foreground : 'white', text : '|' }
* empty : { background : null, foreground : null, text : ' ' }
If `y` is negative or `'-0'` it will be treated as a relative coordinate.
var bar = multi.rel(x, y, params)
---------------------------------
Create a new progress bar at an absolute `x` and relative `y` coordinate with
respect to the present `multi.offset`.
multi.drop(params, cb)
----------------------
Create a new progress bar at the present cursor location. The `bar` object will
be passed to `cb(bar)` once the cursor location has been determined.
multi.on(...), multi.removeListener(...), multi.destroy(...), multi.write(...)
------------------------------------------------------------------------------
Call event emitter functions on the underlying `charm` object.
multi.offset
------------
This getter/setter controls the positioning for relative progress bars.
Increment this value whenever you write a newline to the stream to prevent the
pending progress bars from drifting down from their original positions.
bar.percent(p, msg=p + ' %')
----------------------------
Update the progress bar to `p` percent, a value between 0 and 100, inclusive.
The text to the right of the progress bar will be set to `msg`.
bar.ratio(n, d, msg=n + ' / ' + d)
----------------------------------
Update the progress bar with a ratio, `n/d`.
The text to the right of the progress bar will be set to `msg`.
attributes
==========
multi.charm
-----------
The [charm](https://github.com/substack/node-charm) object used internally to
draw the progress bars.
install
=======
With [npm](http://npmjs.org) do:
npm install multimeter

View File

@@ -0,0 +1,23 @@
var multimeter = require('multimeter');
var multi = multimeter(process);
multi.on('^C', function () {
multi.charm.cursor(true);
multi.write('\n').destroy();
process.exit();
});
multi.charm.cursor(false);
multi.drop(function (bar) {
var iv = setInterval(function () {
var p = bar.percent();
bar.percent(p + 1);
if (p >= 100) {
clearInterval(iv);
multi.charm.cursor(true);
multi.write('\n').destroy();
}
}, 25);
});

View File

@@ -0,0 +1,47 @@
var multimeter = require('multimeter');
var multi = multimeter(process);
multi.on('^C', process.exit);
multi.charm.reset();
var bars = [];
var progress = [];
var deltas = [];
multi.write('Progress:\n\n');
for (var i = 0; i < 5; i++) {
var s = 'ABCDE'[i] + ': \n';
multi.write(s);
var bar = multi(s.length, i + 3, {
width : 20,
solid : {
text : '|',
foreground : 'white',
background : 'blue'
},
empty : { text : ' ' },
});
bars.push(bar);
deltas[i] = 1 + Math.random() * 9;
progress.push(0);
}
multi.write('\nbeep boop\n');
var pending = progress.length;
var iv = setInterval(function () {
progress.forEach(function (p, i) {
progress[i] += Math.random() * deltas[i];
bars[i].percent(progress[i]);
if (p < 100 && progress[i] >= 100) pending --;
if (pending === 0) {
multi.write('\nAll done.\n');
multi.destroy();
clearInterval(iv);
pending --;
}
});
}, 100);

View File

@@ -0,0 +1,52 @@
var multimeter = require('multimeter');
var multi = multimeter(process);
multi.on('^C', process.exit);
var bars = [];
var progress = [];
var deltas = [];
multi.write('Progress:\n\n');
for (var i = 0; i < 5; i++) {
var s = 'ABCDE'[i] + ': \n';
multi.write(s);
var bar = multi.rel(4, i, {
width : 20,
solid : {
text : '|',
foreground : 'white',
background : 'blue'
},
empty : { text : ' ' },
});
bars.push(bar);
deltas[i] = 1 + Math.random() * 9;
progress.push(0);
}
multi.offset += 2;
multi.write('\nbeep');
setTimeout(function () {
multi.offset ++;
multi.write('\n boop');
}, 2000);
var pending = progress.length;
var iv = setInterval(function () {
progress.forEach(function (p, i) {
progress[i] += Math.random() * deltas[i];
bars[i].percent(progress[i]);
if (p < 100 && progress[i] >= 100) pending --;
if (pending === 0) {
multi.write('\nAll done.\n');
multi.destroy();
clearInterval(iv);
pending --;
}
});
}, 100);

View File

@@ -0,0 +1,11 @@
var multimeter = require('multimeter');
var multi = multimeter(process);
multi.drop(function (bar) {
var iv = setInterval(function () {
var p = bar.percent();
bar.percent(p + 1);
if (p >= 100) clearInterval(iv);
}, 25);
});

View File

@@ -0,0 +1,37 @@
var multimeter = require('multimeter');
var multi = multimeter(process);
var charm = multi.charm;
charm.on('^C', process.exit);
charm.reset();
var xs = [];
for (var i = 0; i < 100; i++) xs.push(i);
console.log('Calculating the sum of [0..100]:\n');
charm.write(' ');
multi.drop(function (bar) {
bar.percent(0);
charm.write('\n\nResult: ');
charm.position(function (x, y) {
var sum = 0;
var iv = setInterval(function () {
sum += xs.shift();
bar.percent(100 - xs.length);
charm
.position(x, y)
.erase('end')
.write(sum.toString())
;
if (xs.length === 0) {
clearInterval(iv);
multi.destroy();
}
}, 50);
});
});

View File

@@ -0,0 +1,55 @@
var http = require('http');
var multimeter = require('multimeter');
http.createServer(function (req, res) {
res.setHeader('content-type', 'application/octet-stream');
var multi = multimeter(res);
multi.charm.on('^C', process.exit);
multi.charm.reset();
var bars = [];
var progress = [];
var deltas = [];
for (var i = 0; i < 5; i++) {
var s = 'ABCDE'[i] + ': \n';
multi.write(s);
var bar = multi(s.length, i + 1, {
width : 20,
solid : {
text : '|',
foreground : 'white',
background : 'blue'
},
empty : { text : ' ' },
});
bars.push(bar);
deltas[i] = 1 + Math.random() * 9;
progress.push(0);
}
multi.write('\nbeep boop\n');
var pending = progress.length;
var iv = setInterval(function () {
progress.forEach(function (p, i) {
progress[i] += Math.random() * deltas[i];
bars[i].percent(progress[i]);
if (p < 100 && progress[i] >= 100) pending --;
if (pending === 0) {
multi.write('\nAll done.\n');
res.end();
}
});
}, 100);
res.connection.on('end', function () {
multi.destroy();
clearInterval(iv);
});
}).listen(8080);
console.log('curl -N localhost:8080');

View File

@@ -0,0 +1,60 @@
var http = require('http');
var multimeter = require('multimeter');
http.createServer(function (req, res) {
res.setHeader('content-type', 'application/octet-stream');
var multi = multimeter(res);
multi.charm.on('^C', process.exit);
var bars = [];
var progress = [];
var deltas = [];
for (var i = 0; i < 5; i++) {
var s = 'ABCDE'[i] + ': \n';
multi.write(s);
var bar = multi.rel(4, i, {
width : 20,
solid : {
text : '|',
foreground : 'white',
background : 'blue'
},
empty : { text : ' ' },
});
bars.push(bar);
deltas[i] = 5 + Math.random() * 10;
progress.push(0);
}
multi.offset += 2;
multi.write('\nbeep');
setTimeout(function () {
multi.offset ++;
multi.write('\n boop');
}, 1000);
var pending = progress.length;
var iv = setInterval(function () {
progress.forEach(function (p, i) {
progress[i] += Math.random() * deltas[i];
bars[i].percent(progress[i]);
if (p < 100 && progress[i] >= 100) pending --;
if (pending === 0) {
multi.write('\nAll done.\n');
res.end();
}
});
}, 100);
res.connection.on('end', function () {
multi.destroy();
clearInterval(iv);
});
}).listen(8080);
console.log('curl -N localhost:8080');

View File

@@ -0,0 +1,45 @@
var http = require('http');
var multimeter = require('multimeter');
http.createServer(function (req, res) {
var multi = multimeter(res);
var charm = multi.charm;
var xs = [];
for (var i = 0; i < 100; i++) xs.push(i);
charm.reset()
.write('Calculating the sum of [0..100]:\n\n')
;
var bar = multi(4, 3, { width : 20 });
bar.percent(0);
var sum = 0;
charm.write('\n\nResult: ' + sum);
var iv = setInterval(function () {
var x = xs.shift();
bar.percent(100 - xs.length);
charm
.left(sum.toString().length)
.erase('end')
;
sum += x;
charm.write(sum.toString());
if (xs.length === 0) {
charm.write('\n');
res.end();
}
}, 50);
res.connection.on('end', function () {
multi.destroy();
clearInterval(iv);
});
}).listen(8081);
console.log('curl -N localhost:8081');

76
api.hyungi.net/node_modules/pm2-multimeter/index.js generated vendored Normal file
View File

@@ -0,0 +1,76 @@
var charmer = require('charm');
var Bar = require('./lib/bar');
var exports = module.exports = function (c) {
if (c instanceof charmer.Charm) {
var charm = c;
}
else {
var charm = charmer.apply(null, arguments);
charm.on('^C', function () {
charm.destroy();
});
}
var multi = function (x, y, params) {
if (typeof x === 'object') {
params = x;
x = params.x;
y = params.y;
}
if (!params) params = {};
if (x === undefined) x = '+0';
if (y === undefined) y = '+0';
var bar = new Bar(charm, x, y, params);
multi.bars.push(bar);
bar.offset = multi.offset;
multi.on('offset', function (o) {
bar.offset = o;
});
return bar;
};
multi.bars = [];
multi.rel = function (x, y, params) {
return multi(x, '-' + y, params);
};
multi.drop = function (params, cb) {
if (!cb) { cb = params; params = {} }
charm.position(function (x, y) {
var bar = new Bar(charm, x, y, params);
multi.bars.push(bar);
multi.on('offset', function (o) {
bar.offset = o;
});
cb(bar);
});
};
multi.charm = charm;
charm.setMaxListeners(0);
multi.destroy = charm.destroy.bind(charm);
multi.on = charm.on.bind(charm);
multi.emit = charm.emit.bind(charm);
multi.removeListener = charm.removeListener.bind(charm);
multi.write = charm.write.bind(charm);
(function () {
var offset = 0;
Object.defineProperty(multi, 'offset', {
set : function (o) {
offset = o;
multi.emit('offset', o);
},
get : function () {
return offset;
}
});
})();
return multi;
};

111
api.hyungi.net/node_modules/pm2-multimeter/lib/bar.js generated vendored Normal file
View File

@@ -0,0 +1,111 @@
var Bar = module.exports = function (charm, x, y, params) {
this.charm = charm;
this.x = x;
this.y = y;
this.width = params.width || 10;
this.offset = params.offset || 0;
this.before = params.before || '[';
this.after = params.after || '] ';
this.solid = params.solid || {
background : 'blue',
foreground : 'white',
text : '|'
};
this.empty = params.empty || {
background : null,
foreground : null,
text : ' '
};
this.progress = {
percent : 0,
ratio : 0
};
}
Bar.prototype.draw = function (bars, msg) {
bars = Math.floor(bars);
this.charm.push(true);
if (this.y.toString().match(/^[+-]/)) {
if (this.y.toString().match(/^-/)) {
this.charm.up(-this.y + this.offset);
}
else if (this.y.toString().match(/^\+/)) {
this.charm.down(+this.y - this.offset);
}
this.charm.column(+this.x);
}
else {
this.charm.position(this.x, this.y);
}
this.charm.write(this.before);
if (this.solid.background) {
this.charm.background(this.solid.background);
}
if (this.solid.foreground) {
this.charm.foreground(this.solid.foreground);
}
this.charm
.write(Array(bars + 1).join(this.solid.text))
.display('reset')
;
if (this.empty.background) {
this.charm.background(this.empty.background);
}
if (this.empty.foreground) {
this.charm.foreground(this.empty.foreground);
}
this.charm
.write(Array(this.width - bars + 1).join(this.empty.text))
.write(this.after + msg)
;
this.charm.pop(true);
return this;
};
Bar.prototype.percent = function (p, msg) {
if (p === undefined) {
return this.progress.percent;
}
else {
p = Math.min(100, p);
this.progress.percent = p;
this.progress.ratio = [ p, 100 ];
this.draw(
this.width * p / 100,
msg || (Math.floor(p) + ' %')
);
return this;
}
};
Bar.prototype.ratio = function (n, d, msg) {
if (n === undefined && d === undefined) {
return this.progress.ratio;
}
else {
var f = n / d;
this.progress.ratio = [ n, d ];
this.progress.percent = f * 100;
this.draw(
this.width * f,
msg || (n + ' / ' + d)
);
return this;
}
};

View File

@@ -0,0 +1,34 @@
{
"name" : "pm2-multimeter",
"version" : "0.1.2",
"description" : "render multiple progress bars at once on the terminal with eventlimit maxed",
"main" : "index.js",
"directories" : {
"lib" : ".",
"example" : "example",
"test" : "test"
},
"dependencies" : {
"charm" : "~0.1.1"
},
"repository" : {
"type" : "git",
"url" : "https://github.com/Unitech/node-multimeter.git"
},
"keywords" : [
"progress",
"bar",
"status",
"meter",
"terminal",
"console",
"ansi"
],
"author" : {
"name" : "James Halliday",
"email" : "mail@substack.net",
"url" : "http://substack.net"
},
"license" : "MIT/X11",
"engine" : { "node" : ">=0.4" }
}