mirror of
https://github.com/quine-global/hyper.git
synced 2026-01-13 04:28:41 -09:00
Unicode Support / Cursor issues Fix (#740)
* Add container with a fixed width around unicode characters * Make container width dynamic and fix wide chars clipping issue * Finer control on the creation of containers for text inserted in the terminal
This commit is contained in:
parent
27a20e0cfc
commit
da4858a76e
2 changed files with 102 additions and 3 deletions
102
lib/hterm.js
102
lib/hterm.js
|
|
@ -1,10 +1,16 @@
|
|||
import {hterm, lib} from 'hterm-umdjs';
|
||||
import fromCharCode from './utils/key-code';
|
||||
import runes from 'runes';
|
||||
|
||||
const selection = require('./utils/selection');
|
||||
import fromCharCode from './utils/key-code';
|
||||
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 () {
|
||||
// We need to clear the DOM range to reset anchorNode
|
||||
|
|
@ -12,6 +18,25 @@ hterm.Terminal.prototype.selectAll = function () {
|
|||
selection.all(this);
|
||||
};
|
||||
|
||||
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) {
|
||||
|
|
@ -23,6 +48,79 @@ hterm.Terminal.prototype.onMouse_ = function (e) {
|
|||
return oldMouse.call(this, e);
|
||||
};
|
||||
|
||||
function containsNonLatinCodepoints(s) {
|
||||
return /[^\u0000-\u00ff]/.test(s);
|
||||
}
|
||||
hterm.Terminal.IO.prototype.writeUTF8 = function (string) {
|
||||
if (this.terminal_.io !== this) {
|
||||
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 {
|
||||
this.terminal_.interpret(string);
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
// there's no option to turn off the size overlay
|
||||
hterm.Terminal.prototype.overlaySize = function () {};
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,8 @@
|
|||
"reselect": "2.5.4",
|
||||
"seamless-immutable": "6.1.3",
|
||||
"semver": "5.3.0",
|
||||
"uuid": "2.0.2"
|
||||
"uuid": "2.0.2",
|
||||
"runes": "^0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^0.16.0",
|
||||
|
|
|
|||
Loading…
Reference in a new issue