* Fix crash with JuiceSSH
* Lots of WIP on FSE * Various notes & fixes
This commit is contained in:
parent
2391ce6bc9
commit
aab07bb330
|
@ -67,6 +67,7 @@ function ClientTerminal(output) {
|
||||||
// XTERM
|
// XTERM
|
||||||
// * PuTTY
|
// * PuTTY
|
||||||
// LINUX
|
// LINUX
|
||||||
|
// * JuiceSSH - also via TERM=
|
||||||
// QNX
|
// QNX
|
||||||
// SCREEN
|
// SCREEN
|
||||||
// * ConnectBot
|
// * ConnectBot
|
||||||
|
@ -134,6 +135,9 @@ ClientTerminal.prototype.write = function(s, convertLineFeeds) {
|
||||||
this.output.write(this.iconv.encode(s, this.outputEncoding));
|
this.output.write(this.iconv.encode(s, this.outputEncoding));
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// :TODO: probably need to update these to convert IAC (0xff) -> IACIAC (escape it)
|
||||||
|
|
||||||
ClientTerminal.prototype.write = function(s, convertLineFeeds) {
|
ClientTerminal.prototype.write = function(s, convertLineFeeds) {
|
||||||
this.output.write(this.encode(s, convertLineFeeds));
|
this.output.write(this.encode(s, convertLineFeeds));
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,6 @@ var SpinnerMenuView = require('./spinner_menu_view.js').SpinnerMenuView;
|
||||||
var ToggleMenuView = require('./toggle_menu_view.js').ToggleMenuView;
|
var ToggleMenuView = require('./toggle_menu_view.js').ToggleMenuView;
|
||||||
var MaskEditTextView = require('./mask_edit_text_view.js').MaskEditTextView;
|
var MaskEditTextView = require('./mask_edit_text_view.js').MaskEditTextView;
|
||||||
var StatusBarView = require('./status_bar_view.js').StatusBarView;
|
var StatusBarView = require('./status_bar_view.js').StatusBarView;
|
||||||
|
|
||||||
var MultiLineEditTextView = require('./multi_line_edit_text_view.js').MultiLineEditTextView;
|
var MultiLineEditTextView = require('./multi_line_edit_text_view.js').MultiLineEditTextView;
|
||||||
|
|
||||||
var Config = require('./config.js').config;
|
var Config = require('./config.js').config;
|
||||||
|
@ -210,7 +209,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
|
||||||
|
|
||||||
default :
|
default :
|
||||||
options.text = this.getPredefinedViewLabel(mci.code);
|
options.text = this.getPredefinedViewLabel(mci.code);
|
||||||
if(options.text) {
|
if(_.isString(options.text)) {
|
||||||
view = new TextView(options);
|
view = new TextView(options);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
/* jslint node: true */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function Message(options) {
|
||||||
|
|
||||||
|
}
|
|
@ -100,12 +100,13 @@ function MultiLineEditTextView(options) {
|
||||||
// * http://www.bbsdocumentary.com/library/PROGRAMS/GRAPHICS/ANSI/bansi.txt
|
// * http://www.bbsdocumentary.com/library/PROGRAMS/GRAPHICS/ANSI/bansi.txt
|
||||||
//
|
//
|
||||||
// This seems overkill though, so let's default to 4 :)
|
// This seems overkill though, so let's default to 4 :)
|
||||||
|
// :TODO: what shoudl this really be? Maybe 8 is OK
|
||||||
//
|
//
|
||||||
this.tabWidth = _.isNumber(options.tabWidth) ? options.tabWidth : 4;
|
this.tabWidth = _.isNumber(options.tabWidth) ? options.tabWidth : 4;
|
||||||
|
|
||||||
this.textLines = [];
|
this.textLines = [];
|
||||||
this.topVisibleIndex = 0;
|
this.topVisibleIndex = 0;
|
||||||
this.mode = options.mode || 'edit'; // edit | preview
|
this.mode = options.mode || 'edit'; // edit | preview | read-only
|
||||||
|
|
||||||
//
|
//
|
||||||
// cursorPos represents zero-based row, col positions
|
// cursorPos represents zero-based row, col positions
|
||||||
|
@ -1052,7 +1053,7 @@ MultiLineEditTextView.prototype.setText = function(text) {
|
||||||
//this.textLines = [ { text : '' } ];
|
//this.textLines = [ { text : '' } ];
|
||||||
//this.insertRawText('');
|
//this.insertRawText('');
|
||||||
//text = "Tab:\r\n\tA\tB\tC\tD\tE\tF\tG\r\n reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeally long word!!!";
|
//text = "Tab:\r\n\tA\tB\tC\tD\tE\tF\tG\r\n reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeally long word!!!";
|
||||||
text = require('fs').readFileSync('/home/bashby/Downloads/test_text.txt', { encoding : 'utf-8'});
|
text = require('fs').readFileSync('/home/nuskooler/Downloads/test_text.txt', { encoding : 'utf-8'});
|
||||||
|
|
||||||
this.insertRawText(text);//, 0, 0);
|
this.insertRawText(text);//, 0, 0);
|
||||||
this.cursorEndOfDocument();
|
this.cursorEndOfDocument();
|
||||||
|
|
|
@ -598,7 +598,9 @@ TelnetClient.prototype.handleSbCommand = function(evt) {
|
||||||
Log.debug({ termHeight : self.term.termHeight, source : 'NEW-ENVIRON'}, 'Window height updated');
|
Log.debug({ termHeight : self.term.termHeight, source : 'NEW-ENVIRON'}, 'Window height updated');
|
||||||
} else {
|
} else {
|
||||||
if(name in self.term.env) {
|
if(name in self.term.env) {
|
||||||
assert(evt.type === SB_COMMANDS.INFO);
|
assert(
|
||||||
|
SB_COMMANDS.INFO === evt.type || SB_COMMANDS.IS === evt.type,
|
||||||
|
'Unexpected type: ' + evt.type);
|
||||||
|
|
||||||
Log.warn(
|
Log.warn(
|
||||||
{ varName : name, value : evt.envVars[name], existingValue : self.term.env[name] },
|
{ varName : name, value : evt.envVars[name], existingValue : self.term.env[name] },
|
||||||
|
|
|
@ -70,6 +70,7 @@ function View(options) {
|
||||||
this.dimens = { width : 0, height : 0 };
|
this.dimens = { width : 0, height : 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// :TODO: Just use styleSGRx for these, e.g. styleSGR0, styleSGR1 = norm/focus
|
||||||
this.ansiSGR = options.ansiSGR || ansi.getSGRFromGraphicRendition( { fg : 39, bg : 49 }, true);
|
this.ansiSGR = options.ansiSGR || ansi.getSGRFromGraphicRendition( { fg : 39, bg : 49 }, true);
|
||||||
this.ansiFocusSGR = options.ansiFocusSGR || this.ansiSGR;
|
this.ansiFocusSGR = options.ansiFocusSGR || this.ansiSGR;
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,7 @@ function ViewController(options) {
|
||||||
this.client = options.client;
|
this.client = options.client;
|
||||||
this.views = {}; // map of ID -> view
|
this.views = {}; // map of ID -> view
|
||||||
this.formId = options.formId || 0;
|
this.formId = options.formId || 0;
|
||||||
this.mciViewFactory = new MCIViewFactory(this.client);
|
this.mciViewFactory = new MCIViewFactory(this.client); // :TODO: can this not be a singleton?
|
||||||
//this.submitKeyMap = {};
|
|
||||||
|
|
||||||
this.actionKeyMap = {};
|
this.actionKeyMap = {};
|
||||||
|
|
||||||
|
@ -60,15 +59,6 @@ function ViewController(options) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
var submitViewId = self.submitKeyMap[key.name];
|
|
||||||
if(submitViewId) {
|
|
||||||
self.switchFocus(submitViewId);
|
|
||||||
self.submitForm();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self.focusedView && self.focusedView.acceptsInput) {
|
if(self.focusedView && self.focusedView.acceptsInput) {
|
||||||
|
@ -83,7 +73,7 @@ function ViewController(options) {
|
||||||
self.nextFocus();
|
self.nextFocus();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'accept' : // :TODO: consider naming this 'done'
|
case 'accept' :
|
||||||
if(self.focusedView && self.focusedView.submit) {
|
if(self.focusedView && self.focusedView.submit) {
|
||||||
self.submitForm();
|
self.submitForm();
|
||||||
} else {
|
} else {
|
||||||
|
@ -146,7 +136,7 @@ function ViewController(options) {
|
||||||
if(propAsset) {
|
if(propAsset) {
|
||||||
switch(propAsset.type) {
|
switch(propAsset.type) {
|
||||||
case 'config' :
|
case 'config' :
|
||||||
propValue = asset.resolveConfigAsset(config[propName]);
|
propValue = asset.resolveConfigAsset(conf[propName]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// :TODO: handle @art (e.g. text : @art ...)
|
// :TODO: handle @art (e.g. text : @art ...)
|
||||||
|
@ -196,18 +186,6 @@ function ViewController(options) {
|
||||||
initialFocusId = viewId;
|
initialFocusId = viewId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if(view.submit) {
|
|
||||||
submitId = viewId;
|
|
||||||
|
|
||||||
if(_.isArray(mciConf.submit)) {
|
|
||||||
for(var i = 0; i < mciConf.submit.length; i++) {
|
|
||||||
self.submitKeyMap[mciConf.submit[i]] = viewId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
nextItem(null);
|
nextItem(null);
|
||||||
},
|
},
|
||||||
function complete(err) {
|
function complete(err) {
|
||||||
|
|
Binary file not shown.
108
mods/fse.js
108
mods/fse.js
|
@ -1,13 +1,15 @@
|
||||||
/* jslint node: true */
|
/* jslint node: true */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var MenuModule = require('../core/menu_module.js').MenuModule;
|
var MenuModule = require('../core/menu_module.js').MenuModule;
|
||||||
var ViewController = require('../core/view_controller.js').ViewController;
|
var ViewController = require('../core/view_controller.js').ViewController;
|
||||||
var ansi = require('../core/ansi_term.js');
|
var ansi = require('../core/ansi_term.js');
|
||||||
|
var theme = require('../core/theme.js');
|
||||||
|
var MultiLineEditTextView = require('../core/multi_line_edit_text_view.js').MultiLineEditTextView;
|
||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
|
|
||||||
exports.getModule = FullScreenEditorModule;
|
exports.getModule = FullScreenEditorModule;
|
||||||
|
|
||||||
|
@ -39,7 +41,9 @@ function FullScreenEditorModule(options) {
|
||||||
body : 1,
|
body : 1,
|
||||||
footerEdit : 2,
|
footerEdit : 2,
|
||||||
footerEditMenu : 3,
|
footerEditMenu : 3,
|
||||||
fotoerView : 4,
|
footerView : 4,
|
||||||
|
|
||||||
|
help : 50,
|
||||||
}[name];
|
}[name];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,6 +83,44 @@ function FullScreenEditorModule(options) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.redrawScreen = function(options, cb) {
|
||||||
|
var comps = [ 'header', 'body' ];
|
||||||
|
var art = self.menuConfig.config.art;
|
||||||
|
|
||||||
|
self.client.term.rawWrite(ansi.resetScreen());
|
||||||
|
|
||||||
|
async.series(
|
||||||
|
[
|
||||||
|
function displayHeaderAndBody(callback) {
|
||||||
|
async.eachSeries( comps, function dispArt(n, next) {
|
||||||
|
self.displayArtAsset(art[n], function artDisplayed(err, artData) {
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
|
}, function complete(err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function displayFooter(callback) {
|
||||||
|
// we have to treat the footer special
|
||||||
|
self.redrawFooter( { clear : false, footerName : self.getFooterName() }, function footerDisplayed(err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function refreshViews(callback) {
|
||||||
|
comps.push(self.getFooterName());
|
||||||
|
|
||||||
|
comps.forEach(function artComp(n) {
|
||||||
|
self.viewControllers[n].redrawAll();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
],
|
||||||
|
function complete(err) {
|
||||||
|
cb(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
this.switchFooter = function(cb) {
|
this.switchFooter = function(cb) {
|
||||||
var footerName = self.getFooterName();
|
var footerName = self.getFooterName();
|
||||||
|
|
||||||
|
@ -231,6 +273,52 @@ function FullScreenEditorModule(options) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.displayHelp = function() {
|
||||||
|
//
|
||||||
|
// Replace body area with a temporary read-only MultiLineEditText
|
||||||
|
// with help contents. ESC or 'Q' closes back to previous state.
|
||||||
|
//
|
||||||
|
var formId = self.getFormId('help');
|
||||||
|
|
||||||
|
if(_.isUndefined(self.viewControllers.help)) {
|
||||||
|
self.addViewController('help', new ViewController( { client : self.client, formId : formId } ));
|
||||||
|
|
||||||
|
var helpViewOpts = {
|
||||||
|
position : self.getBodyView().position,
|
||||||
|
//dimens : self.getBodyView().dimens,
|
||||||
|
acceptsFocus : true,
|
||||||
|
acceptsInput : true,
|
||||||
|
id : 1,
|
||||||
|
client : self.client,
|
||||||
|
ansiSGR : ansi.sgr( [ 'normal', 'reset' ] ), // :TODO: use a styleSGRx here; default to white on black
|
||||||
|
};
|
||||||
|
|
||||||
|
var helpView = new MultiLineEditTextView(helpViewOpts);
|
||||||
|
// :TODO: this is to work around a bug... dimens in ctor should be enough!
|
||||||
|
helpView.setWidth(self.getBodyView().dimens.width);
|
||||||
|
helpView.setHeight(self.getBodyView().dimens.height);
|
||||||
|
helpView.setText('Some help text...')
|
||||||
|
|
||||||
|
self.viewControllers.help.addView(helpView);
|
||||||
|
self.viewControllers.help.switchFocus(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.viewControllers.help.redrawAll();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.displayHelp2 = function() {
|
||||||
|
self.client.term.rawWrite(ansi.resetScreen());
|
||||||
|
|
||||||
|
theme.displayThemeArt( { name : self.menuConfig.config.art.help, client : self.client },
|
||||||
|
function artDisplayed(err, artData) {
|
||||||
|
self.client.waitForKeyPress(function keyPress(ch, key) {
|
||||||
|
self.redrawScreen();
|
||||||
|
self.viewControllers.footerEditMenu.setFocus(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
this.observeEditEvents = function() {
|
this.observeEditEvents = function() {
|
||||||
var bodyView = self.getBodyView();
|
var bodyView = self.getBodyView();
|
||||||
|
|
||||||
|
@ -281,6 +369,12 @@ function FullScreenEditorModule(options) {
|
||||||
},
|
},
|
||||||
editModeMenu : function(formData, extraArgs) {
|
editModeMenu : function(formData, extraArgs) {
|
||||||
console.log('menu ' + formData.value['1'])
|
console.log('menu ' + formData.value['1'])
|
||||||
|
|
||||||
|
if(3 == formData.value['1']) {
|
||||||
|
console.log('Display help...')
|
||||||
|
self.viewControllers.footerEditMenu.setFocus(false);
|
||||||
|
self.displayHelp2();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -502,7 +502,8 @@
|
||||||
"body" : "demo_fse_netmail_body.ans",
|
"body" : "demo_fse_netmail_body.ans",
|
||||||
"footerEdit" : "demo_fse_netmail_footer_edit.ans",
|
"footerEdit" : "demo_fse_netmail_footer_edit.ans",
|
||||||
"footerEditMenu" : "demo_fse_netmail_footer_edit_menu.ans",
|
"footerEditMenu" : "demo_fse_netmail_footer_edit_menu.ans",
|
||||||
"footerView" : "demo_fse_netmail_footer_view.ans"
|
"footerView" : "demo_fse_netmail_footer_view.ans",
|
||||||
|
"help" : "demo_fse_netmail_help.ans"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"form" : {
|
"form" : {
|
||||||
|
@ -616,6 +617,17 @@
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"5" : {
|
||||||
|
"ML1" : {
|
||||||
|
"mci" : {
|
||||||
|
"ML1" : {
|
||||||
|
"width" : 79,
|
||||||
|
"height" : 17,
|
||||||
|
"text" : "" // :TODO: fixme
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue