UNPKG

@dcloudio/uni-debugger

Version:

uni-app debugger

150 lines (132 loc) 4.4 kB
// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /** * @unrestricted */ Terminal.TerminalWidget = class extends UI.VBox { constructor() { super(true); this.registerRequiredCSS('terminal/xterm.js/build/xterm.css'); this.registerRequiredCSS('terminal/terminal.css'); this.element.classList.add('terminal-root'); this._init(); this._linkifier = new Components.Linkifier(); this._config = {attributes: true, childList: true, characterData: true, subtree: true}; } async _init() { const backend = await Services.serviceManager.createRemoteService('Terminal'); this._initialized(backend); } /** * @param {?Services.ServiceManager.Service} backend */ _initialized(backend) { if (!backend) { if (!this._unavailableLabel) { this._unavailableLabel = this.contentElement.createChild('div', 'terminal-error-message fill'); this._unavailableLabel.createChild('div').textContent = Common.UIString('Terminal service is not available'); } setTimeout(this._init.bind(this), 2000); return; } if (this._unavailableLabel) { this._unavailableLabel.remove(); delete this._unavailableLabel; } this._backend = backend; if (!this._term) { this._term = new Terminal({cursorBlink: true}); this._term.open(this.contentElement); this._mutationObserver = new MutationObserver(this._linkify.bind(this)); this._mutationObserver.observe(this.contentElement, this._config); this._term.on('data', data => { this._backend.send('write', {data: data}); }); this._term.fit(); this._term.on('resize', size => { this._backend.send('resize', {cols: size.cols, rows: size.rows}); }); } this._backend.send('init', {cols: this._term.cols, rows: this._term.rows}); this._backend.on('data', result => { this._term.write(result.data); }); this._backend.on('disposed', this._disposed.bind(this)); } /** * @override */ onResize() { if (this._term) this._term.fit(); } _disposed() { this._initialized(null); } /** * @override */ ownerViewDisposed() { if (this._backend) this._backend.dispose(); } _linkify() { this._mutationObserver.takeRecords(); this._mutationObserver.disconnect(); this._linkifier.reset(); const rows = this._term['rowContainer'].children; for (let i = 0; i < rows.length; i++) this._linkifyTerminalLine(rows[i]); this._mutationObserver.observe(this.contentElement, this._config); } /** * @param {string} string */ _linkifyText(string) { const regex1 = /([/\w\.-]*)+\:([\d]+)(?:\:([\d]+))?/; const regex2 = /([/\w\.-]*)+\(([\d]+),([\d]+)\)/; const container = createDocumentFragment(); while (string) { const linkString = regex1.exec(string) || regex2.exec(string); if (!linkString) break; const text = linkString[0]; const path = linkString[1]; const lineNumber = parseInt(linkString[2], 10) - 1 || 0; const columnNumber = parseInt(linkString[3], 10) - 1 || 0; const uiSourceCode = Workspace.workspace.uiSourceCodes().find(uisc => uisc.url().endsWith(path)); const linkIndex = string.indexOf(text); const nonLink = string.substring(0, linkIndex); container.appendChild(createTextNode(nonLink)); if (uiSourceCode) { container.appendChild(Components.Linkifier.linkifyURL( uiSourceCode.url(), {text, lineNumber, columnNumber, maxLengh: Number.MAX_VALUE, className: 'terminal-link'})); } else { container.appendChild(createTextNode(text)); } string = string.substring(linkIndex + text.length); } if (string) container.appendChild(createTextNode(string)); return container; } /** * @param {!Node} line */ _linkifyTerminalLine(line) { let node = line.firstChild; while (node) { if (node.nodeType !== Node.TEXT_NODE) { node = node.nextSibling; continue; } const nextNode = node.nextSibling; node.remove(); const linkified = this._linkifyText(node.textContent); line.insertBefore(linkified, nextNode); node = nextNode; } } };