Skip to content

Commit 1daf594

Browse files
upgrade to xterm v5
1 parent 8337acb commit 1daf594

File tree

6 files changed

+94
-91
lines changed

6 files changed

+94
-91
lines changed

bin/snapshot-libs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ if (false) {
2323
require('mousetrap');
2424
require('open');
2525
require('xterm-addon-fit');
26-
require('xterm-addon-ligatures');
2726
require('xterm-addon-search');
2827
require('xterm-addon-web-links');
2928
require('xterm-addon-webgl');
29+
require('xterm-addon-canvas');
3030
require('xterm');
3131
}

lib/components/term.tsx

Lines changed: 49 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {FitAddon} from 'xterm-addon-fit';
44
import {WebLinksAddon} from 'xterm-addon-web-links';
55
import {SearchAddon, ISearchDecorationOptions} from 'xterm-addon-search';
66
import {WebglAddon} from 'xterm-addon-webgl';
7+
import {CanvasAddon} from 'xterm-addon-canvas';
78
import {LigaturesAddon} from 'xterm-addon-ligatures';
89
import {Unicode11Addon} from 'xterm-addon-unicode11';
910
import {clipboard, shell} from 'electron';
@@ -12,7 +13,7 @@ import terms from '../terms';
1213
import processClipboard from '../utils/paste';
1314
import _SearchBox from './searchBox';
1415
import {TermProps} from '../hyper';
15-
import {ObjectTypedKeys} from '../utils/object';
16+
import {pickBy, isEqual} from 'lodash';
1617
import {decorate} from '../utils/plugins';
1718
import 'xterm/css/xterm.css';
1819

@@ -57,14 +58,13 @@ const getTermOptions = (props: TermProps): ITerminalOptions => {
5758
letterSpacing: props.letterSpacing,
5859
allowTransparency: needTransparency,
5960
macOptionClickForcesSelection: props.macOptionSelectionMode === 'force',
60-
bellStyle: props.bell === 'SOUND' ? 'sound' : 'none',
6161
windowsMode: isWindows,
6262
theme: {
6363
foreground: props.foregroundColor,
6464
background: backgroundColor,
6565
cursor: props.cursorColor,
6666
cursorAccent: props.cursorAccentColor,
67-
selection: props.selectionColor,
67+
selectionBackground: props.selectionColor,
6868
black: props.colors.black,
6969
red: props.colors.red,
7070
green: props.colors.green,
@@ -83,7 +83,8 @@ const getTermOptions = (props: TermProps): ITerminalOptions => {
8383
brightWhite: props.colors.lightWhite
8484
},
8585
screenReaderMode: props.screenReaderMode,
86-
overviewRulerWidth: 20
86+
overviewRulerWidth: 20,
87+
allowProposedApi: true
8788
};
8889
};
8990

@@ -107,7 +108,8 @@ export default class Term extends React.PureComponent<
107108
termWrapperRef: HTMLElement | null;
108109
termOptions: ITerminalOptions;
109110
disposableListeners: IDisposable[];
110-
termDefaultBellSound: string | null;
111+
defaultBellSound: HTMLAudioElement | null;
112+
bellSound: HTMLAudioElement | null;
111113
fitAddon: FitAddon;
112114
searchAddon: SearchAddon;
113115
static rendererTypes: Record<string, string>;
@@ -131,7 +133,8 @@ export default class Term extends React.PureComponent<
131133
this.termWrapperRef = null;
132134
this.termOptions = {};
133135
this.disposableListeners = [];
134-
this.termDefaultBellSound = null;
136+
this.defaultBellSound = null;
137+
this.bellSound = null;
135138
this.fitAddon = new FitAddon();
136139
this.searchAddon = new SearchAddon();
137140
this.searchDecorations = {
@@ -158,7 +161,14 @@ export default class Term extends React.PureComponent<
158161

159162
this.termOptions = getTermOptions(props);
160163
this.term = props.term || new Terminal(this.termOptions);
161-
this.termDefaultBellSound = this.term.getOption('bellSound');
164+
this.defaultBellSound = new Audio(
165+
// Source: https://freesound.org/people/altemark/sounds/45759/
166+
// This sound is released under the Creative Commons Attribution 3.0 Unported
167+
// (CC BY 3.0) license. It was created by 'altemark'. No modifications have been
168+
// made, apart from the conversion to base64.
169+
'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjMyLjEwNAAAAAAAAAAAAAAA//tQxAADB8AhSmxhIIEVCSiJrDCQBTcu3UrAIwUdkRgQbFAZC1CQEwTJ9mjRvBA4UOLD8nKVOWfh+UlK3z/177OXrfOdKl7pyn3Xf//WreyTRUoAWgBgkOAGbZHBgG1OF6zM82DWbZaUmMBptgQhGjsyYqc9ae9XFz280948NMBWInljyzsNRFLPWdnZGWrddDsjK1unuSrVN9jJsK8KuQtQCtMBjCEtImISdNKJOopIpBFpNSMbIHCSRpRR5iakjTiyzLhchUUBwCgyKiweBv/7UsQbg8isVNoMPMjAAAA0gAAABEVFGmgqK////9bP/6XCykxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq'
170+
);
171+
this.setBellSound(props.bell, props.bellSound);
162172

163173
// The parent element for the terminal is attached and removed manually so
164174
// that we can preserve it across mounts and unmounts of the component
@@ -186,35 +196,27 @@ export default class Term extends React.PureComponent<
186196
}
187197
Term.reportRenderer(props.uid, useWebGL ? 'WebGL' : 'Canvas');
188198

189-
const shallActivateWebLink = (event: Record<string, any> | undefined): boolean => {
190-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
191-
return event && (!props.webLinksActivationKey || event[`${props.webLinksActivationKey}Key`]);
199+
const shallActivateWebLink = (event: MouseEvent): boolean => {
200+
if (!event) return false;
201+
return props.webLinksActivationKey ? event[`${props.webLinksActivationKey}Key`] : true;
192202
};
193203

194204
// eslint-disable-next-line @typescript-eslint/unbound-method
195205
this.term.attachCustomKeyEventHandler(this.keyboardHandler);
196206
this.term.loadAddon(this.fitAddon);
197207
this.term.loadAddon(this.searchAddon);
198208
this.term.loadAddon(
199-
new WebLinksAddon(
200-
(event: MouseEvent | undefined, uri: string) => {
201-
if (shallActivateWebLink(event)) void shell.openExternal(uri);
202-
},
203-
{
204-
// prevent default electron link handling to allow selection, e.g. via double-click
205-
willLinkActivate: (event: MouseEvent | undefined) => {
206-
event?.preventDefault();
207-
return shallActivateWebLink(event);
208-
},
209-
priority: Date.now()
210-
}
211-
)
209+
new WebLinksAddon((event, uri) => {
210+
if (shallActivateWebLink(event)) void shell.openExternal(uri);
211+
})
212212
);
213213
this.term.open(this.termRef);
214214
if (useWebGL) {
215215
this.term.loadAddon(new WebglAddon());
216+
} else {
217+
this.term.loadAddon(new CanvasAddon());
216218
}
217-
if (props.disableLigatures !== true && !useWebGL) {
219+
if (props.disableLigatures !== true) {
218220
this.term.loadAddon(new LigaturesAddon());
219221
}
220222
this.term.loadAddon(new Unicode11Addon());
@@ -252,6 +254,10 @@ export default class Term extends React.PureComponent<
252254
this.disposableListeners.push(this.term.onData(props.onData));
253255
}
254256

257+
this.term.onBell(() => {
258+
this.ringBell();
259+
});
260+
255261
if (props.onResize) {
256262
this.disposableListeners.push(
257263
this.term.onResize(({cols, rows}) => {
@@ -393,47 +399,38 @@ export default class Term extends React.PureComponent<
393399
return !e.catched;
394400
}
395401

402+
setBellSound(bell: string | null, sound: string | null) {
403+
if (bell?.toUpperCase() === 'SOUND') {
404+
this.bellSound = sound ? new Audio(sound) : this.defaultBellSound;
405+
} else {
406+
this.bellSound = null;
407+
}
408+
}
409+
410+
ringBell() {
411+
void this.bellSound?.play();
412+
}
413+
396414
componentDidUpdate(prevProps: TermProps) {
397415
if (!prevProps.cleared && this.props.cleared) {
398416
this.clear();
399417
}
400418

401419
const nextTermOptions = getTermOptions(this.props);
402420

403-
// Use bellSound in nextProps if it exists
404-
// otherwise use the default sound found in xterm.
405-
nextTermOptions.bellSound = this.props.bellSound || this.termDefaultBellSound!;
421+
if (prevProps.bell !== this.props.bell || prevProps.bellSound !== this.props.bellSound) {
422+
this.setBellSound(this.props.bell, this.props.bellSound);
423+
}
406424

407425
if (prevProps.search && !this.props.search) {
408426
this.closeSearchBox();
409427
}
410428

411429
// Update only options that have changed.
412-
ObjectTypedKeys(nextTermOptions)
413-
.filter((option) => option !== 'theme' && nextTermOptions[option] !== this.termOptions[option])
414-
.forEach((option) => {
415-
try {
416-
this.term.setOption(option, nextTermOptions[option]);
417-
} catch (_e) {
418-
const e = _e as {message: string};
419-
if (/The webgl renderer only works with the webgl char atlas/i.test(e.message)) {
420-
// Ignore this because the char atlas will also be changed
421-
} else {
422-
throw e;
423-
}
424-
}
425-
});
426-
427-
// Do we need to update theme?
428-
const shouldUpdateTheme =
429-
!this.termOptions.theme ||
430-
nextTermOptions.rendererType !== this.termOptions.rendererType ||
431-
ObjectTypedKeys(nextTermOptions.theme!).some(
432-
(option) => nextTermOptions.theme![option] !== this.termOptions.theme![option]
433-
);
434-
if (shouldUpdateTheme) {
435-
this.term.setOption('theme', nextTermOptions.theme);
436-
}
430+
this.term.options = pickBy(
431+
nextTermOptions,
432+
(value, key) => !isEqual(this.termOptions[key as keyof ITerminalOptions], value)
433+
);
437434

438435
this.termOptions = nextTermOptions;
439436

lib/hyper.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ export type uiState = Immutable<{
102102
updateReleaseUrl: string | null;
103103
updateVersion: string | null;
104104
webGLRenderer: boolean;
105-
webLinksActivationKey: string;
105+
webLinksActivationKey: 'ctrl' | 'alt' | 'meta' | 'shift' | '';
106106
}>;
107107

108108
export type session = {
@@ -381,7 +381,7 @@ export type TermProps = {
381381
uiFontFamily: string;
382382
url: string | null;
383383
webGLRenderer: boolean;
384-
webLinksActivationKey: string;
384+
webLinksActivationKey: 'ctrl' | 'alt' | 'meta' | 'shift' | '';
385385
ref_: (uid: string, term: Term | null) => void;
386386
} & extensionProps;
387387

package.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,14 @@
5959
"typescript-json-schema": "0.57.0",
6060
"uuid": "9.0.0",
6161
"webpack-cli": "5.1.4",
62-
"xterm": "4.19.0",
63-
"xterm-addon-fit": "^0.5.0",
64-
"xterm-addon-ligatures": "0.6.0-beta.19",
65-
"xterm-addon-search": "^0.9.0",
66-
"xterm-addon-unicode11": "^0.3.0",
67-
"xterm-addon-web-links": "^0.6.0",
68-
"xterm-addon-webgl": "0.12.0"
62+
"xterm": "5.2.1",
63+
"xterm-addon-canvas": "0.4.0",
64+
"xterm-addon-fit": "0.7.0",
65+
"xterm-addon-ligatures": "0.6.0",
66+
"xterm-addon-search": "0.12.0",
67+
"xterm-addon-unicode11": "0.5.0",
68+
"xterm-addon-web-links": "0.8.0",
69+
"xterm-addon-webgl": "0.15.0"
6970
},
7071
"devDependencies": {
7172
"@ava/babel": "2.0.0",

webpack.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,10 @@ const config: webpack.Configuration[] = [
118118
mousetrap: 'require("./node_modules/mousetrap/mousetrap.js")',
119119
open: 'require("./node_modules/open/index.js")',
120120
'xterm-addon-fit': 'require("./node_modules/xterm-addon-fit/lib/xterm-addon-fit.js")',
121-
'xterm-addon-ligatures': 'require("./node_modules/xterm-addon-ligatures/lib/xterm-addon-ligatures.js")',
122121
'xterm-addon-search': 'require("./node_modules/xterm-addon-search/lib/xterm-addon-search.js")',
123122
'xterm-addon-web-links': 'require("./node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js")',
124123
'xterm-addon-webgl': 'require("./node_modules/xterm-addon-webgl/lib/xterm-addon-webgl.js")',
124+
'xterm-addon-canvas': 'require("./node_modules/xterm-addon-canvas/lib/xterm-addon-canvas.js")',
125125
xterm: 'require("./node_modules/xterm/lib/xterm.js")'
126126
},
127127
plugins: [

yarn.lock

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7532,43 +7532,48 @@ xtend@^4.0.0, xtend@^4.0.2, xtend@~4.0.0:
75327532
resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
75337533
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
75347534

7535-
xterm-addon-fit@^0.5.0:
7536-
version "0.5.0"
7537-
resolved "https://registry.npmjs.org/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596"
7538-
integrity sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==
7535+
xterm-addon-canvas@0.4.0:
7536+
version "0.4.0"
7537+
resolved "https://registry.npmjs.org/xterm-addon-canvas/-/xterm-addon-canvas-0.4.0.tgz#a6ee6a56deb0c495fcef29afe6d94b7119a0f334"
7538+
integrity sha512-iTC8CdjX9+hGX7jiEuiDMXzHsY/FKJdVnbjep5xjRXNu7RKOk15xuecIkJ7HZORqMVPpr4DGS3jyd9XUoBuxqw==
7539+
7540+
xterm-addon-fit@0.7.0:
7541+
version "0.7.0"
7542+
resolved "https://registry.npmjs.org/xterm-addon-fit/-/xterm-addon-fit-0.7.0.tgz#b8ade6d96e63b47443862088f6670b49fb752c6a"
7543+
integrity sha512-tQgHGoHqRTgeROPnvmtEJywLKoC/V9eNs4bLLz7iyJr1aW/QFzRwfd3MGiJ6odJd9xEfxcW36/xRU47JkD5NKQ==
75397544

7540-
xterm-addon-ligatures@0.6.0-beta.19:
7541-
version "0.6.0-beta.19"
7542-
resolved "https://registry.npmjs.org/xterm-addon-ligatures/-/xterm-addon-ligatures-0.6.0-beta.19.tgz#5e43eeaf84968e014769a5f2c6a3a3601dc4771c"
7543-
integrity sha512-A0BIjFF6g5aPI0HiI2JMhhMV3gaHbpZ+ua+UNagkID0GxZ/ezn0wVOAtNQl/KlqnFueoyZIxlbyXmWNAfJVPRg==
7545+
xterm-addon-ligatures@0.6.0:
7546+
version "0.6.0"
7547+
resolved "https://registry.npmjs.org/xterm-addon-ligatures/-/xterm-addon-ligatures-0.6.0.tgz#c51801b0150c62ac1165654757b55c796457d195"
7548+
integrity sha512-DxiYCXXYEpnwr8li4/QhG64exjrLX1nHBfNNfrQgx5e8Z9tK2SjWKpxI6PZEy++8+YdL1F7VjWI4aKOaDt2VVw==
75447549
dependencies:
75457550
font-finder "^1.1.0"
75467551
font-ligatures "^1.4.1"
75477552

7548-
xterm-addon-search@^0.9.0:
7549-
version "0.9.0"
7550-
resolved "https://registry.npmjs.org/xterm-addon-search/-/xterm-addon-search-0.9.0.tgz#95278ebb818cfcf882209ae75be96e0bea5d52a5"
7551-
integrity sha512-aoolI8YuHvdGw+Qjg8g2M4kst0v86GtB7WeBm4F0jNXA005/6QbWWy9eCsvnIDLJOFI5JSSrZnD6CaOkvBQYPA==
7553+
xterm-addon-search@0.12.0:
7554+
version "0.12.0"
7555+
resolved "https://registry.npmjs.org/xterm-addon-search/-/xterm-addon-search-0.12.0.tgz#2ef8f56aecf699a3989223a1260f1e079d7c74e2"
7556+
integrity sha512-hXAuO7Ts2+Jf9K8mZrUx8IFd7c/Flgks/jyqA1L4reymyfmXtcsd+WDLel8R9Tgy2CLyKABVBP09/Ua/FmXcvg==
75527557

7553-
xterm-addon-unicode11@^0.3.0:
7554-
version "0.3.0"
7555-
resolved "https://registry.npmjs.org/xterm-addon-unicode11/-/xterm-addon-unicode11-0.3.0.tgz#e4435c3c91a5294a7eb8b79c380acbb28a659463"
7556-
integrity sha512-x5fHDZT2j9tlTlHnzPHt++9uKZ2kJ/lYQOj3L6xJA22xoJsS8UQRw/5YIFg2FUHqEAbV77Z1fZij/9NycMSH/A==
7558+
xterm-addon-unicode11@0.5.0:
7559+
version "0.5.0"
7560+
resolved "https://registry.npmjs.org/xterm-addon-unicode11/-/xterm-addon-unicode11-0.5.0.tgz#41c0d96acc1e3bb6c6596eee64e163b6bca74be7"
7561+
integrity sha512-Jm4/g4QiTxiKiTbYICQgC791ubhIZyoIwxAIgOW8z8HWFNY+lwk+dwaKEaEeGBfM48Vk8fklsUW9u/PlenYEBg==
75577562

7558-
xterm-addon-web-links@^0.6.0:
7559-
version "0.6.0"
7560-
resolved "https://registry.npmjs.org/xterm-addon-web-links/-/xterm-addon-web-links-0.6.0.tgz#0296cb6c99588847894670d998c9ea6a6aeb26ee"
7561-
integrity sha512-H6XzjWWZu8FBo+fnYpxdPk9w5M6drbsvwPEJZGRS38MihiQaVFpKlCMKdfRgDbKGE530tw1yH54rhpZfHgt2/A==
7563+
xterm-addon-web-links@0.8.0:
7564+
version "0.8.0"
7565+
resolved "https://registry.npmjs.org/xterm-addon-web-links/-/xterm-addon-web-links-0.8.0.tgz#2cb1d57129271022569208578b0bf4774e7e6ea9"
7566+
integrity sha512-J4tKngmIu20ytX9SEJjAP3UGksah7iALqBtfTwT9ZnmFHVplCumYQsUJfKuS+JwMhjsjH61YXfndenLNvjRrEw==
75627567

7563-
xterm-addon-webgl@0.12.0:
7564-
version "0.12.0"
7565-
resolved "https://registry.npmjs.org/xterm-addon-webgl/-/xterm-addon-webgl-0.12.0.tgz#2fba8d31890a122adafa1c2fb945482e2ae12973"
7566-
integrity sha512-3P5ihdjPnxH6Wrvqjki9UD+duoVrp1fvnO/pSpXP2F1L2GwY6TDNExgj8Yg141vMCNgQbcVqmsTLYEYZxjY92A==
7568+
xterm-addon-webgl@0.15.0:
7569+
version "0.15.0"
7570+
resolved "https://registry.npmjs.org/xterm-addon-webgl/-/xterm-addon-webgl-0.15.0.tgz#c10f93ca619524f5a470eaac44258bab0ae8e3c7"
7571+
integrity sha512-ZLcqogMFHr4g/YRhcCh3xE8tTklnyut/M+O/XhVsFBRB/YCvYhPdLQ5/AQk54V0wjWAQpa8CF3W8DVR9OqyMCg==
75677572

7568-
xterm@4.19.0:
7569-
version "4.19.0"
7570-
resolved "https://registry.npmjs.org/xterm/-/xterm-4.19.0.tgz#c0f9d09cd61de1d658f43ca75f992197add9ef6d"
7571-
integrity sha512-c3Cp4eOVsYY5Q839dR5IejghRPpxciGmLWWaP9g+ppfMeBChMeLa1DCA+pmX/jyDZ+zxFOmlJL/82qVdayVoGQ==
7573+
xterm@5.2.1:
7574+
version "5.2.1"
7575+
resolved "https://registry.npmjs.org/xterm/-/xterm-5.2.1.tgz#b3fea7bdb55b9be1d4b31f4cd1091f26ac42afb8"
7576+
integrity sha512-cs5Y1fFevgcdoh2hJROMVIWwoBHD80P1fIP79gopLHJIE4kTzzblanoivxTiQ4+92YM9IxS36H1q0MxIJXQBcA==
75727577

75737578
y18n@^5.0.5:
75747579
version "5.0.5"

0 commit comments

Comments
 (0)