UNPKG

@theia/workspace

Version:
224 lines (209 loc) • 10.1 kB
// ***************************************************************************** // Copyright (C) 2018 Red Hat, Inc. 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-only WITH Classpath-exception-2.0 // ***************************************************************************** import { injectable, inject, postConstruct } from '@theia/core/shared/inversify'; import URI from '@theia/core/lib/common/uri'; import { Path } from '@theia/core/lib/common/path'; import { ApplicationShell, NavigatableWidget, WidgetManager } from '@theia/core/lib/browser'; import { VariableContribution, VariableRegistry, Variable } from '@theia/variable-resolver/lib/browser'; import { WorkspaceService } from './workspace-service'; import { FileService } from '@theia/filesystem/lib/browser/file-service'; import { nls } from '@theia/core'; @injectable() export class WorkspaceVariableContribution implements VariableContribution { @inject(WorkspaceService) protected readonly workspaceService: WorkspaceService; @inject(ApplicationShell) protected readonly shell: ApplicationShell; @inject(FileService) protected readonly fileService: FileService; @inject(WidgetManager) protected readonly widgetManager: WidgetManager; protected currentWidget: NavigatableWidget | undefined; @postConstruct() protected init(): void { this.shell.onDidChangeCurrentWidget(() => this.updateCurrentWidget()); this.widgetManager.onDidCreateWidget(({ widget }) => { if (NavigatableWidget.is(widget)) { widget.onDidChangeVisibility(() => { if (widget.isVisible) { this.addRecentlyVisible(widget); } else { this.removeRecentlyVisible(widget); } this.updateCurrentWidget(); }); widget.onDidDispose(() => { this.removeRecentlyVisible(widget); this.updateCurrentWidget(); }); } }); for (const widget of this.shell.widgets) { if (NavigatableWidget.is(widget) && widget.isVisible) { this.addRecentlyVisible(widget); } } this.updateCurrentWidget(); } protected readonly recentlyVisibleIds: string[] = []; protected get recentlyVisible(): NavigatableWidget | undefined { const id = this.recentlyVisibleIds[0]; const widget = id && this.shell.getWidgetById(id) || undefined; if (NavigatableWidget.is(widget)) { return widget; } return undefined; } protected addRecentlyVisible(widget: NavigatableWidget): void { this.removeRecentlyVisible(widget); this.recentlyVisibleIds.unshift(widget.id); } protected removeRecentlyVisible(widget: NavigatableWidget): void { const index = this.recentlyVisibleIds.indexOf(widget.id); if (index !== -1) { this.recentlyVisibleIds.splice(index, 1); } } protected updateCurrentWidget(): void { const { currentWidget } = this.shell; if (NavigatableWidget.is(currentWidget)) { this.currentWidget = currentWidget; } else if (!this.currentWidget || !this.currentWidget.isVisible) { this.currentWidget = this.recentlyVisible; } } registerVariables(variables: VariableRegistry): void { this.registerWorkspaceRootVariables(variables); variables.registerVariable({ name: 'file', description: nls.localize('theia/workspace/variables/file/description', 'The path of the currently opened file'), resolve: () => { const uri = this.getResourceUri(); return uri && this.fileService.fsPath(uri); } }); variables.registerVariable({ name: 'fileBasename', description: nls.localize('theia/workspace/variables/fileBasename/description', 'The basename of the currently opened file'), resolve: () => { const uri = this.getResourceUri(); return uri && uri.path.base; } }); variables.registerVariable({ name: 'fileBasenameNoExtension', description: nls.localize('theia/workspace/variables/fileBasenameNoExtension/description', "The currently opened file's name without extension"), resolve: () => { const uri = this.getResourceUri(); return uri && uri.path.name; } }); variables.registerVariable({ name: 'fileDirname', description: nls.localize('theia/workspace/variables/fileDirname/description', "The name of the currently opened file's directory"), resolve: () => { const uri = this.getResourceUri(); return uri && uri.path.dir.toString(); } }); variables.registerVariable({ name: 'fileExtname', description: nls.localize('theia/workspace/variables/fileExtname/description', 'The extension of the currently opened file'), resolve: () => { const uri = this.getResourceUri(); return uri && uri.path.ext; } }); } protected registerWorkspaceRootVariables(variables: VariableRegistry): void { const scoped = (variable: Variable): Variable => ({ name: variable.name, description: variable.description, resolve: (context, workspaceRootName) => { const workspaceRoot = workspaceRootName && this.workspaceService.tryGetRoots().find(r => r.resource.path.name === workspaceRootName); return variable.resolve(workspaceRoot ? workspaceRoot.resource : context); } }); variables.registerVariable(scoped({ name: 'workspaceRoot', description: nls.localize('theia/workspace/variables/workspaceRoot/description', 'The path of the workspace root folder'), resolve: (context?: URI) => { const uri = this.getWorkspaceRootUri(context); return uri && this.fileService.fsPath(uri); } })); variables.registerVariable(scoped({ name: 'workspaceFolder', description: nls.localize('theia/workspace/variables/workspaceFolder/description', 'The path of the workspace root folder'), resolve: (context?: URI) => { const uri = this.getWorkspaceRootUri(context); return uri && this.fileService.fsPath(uri); } })); variables.registerVariable(scoped({ name: 'workspaceRootFolderName', description: nls.localize('theia/workspace/variables/workspaceRootFolderName/description', 'The name of the workspace root folder'), resolve: (context?: URI) => { const uri = this.getWorkspaceRootUri(context); return uri && uri.displayName; } })); variables.registerVariable(scoped({ name: 'workspaceFolderBasename', description: nls.localize('theia/workspace/variables/workspaceFolderBasename/description', 'The name of the workspace root folder'), resolve: (context?: URI) => { const uri = this.getWorkspaceRootUri(context); return uri && uri.displayName; } })); variables.registerVariable(scoped({ name: 'cwd', description: nls.localize('theia/workspace/variables/cwd/description', "The task runner's current working directory on startup"), resolve: (context?: URI) => { const uri = this.getWorkspaceRootUri(context); return (uri && this.fileService.fsPath(uri)) || ''; } })); variables.registerVariable(scoped({ name: 'relativeFile', description: nls.localize('theia/workspace/variables/relativeFile/description', "The currently opened file's path relative to the workspace root"), resolve: (context?: URI) => { const uri = this.getResourceUri(); return uri && this.getWorkspaceRelativePath(uri, context); } })); variables.registerVariable(scoped({ name: 'relativeFileDirname', description: nls.localize('theia/workspace/variables/relativeFileDirname/description', "The current opened file's dirname relative to ${workspaceFolder}"), resolve: (context?: URI) => { const uri = this.getResourceUri(); const relativePath = uri && this.getWorkspaceRelativePath(uri, context); return relativePath && new Path(relativePath).dir.toString(); } })); } getWorkspaceRootUri(uri: URI | undefined = this.getResourceUri()): URI | undefined { return this.workspaceService.getWorkspaceRootUri(uri); } getResourceUri(): URI | undefined { return this.currentWidget && this.currentWidget.getResourceUri(); } getWorkspaceRelativePath(uri: URI, context?: URI): string | undefined { const workspaceRootUri = this.getWorkspaceRootUri(context || uri); const path = workspaceRootUri && workspaceRootUri.path.relative(uri.path); return path && path.toString(); } }