Major improvements to quote builder for pre-formatted text/etc.

This commit is contained in:
Bryan Ashby 2017-08-27 20:08:13 -06:00
parent 1c736debf3
commit 1bad0de5c1
2 changed files with 77 additions and 13 deletions

View File

@ -10,7 +10,7 @@ const Errors = require('./enig_error.js').Errors;
const ANSI = require('./ansi_term.js'); const ANSI = require('./ansi_term.js');
const { const {
prepAnsi, isAnsi, prepAnsi, isAnsi, isFormattedLine,
splitTextAtTerms, splitTextAtTerms,
renderSubstr renderSubstr
} = require('./string_util.js'); } = require('./string_util.js');
@ -481,6 +481,20 @@ Message.prototype.getQuoteLines = function(options, cb) {
}); });
} }
function getFormattedLine(line) {
// for pre-formatted text, we just append a line truncated to fit
let newLen;
const total = line.length + quotePrefix.length;
if(total > options.cols) {
newLen = options.cols - total;
} else {
newLen = total;
}
return `${quotePrefix}${line.slice(0, newLen)}`;
}
if(options.isAnsi) { if(options.isAnsi) {
prepAnsi( prepAnsi(
this.message.replace(/\r?\n/g, '\r\n'), // normalized LF -> CRLF this.message.replace(/\r?\n/g, '\r\n'), // normalized LF -> CRLF
@ -507,6 +521,7 @@ Message.prototype.getQuoteLines = function(options, cb) {
// strip colors, colorize the lines, etc. If we exclude the prefixes, this seems to do // strip colors, colorize the lines, etc. If we exclude the prefixes, this seems to do
// the trick and allow them to leave them alone! // the trick and allow them to leave them alone!
// //
// :TODO: The way this bumps to the right is super annoying -- it would be nice to just invert the entire line
split.forEach(l => { split.forEach(l => {
quoteLines.push(`${lastSgr}${l}`); quoteLines.push(`${lastSgr}${l}`);
@ -522,7 +537,7 @@ Message.prototype.getQuoteLines = function(options, cb) {
} else { } else {
const QUOTE_RE = /^ ((?:[A-Za-z0-9]{2}\> )+(?:[A-Za-z0-9]{2}\>)*) */; const QUOTE_RE = /^ ((?:[A-Za-z0-9]{2}\> )+(?:[A-Za-z0-9]{2}\>)*) */;
const quoted = []; const quoted = [];
const input = this.message.trim().replace(/\b/g, ''); const input = _.trimEnd(this.message).replace(/\b/g, '');
// find *last* tearline // find *last* tearline
let tearLinePos = this.getTearLinePosition(input); let tearLinePos = this.getTearLinePosition(input);
@ -535,23 +550,42 @@ Message.prototype.getQuoteLines = function(options, cb) {
// - New (pre)quoted line - quote_line // - New (pre)quoted line - quote_line
// - Continuation of new/quoted line // - Continuation of new/quoted line
// //
// :TODO: keep lines as-is that // Also:
// - have extended ASCII // - Detect pre-formatted lines & try to keep them as-is
// - have tabs or " " (3+ spaces), e.g. pre-formatting
// - contain pipe codes
// //
let state; let state;
let buf = ''; let buf = '';
let quoteMatch; let quoteMatch;
if(quoted.length > 0) {
//
// Preserve paragraph seperation.
//
// FSC-0032 states something about leaving blank lines fully blank
// (without a prefix) but it seems nicer (and more consistent with other systems)
// to put 'em in.
//
quoted.push(quotePrefix);
}
paragraph.split(/\r?\n/).forEach(line => { paragraph.split(/\r?\n/).forEach(line => {
if(0 === line.trim().length) {
// see blank line notes above
return quoted.push(quotePrefix);
}
quoteMatch = line.match(QUOTE_RE); quoteMatch = line.match(QUOTE_RE);
switch(state) { switch(state) {
case 'line' : case 'line' :
if(quoteMatch) { if(quoteMatch) {
if(isFormattedLine(line)) {
quoted.push(getFormattedLine(line.replace(/\s/, '')));
} else {
quoted.push(...getWrapped(buf, quoteMatch[1])); quoted.push(...getWrapped(buf, quoteMatch[1]));
state = 'quote_line'; state = 'quote_line';
buf = line; buf = line;
}
} else { } else {
buf += ` ${line}`; buf += ` ${line}`;
} }
@ -574,8 +608,12 @@ Message.prototype.getQuoteLines = function(options, cb) {
break; break;
default : default :
if(isFormattedLine(line)) {
quoted.push(getFormattedLine(line));
} else {
state = quoteMatch ? 'quote_line' : 'line'; state = quoteMatch ? 'quote_line' : 'line';
buf = 'line' === state ? line : line.replace(/\s/, '');//_.trimStart(line); buf = 'line' === state ? line : line.replace(/\s/, ''); // trim *first* leading space, if any
}
break; break;
} }
}); });

View File

@ -27,6 +27,7 @@ exports.cleanControlCodes = cleanControlCodes;
exports.prepAnsi = prepAnsi; exports.prepAnsi = prepAnsi;
exports.isAnsi = isAnsi; exports.isAnsi = isAnsi;
exports.isAnsiLine = isAnsiLine; exports.isAnsiLine = isAnsiLine;
exports.isFormattedLine = isFormattedLine;
exports.splitTextAtTerms = splitTextAtTerms; exports.splitTextAtTerms = splitTextAtTerms;
// :TODO: create Unicode verison of this // :TODO: create Unicode verison of this
@ -582,6 +583,31 @@ function isAnsiLine(line) {
return isAnsi(line);// || renderStringLength(line) < line.length; return isAnsi(line);// || renderStringLength(line) < line.length;
} }
//
// Returns true if the line is considered "formatted". A line is
// considered formatted if it contains:
// * ANSI
// * Pipe codes
// * Extended (CP437) ASCII - https://www.ascii-codes.com/
// * Tabs
// * Contigous 3+ spaces before the end of the line
//
function isFormattedLine(line) {
if(renderStringLength(line) < line.length) {
return true; // ANSI or Pipe Codes
}
if(line.match(/[\t\x00-\x1f\x80-\xff]/)) { // eslint-disable-line no-control-regex
return true;
}
if(_.trimEnd(line).match(/[ ]{3,}/)) {
return true;
}
return false;
}
function isAnsi(input) { function isAnsi(input) {
// //
// * ANSI found - limited, just colors // * ANSI found - limited, just colors
@ -603,7 +629,7 @@ function isAnsi(input) {
*/ */
// :TODO: if a similar method is kept, use exec() until threshold // :TODO: if a similar method is kept, use exec() until threshold
const ANSI_DET_REGEXP = /(?:\x1b\x5b)[\?=;0-9]*?[ABCDEFGHJKLMSTfhlmnprsu]/g; const ANSI_DET_REGEXP = /(?:\x1b\x5b)[\?=;0-9]*?[ABCDEFGHJKLMSTfhlmnprsu]/g; // eslint-disable-line no-control-regex
const m = input.match(ANSI_DET_REGEXP) || []; const m = input.match(ANSI_DET_REGEXP) || [];
return m.length >= 4; // :TODO: do this reasonably, e.g. a percent or soemthing return m.length >= 4; // :TODO: do this reasonably, e.g. a percent or soemthing
} }