Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

complete support of variable substitution #5835

Merged
merged 9 commits into from
Aug 13, 2019
9 changes: 4 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@ Breaking changes:
- [plugin] files from 'plugin-ext/src/api' moved to 'plugin-ext/src/common', renamed 'model.ts' to 'plugin-api-rpc-model.ts', 'plugin-api.ts' to 'plugin-api-rpc.ts'
- [task] ensure that plugin tasks are registered before accessing them [5869](https://github.com/theia-ide/theia/pull/5869)
- `TaskProviderRegistry` and `TaskResolverRegistry` are promisified

Breaking changes:
- [shell][plugin] integrated view containers and views [#5665](https://github.com/theia-ide/theia/pull/5665)
- `Source Control` and `Explorer` are view containers now and previous layout data cannot be loaded for them. Because of it the layout is completely reset.

- [shell][plugin] integrated view containers and views [#5665](https://github.com/theia-ide/theia/pull/5665)
- `Source Control` and `Explorer` are view containers now and previous layout data cannot be loaded for them. Because of it the layout is completely reset.
- [vscode] complete support of variable substitution [#5835](https://github.com/theia-ide/theia/pull/5835)
- inline `VariableQuickOpenItem`

## v0.9.0
- [core] added `theia-widget-noInfo` css class to be used by widgets when displaying no information messages [#5717](https://github.com/theia-ide/theia/pull/5717)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const envVariablesPath = '/services/envs';

export const EnvVariablesServer = Symbol('EnvVariablesServer');
export interface EnvVariablesServer {
getExecPath(): Promise<string>
getVariables(): Promise<EnvVariable[]>
getValue(key: string): Promise<EnvVariable | undefined>
}
Expand Down
10 changes: 9 additions & 1 deletion packages/core/src/node/env-variables/env-variables-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import { injectable } from 'inversify';
import { EnvVariable, EnvVariablesServer } from '../../common/env-variables';
import { isWindows } from '../../common/os';

@injectable()
export class EnvVariablesServerImpl implements EnvVariablesServer {
Expand All @@ -25,15 +26,22 @@ export class EnvVariablesServerImpl implements EnvVariablesServer {
constructor() {
const prEnv = process.env;
Object.keys(prEnv).forEach((key: string) => {
this.envs[key] = {'name' : key, 'value' : prEnv[key]};
this.envs[key] = { 'name': key, 'value': prEnv[key] };
});
}

async getExecPath(): Promise<string> {
return process.execPath;
}

async getVariables(): Promise<EnvVariable[]> {
return Object.keys(this.envs).map(key => this.envs[key]);
}

async getValue(key: string): Promise<EnvVariable | undefined> {
if (isWindows) {
key = key.toLowerCase();
}
return this.envs[key];
}
}
4 changes: 3 additions & 1 deletion packages/debug/src/browser/debug-schema-updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { IJSONSchema } from '@theia/core/lib/common/json-schema';
import URI from '@theia/core/lib/common/uri';
import { DebugService } from '../common/debug-service';
import { debugPreferencesSchema } from './debug-preferences';
import { inputsSchema } from '@theia/variable-resolver/lib/browser/variable-input-schema';

@injectable()
export class DebugSchemaUpdater {
Expand Down Expand Up @@ -82,6 +83,7 @@ const launchSchema: IJSONSchema = {
'type': 'object',
oneOf: []
}
}
},
inputs: inputsSchema.definitions!.inputs
}
};
5 changes: 4 additions & 1 deletion packages/debug/src/browser/debug-session-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ export class DebugSessionManager {
}
const { workspaceFolderUri } = options;
const resolvedConfiguration = await this.resolveDebugConfiguration(options.configuration, workspaceFolderUri);
const configuration = await this.variableResolver.resolve(resolvedConfiguration);
const configuration = await this.variableResolver.resolve(resolvedConfiguration, {
context: options.workspaceFolderUri ? new URI(options.workspaceFolderUri) : undefined,
configurationSection: 'launch'
});
const key = configuration.name + workspaceFolderUri;
const id = this.configurationIds.has(key) ? this.configurationIds.get(key)! + 1 : 0;
this.configurationIds.set(key, id);
Expand Down
8 changes: 8 additions & 0 deletions packages/editor/src/browser/editor-variable-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ export class EditorVariableContribution implements VariableContribution {
return editor ? `${editor.cursor.line + 1}` : undefined;
}
});
variables.registerVariable({
name: 'selectedText',
description: 'The current selected text in the active file',
resolve: () => {
const editor = this.getCurrentEditor();
return editor ? editor.document.getText(editor.selection) : undefined;
}
});
}

protected getCurrentEditor(): TextEditor | undefined {
Expand Down
134 changes: 134 additions & 0 deletions packages/variable-resolver/src/browser/common-variable-contribution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/********************************************************************************
* Copyright (C) 2019 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { injectable, inject } from 'inversify';
import { VariableContribution, VariableRegistry } from './variable';
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
import { CommandService } from '@theia/core/lib/common/command';
import { PreferenceService } from '@theia/core/lib/browser/preferences/preference-service';
import { ResourceContextKey } from '@theia/core/lib/browser/resource-context-key';
import { VariableInput } from './variable-input';
import { QuickInputService } from '@theia/core/lib/browser/quick-open/quick-input-service';
import { QuickPickService, QuickPickItem } from '@theia/core/lib/common/quick-pick-service';
import { MaybeArray, RecursivePartial } from '@theia/core/lib/common/types';

@injectable()
export class CommonVariableContribution implements VariableContribution {

@inject(EnvVariablesServer)
protected readonly env: EnvVariablesServer;

@inject(CommandService)
protected readonly commands: CommandService;

@inject(PreferenceService)
protected readonly preferences: PreferenceService;

@inject(ResourceContextKey)
protected readonly resourceContextKey: ResourceContextKey;

@inject(QuickInputService)
protected readonly quickInputService: QuickInputService;

@inject(QuickPickService)
protected readonly quickPickService: QuickPickService;

async registerVariables(variables: VariableRegistry): Promise<void> {
const execPath = await this.env.getExecPath();
variables.registerVariable({
name: 'execPath',
resolve: () => execPath
});
variables.registerVariable({
name: 'env',
resolve: async (_, envVariableName) => {
const envVariable = envVariableName && await this.env.getValue(envVariableName);
const envValue = envVariable && envVariable.value;
return envValue || '';
}
});
variables.registerVariable({
name: 'config',
resolve: (resourceUri = this.resourceContextKey.get(), preferenceName) => {
if (!preferenceName) {
return undefined;
}
return this.preferences.get(preferenceName, undefined, resourceUri && resourceUri.toString());
}
});
variables.registerVariable({
name: 'command',
resolve: async (_, command) =>
// tslint:disable-next-line:no-return-await
command && await this.commands.executeCommand(command)
});
variables.registerVariable({
name: 'input',
resolve: async (resourceUri = this.resourceContextKey.get(), variable, section) => {
if (!variable || !section) {
return undefined;
}
const configuration = this.preferences.get<RecursivePartial<{ inputs: MaybeArray<VariableInput> }>>(section, undefined, resourceUri && resourceUri.toString());
const inputs = !!configuration && 'inputs' in configuration ? configuration.inputs : undefined;
const input = Array.isArray(inputs) && inputs.find(item => !!item && item.id === variable);
if (!input) {
return undefined;
}
if (input.type === 'promptString') {
if (typeof input.description !== 'string') {
return undefined;
}
return this.quickInputService.open({
prompt: input.description,
value: input.default
});
}
if (input.type === 'pickString') {
if (typeof input.description !== 'string' || !Array.isArray(input.options)) {
return undefined;
}
const elements: QuickPickItem<string>[] = [];
for (const option of input.options) {
if (typeof option !== 'string') {
return undefined;
}
if (option === input.default) {
elements.unshift({
description: 'Default',
label: option,
value: option
});
} else {
elements.push({
label: option,
value: option
});
}
}
return this.quickPickService.show(elements, { placeholder: input.description });
}
if (input.type === 'command') {
if (typeof input.command !== 'string') {
return undefined;
}
return this.commands.executeCommand(input.command, input.args);
}
return undefined;
}
});
}

}

This file was deleted.

Loading