less-pager-mini
Version:
A scrollable terminal pager for Node.js CLI apps (terminal only)
245 lines (244 loc) • 9.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.lineForward = lineForward;
exports.lineBackward = lineBackward;
exports.windowForward = windowForward;
exports.windowBackward = windowBackward;
exports.setWindowForward = setWindowForward;
exports.setWindowBackward = setWindowBackward;
exports.setHalfWindowForward = setHalfWindowForward;
exports.setHalfWindowBackward = setHalfWindowBackward;
exports.setHalfScreenRight = setHalfScreenRight;
exports.setHalfScreenLeft = setHalfScreenLeft;
const helpers_1 = require("../helpers");
const config_1 = require("../config");
/**
* Moves forward by a given offset through content lines or subrows.
*
* @param content - Full content lines.
* @param offset - Number of lines/subrows to move forward.
* @param ignoreEOF - If true, ignores EOF clamp (optional).
*/
function lineForward(content, offset, ignoreEOF = false) {
let currSubRowMax = (0, helpers_1.maxSubRow)(content[config_1.config.row]);
if (isEndPosition(ignoreEOF, content.length, currSubRowMax)) {
(0, helpers_1.ringBell)();
return;
}
if (config_1.config.chopLongLines || config_1.config.col) {
const maxRow = ignoreEOF
? content.length - 1
: Math.max(content.length - config_1.config.window + 1, 0);
config_1.config.row = Math.min(config_1.config.row + offset, maxRow);
return;
}
const rowEnd = ignoreEOF ? null : getEndPosition(content);
const maxRow = rowEnd ? rowEnd.maxRow : content.length - 1;
while (offset > 0 && config_1.config.row <= maxRow) {
currSubRowMax = (0, helpers_1.maxSubRow)(content[config_1.config.row]);
if (config_1.config.row === maxRow && rowEnd)
currSubRowMax = rowEnd.subRow;
if (config_1.config.subRow + offset <= currSubRowMax) {
config_1.config.subRow += offset;
return;
}
offset -= currSubRowMax - config_1.config.subRow + 1;
config_1.config.row++;
config_1.config.subRow = 0;
}
if (rowEnd && config_1.config.row > rowEnd.maxRow) {
config_1.config.row = rowEnd.maxRow;
config_1.config.subRow = rowEnd.subRow;
}
else if (config_1.config.row === content.length) {
config_1.config.row = content.length - 1;
config_1.config.subRow = currSubRowMax;
}
}
/**
* Scroll backward by the given offset.
*
* - Stops and rings bell at BOF, also disables `mode.INIT`.
* - In chopped mode, moves by whole lines.
* - In wrapped mode, moves by sub-rows within a line.
*
* @param content - Full content lines.
* @param offset - Lines or sub-rows to scroll backward.
*/
function lineBackward(content, offset) {
if (!config_1.config.row && !config_1.config.subRow) {
if (config_1.mode.INIT)
config_1.mode.INIT = false;
(0, helpers_1.ringBell)();
return;
}
if (config_1.config.chopLongLines || config_1.config.col) {
config_1.config.row = Math.max(config_1.config.row - offset, 0);
return;
}
while (offset > 0 && config_1.config.row >= 0) {
if (config_1.config.subRow >= offset) {
config_1.config.subRow -= offset;
return;
}
if (config_1.config.row === 0) {
config_1.config.subRow = 0;
return;
}
offset -= config_1.config.subRow + 1;
config_1.config.row--;
config_1.config.subRow = (0, helpers_1.maxSubRow)(content[config_1.config.row]);
}
}
/**
* Scrolls the view forward by a window size.
*
* - If `buffer` is a valid number, it overrides the default window size.
* - Falls back to `config.setWindow` or `config.window - 1` if `buffer` is
* invalid.
* - If `ignoreEOF` is `true`, allows scrolling beyond (END) without clamping.
*
* @param content - The full content to paginate.
* @param buffer - A string array that represents the number of lines to scroll.
* @param ignoreEOF - Whether to bypass EOF constraints during scrolling.
*/
function windowForward(content, buffer, ignoreEOF = false) {
lineForward(content, (0, helpers_1.bufferToNum)(buffer) || config_1.config.setWindow || config_1.config.window - 1, ignoreEOF);
}
/**
* Moves the view backward by one window.
*
* - If `buffer` is a valid number, uses it as the offset.
* - Otherwise, uses `config.setWindow` if set, or defaults to
* `config.window - 1`.
*
* @param content - The full content as an array of lines.
* @param buffer - A string array that represents the number of lines to scroll.
*/
function windowBackward(content, buffer) {
lineBackward(content, (0, helpers_1.bufferToNum)(buffer) || config_1.config.setWindow || config_1.config.window - 1);
}
/**
* Sets a custom window size using the given `buffer`, and scrolls forward.
*
* - If `buffer` is a valid number, updates `config.setWindow` with it.
* - Then scrolls forward by `config.setWindow` or falls back to
* `config.window - 1`.
*
* @param content - The full content as an array of lines.
* @param buffer - A string array that represents the number of lines to scroll.
*/
function setWindowForward(content, buffer) {
config_1.config.setWindow = (0, helpers_1.bufferToNum)(buffer) || config_1.config.setWindow;
lineForward(content, config_1.config.setWindow || config_1.config.window - 1);
}
/**
* Sets a custom window size using the given `buffer`, and scrolls backward.
*
* - If `buffer` is a valid number, updates `config.setWindow` with it.
* - Then scrolls backward by `config.setWindow` or falls back to
* `config.window - 1`.
*
* @param content - The full content as an array of lines.
* @param buffer - A string array that represents the number of lines to scroll.
*/
function setWindowBackward(content, buffer) {
config_1.config.setWindow = (0, helpers_1.bufferToNum)(buffer) || config_1.config.setWindow;
lineBackward(content, config_1.config.setWindow || config_1.config.window - 1);
}
/**
* Sets a custom half-window size using the given `buffer`, and scrolls forward.
*
* - If `buffer` is a valid number, updates `config.setHalfWindow` with it.
* - Then scrolls forward by `config.setHalfWindow` or falls back to
* `config.halfWindow`.
*
* @param content - The full content as an array of lines.
* @param buffer - A string array that represents the number of lines to scroll.
*/
function setHalfWindowForward(content, buffer) {
config_1.config.setHalfWindow = (0, helpers_1.bufferToNum)(buffer) || config_1.config.setHalfWindow;
lineForward(content, config_1.config.setHalfWindow || config_1.config.halfWindow);
}
/**
* Sets a custom half-window size using the given `buffer`, and scrolls
* backward.
*
* - If `buffer` is a valid number, updates `config.setHalfWindow` with it.
* - Then scrolls backward by `config.setHalfWindow` or falls back to
* `config.halfWindow`.
*
* @param content - The full content as an array of lines.
* @param buffer - A string array that represents the number of lines to scroll.
*/
function setHalfWindowBackward(content, buffer) {
config_1.config.setHalfWindow = (0, helpers_1.bufferToNum)(buffer) || config_1.config.setHalfWindow;
lineBackward(content, config_1.config.setHalfWindow || config_1.config.halfWindow);
}
/**
* Scrolls right by buffer value or half screen width.
*
* @param buffer - Buffer containing scroll offset.
*/
function setHalfScreenRight(buffer) {
if (config_1.mode.INIT)
config_1.mode.INIT = false;
config_1.config.setCol = (0, helpers_1.bufferToNum)(buffer) || config_1.config.setCol;
config_1.config.col += config_1.config.setCol || config_1.config.halfScreenWidth;
}
/**
* Scrolls left by buffer value or half screen width.
*
* @param buffer - Buffer containing scroll offset.
*/
function setHalfScreenLeft(buffer) {
if (config_1.mode.INIT)
config_1.mode.INIT = false;
config_1.config.setCol = (0, helpers_1.bufferToNum)(buffer) || config_1.config.setCol;
config_1.config.col -= config_1.config.setCol || config_1.config.halfScreenWidth;
if (config_1.config.col < 0)
config_1.config.col = 0;
}
/**
* Determines whether the current viewport position is at the end of the
* content.
*
* This check accounts for both EOF mode and the final row/subRow position
* based on whether EOF should be ignored.
*
* @param ignoreEOF - If `true`, skips EOF check and only uses position
* comparison.
* @param contentLength - Total number of content rows.
* @param currSubRowMax - The final sub-row index to compare against.
* @returns `true` if the current position is at the end; otherwise, `false`.
*/
function isEndPosition(ignoreEOF, contentLength, currSubRowMax) {
return ((!ignoreEOF && config_1.mode.EOF) ||
(config_1.config.row === contentLength - 1 && config_1.config.subRow === currSubRowMax));
}
/**
* Calculates the last visible row and subrow for window clamping.
*
* @param content - Full content lines.
* @returns Object with `maxRow` and `subRow` for the end position.
*/
function getEndPosition(content) {
let maxRow = content.length - 1;
let subRow = 0;
let rowCount = 0;
while (maxRow >= 0) {
const subRows = (0, helpers_1.maxSubRow)(content[maxRow]) + 1;
const rowSum = rowCount + subRows;
if (rowSum >= config_1.config.window - 1) {
subRow = rowSum - config_1.config.window + 1;
break;
}
rowCount = rowSum;
maxRow--;
}
if (maxRow < 0) {
maxRow = 0;
subRow = 0;
}
return { maxRow, subRow };
}