@theia/console 1.53.0-next.4 → 1.53.0-next.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -30
- package/package.json +5 -5
- package/src/browser/ansi-console-item.tsx +48 -48
- package/src/browser/console-content-widget.tsx +91 -91
- package/src/browser/console-contribution.ts +143 -143
- package/src/browser/console-frontend-module.ts +32 -32
- package/src/browser/console-history.ts +76 -76
- package/src/browser/console-manager.ts +37 -37
- package/src/browser/console-session-manager.ts +121 -121
- package/src/browser/console-session.ts +61 -61
- package/src/browser/console-widget.ts +298 -298
- package/src/browser/style/index.css +49 -49
- package/src/package.spec.ts +28 -28
|
@@ -1,298 +1,298 @@
|
|
|
1
|
-
// *****************************************************************************
|
|
2
|
-
// Copyright (C) 2018 TypeFox and others.
|
|
3
|
-
//
|
|
4
|
-
// This program and the accompanying materials are made available under the
|
|
5
|
-
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
-
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
-
//
|
|
8
|
-
// This Source Code may also be made available under the following Secondary
|
|
9
|
-
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
-
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
-
// with the GNU Classpath Exception which is available at
|
|
12
|
-
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
-
//
|
|
14
|
-
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
-
// *****************************************************************************
|
|
16
|
-
|
|
17
|
-
import { ElementExt } from '@theia/core/shared/@phosphor/domutils';
|
|
18
|
-
import { injectable, inject, postConstruct, interfaces, Container } from '@theia/core/shared/inversify';
|
|
19
|
-
import { TreeSourceNode } from '@theia/core/lib/browser/source-tree';
|
|
20
|
-
import { ContextKeyService, ContextKey } from '@theia/core/lib/browser/context-key-service';
|
|
21
|
-
import { BaseWidget, PanelLayout, Widget, Message, MessageLoop, StatefulWidget, CompositeTreeNode } from '@theia/core/lib/browser';
|
|
22
|
-
import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
|
|
23
|
-
import URI from '@theia/core/lib/common/uri';
|
|
24
|
-
import { MonacoEditorProvider } from '@theia/monaco/lib/browser/monaco-editor-provider';
|
|
25
|
-
import { ConsoleHistory } from './console-history';
|
|
26
|
-
import { ConsoleContentWidget } from './console-content-widget';
|
|
27
|
-
import { ConsoleSession } from './console-session';
|
|
28
|
-
import { ConsoleSessionManager } from './console-session-manager';
|
|
29
|
-
import * as monaco from '@theia/monaco-editor-core';
|
|
30
|
-
|
|
31
|
-
export const ConsoleOptions = Symbol('ConsoleWidgetOptions');
|
|
32
|
-
export interface ConsoleOptions {
|
|
33
|
-
id: string
|
|
34
|
-
title?: {
|
|
35
|
-
label?: string
|
|
36
|
-
iconClass?: string
|
|
37
|
-
caption?: string
|
|
38
|
-
}
|
|
39
|
-
input: {
|
|
40
|
-
uri: URI
|
|
41
|
-
options?: MonacoEditor.IOptions
|
|
42
|
-
}
|
|
43
|
-
inputFocusContextKey?: ContextKey<boolean>
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
@injectable()
|
|
47
|
-
export class ConsoleWidget extends BaseWidget implements StatefulWidget {
|
|
48
|
-
|
|
49
|
-
static styles = {
|
|
50
|
-
node: 'theia-console-widget',
|
|
51
|
-
content: 'theia-console-content',
|
|
52
|
-
input: 'theia-console-input',
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
static createContainer(parent: interfaces.Container, options: ConsoleOptions): Container {
|
|
56
|
-
const child = ConsoleContentWidget.createContainer(parent);
|
|
57
|
-
child.bind(ConsoleHistory).toSelf();
|
|
58
|
-
child.bind(ConsoleOptions).toConstantValue(options);
|
|
59
|
-
child.bind(ConsoleWidget).toSelf();
|
|
60
|
-
return child;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
@inject(ConsoleOptions)
|
|
64
|
-
protected readonly options: ConsoleOptions;
|
|
65
|
-
|
|
66
|
-
@inject(ConsoleContentWidget)
|
|
67
|
-
readonly content: ConsoleContentWidget;
|
|
68
|
-
|
|
69
|
-
@inject(ConsoleHistory)
|
|
70
|
-
protected readonly history: ConsoleHistory;
|
|
71
|
-
|
|
72
|
-
@inject(ConsoleSessionManager)
|
|
73
|
-
protected readonly sessionManager: ConsoleSessionManager;
|
|
74
|
-
|
|
75
|
-
@inject(MonacoEditorProvider)
|
|
76
|
-
protected readonly editorProvider: MonacoEditorProvider;
|
|
77
|
-
|
|
78
|
-
@inject(ContextKeyService)
|
|
79
|
-
protected readonly contextKeyService: ContextKeyService;
|
|
80
|
-
|
|
81
|
-
protected _input: MonacoEditor;
|
|
82
|
-
protected _inputFocusContextKey: ContextKey<boolean>;
|
|
83
|
-
|
|
84
|
-
constructor() {
|
|
85
|
-
super();
|
|
86
|
-
this.node.classList.add(ConsoleWidget.styles.node);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
@postConstruct()
|
|
90
|
-
protected init(): void {
|
|
91
|
-
this.doInit();
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
protected async doInit(): Promise<void> {
|
|
95
|
-
const { id, title, inputFocusContextKey } = this.options;
|
|
96
|
-
const { label, iconClass, caption } = Object.assign({}, title);
|
|
97
|
-
this.id = id;
|
|
98
|
-
this.title.closable = true;
|
|
99
|
-
this.title.label = label || id;
|
|
100
|
-
if (iconClass) {
|
|
101
|
-
this.title.iconClass = iconClass;
|
|
102
|
-
}
|
|
103
|
-
this.title.caption = caption || label || id;
|
|
104
|
-
|
|
105
|
-
const layout = this.layout = new PanelLayout();
|
|
106
|
-
|
|
107
|
-
this.content.node.classList.add(ConsoleWidget.styles.content);
|
|
108
|
-
this.toDispose.push(this.content);
|
|
109
|
-
layout.addWidget(this.content);
|
|
110
|
-
|
|
111
|
-
const inputWidget = new Widget();
|
|
112
|
-
inputWidget.node.classList.add(ConsoleWidget.styles.input);
|
|
113
|
-
layout.addWidget(inputWidget);
|
|
114
|
-
|
|
115
|
-
const input = this._input = await this.createInput(inputWidget.node);
|
|
116
|
-
this.toDispose.push(input);
|
|
117
|
-
this.toDispose.push(input.getControl().onDidLayoutChange(() => this.resizeContent()));
|
|
118
|
-
|
|
119
|
-
this.toDispose.push(input.getControl().onDidChangeConfiguration(event => {
|
|
120
|
-
if (event.hasChanged(monaco.editor.EditorOption.fontInfo)) {
|
|
121
|
-
this.updateFont();
|
|
122
|
-
}
|
|
123
|
-
}));
|
|
124
|
-
|
|
125
|
-
this.session = this.sessionManager.selectedSession;
|
|
126
|
-
this.toDispose.push(this.sessionManager.onDidChangeSelectedSession(session => {
|
|
127
|
-
// Do not clear the session output when `undefined`.
|
|
128
|
-
if (session) {
|
|
129
|
-
this.session = session;
|
|
130
|
-
}
|
|
131
|
-
}));
|
|
132
|
-
|
|
133
|
-
this.updateFont();
|
|
134
|
-
if (inputFocusContextKey) {
|
|
135
|
-
this.toDispose.push(input.onFocusChanged(() => inputFocusContextKey.set(this.hasInputFocus())));
|
|
136
|
-
this.toDispose.push(input.onCursorPositionChanged(() => input.getControl().createContextKey('consoleNavigationBackEnabled', this.consoleNavigationBackEnabled)));
|
|
137
|
-
this.toDispose.push(input.onCursorPositionChanged(() => input.getControl().createContextKey('consoleNavigationForwardEnabled', this.consoleNavigationForwardEnabled)));
|
|
138
|
-
}
|
|
139
|
-
input.getControl().createContextKey('consoleInputFocus', true);
|
|
140
|
-
const contentContext = this.contextKeyService.createScoped(this.content.node);
|
|
141
|
-
contentContext.setContext('consoleContentFocus', true);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
protected createInput(node: HTMLElement): Promise<MonacoEditor> {
|
|
145
|
-
return this.editorProvider.createInline(this.options.input.uri, node, this.options.input.options);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
protected updateFont(): void {
|
|
149
|
-
const { fontFamily, fontSize, lineHeight } = this._input.getControl().getOption(monaco.editor.EditorOption.fontInfo);
|
|
150
|
-
this.content.node.style.fontFamily = fontFamily;
|
|
151
|
-
this.content.node.style.fontSize = fontSize + 'px';
|
|
152
|
-
this.content.node.style.lineHeight = lineHeight + 'px';
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
protected _session: ConsoleSession | undefined;
|
|
156
|
-
set session(session: ConsoleSession | undefined) {
|
|
157
|
-
if (this._session === session) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
this._session = session;
|
|
161
|
-
this.content.source = session;
|
|
162
|
-
}
|
|
163
|
-
get session(): ConsoleSession | undefined {
|
|
164
|
-
return this._session;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
get input(): MonacoEditor {
|
|
168
|
-
return this._input;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
get consoleNavigationBackEnabled(): boolean {
|
|
172
|
-
const editor = this.input.getControl();
|
|
173
|
-
return !!editor.getPosition()!.equals({ lineNumber: 1, column: 1 });
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
get consoleNavigationForwardEnabled(): boolean {
|
|
177
|
-
const editor = this.input.getControl();
|
|
178
|
-
const lineNumber = editor.getModel()!.getLineCount();
|
|
179
|
-
const column = editor.getModel()!.getLineMaxColumn(lineNumber);
|
|
180
|
-
return !!editor.getPosition()!.equals({ lineNumber, column });
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
selectAll(): void {
|
|
184
|
-
const selection = document.getSelection();
|
|
185
|
-
if (selection) {
|
|
186
|
-
selection.selectAllChildren(this.content.node);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
collapseAll(): void {
|
|
191
|
-
const { root } = this.content.model;
|
|
192
|
-
if (CompositeTreeNode.is(root)) {
|
|
193
|
-
this.content.model.collapseAll(root);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
clear(): void {
|
|
198
|
-
if (this.session) {
|
|
199
|
-
this.session.clear();
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
async execute(): Promise<void> {
|
|
204
|
-
const value = this._input.getControl().getValue();
|
|
205
|
-
this._input.getControl().setValue('');
|
|
206
|
-
this.history.push(value);
|
|
207
|
-
if (this.session) {
|
|
208
|
-
const listener = this.content.model.onNodeRefreshed(() => {
|
|
209
|
-
listener.dispose();
|
|
210
|
-
this.revealLastOutput();
|
|
211
|
-
});
|
|
212
|
-
await this.session.execute(value);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
navigateBack(): void {
|
|
217
|
-
const value = this.history.previous;
|
|
218
|
-
if (value === undefined) {
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
const editor = this.input.getControl();
|
|
222
|
-
editor.setValue(value);
|
|
223
|
-
editor.setPosition({
|
|
224
|
-
lineNumber: 1,
|
|
225
|
-
column: 1
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
navigateForward(): void {
|
|
230
|
-
const value = this.history.next || '';
|
|
231
|
-
const editor = this.input.getControl();
|
|
232
|
-
editor.setValue(value);
|
|
233
|
-
const lineNumber = editor.getModel()!.getLineCount();
|
|
234
|
-
const column = editor.getModel()!.getLineMaxColumn(lineNumber);
|
|
235
|
-
editor.setPosition({ lineNumber, column });
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
protected revealLastOutput(): void {
|
|
239
|
-
const { root } = this.content.model;
|
|
240
|
-
if (TreeSourceNode.is(root)) {
|
|
241
|
-
this.content.model.selectNode(root.children[root.children.length - 1]);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
protected override onActivateRequest(msg: Message): void {
|
|
246
|
-
super.onActivateRequest(msg);
|
|
247
|
-
this._input.focus();
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
protected totalHeight = -1;
|
|
251
|
-
protected totalWidth = -1;
|
|
252
|
-
protected override onResize(msg: Widget.ResizeMessage): void {
|
|
253
|
-
super.onResize(msg);
|
|
254
|
-
this.totalWidth = msg.width;
|
|
255
|
-
this.totalHeight = msg.height;
|
|
256
|
-
this._input.resizeToFit();
|
|
257
|
-
this.resizeContent();
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
protected resizeContent(): void {
|
|
261
|
-
this.totalHeight = this.totalHeight < 0 ? this.computeHeight() : this.totalHeight;
|
|
262
|
-
const inputHeight = this._input.getControl().getLayoutInfo().height;
|
|
263
|
-
const contentHeight = this.totalHeight - inputHeight;
|
|
264
|
-
this.content.node.style.height = `${contentHeight}px`;
|
|
265
|
-
MessageLoop.sendMessage(this.content, new Widget.ResizeMessage(this.totalWidth, contentHeight));
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
protected computeHeight(): number {
|
|
269
|
-
const { verticalSum } = ElementExt.boxSizing(this.node);
|
|
270
|
-
return this.node.offsetHeight - verticalSum;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
storeState(): object {
|
|
274
|
-
const history = this.history.store();
|
|
275
|
-
const input = this.input.storeViewState();
|
|
276
|
-
return {
|
|
277
|
-
history,
|
|
278
|
-
input
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
restoreState(oldState: object): void {
|
|
283
|
-
if ('history' in oldState) {
|
|
284
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
285
|
-
this.history.restore((<any>oldState)['history']);
|
|
286
|
-
}
|
|
287
|
-
this.input.getControl().setValue(this.history.current || '');
|
|
288
|
-
if ('input' in oldState) {
|
|
289
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
290
|
-
this.input.restoreViewState((<any>oldState)['input']);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
hasInputFocus(): boolean {
|
|
295
|
-
return this._input && this._input.isFocused({ strict: true });
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
}
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2018 TypeFox and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { ElementExt } from '@theia/core/shared/@phosphor/domutils';
|
|
18
|
+
import { injectable, inject, postConstruct, interfaces, Container } from '@theia/core/shared/inversify';
|
|
19
|
+
import { TreeSourceNode } from '@theia/core/lib/browser/source-tree';
|
|
20
|
+
import { ContextKeyService, ContextKey } from '@theia/core/lib/browser/context-key-service';
|
|
21
|
+
import { BaseWidget, PanelLayout, Widget, Message, MessageLoop, StatefulWidget, CompositeTreeNode } from '@theia/core/lib/browser';
|
|
22
|
+
import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
|
|
23
|
+
import URI from '@theia/core/lib/common/uri';
|
|
24
|
+
import { MonacoEditorProvider } from '@theia/monaco/lib/browser/monaco-editor-provider';
|
|
25
|
+
import { ConsoleHistory } from './console-history';
|
|
26
|
+
import { ConsoleContentWidget } from './console-content-widget';
|
|
27
|
+
import { ConsoleSession } from './console-session';
|
|
28
|
+
import { ConsoleSessionManager } from './console-session-manager';
|
|
29
|
+
import * as monaco from '@theia/monaco-editor-core';
|
|
30
|
+
|
|
31
|
+
export const ConsoleOptions = Symbol('ConsoleWidgetOptions');
|
|
32
|
+
export interface ConsoleOptions {
|
|
33
|
+
id: string
|
|
34
|
+
title?: {
|
|
35
|
+
label?: string
|
|
36
|
+
iconClass?: string
|
|
37
|
+
caption?: string
|
|
38
|
+
}
|
|
39
|
+
input: {
|
|
40
|
+
uri: URI
|
|
41
|
+
options?: MonacoEditor.IOptions
|
|
42
|
+
}
|
|
43
|
+
inputFocusContextKey?: ContextKey<boolean>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@injectable()
|
|
47
|
+
export class ConsoleWidget extends BaseWidget implements StatefulWidget {
|
|
48
|
+
|
|
49
|
+
static styles = {
|
|
50
|
+
node: 'theia-console-widget',
|
|
51
|
+
content: 'theia-console-content',
|
|
52
|
+
input: 'theia-console-input',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
static createContainer(parent: interfaces.Container, options: ConsoleOptions): Container {
|
|
56
|
+
const child = ConsoleContentWidget.createContainer(parent);
|
|
57
|
+
child.bind(ConsoleHistory).toSelf();
|
|
58
|
+
child.bind(ConsoleOptions).toConstantValue(options);
|
|
59
|
+
child.bind(ConsoleWidget).toSelf();
|
|
60
|
+
return child;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@inject(ConsoleOptions)
|
|
64
|
+
protected readonly options: ConsoleOptions;
|
|
65
|
+
|
|
66
|
+
@inject(ConsoleContentWidget)
|
|
67
|
+
readonly content: ConsoleContentWidget;
|
|
68
|
+
|
|
69
|
+
@inject(ConsoleHistory)
|
|
70
|
+
protected readonly history: ConsoleHistory;
|
|
71
|
+
|
|
72
|
+
@inject(ConsoleSessionManager)
|
|
73
|
+
protected readonly sessionManager: ConsoleSessionManager;
|
|
74
|
+
|
|
75
|
+
@inject(MonacoEditorProvider)
|
|
76
|
+
protected readonly editorProvider: MonacoEditorProvider;
|
|
77
|
+
|
|
78
|
+
@inject(ContextKeyService)
|
|
79
|
+
protected readonly contextKeyService: ContextKeyService;
|
|
80
|
+
|
|
81
|
+
protected _input: MonacoEditor;
|
|
82
|
+
protected _inputFocusContextKey: ContextKey<boolean>;
|
|
83
|
+
|
|
84
|
+
constructor() {
|
|
85
|
+
super();
|
|
86
|
+
this.node.classList.add(ConsoleWidget.styles.node);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@postConstruct()
|
|
90
|
+
protected init(): void {
|
|
91
|
+
this.doInit();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
protected async doInit(): Promise<void> {
|
|
95
|
+
const { id, title, inputFocusContextKey } = this.options;
|
|
96
|
+
const { label, iconClass, caption } = Object.assign({}, title);
|
|
97
|
+
this.id = id;
|
|
98
|
+
this.title.closable = true;
|
|
99
|
+
this.title.label = label || id;
|
|
100
|
+
if (iconClass) {
|
|
101
|
+
this.title.iconClass = iconClass;
|
|
102
|
+
}
|
|
103
|
+
this.title.caption = caption || label || id;
|
|
104
|
+
|
|
105
|
+
const layout = this.layout = new PanelLayout();
|
|
106
|
+
|
|
107
|
+
this.content.node.classList.add(ConsoleWidget.styles.content);
|
|
108
|
+
this.toDispose.push(this.content);
|
|
109
|
+
layout.addWidget(this.content);
|
|
110
|
+
|
|
111
|
+
const inputWidget = new Widget();
|
|
112
|
+
inputWidget.node.classList.add(ConsoleWidget.styles.input);
|
|
113
|
+
layout.addWidget(inputWidget);
|
|
114
|
+
|
|
115
|
+
const input = this._input = await this.createInput(inputWidget.node);
|
|
116
|
+
this.toDispose.push(input);
|
|
117
|
+
this.toDispose.push(input.getControl().onDidLayoutChange(() => this.resizeContent()));
|
|
118
|
+
|
|
119
|
+
this.toDispose.push(input.getControl().onDidChangeConfiguration(event => {
|
|
120
|
+
if (event.hasChanged(monaco.editor.EditorOption.fontInfo)) {
|
|
121
|
+
this.updateFont();
|
|
122
|
+
}
|
|
123
|
+
}));
|
|
124
|
+
|
|
125
|
+
this.session = this.sessionManager.selectedSession;
|
|
126
|
+
this.toDispose.push(this.sessionManager.onDidChangeSelectedSession(session => {
|
|
127
|
+
// Do not clear the session output when `undefined`.
|
|
128
|
+
if (session) {
|
|
129
|
+
this.session = session;
|
|
130
|
+
}
|
|
131
|
+
}));
|
|
132
|
+
|
|
133
|
+
this.updateFont();
|
|
134
|
+
if (inputFocusContextKey) {
|
|
135
|
+
this.toDispose.push(input.onFocusChanged(() => inputFocusContextKey.set(this.hasInputFocus())));
|
|
136
|
+
this.toDispose.push(input.onCursorPositionChanged(() => input.getControl().createContextKey('consoleNavigationBackEnabled', this.consoleNavigationBackEnabled)));
|
|
137
|
+
this.toDispose.push(input.onCursorPositionChanged(() => input.getControl().createContextKey('consoleNavigationForwardEnabled', this.consoleNavigationForwardEnabled)));
|
|
138
|
+
}
|
|
139
|
+
input.getControl().createContextKey('consoleInputFocus', true);
|
|
140
|
+
const contentContext = this.contextKeyService.createScoped(this.content.node);
|
|
141
|
+
contentContext.setContext('consoleContentFocus', true);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
protected createInput(node: HTMLElement): Promise<MonacoEditor> {
|
|
145
|
+
return this.editorProvider.createInline(this.options.input.uri, node, this.options.input.options);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
protected updateFont(): void {
|
|
149
|
+
const { fontFamily, fontSize, lineHeight } = this._input.getControl().getOption(monaco.editor.EditorOption.fontInfo);
|
|
150
|
+
this.content.node.style.fontFamily = fontFamily;
|
|
151
|
+
this.content.node.style.fontSize = fontSize + 'px';
|
|
152
|
+
this.content.node.style.lineHeight = lineHeight + 'px';
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
protected _session: ConsoleSession | undefined;
|
|
156
|
+
set session(session: ConsoleSession | undefined) {
|
|
157
|
+
if (this._session === session) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
this._session = session;
|
|
161
|
+
this.content.source = session;
|
|
162
|
+
}
|
|
163
|
+
get session(): ConsoleSession | undefined {
|
|
164
|
+
return this._session;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
get input(): MonacoEditor {
|
|
168
|
+
return this._input;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
get consoleNavigationBackEnabled(): boolean {
|
|
172
|
+
const editor = this.input.getControl();
|
|
173
|
+
return !!editor.getPosition()!.equals({ lineNumber: 1, column: 1 });
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
get consoleNavigationForwardEnabled(): boolean {
|
|
177
|
+
const editor = this.input.getControl();
|
|
178
|
+
const lineNumber = editor.getModel()!.getLineCount();
|
|
179
|
+
const column = editor.getModel()!.getLineMaxColumn(lineNumber);
|
|
180
|
+
return !!editor.getPosition()!.equals({ lineNumber, column });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
selectAll(): void {
|
|
184
|
+
const selection = document.getSelection();
|
|
185
|
+
if (selection) {
|
|
186
|
+
selection.selectAllChildren(this.content.node);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
collapseAll(): void {
|
|
191
|
+
const { root } = this.content.model;
|
|
192
|
+
if (CompositeTreeNode.is(root)) {
|
|
193
|
+
this.content.model.collapseAll(root);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
clear(): void {
|
|
198
|
+
if (this.session) {
|
|
199
|
+
this.session.clear();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async execute(): Promise<void> {
|
|
204
|
+
const value = this._input.getControl().getValue();
|
|
205
|
+
this._input.getControl().setValue('');
|
|
206
|
+
this.history.push(value);
|
|
207
|
+
if (this.session) {
|
|
208
|
+
const listener = this.content.model.onNodeRefreshed(() => {
|
|
209
|
+
listener.dispose();
|
|
210
|
+
this.revealLastOutput();
|
|
211
|
+
});
|
|
212
|
+
await this.session.execute(value);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
navigateBack(): void {
|
|
217
|
+
const value = this.history.previous;
|
|
218
|
+
if (value === undefined) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
const editor = this.input.getControl();
|
|
222
|
+
editor.setValue(value);
|
|
223
|
+
editor.setPosition({
|
|
224
|
+
lineNumber: 1,
|
|
225
|
+
column: 1
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
navigateForward(): void {
|
|
230
|
+
const value = this.history.next || '';
|
|
231
|
+
const editor = this.input.getControl();
|
|
232
|
+
editor.setValue(value);
|
|
233
|
+
const lineNumber = editor.getModel()!.getLineCount();
|
|
234
|
+
const column = editor.getModel()!.getLineMaxColumn(lineNumber);
|
|
235
|
+
editor.setPosition({ lineNumber, column });
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
protected revealLastOutput(): void {
|
|
239
|
+
const { root } = this.content.model;
|
|
240
|
+
if (TreeSourceNode.is(root)) {
|
|
241
|
+
this.content.model.selectNode(root.children[root.children.length - 1]);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
protected override onActivateRequest(msg: Message): void {
|
|
246
|
+
super.onActivateRequest(msg);
|
|
247
|
+
this._input.focus();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
protected totalHeight = -1;
|
|
251
|
+
protected totalWidth = -1;
|
|
252
|
+
protected override onResize(msg: Widget.ResizeMessage): void {
|
|
253
|
+
super.onResize(msg);
|
|
254
|
+
this.totalWidth = msg.width;
|
|
255
|
+
this.totalHeight = msg.height;
|
|
256
|
+
this._input.resizeToFit();
|
|
257
|
+
this.resizeContent();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
protected resizeContent(): void {
|
|
261
|
+
this.totalHeight = this.totalHeight < 0 ? this.computeHeight() : this.totalHeight;
|
|
262
|
+
const inputHeight = this._input.getControl().getLayoutInfo().height;
|
|
263
|
+
const contentHeight = this.totalHeight - inputHeight;
|
|
264
|
+
this.content.node.style.height = `${contentHeight}px`;
|
|
265
|
+
MessageLoop.sendMessage(this.content, new Widget.ResizeMessage(this.totalWidth, contentHeight));
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
protected computeHeight(): number {
|
|
269
|
+
const { verticalSum } = ElementExt.boxSizing(this.node);
|
|
270
|
+
return this.node.offsetHeight - verticalSum;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
storeState(): object {
|
|
274
|
+
const history = this.history.store();
|
|
275
|
+
const input = this.input.storeViewState();
|
|
276
|
+
return {
|
|
277
|
+
history,
|
|
278
|
+
input
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
restoreState(oldState: object): void {
|
|
283
|
+
if ('history' in oldState) {
|
|
284
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
285
|
+
this.history.restore((<any>oldState)['history']);
|
|
286
|
+
}
|
|
287
|
+
this.input.getControl().setValue(this.history.current || '');
|
|
288
|
+
if ('input' in oldState) {
|
|
289
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
290
|
+
this.input.restoreViewState((<any>oldState)['input']);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
hasInputFocus(): boolean {
|
|
295
|
+
return this._input && this._input.isFocused({ strict: true });
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
}
|