From d6316dd2093b5e0d21823daad911c69989499769 Mon Sep 17 00:00:00 2001 From: Vitaly Domnikov Date: Wed, 14 Dec 2016 11:18:15 -0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Performance=20tuning=20&=20bugfi?= =?UTF-8?q?x=20(#1111)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Perfomance tuning * cleanup matchesContainer method * fixes #1131 --- lib/components/term.js | 3 -- lib/hterm.js | 113 ++++++++++++++--------------------------- 2 files changed, 38 insertions(+), 78 deletions(-) diff --git a/lib/components/term.js b/lib/components/term.js index 7bb64b10..85c2a9fb 100644 --- a/lib/components/term.js +++ b/lib/components/term.js @@ -231,9 +231,6 @@ export default class Term extends Component { .cursor-node[focus="false"] { border-width: 1px !important; } - x-row { - line-height: 1.2em; - } ${hyperCaret} ${osSpecificCss} ${css} diff --git a/lib/hterm.js b/lib/hterm.js index c6f61375..079a986d 100644 --- a/lib/hterm.js +++ b/lib/hterm.js @@ -8,11 +8,6 @@ import selection from './utils/selection'; hterm.defaultStorage = new lib.Storage.Memory(); -// The current width of characters rendered in hterm -let charWidth; -// Containers to resize when char width changes -const containers = []; - // Provide selectAll to terminal viewport hterm.Terminal.prototype.selectAll = function () { // If the cursorNode_ having hyperCaret we need to remove it @@ -24,25 +19,6 @@ hterm.Terminal.prototype.selectAll = function () { } }; -const oldSetFontSize = hterm.Terminal.prototype.setFontSize; -hterm.Terminal.prototype.setFontSize = function (px) { - oldSetFontSize.call(this, px); - charWidth = this.scrollPort_.characterSize.width; - // @TODO Maybe clear old spans from the list of spans to resize ? - // Resize all containers to match the new whar width. - containers.forEach(container => { - if (container && container.style) { - container.style.width = `${container.wcNode ? charWidth * 2 : charWidth}px`; - } - }); -}; - -const oldSyncFontFamily = hterm.Terminal.prototype.syncFontFamily; -hterm.Terminal.prototype.syncFontFamily = function () { - oldSyncFontFamily.call(this); - this.setFontSize(); -}; - // override double click behavior to copy const oldMouse = hterm.Terminal.prototype.onMouse_; hterm.Terminal.prototype.onMouse_ = function (e) { @@ -67,10 +43,10 @@ hterm.TextAttributes.splitWidecharString = function (str) { return ctx; } if (ctx.acc) { - context.items.push({str: ctx.acc}); + ctx.items.push({str: ctx.acc}); ctx.acc = ''; } - context.items.push({str: rune, wcNode: true}); + ctx.items.push({str: rune, wcNode: true}); return ctx; }, {items: [], acc: ''}); if (context.acc) { @@ -140,69 +116,56 @@ hterm.Terminal.IO.prototype.writeUTF8 = function (string) { throw new Error('Attempt to print from inactive IO object.'); } - if (containsNonLatinCodepoints(string)) { - const splitString = runes(string); - const length = splitString.length; - this.terminal_.getTextAttributes().hasUnicode = true; - - for (let curChar = 0; curChar <= length; curChar++) { - this.terminal_.interpret(splitString[curChar]); - } - - this.terminal_.getTextAttributes().hasUnicode = false; - } else { + if (!containsNonLatinCodepoints(string)) { this.terminal_.interpret(string); + return; } + + runes(string).forEach(rune => { + this.terminal_.getTextAttributes().unicodeNode = containsNonLatinCodepoints(rune); + this.terminal_.interpret(rune); + this.terminal_.getTextAttributes().unicodeNode = false; + }); +}; + +const oldIsDefault = hterm.TextAttributes.prototype.isDefault; +hterm.TextAttributes.prototype.isDefault = function () { + return !this.unicodeNode && oldIsDefault.call(this); +}; + +const oldSetFontSize = hterm.Terminal.prototype.setFontSize; +hterm.Terminal.prototype.setFontSize = function (px) { + oldSetFontSize.call(this, px); + const doc = this.getDocument(); + let unicodeNodeStyle = doc.getElementById('hyper-unicode-styles'); + if (!unicodeNodeStyle) { + unicodeNodeStyle = doc.createElement('style'); + unicodeNodeStyle.setAttribute('id', 'hyper-unicode-styles'); + doc.head.appendChild(unicodeNodeStyle); + } + unicodeNodeStyle.innerHTML = ` + .unicode-node { + display: inline-block; + width: ${this.scrollPort_.characterSize.width}px; + } + `; }; const oldCreateContainer = hterm.TextAttributes.prototype.createContainer; hterm.TextAttributes.prototype.createContainer = function (text) { const container = oldCreateContainer.call(this, text); - - if (container.style && text.length === 1 && containsNonLatinCodepoints(text)) { - container.style.width = `${container.wcNode ? charWidth * 2 : charWidth}px`; - container.style.display = 'inline-block'; - - // If the container has unicode text, the char can overlap neigbouring containers. We need - // to ensure that the text is not hidden behind other containers. - container.style.overflow = 'visible'; - container.style.position = 'relative'; - - // Remember this container to resize it later when font size changes. - containers.push(container); + if (container.style && runes(text).length === 1 && containsNonLatinCodepoints(text)) { + container.className += ' unicode-node'; } - return container; }; // Do not match containers when one of them has unicode text (unicode chars need to be alone in their containers) const oldMatchesContainer = hterm.TextAttributes.prototype.matchesContainer; hterm.TextAttributes.prototype.matchesContainer = function (obj) { - const content = typeof obj === 'string' ? obj : obj.textContent; - if (containsNonLatinCodepoints(content)) { - return false; - } - - if (this.hasUnicode) { - return false; - } - - return oldMatchesContainer.call(this, obj); -}; - -/** - * Override 'containersMatch' so that containers with unicode do not match anything. - */ -const oldContainersMatch = hterm.TextAttributes.containersMatch; -hterm.TextAttributes.containersMatch = function (obj1, obj2) { - const content1 = typeof obj1 === 'string' ? obj1 : obj1.textContent; - const content2 = typeof obj2 === 'string' ? obj2 : obj2.textContent; - - if (containsNonLatinCodepoints(content1) || containsNonLatinCodepoints(content2)) { - return false; - } - - return oldContainersMatch(obj1, obj2); + return oldMatchesContainer.call(this, obj) && + !this.unicodeNode && + !containsNonLatinCodepoints(obj.textContent); }; // there's no option to turn off the size overlay