* Fix crash with JuiceSSH

* Lots of WIP on FSE
* Various notes & fixes
This commit is contained in:
Bryan Ashby 2015-07-11 16:39:42 -06:00
parent 2391ce6bc9
commit aab07bb330
10 changed files with 136 additions and 39 deletions

View File

@ -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));
}; };

View File

@ -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;

6
core/message.js Normal file
View File

@ -0,0 +1,6 @@
/* jslint node: true */
'use strict';
function Message(options) {
}

View File

@ -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();

View File

@ -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] },

View File

@ -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;

View File

@ -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.

View File

@ -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();
}
} }
}; };
} }

View File

@ -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
}
}
}
} }
} }
/* /*