ansi-scrollbox
Advanced tools
Comparing version 0.1.0 to 0.2.0
@@ -7,3 +7,8 @@ # ansi-scrollbox change log | ||
## 0.2.0 | ||
* Calculate all scrolling from the start of the content. | ||
Previously scrolling to the end, then back up, would calculate scrolling from the end of the content, so the content would autoscroll as it was updated. Now ansi-scrollbox only autoscrolls if you're at the very bottom. | ||
* Add a `subscribe(listener)` API to listen for updates to content, size or scroll | ||
## 0.1.0 | ||
* Initial (pretty beta) release. |
@@ -38,3 +38,3 @@ var scrollbox = require('./') | ||
write() | ||
setInterval(write, 100) | ||
box.subscribe(write) | ||
@@ -41,0 +41,0 @@ // make `process.stdin` begin emitting "keypress" events |
63
index.js
@@ -7,12 +7,22 @@ var assert = require('assert') | ||
assert.equal(typeof opts, 'object', 'opts must be object') | ||
// user facing state | ||
var content = opts.content || '' | ||
var width = opts.width | ||
var height = opts.height | ||
// list of lines (split `content` according to `width`) | ||
// so we can easily show parts of the scrollable content | ||
var lines = [] | ||
var linesDirty = false | ||
var linesDirty = false // if true `lines` needs to be updated before use | ||
var sub = Subscribable() | ||
var instance = { | ||
subscribe: sub.subscribe, | ||
setContent: setContent, | ||
resize: resize, | ||
scroll: scroll, | ||
scrollUp: scrollUp, | ||
scrollDown: scrollDown, | ||
keypress: keypress, | ||
@@ -33,2 +43,3 @@ toString: toString, | ||
linesDirty = true | ||
sub.notify() | ||
} | ||
@@ -44,2 +55,3 @@ | ||
linesDirty = true | ||
sub.notify() | ||
} | ||
@@ -51,5 +63,12 @@ | ||
offset = _offset | ||
sub.notify() | ||
} | ||
function scrollUp (d) { | ||
scroll(offset < 0 ? offset - d : Math.max(offset - d, 0)) | ||
} | ||
function scrollDown (d) { | ||
scroll(offset >= 0 ? offset + d : Math.min(offset + d, -1)) | ||
} | ||
// TODO optimize | ||
// TODO optimize somehow | ||
function updateLinesCache () { | ||
@@ -60,6 +79,20 @@ lines = wrapAnsi(content, width, { wordWrap: false }).split('\n') | ||
// ensure `offset` is an in-range scroll offset (first visible line index) | ||
// or -1 (stick to bottom) | ||
function resolveOffset () { | ||
if (offset === -1) return | ||
if (offset >= lines.length - height) { | ||
offset = Math.max(0, lines.length - height) | ||
} else if (offset < -1) { | ||
offset = Math.max(0, lines.length + offset + 1 - height) | ||
} | ||
} | ||
function toString () { | ||
if (linesDirty) updateLinesCache() | ||
var o = offset < 0 ? lines.length - height + offset : Math.min(lines.length - height, offset) | ||
resolveOffset() | ||
var o = offset === -1 ? lines.length - height : Math.min(lines.length - height, offset) | ||
var visible = lines.slice(o, o + height) | ||
// fill the rest of the space so height doesn't vary | ||
while (visible.length < height) visible.push('') | ||
@@ -72,6 +105,6 @@ return visible.join('\n') | ||
if (key.name === 'down' || key.name === 'j') { | ||
offset = offset >= 0 ? offset + 1 : Math.min(offset + 1, -1) | ||
scrollDown(1) | ||
} | ||
if (key.name === 'up' || key.name === 'k') { | ||
offset = offset < 0 ? offset - 1 : Math.max(offset - 1, 0) | ||
scrollUp(1) | ||
} | ||
@@ -84,1 +117,21 @@ if (key.name === 'home') offset = 0 | ||
} | ||
function Subscribable () { | ||
var listeners = [] | ||
function subscribe (fn) { | ||
listeners.push(fn) | ||
return function () { | ||
var i = listeners.indexOf(fn) | ||
if (i !== -1) listeners.splice(i, 1) | ||
} | ||
} | ||
function notify () { | ||
listeners.forEach(function (fn) { fn() }) | ||
} | ||
return { | ||
subscribe: subscribe, | ||
notify: notify | ||
} | ||
} |
{ | ||
"name": "ansi-scrollbox", | ||
"description": "a basic scrollable area for terminal apps", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"author": "Renée Kooi <renee@kooi.me>", | ||
@@ -6,0 +6,0 @@ "bugs": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
8361
164