Add PCB/WildCat!, WWIV, Renegade, etc. color code support to file descriptions
This commit is contained in:
parent
30d76d173e
commit
6d31589c8b
|
@ -11,11 +11,13 @@ exports.enigmaToAnsi = enigmaToAnsi;
|
|||
exports.stripPipeCodes = exports.stripEnigmaCodes = stripEnigmaCodes;
|
||||
exports.pipeStrLen = exports.enigmaStrLen = enigmaStrLen;
|
||||
exports.pipeToAnsi = exports.renegadeToAnsi = renegadeToAnsi;
|
||||
exports.controlCodesToAnsi = controlCodesToAnsi;
|
||||
|
||||
// :TODO: Not really happy with the module name of "color_codes". Would like something better
|
||||
|
||||
|
||||
|
||||
|
||||
// Also add:
|
||||
// * fromCelerity(): |<case sensitive letter>
|
||||
// * fromPCBoard(): (@X<bg><fg>)
|
||||
|
@ -148,3 +150,159 @@ function renegadeToAnsi(s, client) {
|
|||
|
||||
return (0 === result.length ? s : result + s.substr(lastIndex));
|
||||
}
|
||||
|
||||
//
|
||||
// Converts various control codes popular in BBS packages
|
||||
// to ANSI escape sequences. Additionaly supports ENiGMA style
|
||||
// MCI codes.
|
||||
//
|
||||
// Supported control code formats:
|
||||
// * Renegade : |##
|
||||
// * PCBoard : @X## where the first number/char is FG color, and second is BG
|
||||
// * WildCat! : @##@ the same as PCBoard without the X prefix, but with a @ suffix
|
||||
// * WWIV : ^#
|
||||
//
|
||||
// TODO: Add Synchronet and Celerity format support
|
||||
//
|
||||
// Resources:
|
||||
// * http://wiki.synchro.net/custom:colors
|
||||
//
|
||||
function controlCodesToAnsi(s, client) {
|
||||
const RE = /(\|([A-Z0-9]{2})|\|)|(\@X([0-9A-F]{2}))|(\@([0-9A-F]{2})\@)|(\x03[0-9]|\x03)/g; // eslint-disable-line no-control-regex
|
||||
|
||||
let m;
|
||||
let result = '';
|
||||
let lastIndex = 0;
|
||||
let v;
|
||||
let fg;
|
||||
let bg;
|
||||
|
||||
while((m = RE.exec(s))) {
|
||||
switch(m[0].charAt(0)) {
|
||||
case '|' :
|
||||
// Renegade or ENiGMA MCI
|
||||
v = parseInt(m[2], 10);
|
||||
|
||||
if(isNaN(v)) {
|
||||
v = getPredefinedMCIValue(client, m[2]) || m[0]; // value itself or literal
|
||||
}
|
||||
|
||||
if(_.isString(v)) {
|
||||
result += s.substr(lastIndex, m.index - lastIndex) + v;
|
||||
} else {
|
||||
v = ansi.sgr({
|
||||
0 : [ 'reset', 'black' ],
|
||||
1 : [ 'reset', 'blue' ],
|
||||
2 : [ 'reset', 'green' ],
|
||||
3 : [ 'reset', 'cyan' ],
|
||||
4 : [ 'reset', 'red' ],
|
||||
5 : [ 'reset', 'magenta' ],
|
||||
6 : [ 'reset', 'yellow' ],
|
||||
7 : [ 'reset', 'white' ],
|
||||
|
||||
8 : [ 'bold', 'black' ],
|
||||
9 : [ 'bold', 'blue' ],
|
||||
10 : [ 'bold', 'green' ],
|
||||
11 : [ 'bold', 'cyan' ],
|
||||
12 : [ 'bold', 'red' ],
|
||||
13 : [ 'bold', 'magenta' ],
|
||||
14 : [ 'bold', 'yellow' ],
|
||||
15 : [ 'bold', 'white' ],
|
||||
|
||||
16 : [ 'blackBG' ],
|
||||
17 : [ 'blueBG' ],
|
||||
18 : [ 'greenBG' ],
|
||||
19 : [ 'cyanBG' ],
|
||||
20 : [ 'redBG' ],
|
||||
21 : [ 'magentaBG' ],
|
||||
22 : [ 'yellowBG' ],
|
||||
23 : [ 'whiteBG' ],
|
||||
}[v] || 'normal');
|
||||
|
||||
result += s.substr(lastIndex, m.index - lastIndex) + v;
|
||||
}
|
||||
break;
|
||||
|
||||
case '@' :
|
||||
// PCBoard @X## or Wildcat! @##@
|
||||
if('@' === m[0].substr(-1)) {
|
||||
// Wildcat!
|
||||
v = m[6];
|
||||
} else {
|
||||
v = m[4];
|
||||
}
|
||||
|
||||
fg = {
|
||||
0 : [ 'reset', 'black' ],
|
||||
1 : [ 'reset', 'blue' ],
|
||||
2 : [ 'reset', 'green' ],
|
||||
3 : [ 'reset', 'cyan' ],
|
||||
4 : [ 'reset', 'red' ],
|
||||
5 : [ 'reset', 'magenta' ],
|
||||
6 : [ 'reset', 'yellow' ],
|
||||
7 : [ 'reset', 'white' ],
|
||||
|
||||
8 : [ 'blink', 'black' ],
|
||||
9 : [ 'blink', 'blue' ],
|
||||
A : [ 'blink', 'green' ],
|
||||
B : [ 'blink', 'cyan' ],
|
||||
C : [ 'blink', 'red' ],
|
||||
D : [ 'blink', 'magenta' ],
|
||||
E : [ 'blink', 'yellow' ],
|
||||
F : [ 'blink', 'white' ],
|
||||
}[v.charAt(0)] || ['normal'];
|
||||
|
||||
bg = {
|
||||
0 : [ 'blackBG' ],
|
||||
1 : [ 'blueBG' ],
|
||||
2 : [ 'greenBG' ],
|
||||
3 : [ 'cyanBG' ],
|
||||
4 : [ 'redBG' ],
|
||||
5 : [ 'magentaBG' ],
|
||||
6 : [ 'yellowBG' ],
|
||||
7 : [ 'whiteBG' ],
|
||||
|
||||
8 : [ 'bold', 'blackBG' ],
|
||||
9 : [ 'bold', 'blueBG' ],
|
||||
A : [ 'bold', 'greenBG' ],
|
||||
B : [ 'bold', 'cyanBG' ],
|
||||
C : [ 'bold', 'redBG' ],
|
||||
D : [ 'bold', 'magentaBG' ],
|
||||
E : [ 'bold', 'yellowBG' ],
|
||||
F : [ 'bold', 'whiteBG' ],
|
||||
}[v.charAt(1)] || [ 'normal' ];
|
||||
|
||||
v = ansi.sgr(fg.concat(bg));
|
||||
result += s.substr(lastIndex, m.index - lastIndex) + v;
|
||||
break;
|
||||
|
||||
case '\x03' :
|
||||
v = parseInt(m[8], 10);
|
||||
|
||||
if(isNaN(v)) {
|
||||
v += m[0];
|
||||
} else {
|
||||
v = ansi.sgr({
|
||||
0 : [ 'reset', 'black' ],
|
||||
1 : [ 'bold', 'cyan' ],
|
||||
2 : [ 'bold', 'yellow' ],
|
||||
3 : [ 'reset', 'magenta' ],
|
||||
4 : [ 'bold', 'white', 'blueBG' ],
|
||||
5 : [ 'reset', 'green' ],
|
||||
6 : [ 'bold', 'blink', 'red' ],
|
||||
7 : [ 'bold', 'blue' ],
|
||||
8 : [ 'reset', 'blue' ],
|
||||
9 : [ 'reset', 'cyan' ],
|
||||
}[v] || 'normal');
|
||||
}
|
||||
|
||||
result += s.substr(lastIndex, m.index - lastIndex) + v;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
lastIndex = RE.lastIndex;
|
||||
}
|
||||
|
||||
return (0 === result.length ? s : result + s.substr(lastIndex));
|
||||
}
|
|
@ -2,22 +2,23 @@
|
|||
'use strict';
|
||||
|
||||
// ENiGMA½
|
||||
const MenuModule = require('../core/menu_module.js').MenuModule;
|
||||
const ViewController = require('../core/view_controller.js').ViewController;
|
||||
const ansi = require('../core/ansi_term.js');
|
||||
const theme = require('../core/theme.js');
|
||||
const FileEntry = require('../core/file_entry.js');
|
||||
const stringFormat = require('../core/string_format.js');
|
||||
const FileArea = require('../core/file_base_area.js');
|
||||
const Errors = require('../core/enig_error.js').Errors;
|
||||
const ErrNotEnabled = require('../core/enig_error.js').ErrorReasons.NotEnabled;
|
||||
const ArchiveUtil = require('../core/archive_util.js');
|
||||
const Config = require('../core/config.js').config;
|
||||
const DownloadQueue = require('../core/download_queue.js');
|
||||
const FileAreaWeb = require('../core/file_area_web.js');
|
||||
const FileBaseFilters = require('../core/file_base_filter.js');
|
||||
const resolveMimeType = require('../core/mime_util.js').resolveMimeType;
|
||||
const isAnsi = require('../core/string_util.js').isAnsi;
|
||||
const MenuModule = require('../core/menu_module.js').MenuModule;
|
||||
const ViewController = require('../core/view_controller.js').ViewController;
|
||||
const ansi = require('../core/ansi_term.js');
|
||||
const theme = require('../core/theme.js');
|
||||
const FileEntry = require('../core/file_entry.js');
|
||||
const stringFormat = require('../core/string_format.js');
|
||||
const FileArea = require('../core/file_base_area.js');
|
||||
const Errors = require('../core/enig_error.js').Errors;
|
||||
const ErrNotEnabled = require('../core/enig_error.js').ErrorReasons.NotEnabled;
|
||||
const ArchiveUtil = require('../core/archive_util.js');
|
||||
const Config = require('../core/config.js').config;
|
||||
const DownloadQueue = require('../core/download_queue.js');
|
||||
const FileAreaWeb = require('../core/file_area_web.js');
|
||||
const FileBaseFilters = require('../core/file_base_filter.js');
|
||||
const resolveMimeType = require('../core/mime_util.js').resolveMimeType;
|
||||
const isAnsi = require('../core/string_util.js').isAnsi;
|
||||
const controlCodesToAnsi = require('../core/color_codes.js').controlCodesToAnsi;
|
||||
|
||||
// deps
|
||||
const async = require('async');
|
||||
|
@ -385,9 +386,19 @@ exports.getModule = class FileAreaList extends MenuModule {
|
|||
if(_.isString(self.currentFileEntry.desc)) {
|
||||
const descView = self.viewControllers.browse.getView(MciViewIds.browse.desc);
|
||||
if(descView) {
|
||||
if(isAnsi(self.currentFileEntry.desc)) {
|
||||
//
|
||||
// For descriptions we want to support as many color code systems
|
||||
// as we can for coverage of what is found in the while (e.g. Renegade
|
||||
// pipes, PCB @X##, etc.)
|
||||
//
|
||||
// MLTEV doesn't support all of this, so convert. If we produced ANSI
|
||||
// esc sequences, we'll proceed with specialization, else just treat
|
||||
// it as text.
|
||||
//
|
||||
const desc = controlCodesToAnsi(self.currentFileEntry.desc);
|
||||
if(desc.length != self.currentFileEntry.desc.length || isAnsi(desc)) {
|
||||
descView.setAnsi(
|
||||
self.currentFileEntry.desc,
|
||||
desc,
|
||||
{
|
||||
prepped : false,
|
||||
forceLineTerm : true
|
||||
|
|
Loading…
Reference in New Issue