diff --git a/core/ansi_escape_parser.js b/core/ansi_escape_parser.js index ad41fd27..c6d1276c 100644 --- a/core/ansi_escape_parser.js +++ b/core/ansi_escape_parser.js @@ -21,10 +21,16 @@ function ANSIEscapeParser(options) { events.EventEmitter.call(this); this.column = 1; - this.row = 1; this.scrollBack = 0; this.graphicRendition = {}; + if(options.startRow != null) { + this.row = options.startRow; + } + else { + this.row = 1; + } + this.parseState = { re : /(?:\x1b\x5b)([?=;0-9]*?)([ABCDHJKfhlmnpsu])/g, // eslint-disable-line no-control-regex }; diff --git a/core/art.js b/core/art.js index 1d0358c2..7385d08a 100644 --- a/core/art.js +++ b/core/art.js @@ -269,6 +269,7 @@ function display(client, art, options, cb) { termHeight : client.term.termHeight, termWidth : client.term.termWidth, trailingLF : options.trailingLF, + startRow : options.startRow, }); let parseComplete = false; diff --git a/core/fse.js b/core/fse.js index 361bbeff..8674fb3b 100644 --- a/core/fse.js +++ b/core/fse.js @@ -603,7 +603,7 @@ exports.FullScreenEditorModule = exports.getModule = class FullScreenEditorModul theme.displayThemedAsset( footerArt, self.client, - { font : self.menuConfig.font }, + { font : self.menuConfig.font, startRow: self.header.height + self.body.height }, function displayed(err, artData) { callback(err, artData); } @@ -626,19 +626,34 @@ exports.FullScreenEditorModule = exports.getModule = class FullScreenEditorModul async.series( [ function displayHeaderAndBody(callback) { - async.eachSeries( comps, function dispArt(n, next) { - theme.displayThemedAsset( - art[n], - self.client, - { font : self.menuConfig.font }, - function displayed(err) { - next(err); + async.waterfall( + [ + function displayHeader(callback) { + theme.displayThemedAsset( + art['header'], + self.client, + { font : self.menuConfig.font }, + function displayed(err, artInfo) { + return callback(err, artInfo); + } + ); + }, + function displayBody(artInfo, callback) { + theme.displayThemedAsset( + art['header'], + self.client, + { font : self.menuConfig.font, startRow: artInfo.height + 1 }, + function displayed(err, artInfo) { + return callback(err, artInfo); + } + ); } - ); - }, function complete(err) { - //self.body.height = self.client.term.termHeight - self.header.height - 1; - callback(err); - }); + ], + function complete(err) { + //self.body.height = self.client.term.termHeight - self.header.height - 1; + callback(err); + } + ); }, function displayFooter(callback) { // we have to treat the footer special @@ -700,31 +715,39 @@ exports.FullScreenEditorModule = exports.getModule = class FullScreenEditorModul assert(_.isObject(art)); - async.series( + async.waterfall( [ function beforeDisplayArt(callback) { self.beforeArt(callback); }, - function displayHeaderAndBodyArt(callback) { - async.eachSeries( [ 'header', 'body' ], function dispArt(n, next) { - theme.displayThemedAsset( - art[n], - self.client, - { font : self.menuConfig.font }, - function displayed(err, artData) { - if(artData) { - mciData[n] = artData; - self[n] = { height : artData.height }; - } - - next(err); + function displayHeader(callback) { + theme.displayThemedAsset( + art.header, + self.client, + { font : self.menuConfig.font }, + function displayed(err, artInfo) { + if(artInfo) { + mciData['header'] = artInfo; + self.header = {height: artInfo.height}; } - ); - }, function complete(err) { - callback(err); - }); + return callback(err, artInfo); + } + ); }, - function displayFooter(callback) { + function displayBody(artInfo, callback) { + theme.displayThemedAsset( + art.body, + self.client, + { font : self.menuConfig.font, startRow: artInfo.height }, + function displayed(err, artInfo) { + if(artInfo) { + mciData['body'] = artInfo; + self.body = {height: artInfo.height - self.header.height}; + } + return callback(err, artInfo); + }); + }, + function displayFooter(artInfo, callback) { self.setInitialFooterMode(); var footerName = self.getFooterName(); diff --git a/core/menu_module.js b/core/menu_module.js index 8fd2f5d2..990f7f78 100644 --- a/core/menu_module.js +++ b/core/menu_module.js @@ -124,6 +124,11 @@ exports.MenuModule = class MenuModule extends PluginModule { return callback(null); } + if(self.client.term.termHeight > 0 && pausePosition.row > self.client.termHeight) { + // If this scrolled, the prompt will go to the bottom of the screen + pausePosition.row = self.client.termHeight; + } + return self.pausePrompt(pausePosition, callback); }, function finishAndNext(callback) { diff --git a/core/show_art.js b/core/show_art.js index 7e53ca60..4236760c 100644 --- a/core/show_art.js +++ b/core/show_art.js @@ -171,22 +171,15 @@ exports.getModule = class ShowArtModule extends MenuModule { return callback(err); } const mciData = { menu : artData.mciMap }; - return callback(null, mciData); + if(self.client.term.termHeight > 0 && artData.height > self.client.term.termHeight) { + // We must have scrolled, adjust the positioning for pause + artData.height = self.client.term.termHeight; + } + const pausePosition = { row: artData.height + 1, col: 1}; + return callback(null, mciData, pausePosition); } ); }, - function recordCursorPosition(mciData, callback) { - if(!options.pause) { - return callback(null, mciData, null); // cursor position not needed - } - - self.client.once('cursor position report', pos => { - const pausePosition = { row : pos[0], col : 1 }; - return callback(null, mciData, pausePosition); - }); - - self.client.term.rawWrite(ANSI.queryPos()); - }, function afterArtDisplayed(mciData, pausePosition, callback) { self.mciReady(mciData, err => { return callback(err, pausePosition); diff --git a/core/theme.js b/core/theme.js index 98643c40..f574c62f 100644 --- a/core/theme.js +++ b/core/theme.js @@ -495,6 +495,7 @@ function displayPreparedArt(options, artInfo, cb) { sauce : artInfo.sauce, font : options.font, trailingLF : options.trailingLF, + startRow : options.startRow, }; art.display(options.client, artInfo.data, displayOpts, (err, mciMap, extraInfo) => { return cb(err, { mciMap : mciMap, artInfo : artInfo, extraInfo : extraInfo } ); @@ -585,7 +586,11 @@ function displayThemedPrompt(name, client, options, cb) { } if(options.row != null) { - artInfo.startRow = options.row - artInfo.height; + artInfo.startRow = options.row; + if(client.term.termHeight > 0 && artInfo.startRow + artInfo.height > client.term.termHeight) { + // in this case, we will have scrolled + artInfo.startRow = client.term.termHeight - artInfo.height; + } } return callback(null, promptConfig, artInfo); @@ -614,7 +619,7 @@ function displayThemedPrompt(name, client, options, cb) { }); }, function clearPauseArt(artInfo, assocViewController, callback) { - // Only clear with height if clearPrompt is true and if we were able + // Only clear with height if clearPrompt is true and if we were able // to determine the row if(options.clearPrompt && artInfo.startRow) { if(artInfo.startRow && artInfo.height) {