* predefined_mci.js: General method for resolving MCI codes -> string

* Changed MCI resolution to use object to function mapping so entries not yet available would not be executed
* enigmaToAnsi() can now (optionally) resolve MCI codes
* pipeWrite() resolves MCI codes
This commit is contained in:
Bryan Ashby 2015-09-10 21:01:04 -06:00
parent 870e5a9136
commit 6b03b5357f
6 changed files with 130 additions and 116 deletions

View File

@ -138,7 +138,7 @@ ClientTerminal.prototype.rawWrite = function(s) {
};
ClientTerminal.prototype.pipeWrite = function(s) {
this.write(enigmaToAnsi(s));
this.write(enigmaToAnsi(s, this));
};
ClientTerminal.prototype.encode = function(s, convertLineFeeds) {

View File

@ -1,9 +1,11 @@
/* jslint node: true */
'use strict';
var ansi = require('./ansi_term.js');
var ansi = require('./ansi_term.js');
var getPredefinedMCIValue = require('./predefined_mci.js').getPredefinedMCIValue;
var assert = require('assert');
var assert = require('assert');
var _ = require('lodash');
exports.pipeToAnsi = exports.enigmaToAnsi = enigmaToAnsi;
exports.stripPipeCodes = exports.stripEnigmaCodes = stripEnigmaCodes;
@ -21,13 +23,13 @@ exports.renegadeToAnsi = renegadeToAnsi;
// * fromWWIV(): <ctrl-c><0-7>
// * fromSyncronet(): <ctrl-a><colorCode>
// See http://wiki.synchro.net/custom:colors
function enigmaToAnsi(s) {
function enigmaToAnsi(s, client) {
if(-1 == s.indexOf('|')) {
return s; // no pipe codes present
}
var result = '';
var re = /\|(\d{2}|\|)/g;
var re = /\|([A-Z\d]{2}|\|)/g;
var m;
var lastIndex = 0;
while((m = re.exec(s))) {
@ -41,22 +43,33 @@ function enigmaToAnsi(s) {
// convert to number
val = parseInt(val, 10);
if(isNaN(val)) {
val = 0;
//
// ENiGMA MCI code? Only available if |client|
// is supplied.
//
console.log('attempting to resolve ' + m[1])
val = getPredefinedMCIValue(client, m[1]) || ('|' + m[1]); // value itself or literal
console.log(val)
}
assert(val >= 0 && val <= 47);
if(_.isString(val)) {
result += s.substr(lastIndex, m.index - lastIndex) + val;
} else {
assert(val >= 0 && val <= 47);
var attr = '';
if(7 == val) {
attr = ansi.sgr('normal');
} else if (val < 7 || val >= 16) {
attr = ansi.sgr(['normal', val]);
} else if (val <= 15) {
attr = ansi.sgr(['normal', val - 8, 'bold']);
}
var attr = '';
if(7 == val) {
attr = ansi.sgr('normal');
} else if (val < 7 || val >= 16) {
attr = ansi.sgr(['normal', val]);
} else if (val <= 15) {
attr = ansi.sgr(['normal', val - 8, 'bold']);
}
result += s.substr(lastIndex, m.index - lastIndex) + attr;
lastIndex = re.lastIndex;
result += s.substr(lastIndex, m.index - lastIndex) + attr;
}
lastIndex = re.lastIndex;
}
result = (0 === result.length ? s : result + s.substr(lastIndex));
@ -65,7 +78,7 @@ function enigmaToAnsi(s) {
}
function stripEnigmaCodes(s) {
return s.replace(/\|[\d]{2}/g, '');
return s.replace(/\|[A-Z\d]{2}/g, '');
}
function enigmaStrLen(s) {

View File

@ -86,9 +86,9 @@ function prepareTerminal(term) {
function displayBanner(term) {
// :TODO: add URL(s) to banner
term.pipeWrite(
('|33Conected to |32EN|33|01i|00|32|22GMA|32|01½|00 |33BBS version|31|01 {0}\n' +
'|33Conected to |32EN|33|01i|00|32|22GMA|32|01½|00 |33BBS version|31|01 |VN\n' +
'|00|33Copyright (c) 2014-2015 Bryan Ashby |33|01- |31|01http://l33t.codes/\n' +
'|00').format(packageJson.version));
'|00');
}
function connectEntry(client) {

View File

@ -11,17 +11,13 @@ var ToggleMenuView = require('./toggle_menu_view.js').ToggleMenuView;
var MaskEditTextView = require('./mask_edit_text_view.js').MaskEditTextView;
var StatusBarView = require('./status_bar_view.js').StatusBarView;
var MultiLineEditTextView = require('./multi_line_edit_text_view.js').MultiLineEditTextView;
var getMessageAreaByName = require('./message_area.js').getMessageAreaByName;
var Config = require('./config.js').config;
var getPredefinedMCIValue = require('./predefined_mci.js').getPredefinedMCIValue;
var ansi = require('./ansi_term.js');
var packageJson = require('../package.json');
var assert = require('assert');
var os = require('os');
var _ = require('lodash');
var moment = require('moment');
exports.MCIViewFactory = MCIViewFactory;
@ -29,94 +25,6 @@ function MCIViewFactory(client) {
this.client = client;
}
// :TODO: This portion should be made more generic so pipe code formatting can use it!
// e..g MCIPrint() -> enigmaToAnsi() ->
MCIViewFactory.prototype.getPredefinedViewLabel = function(code) {
var self = this;
function getMessageAreaDescription() {
var area = getMessageAreaByName(self.client.user.properties.message_area_name);
return area ? area.desc : '';
}
function getCurrentMenuDescription() {
return _.has(self, 'client.currentMenuModule.menuConfig.desc') ? self.client.currentMenuModule.menuConfig.desc : '';
}
try {
return {
BN : Config.general.boardName,
VL : 'ENiGMA½ v' + packageJson.version,
VN : packageJson.version,
UN : this.client.user.username,
UI : this.client.user.userId.toString(),
UG : _.values(this.client.user.groups).join(', '),
UR : this.client.user.properties.real_name,
LO : this.client.user.properties.location,
UA : this.client.user.getAge().toString(),
UB : moment(this.client.user.properties.birthdate).format(this.client.currentTheme.helpers.getDateFormat()),
US : this.client.user.properties.sex,
UE : this.client.user.properties.email_address,
UW : this.client.user.properties.web_address,
UF : this.client.user.properties.affiliation,
UT : this.client.user.properties.theme_id,
UC : this.client.user.properties.login_count.toString(),
MS : moment(this.client.user.properties.account_created).format(this.client.currentTheme.helpers.getDateFormat()),
CS : this.client.currentStatus,
MD : getCurrentMenuDescription(),
MA : getMessageAreaDescription(),
SH : this.client.term.termHeight.toString(),
SW : this.client.term.termWidth.toString(),
ND : this.client.node.toString(),
// :TODO: change to CD for 'Current Date'
DT : moment().format(this.client.currentTheme.helpers.getDateFormat()),
CT : moment().format(this.client.currentTheme.helpers.getTimeFormat()),
OS : {
linux : 'Linux',
darwin : 'Mac OS X',
win32 : 'Windows',
sunos : 'SunOS',
freebsd : 'FreeBSD',
}[os.platform()] || os.type(),
OA : os.arch(),
SC : os.cpus()[0].model,
IP : this.client.address().address,
}[code];
} catch(e) {
this.client.log.warn( { code : code, exception : e.message }, 'Exception caught attempting to construct predefined label');
}
};
/*
MCIViewFactory.getUserViewClass = function(code) {
return {
TL : TextView,
ET : EditTextView,
ME : MaskEditTextView,
MT : MultiLineEditTextView,
PL : TextView,
BT : ButtonView,
VM : VerticalMenuView,
HM : HorizontalMenuView,
SM : SpinnerMenuView,
TM : ToggleMenuView,
}[code];
};
*/
MCIViewFactory.UserViewCodes = [
'TL', 'ET', 'ME', 'MT', 'PL', 'BT', 'VM', 'HM', 'SM', 'TM'
];
@ -202,7 +110,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
// Pre-defined Label (Text View)
case 'PL' :
if(mci.args.length > 0) {
options.text = this.getPredefinedViewLabel(mci.args[0]);
options.text = getPredefinedMCIValue(this.client, mci.args[0]);
if(options.text) {
setOption(1, 'textStyle');
setOption(2, 'justify');
@ -272,7 +180,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
break;
default :
options.text = this.getPredefinedViewLabel(mci.code);
options.text = getPredefinedMCIValue(this.client, mci.code);
if(_.isString(options.text)) {
setWidth(0);

84
core/predefined_mci.js Normal file
View File

@ -0,0 +1,84 @@
/* jslint node: true */
'use strict';
var Config = require('./config.js').config;
var Log = require('./logger.js').log;
var getMessageAreaByName = require('./message_area.js').getMessageAreaByName;
var packageJson = require('../package.json');
var assert = require('assert');
var os = require('os');
var _ = require('lodash');
var moment = require('moment');
exports.getPredefinedMCIValue = getPredefinedMCIValue;
function getPredefinedMCIValue(client, code) {
if(!client || !code) {
return;
}
try {
return {
BN : function boardName() { return Config.general.boardName },
VL : function versionLabel() { return 'ENiGMA½ v' + packageJson.version },
VN : function version() { return packageJson.version },
UN : function userName() { return client.user.username },
UI : function userId() { return client.user.userId.toString() },
UG : function groups() { return _.values(client.user.groups).join(', ') },
UR : function realName() { return client.user.properties.real_name },
LO : function location() { return client.user.properties.location },
UA : function age() { return client.user.getAge().toString() },
UB : function birthdate() { return moment(client.user.properties.birthdate).format(client.currentTheme.helpers.getDateFormat()) },
US : function sex() { return client.user.properties.sex },
UE : function emailAddres() { return client.user.properties.email_address },
UW : function webAddress() { return client.user.properties.web_address },
UF : function affils() { return client.user.properties.affiliation },
UT : function themeId() { return client.user.properties.theme_id },
UC : function loginCount() { return client.user.properties.login_count.toString() },
MS : function accountCreated() { return moment(client.user.properties.account_created).format(client.currentTheme.helpers.getDateFormat()) },
CS : function currentStatus() { return client.currentStatus },
MD : function currentMenuDescription() {
return _.has(self, 'client.currentMenuModule.menuConfig.desc') ? client.currentMenuModule.menuConfig.desc : '';
},
MA : function messageAreaDescription() {
var area = getMessageAreaByName(client.user.properties.message_area_name);
return area ? area.desc : '';
},
SH : function termHeight() { return client.term.termHeight.toString() },
SW : function termWidth() { return client.term.termWidth.toString() },
ND : function connectedNode() { return client.node.toString() },
// :TODO: change to CD for 'Current Date'
DT : function date() { return moment().format(client.currentTheme.helpers.getDateFormat()) },
CT : function time() { return moment().format(client.currentTheme.helpers.getTimeFormat()) },
OS : function operatingSystem() {
return {
linux : 'Linux',
darwin : 'Mac OS X',
win32 : 'Windows',
sunos : 'SunOS',
freebsd : 'FreeBSD',
}[os.platform()] || os.type();
},
OA : function systemArchitecture() { return os.arch() },
SC : function systemCpuModel() { return os.cpus()[0].model },
IP : function clientIpAddress() { return client.address().address },
}[code]();
} catch(e) {
// Don't use client.log here as we may not have a client logger established yet!!
Log.warn( { code : code, exception : e.message }, 'Exception caught attempting to construct predefined label');
}
}

View File

@ -2,9 +2,17 @@
/*
ENiGMA½ Menu Configuration
See http://hjson.org/ for syntax
This configuration is in HJSON format. Strict to-spec JSON is also
perfectly valid. The hjson npm can be used to convert to/from JSON.
See http://hjson.org/ for more information and syntax.
*/
/*
:TODO: Fully convert to HJSON
Menu Configuration
Tip: demjson's jsonlint is an excellent tool for linting JSON files
@ -422,6 +430,7 @@
config: {
art: {
header: MSGVHDR
// :TODO: fix these!!
body: demo_fse_netmail_body.ans
footerEdit: demo_fse_netmail_footer_edit.ans
footerEditMenu: demo_fse_netmail_footer_edit_menu.ans