Skip to content

Commit

Permalink
Paginator now handles multiple lines (#602)
Browse files Browse the repository at this point in the history
Prior to this, a list with multi-line items works erratically; the
current selection might be off the screen, or the list height may vary
depending on which items are selected.

As part of this, Paginator now takes an optional ScreenManager instance.
Prompts have been updated accordingly.
  • Loading branch information
joshkel authored and SBoudrias committed Nov 12, 2017
1 parent b701876 commit 70174ed
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 13 deletions.
2 changes: 1 addition & 1 deletion lib/prompts/checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function Prompt() {
// Make sure no default is set (so it won't be printed)
this.opt.default = null;

this.paginator = new Paginator();
this.paginator = new Paginator(this.screen);
}
util.inherits(Prompt, Base);

Expand Down
2 changes: 1 addition & 1 deletion lib/prompts/expand.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function Prompt() {
// Setup the default string (capitalize the default key)
this.opt.default = this.generateChoicesString(this.opt.choices, this.opt.default);

this.paginator = new Paginator();
this.paginator = new Paginator(this.screen);
}
util.inherits(Prompt, Base);

Expand Down
2 changes: 1 addition & 1 deletion lib/prompts/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function Prompt() {
// Make sure no default is set (so it won't be printed)
this.opt.default = null;

this.paginator = new Paginator();
this.paginator = new Paginator(this.screen);
}
util.inherits(Prompt, Base);

Expand Down
11 changes: 10 additions & 1 deletion lib/utils/paginator.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,25 @@ var chalk = require('chalk');
* a subset of the choices if the list is too long.
*/

var Paginator = module.exports = function () {
var Paginator = module.exports = function (screen) {
this.pointer = 0;
this.lastIndex = 0;
this.screen = screen;
};

Paginator.prototype.paginate = function (output, active, pageSize) {
pageSize = pageSize || 7;
var middleOfList = Math.floor(pageSize / 2);
var lines = output.split('\n');

if (this.screen) {
lines = this.screen.breakLines(lines);
active = _.sum(lines.map(function (lineParts) {
return lineParts.length;
}).splice(0, active));
lines = _.flatten(lines);
}

// Make sure there's enough lines to paginate
if (lines.length <= pageSize) {
return output;
Expand Down
20 changes: 11 additions & 9 deletions lib/utils/screen-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ ScreenManager.prototype.render = function (content, bottomContent) {
var cursorPos = this.rl._getCursorPos();
var width = this.normalizedCliWidth();

content = forceLineReturn(content, width);
content = this.forceLineReturn(content, width);
if (bottomContent) {
bottomContent = forceLineReturn(bottomContent, width);
bottomContent = this.forceLineReturn(bottomContent, width);
}
// Manually insert an extra line if we're at the end of the line.
// This prevent the cursor from appearing at the beginning of the
Expand Down Expand Up @@ -115,9 +115,10 @@ ScreenManager.prototype.normalizedCliWidth = function () {
return width;
};

function breakLines(lines, width) {
// Break lines who're longuer than the cli width so we can normalize the natural line
// returns behavior accross terminals.
ScreenManager.prototype.breakLines = function (lines, width) {
// Break lines who're longer than the cli width so we can normalize the natural line
// returns behavior across terminals.
width = width || this.normalizedCliWidth();
var regex = new RegExp(
'(?:(?:\\033[[0-9;]*m)*.?){1,' + width + '}',
'g'
Expand All @@ -128,8 +129,9 @@ function breakLines(lines, width) {
chunk.pop();
return chunk || '';
});
}
};

function forceLineReturn(content, width) {
return _.flatten(breakLines(content.split('\n'), width)).join('\n');
}
ScreenManager.prototype.forceLineReturn = function (content, width) {
width = width || this.normalizedCliWidth();
return _.flatten(this.breakLines(content.split('\n'), width)).join('\n');
};

0 comments on commit 70174ed

Please sign in to comment.