Skip to content

Commit

Permalink
ScreenBuffer#put() now supports 'ansi' for the 'markup' option (#153)…
Browse files Browse the repository at this point in the history
… ; Improved the TextBuffer's doc
  • Loading branch information
cronvel committed Feb 18, 2021
1 parent bd4990e commit d5aeb3a
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 26 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@

v1.48.1
-------

ScreenBuffer#put() now supports 'ansi' for the 'markup' option (#153)
Improved the TextBuffer's doc


v1.48.0
-------

Expand Down
3 changes: 2 additions & 1 deletion doc/ScreenBuffer.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ It clears the *screenBuffer*, this is like calling [.fill()](#ref.ScreenBuffer.f
* options `Object`, where:
* x `integer` (optional) x-coordinate where to put the text, bypassing the cursor x-coordinate
* y `integer` (optional) y-coordinate where to put the text, bypassing the cursor y-coordinate
* markup `boolean` true if the text contains markup that should be interpreted
* markup `boolean` or 'ansi', true if the text contains markup that should be interpreted,
'ansi' if it contains *ANSI* code
* attr `Object` or `integer` attributes of the chars (attribute object or bit flags,
see: [the attribute object](#ref.ScreenBuffer.attributes))
* wrap `boolean` if true, text wrapping is enabled: when the cursor move beyond the last column, it is moved to the begining
Expand Down
106 changes: 103 additions & 3 deletions doc/TextBuffer.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ a small text-editor in early alpha stage, featuring a javascript syntax hilighte
* [.getHidden()](#ref.TextBuffer.getHidden)
* [.setHidden()](#ref.TextBuffer.setHidden)
* [.getContentSize()](#ref.TextBuffer.getContentSize)
* [.getCursorOffset()](#ref.TextBuffer.getCursorOffset)
* [.setCursorOffset()](#ref.TextBuffer.setCursorOffset)
* [.setEmptyCellAttr()](#ref.TextBuffer.setEmptyCellAttr)
* [.setAttrAt()](#ref.TextBuffer.setAttrAt)
* [.setAttrCodeAt()](#ref.TextBuffer.setAttrCodeAt)
Expand All @@ -59,14 +61,21 @@ a small text-editor in early alpha stage, featuring a javascript syntax hilighte
* [.moveBackward()](#ref.TextBuffer.moveBackward)
* [.moveToStartOfWord()](#ref.TextBuffer.moveToStartOfWord)
* [.moveToEndOfWord()](#ref.TextBuffer.moveToEndOfWord)
* [.moveToStartOfLine()](#ref.TextBuffer.moveToStartOfLine)
* [.moveToEndOfLine()](#ref.TextBuffer.moveToEndOfLine)
* [.moveToStartOfBuffer()](#ref.TextBuffer.moveToStartOfBuffer)
* [.moveToEndOfBuffer()](#ref.TextBuffer.moveToEndOfBuffer)
* [.moveInBound()](#ref.TextBuffer.moveInBound)
* [.insert()](#ref.TextBuffer.insert)
* [.prepend()](#ref.TextBuffer.prepend)
* [.append()](#ref.TextBuffer.append)
* [.delete()](#ref.TextBuffer.delete)
* [.backDelete()](#ref.TextBuffer.backDelete)
* [.newLine()](#ref.TextBuffer.newLine)
* [.joinLine()](#ref.TextBuffer.joinLine)
* [.iterate()](#ref.TextBuffer.iterate)
* [.wrapLine()](#ref.TextBuffer.wrapLine)
* [.wrapAllLines()](#ref.TextBuffer.wrapAllLines)
* [.draw()](#ref.TextBuffer.draw)
* [.drawCursor()](#ref.TextBuffer.drawCursor)
* [.load()](#ref.TextBuffer.load)
Expand Down Expand Up @@ -116,10 +125,13 @@ It extracts and returns the text content of the *textBuffer*.


<a name="ref.TextBuffer.setText"></a>
### .setText( text , markup )
### .setText( text , [ [markup] , baseAttr ] )

* text `string` the text content
* markup `boolean` true if the text contains markup that should be interpreted
* markup `boolean` or 'ansi', true if the text contains markup that should be interpreted
'ansi' if it contains *ANSI* code (default: false - raw text)
* baseAttr `object` or `integer`, an attribute used as the base attribute for the text content
(if there is markup, the markup attributes are *stacked* with this base attribute)

This set the text content of the *textBuffer*.

Expand Down Expand Up @@ -153,6 +165,22 @@ It returns an object with a *width* and *height* properties: the size of the tex



<a name="ref.TextBuffer.getCursorOffset"></a>
### .getCursorOffset()

It returns the cursor offset in the raw text content.



<a name="ref.TextBuffer.setCursorOffset"></a>
### .setCursorOffset( offset )

* offset `integer` the new offset of the cursor

It set the cursor offset in the raw text content.



<a name="ref.TextBuffer.setEmptyCellAttr"></a>
### .setEmptyCellAttr( attr )

Expand Down Expand Up @@ -344,13 +372,34 @@ It moves the *textBuffer*'s cursor to the end of the current word.



<a name="ref.TextBuffer.moveToStartOfLine"></a>
### .moveToStartOfLine()

It moves the *textBuffer*'s cursor to the begining of the current line.



<a name="ref.TextBuffer.moveToEndOfLine"></a>
### .moveToEndOfLine()

It moves the *textBuffer*'s cursor to the end of the current line.



<a name="ref.TextBuffer.moveToStartOfBuffer"></a>
### .moveToStartOfBuffer()

It moves the *textBuffer*'s cursor to the begining of the buffer (i.e. the begining of the first line).



<a name="ref.TextBuffer.moveToEndOfBuffer"></a>
### .moveToEndOfBuffer()

It moves the *textBuffer*'s cursor to the end of the buffer (i.e. the end of the last line).



<a name="ref.TextBuffer.moveInBound"></a>
### .moveInBound( ignoreCx )

Expand All @@ -361,16 +410,44 @@ It moves the *textBuffer*'s cursor in bound, i.e. to a cell that has text conten


<a name="ref.TextBuffer.insert"></a>
### .insert( text , [attr] )
### .insert( text , [ [markup] , attr ] )

* text `string` the raw text to insert
* markup `boolean` or 'ansi', true if the text contains markup that should be interpreted
'ansi' if it contains *ANSI* code (default: false - raw text)
* attr `Object` or `integer` (optional, default: the empty cell attributes) attributes of the text about to be inserted
(attribute object or bit flags, see: [the attribute object](ScreenBuffer.md#ref.ScreenBuffer.attributes))

It inserts the text at the current cursor position, with the given attributes.



<a name="ref.TextBuffer.prepend"></a>
### .prepend( text , [ [markup] , attr ] )

* text `string` the raw text to insert
* markup `boolean` or 'ansi', true if the text contains markup that should be interpreted
'ansi' if it contains *ANSI* code (default: false - raw text)
* attr `Object` or `integer` (optional, default: the empty cell attributes) attributes of the text about to be inserted
(attribute object or bit flags, see: [the attribute object](ScreenBuffer.md#ref.ScreenBuffer.attributes))

It prepend the text (i.e. insert it at the begining), with the given attributes.



<a name="ref.TextBuffer.append"></a>
### .append( text , [ [markup] , attr ] )

* text `string` the raw text to insert
* markup `boolean` or 'ansi', true if the text contains markup that should be interpreted
'ansi' if it contains *ANSI* code (default: false - raw text)
* attr `Object` or `integer` (optional, default: the empty cell attributes) attributes of the text about to be inserted
(attribute object or bit flags, see: [the attribute object](ScreenBuffer.md#ref.ScreenBuffer.attributes))

It append the text (i.e. insert it at the end), with the given attributes.



<a name="ref.TextBuffer.delete"></a>
### .delete( [n] )

Expand Down Expand Up @@ -425,6 +502,29 @@ It iterates over the whole *textBuffer*, using the *callback* for each cell.



<a name="ref.TextBuffer.wrapLine"></a>
### .wrapLine( [y] , [width] , [wordWrap] )

* y `integer` the line to wrap (default: current line, the line where the cursor is)
* width `integer` the wanted width (default: the current textBuffer's *lineWrapWidth*)
* wordWrap `boolean` if true, force word-aware line-splitting (default: the current textBuffer's *wordWrap*)

It wraps the current line (or the line *y*), splitting it as many times it is necessary to fit the wanted width.

The *wordWrap* option can be used to avoid splitting in a middle of a word or before punctuation.



<a name="ref.TextBuffer.wrapAllLines"></a>
### .wrapAllLines( [width] , [wordWrap] )

* width `integer` the wanted width (default: the current textBuffer's *lineWrapWidth*)
* wordWrap `boolean` if true, force word-aware line-splitting (default: the current textBuffer's *wordWrap*)

Same than [`.wrapLine()`](#ref.TextBuffer.wrapLine), but for all lines.



<a name="ref.TextBuffer.draw"></a>
### .draw( [options] )

Expand Down
14 changes: 8 additions & 6 deletions lib/ScreenBuffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ ScreenBuffer.prototype.markupOptions = misc.markupOptions ;
options:
* x: bypass this.cx
* y: bypass this.cy
* markup: boolean, true if the text contains markup that should be interpreted
* markup: boolean or 'ansi', true if the text contains markup that should be interpreted, 'ansi' if it contains ansi code
* attr: standard attributes
* resumeAttr: attr to resume to
* wrap: text wrapping, when the cursor move beyond the last column, it is moved to the begining of the next line
Expand All @@ -283,7 +283,7 @@ ScreenBuffer.prototype.markupOptions = misc.markupOptions ;
*/
// Shared
ScreenBuffer.prototype.put = function( options , str , ... args ) {
var startX , startY , x , y , dx , dy , baseAttr , attr , attrObject , wrap ;
var parser , startX , startY , x , y , dx , dy , baseAttr , attr , attrObject , wrap ;

// Manage options
if ( ! options ) { options = {} ; }
Expand Down Expand Up @@ -338,11 +338,13 @@ ScreenBuffer.prototype.put = function( options , str , ... args ) {
}

if ( args.length ) {
str = options.markup ?
this.preserveMarkupFormat( str , ... args ) :
string.format( str , ... args ) ;
str = ! options.markup || options.markup === 'ansi' ? string.format( str , ... args ) :
this.preserveMarkupFormat( str , ... args ) ;
}

parser = ! options.markup ? null :
options.markup === 'ansi' ? termkit.parseAnsi :
termkit.parseMarkup ;

// The processing of raw chunk of text
var processRaw = part => {
Expand Down Expand Up @@ -440,7 +442,7 @@ ScreenBuffer.prototype.put = function( options , str , ... args ) {
}
else {
attrObject = this.attr2object( attr ) ;
termkit.parseMarkup( str , this.markupOptions ).forEach( part => {
parser( str , this.markupOptions ).forEach( part => {
if ( typeof part === 'string' ) {
processRaw( part ) ;
}
Expand Down
20 changes: 6 additions & 14 deletions lib/TextBuffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,9 @@ TextBuffer.prototype.getCursorSplittedText = function() {



// TODOC: .setText( text , [[hasMarkup] , baseAttr ] )
// .setText( text , [[hasMarkup] , baseAttr ] )
TextBuffer.prototype.setText = function( text , hasMarkup , baseAttr ) {
// Argument management
if ( typeof hasMarkup !== 'boolean' && typeof hasMarkup !== 'string' ) {
baseAttr = hasMarkup ;
hasMarkup = false ;
Expand Down Expand Up @@ -250,8 +251,7 @@ TextBuffer.prototype.getContentSize = function() {



// TODOC
// Cursor offset in the text-content (excludind fillers)
// Cursor offset in the text-content (excluding fillers)
TextBuffer.prototype.getCursorOffset = function() {
var x , y , line , offset = 0 ;

Expand All @@ -275,7 +275,6 @@ TextBuffer.prototype.getCursorOffset = function() {



// TODOC
// Set the cursor position (cx,cy) depending on the offset in the text-content (excludind fillers)
TextBuffer.prototype.setCursorOffset = function( offset ) {
var line ;
Expand Down Expand Up @@ -368,7 +367,6 @@ const FORBIDDEN_SPLIT = new Set( [



// /!\ TODOC /!\
// Wrap/word-wrap the current line, stop on the next explicit '\n' or at the end of the buffer.
// Return the next line to scan.
// /!\ Should probably .reTabLine()
Expand Down Expand Up @@ -549,12 +547,11 @@ TextBuffer.prototype.wrapLine = function( startY = this.cy , width = this.lineWr



// /!\ TODOC /!\
TextBuffer.prototype.wrapAllLines = function( width = this.lineWrapWidth ) {
TextBuffer.prototype.wrapAllLines = function( width = this.lineWrapWidth , wordWrap = this.wordWrap ) {
var y = 0 ;

while ( y < this.buffer.length ) {
y = this.wrapLine( y , width ) ;
y = this.wrapLine( y , width , wordWrap ) ;
}
} ;

Expand Down Expand Up @@ -961,7 +958,6 @@ TextBuffer.prototype.moveToStartOfWord = function() {



// TODOC
TextBuffer.prototype.moveToStartOfLine = function() { this.cx = 0 ; } ;


Expand All @@ -982,13 +978,11 @@ TextBuffer.prototype.moveToEndOfLine = function() {



// TODOC
// Move to the start of the buffer: 0,0
TextBuffer.prototype.moveToStartOfBuffer = function() { this.cx = this.cy = 0 ; } ;



// TODOC
// Move to the end of the buffer: end of line of the last line
TextBuffer.prototype.moveToEndOfBuffer = function() {
this.cy = this.buffer.length ? this.buffer.length - 1 : 0 ;
Expand Down Expand Up @@ -1017,7 +1011,7 @@ TextBuffer.prototype.moveInBound = function( ignoreCx ) {



// TODOC: .insert( text , [[hasMarkup] , attr ] )
// .insert( text , [[hasMarkup] , attr ] )
TextBuffer.prototype.insert = function( text , hasMarkup , attr ) {
var lines , index , length , parser ;

Expand Down Expand Up @@ -1050,15 +1044,13 @@ TextBuffer.prototype.insert = function( text , hasMarkup , attr ) {



// TODOC
TextBuffer.prototype.prepend = function( text , hasMarkup , attr ) {
this.moveToStartOfBuffer() ;
this.insert( text , hasMarkup , attr ) ;
} ;



// TODOC
TextBuffer.prototype.append = function( text , hasMarkup , attr ) {
this.moveToEndOfBuffer() ;
this.insert( text , hasMarkup , attr ) ;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "terminal-kit",
"version": "1.48.0",
"version": "1.48.1",
"description": "256 colors, keys and mouse, input field, progress bars, screen buffer (including 32-bit composition and image loading), text buffer, and many more... Whether you just need colors and styles, build a simple interactive command line tool or a complexe terminal app: this is the absolute terminal lib for Node.js!",
"main": "lib/termkit.js",
"directories": {
Expand Down
2 changes: 1 addition & 1 deletion sample/document/text-box-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ term.clear() ;
var text ;
//text = 'Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.' ;
//text = 'Permission is hereby ^Y^+granted^:, ^C^+free^ of charge, to any person obtaining a copy of this ^/software^ and associated documentation files (the ^/"Software"^:), to deal in the ^/Software^ without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the ^/Software^:, and to permit persons to whom the ^/Software^ is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice ^R^_shall^ be included in all copies or substantial portions of the ^/Software^:.\n\n^+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.' ;
text = 'Permission is hereby \x1b[31mgranted\x1b[0m, free of \x1b[1;3mcharge\x1b[0m, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.' ;
text = 'Permission is hereby \x1b[31mgranted\x1b[0m, free of \x1b[1;32mcharge\x1b[0m, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.' ;

/*
// Test forbidden splitters
Expand Down

0 comments on commit d5aeb3a

Please sign in to comment.