cl-paginator
v2.0.1
Published
Splits text in pages to show in console, waiting for user interaction to continue the code
Downloads
27
Maintainers
Readme
Cl-Paginator
Split and show your text in console with user interaction
This Node.js module allows you to split and fit the text in console, dividing it in pages which user can go through.
I decided to create this based on Inquirer paginator util used on some prompts, 'cause it's quite useful when creating a CLI.
Getting started
Installation
npm install cl-paginator
Usage
import { Paginator } from 'cl-paginator'
// const { Paginator } = require('cl-paginator')
var paginator = new Paginator(/* PageOptions */)
paginator.options({/* PageOptions */})
paginator.print(/* just text*/, /* PageOptions */)
Also, you can try it on Repl.it
How this works
paginator.print(text: string, options?: pageOptions)
Firstly, splits the given text to fit well in the console or the terminal option terminal: {cols, rows}
, without intercalated words. Then, listens to data
signals from a NodeJS.ReadStream
like process.stdin
(keyboard input) to check if Up or Down keys are pressed, then moving the current page.
Methods
/**
* Capture key arrows for moving the text UP and DOWN with a determinate PageSize.
* Use Message option for show an static text above the text.
* @param {string} text Defines the text to split up and fit in the console.
* @param {pageOptions | undefined} options Defines the options.
* @async Uses Promises, awaiting for the Return key pressed.
* @returns Promise, resolving in Boolean True.
*/
async paginator.print(text: string, options?: pageOptions)
Options
interface pageOptions {
/**
* Defines the max number of lines to show in console. Use a positive integer
* @default 5
*/
page_size?: number;
/**
* Shows an static message above the text
* @default "Paginated text:"
*/
message?: string;
/**
* Shows a short suffix to help the user
* @default "(Use arrow keys)"
*/
suffix?: string;
/**
* Shows a message for help to continue executing the code
* @default "Press return key to exit"
*/
exit_message?: string;
/**
* Whether it's necessary to read all (going to bottom) or not to quit
* @default true
*/
read_to_return?: boolean;
/**
* The `NodeJS.WriteStream` to write on
* @default process.stdout
*/
writable?: NodeJS.WriteStream;
/**
* The `NodeJS.ReadStream` to read from
* @default process.stdin
*/
readable?: NodeJS.ReadStream;
/**
* Sets the maximum number of columns and rows.
* @default { cols: 0, rows: 0 } // Automatic
*/
terminal?: { cols?: number; rows?: number };
/**
* Sets the paginator style
* @default { }
*/
style?: { enum?: chalk.Chalk };
}
Also, you can define the default options to be used in every print.
paginator.options(options?: pageOptions): this
// or
var pagCustom = new Paginator(options?: pageOptions)
End
Stops the Paginator instance, without closing the program.
paginator.print('a') // a
paginator.end() // Stops the paginator inmediately, without closing the program with 'process.exit()'
Properties
Opts
Returns the Paginator instance options.
paginator.opts: pageOptions
Pages
Returns the Paginator instance total pages.
paginator.pages: number
Position
Returns or sets the actual position in Paginator instance.
paginator.position: number // Returns the position
paginator.position = 2 // Sets the position
Actual Text
Returns the actualText, the text that is writed on writable ReadStream.
paginator.actualText: string
Chaining
paginator.options(/* pageOptions */).print('Hello')
// `print` method is promise-based, therefore you would need to use `then` to chain next `print`s.
paginator.print('A').then(pag => pag.print('E')).then(pag => pag.print('I'))
Examples
Simple Lorem Ipsum
var text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...' // Just a big lorem ipsum
paginator.print(text, {page_size: 10}) // Shows 10 lines per page
Options
var text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...' // The same big lorem ipsum
paginator.print(lorem, {
page_size: 10,
exit_message: 'Please, press return to exit :D',
message: 'A big lorem ipsum!',
suffix: 'Use those arrows',
read_to_return: false
})
Chalk integration
import chalk from 'chalk'
var text = chalk`Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod {bold.green tempor incididunt ut labore et dolore magna aliqua...}`
paginator.print(text, {
page_size: 10,
suffix: 'Use the arrows!',
read_to_return: false
})
Stream integration
var writable = new Writable() // new NodeJS.WriteStream
var readable = new Readable() // new NodeJS.ReadStream
readable.setRawMode(true) // Allows Ansi Escaping
readable.resume()
var text = var text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...' // The same big lorem ipsum
paginator.print(text, {
page_size: 10,
writable: writable, // This allows to write on 'writable' WriteStream.
readable: readable, // This allows to read the input on 'readable' ReadStream.
})
// Check the examples folder for more info.
Writable
This needs just a bit of configuration, unless you want to make it really useful, such as storing every chunk that is writed in the instance.
Recommendation: As this package is oriented to be used in a console, it uses Ansi Escapes to do a lot of things, like erasing the console or hiding/showing the cursor, I recommend you to use a filter that erases all your data when this kind of Ansi Escapes are writed.
Ansi-Escapes,
Ansi-Regex
const clearAnsi = ['\x1B[0J', ansiEscapes.clearScreen, ansiEscapes.clearTerminal, /* and so on... */]
// This method is extended from 'WriteStream'. You need to put your code here to make it work, don't overwrite the 'write' method, use '_write' instead
public _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null | undefined) => void) {
this.all += chunk // Saves the chunk in a permanent data
this.data += chunk // Saves the chunk in a temporal data
this.emit('writed', this.data) // Emits a 'writed' event with the temporal data, to make it versatille
var reg = this.data.match(ansiRegex()) // Matchs every Ansi Escape
var match = clearAnsi.some((val) => { return reg?.includes(val) })
if (match) { this.clear() } // If matchs any Ansi Escape oriented to cleaning~ erase the temporal data
callback()
}
Readable
If you want to create an automated ReadStream with Cl-Paginator
, you need to use ANSI escape codes, line \x0d
or x1b[A
.
Such as:
class Readable extends ReadStream {
constructor() {
super(0)
}
public emitKey(key: string) { // You could make an external function, instead
this.emit('data', Buffer.from(data.split("").map((v) => v.charCodeAt(0))))
}
}
// Then~
var readable = new Readable()
var paginator = new Paginator({ readable })
paginator.print(/* What you want~ */)
readable.emitKey("\x1b[B") // "Presses" the down key
readable.emitKey("\x0d") // "Presses" the return key
readable.emitKey("\x03") // Exits the program
Know issues
- It's possible that Streams don't work properly.