* Better isAnsi() regex
* Handle word wrap within ANSI on plain text lines
This commit is contained in:
parent
fa465613a1
commit
bf8552e24f
|
@ -8,6 +8,7 @@ const ANSI = require('./ansi_term.js');
|
||||||
|
|
||||||
// deps
|
// deps
|
||||||
const iconv = require('iconv-lite');
|
const iconv = require('iconv-lite');
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
exports.stylizeString = stylizeString;
|
exports.stylizeString = stylizeString;
|
||||||
exports.pad = pad;
|
exports.pad = pad;
|
||||||
|
@ -23,6 +24,7 @@ exports.formatByteSize = formatByteSize;
|
||||||
exports.cleanControlCodes = cleanControlCodes;
|
exports.cleanControlCodes = cleanControlCodes;
|
||||||
exports.prepAnsi = prepAnsi;
|
exports.prepAnsi = prepAnsi;
|
||||||
exports.isAnsi = isAnsi;
|
exports.isAnsi = isAnsi;
|
||||||
|
exports.isAnsiLine = isAnsiLine;
|
||||||
exports.splitTextAtTerms = splitTextAtTerms;
|
exports.splitTextAtTerms = splitTextAtTerms;
|
||||||
|
|
||||||
// :TODO: create Unicode verison of this
|
// :TODO: create Unicode verison of this
|
||||||
|
@ -380,13 +382,12 @@ function prepAnsi(input, options, cb) {
|
||||||
return cb(null, '');
|
return cb(null, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
options.termWidth = options.termWidth || 80;
|
options.termWidth = options.termWidth || 80;
|
||||||
options.termHeight = options.termHeight || 25;
|
options.termHeight = options.termHeight || 25;
|
||||||
|
options.cols = options.cols || options.termWidth || 80;
|
||||||
options.cols = options.cols || options.termWidth || 80;
|
options.rows = options.rows || options.termHeight || 'auto';
|
||||||
options.rows = options.rows || options.termHeight || 'auto';
|
options.startCol = options.startCol || 1;
|
||||||
|
options.preserveTextLines = options.preserveTextLines || false;
|
||||||
options.startCol = options.startCol || 1;
|
|
||||||
|
|
||||||
const canvas = Array.from( { length : 'auto' === options.rows ? 25 : options.rows }, () => Array.from( { length : options.cols}, () => new Object() ) );
|
const canvas = Array.from( { length : 'auto' === options.rows ? 25 : options.rows }, () => Array.from( { length : options.cols}, () => new Object() ) );
|
||||||
const parser = new ANSIEscapeParser( { termHeight : options.termHeight, termWidth : options.termWidth } );
|
const parser = new ANSIEscapeParser( { termHeight : options.termHeight, termWidth : options.termWidth } );
|
||||||
|
@ -463,24 +464,52 @@ function prepAnsi(input, options, cb) {
|
||||||
parser.on('complete', () => {
|
parser.on('complete', () => {
|
||||||
let output = '';
|
let output = '';
|
||||||
let lastSgr = '';
|
let lastSgr = '';
|
||||||
|
let line;
|
||||||
|
let textState = 'new';
|
||||||
canvas.slice(0, lastRow + 1).forEach(row => {
|
canvas.slice(0, lastRow + 1).forEach(row => {
|
||||||
const lastCol = getLastPopulatedColumn(row) + 1;
|
const lastCol = getLastPopulatedColumn(row) + 1;
|
||||||
|
|
||||||
let i;
|
let i;
|
||||||
|
line = '';
|
||||||
for(i = 0; i < lastCol; ++i) {
|
for(i = 0; i < lastCol; ++i) {
|
||||||
const col = row[i];
|
const col = row[i];
|
||||||
if(col.sgr) {
|
if(col.sgr) {
|
||||||
lastSgr = col.sgr;
|
lastSgr = col.sgr;
|
||||||
}
|
}
|
||||||
output += `${col.sgr || ''}${col.char || ' '}`;
|
line += `${col.sgr || ''}${col.char || ' '}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i < row.length) {
|
if(options.preserveTextLines && !isAnsiLine(line)) {
|
||||||
output += `${ANSI.blackBG()}${row.slice(i).map( () => ' ').join('')}${lastSgr}`;
|
switch(textState) {
|
||||||
}
|
case 'new' :
|
||||||
|
line = _.trimStart(line);
|
||||||
|
if(line) {
|
||||||
|
textState = 'cont';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
if(options.startCol + options.cols < options.termWidth || options.forceLineTerm) {
|
case 'cont' :
|
||||||
output += '\r\n';
|
line = ' ' + line;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
output += line;
|
||||||
|
} else {
|
||||||
|
if('cont' === textState) {
|
||||||
|
output += '\r\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
textState = 'new';
|
||||||
|
|
||||||
|
output += line;
|
||||||
|
|
||||||
|
if(i < row.length) {
|
||||||
|
output += `${ANSI.blackBG()}${row.slice(i).map( () => ' ').join('')}${lastSgr}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(options.startCol + options.cols < options.termWidth || options.forceLineTerm) {
|
||||||
|
output += '\r\n';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -490,6 +519,10 @@ function prepAnsi(input, options, cb) {
|
||||||
parser.parse(input);
|
parser.parse(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isAnsiLine(line) {
|
||||||
|
return isAnsi(line);// || renderStringLength(line) < line.length;
|
||||||
|
}
|
||||||
|
|
||||||
function isAnsi(input) {
|
function isAnsi(input) {
|
||||||
//
|
//
|
||||||
// * ANSI found - limited, just colors
|
// * ANSI found - limited, just colors
|
||||||
|
@ -510,8 +543,9 @@ function isAnsi(input) {
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const ANSI_DET_REGEXP = /(?:\x1b\x5b)[0-9]{1,3}[ABCDEFGJKLMSTrsuHfhlm]/g;
|
const ANSI_DET_REGEXP = /(?:\x1b\x5b)[\?=;0-9]*?[ABCDEFGHJKLMSTfhlmnprsu]/g;
|
||||||
return ( input.match(ANSI_DET_REGEXP) || [] ).length > 4; // :TODO: do this reasonably, e.g. a percent or soemthing
|
const m = input.match(ANSI_DET_REGEXP) || [];
|
||||||
|
return m.length >= 4; // :TODO: do this reasonably, e.g. a percent or soemthing
|
||||||
}
|
}
|
||||||
|
|
||||||
function splitTextAtTerms(s) {
|
function splitTextAtTerms(s) {
|
||||||
|
|
Loading…
Reference in New Issue