From 6b03b5357fdba83dd012f20483ead2b411ae1b89 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Thu, 10 Sep 2015 21:01:04 -0600 Subject: [PATCH] * 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 --- core/client_term.js | 2 +- core/color_codes.js | 47 ++++++++++++------- core/connect.js | 4 +- core/mci_view_factory.js | 98 ++-------------------------------------- core/predefined_mci.js | 84 ++++++++++++++++++++++++++++++++++ mods/menu.hjson | 11 ++++- 6 files changed, 130 insertions(+), 116 deletions(-) create mode 100644 core/predefined_mci.js diff --git a/core/client_term.js b/core/client_term.js index 0e67b6e4..e3e5f7a5 100644 --- a/core/client_term.js +++ b/core/client_term.js @@ -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) { diff --git a/core/color_codes.js b/core/color_codes.js index 0676c780..591b7862 100644 --- a/core/color_codes.js +++ b/core/color_codes.js @@ -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(): <0-7> // * fromSyncronet(): // 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) { diff --git a/core/connect.js b/core/connect.js index b326ed9e..2946be90 100644 --- a/core/connect.js +++ b/core/connect.js @@ -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) { diff --git a/core/mci_view_factory.js b/core/mci_view_factory.js index 2adb019f..5d90a866 100644 --- a/core/mci_view_factory.js +++ b/core/mci_view_factory.js @@ -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); diff --git a/core/predefined_mci.js b/core/predefined_mci.js new file mode 100644 index 00000000..d0e7a2b9 --- /dev/null +++ b/core/predefined_mci.js @@ -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'); + } +} diff --git a/mods/menu.hjson b/mods/menu.hjson index 2d87923d..d8cc932a 100644 --- a/mods/menu.hjson +++ b/mods/menu.hjson @@ -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