forked from eclipse-theia/theia
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce the Variable Resolver Extension
Signed-off-by: Artem Zatsarynnyi <azatsary@redhat.com>
- Loading branch information
1 parent
f4de4f5
commit ea79ea1
Showing
15 changed files
with
700 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# Theia - Variable Resolver Extension | ||
|
||
The extension provides variable substitution mechanism inside of strings using `${variableName}` syntax. | ||
|
||
## Variable Contribution Point | ||
Extension provides a hook that allows any extensions to contribute its own variables. | ||
Here's the example of contributing two variables: | ||
- `${file}` - returns the name of the file opened in the current editor | ||
- `${lineNumber}` - returns the current line number in the current file | ||
|
||
```typescript | ||
@injectable() | ||
export class EditorVariableContribution implements VariableContribution { | ||
|
||
constructor( | ||
@inject(EditorManager) protected readonly editorManager: EditorManager | ||
) { } | ||
|
||
registerVariables(variables: VariableRegistry): void { | ||
variables.registerVariable({ | ||
name: 'file', | ||
description: 'The name of the file opened in the current editor', | ||
resolve: () => { | ||
const currentEditor = this.getCurrentEditor(); | ||
if (currentEditor) { | ||
return currentEditor.uri.displayName; | ||
} | ||
return undefined; | ||
} | ||
}); | ||
variables.registerVariable({ | ||
name: 'lineNumber', | ||
description: 'The current line number in the current file', | ||
resolve: () => { | ||
const currentEditor = this.getCurrentEditor(); | ||
if (currentEditor) { | ||
return `${currentEditor.cursor.line + 1}`; | ||
} | ||
return undefined; | ||
} | ||
}); | ||
} | ||
|
||
protected getCurrentEditor(): TextEditor | undefined { | ||
const currentEditor = this.editorManager.currentEditor; | ||
if (currentEditor) { | ||
return currentEditor.editor; | ||
} | ||
return undefined; | ||
} | ||
} | ||
``` | ||
|
||
Note that a Variable is resolved to `MaybePromise<string | undefined>` which means that it can be resolved synchronously or within a Promise. | ||
|
||
## Using the Variable Resolver Service | ||
|
||
There's the example of how one can use Variable Resolver Service in its own plugin: | ||
```typescript | ||
@injectable() | ||
export class MyService { | ||
|
||
constructor( | ||
@inject(VariableResolverService) protected readonly variableResolver: VariableResolverService | ||
) { } | ||
|
||
async resolve(): Promise<void> { | ||
const text = 'cursor is in file ${file} on line ${lineNumber}'; | ||
const resolved = await this.variableResolver.resolve(text); | ||
console.log(resolved); | ||
} | ||
} | ||
``` | ||
|
||
If `package.json` file is currently opened and cursor is on line 5 then the following output will be logged to the console: | ||
``` | ||
cursor is in file package.json on line 5 | ||
``` | ||
|
||
## License | ||
[Apache-2.0](https://github.com/theia-ide/theia/blob/master/LICENSE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"extends": "../../configs/base.tsconfig", | ||
"compilerOptions": { | ||
"rootDir": "src", | ||
"outDir": "lib" | ||
}, | ||
"include": [ | ||
"src" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
{ | ||
"name": "@theia/variable-resolver", | ||
"version": "0.3.7", | ||
"description": "Theia - Variable Resolver Extension", | ||
"dependencies": { | ||
"@theia/core": "^0.3.7" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"theiaExtensions": [ | ||
{ | ||
"frontend": "lib/browser/variable-resolver-frontend-module" | ||
} | ||
], | ||
"keywords": [ | ||
"theia-extension" | ||
], | ||
"license": "Apache-2.0", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/theia-ide/theia.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/theia-ide/theia/issues" | ||
}, | ||
"homepage": "https://github.com/theia-ide/theia", | ||
"contributors": [ | ||
{ | ||
"name": "Artem Zatsarynnyi", | ||
"email": "azatsary@redhat.com" | ||
} | ||
], | ||
"files": [ | ||
"lib", | ||
"src" | ||
], | ||
"scripts": { | ||
"prepare": "yarn run clean && yarn run build", | ||
"clean": "theiaext clean", | ||
"build": "theiaext build", | ||
"watch": "theiaext watch", | ||
"test": "theiaext test", | ||
"docs": "theiaext docs" | ||
}, | ||
"devDependencies": { | ||
"@theia/ext-scripts": "^0.2.0" | ||
}, | ||
"nyc": { | ||
"extends": "../../configs/nyc.json" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
* Copyright (C) 2018 Red Hat, Inc. and others. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
*/ | ||
|
||
export * from './variable'; | ||
export * from './variable-quick-open-service'; | ||
export * from './variable-resolver-service'; |
60 changes: 60 additions & 0 deletions
60
packages/variable-resolver/src/browser/variable-quick-open-service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright (C) 2018 Red Hat, Inc. and others. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
*/ | ||
|
||
import { inject, injectable } from 'inversify'; | ||
import { QuickOpenService, QuickOpenModel, QuickOpenItem, QuickOpenMode } from '@theia/core/lib/browser/quick-open/'; | ||
import { VariableRegistry } from './variable'; | ||
|
||
@injectable() | ||
export class VariableQuickOpenService implements QuickOpenModel { | ||
|
||
protected items: QuickOpenItem[]; | ||
|
||
constructor( | ||
@inject(VariableRegistry) protected readonly variableRegistry: VariableRegistry, | ||
@inject(QuickOpenService) protected readonly quickOpenService: QuickOpenService | ||
) { } | ||
|
||
open(): void { | ||
this.items = this.variableRegistry.getVariables().map( | ||
v => new VariableQuickOpenItem(v.name, v.description) | ||
); | ||
|
||
this.quickOpenService.open(this, { | ||
placeholder: 'Registered variables', | ||
fuzzyMatchLabel: true, | ||
fuzzyMatchDescription: true, | ||
fuzzySort: true | ||
}); | ||
} | ||
|
||
onType(lookFor: string, acceptor: (items: QuickOpenItem[]) => void): void { | ||
acceptor(this.items); | ||
} | ||
} | ||
|
||
export class VariableQuickOpenItem extends QuickOpenItem { | ||
|
||
constructor( | ||
protected readonly name: string, | ||
protected readonly description?: string | ||
) { | ||
super(); | ||
} | ||
|
||
getLabel(): string { | ||
return '${' + this.name + '}'; | ||
} | ||
|
||
getDetail(): string { | ||
return this.description || ''; | ||
} | ||
|
||
run(mode: QuickOpenMode): boolean { | ||
return false; | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
packages/variable-resolver/src/browser/variable-resolver-frontend-contribution.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* Copyright (C) 2018 Red Hat, Inc. and others. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
*/ | ||
|
||
import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom'; | ||
|
||
let disableJSDOM = enableJSDOM(); | ||
|
||
import * as chai from 'chai'; | ||
import { Container, ContainerModule } from 'inversify'; | ||
import { QuickOpenService } from '@theia/core/lib/browser'; | ||
import { ILogger, bindContributionProvider } from '@theia/core/lib/common'; | ||
import { MockLogger } from '@theia/core/lib/common/test/mock-logger'; | ||
import { VariableContribution, VariableRegistry } from './variable'; | ||
import { VariableQuickOpenService } from './variable-quick-open-service'; | ||
import { VariableResolverFrontendContribution } from './variable-resolver-frontend-contribution'; | ||
|
||
disableJSDOM(); | ||
|
||
const expect = chai.expect; | ||
|
||
before(() => { | ||
chai.config.showDiff = true; | ||
chai.config.includeStack = true; | ||
}); | ||
|
||
describe('variable-resolver-frontend-contribution', () => { | ||
|
||
let testContainer: Container; | ||
let variableRegistry: VariableRegistry; | ||
|
||
before(() => { | ||
disableJSDOM = enableJSDOM(); | ||
|
||
testContainer = new Container(); | ||
const module = new ContainerModule((bind, unbind, isBound, rebind) => { | ||
bindContributionProvider(bind, VariableContribution); | ||
bind(VariableContribution).toConstantValue(new TestVariableContribution()); | ||
|
||
bind(ILogger).to(MockLogger); | ||
bind(VariableRegistry).toSelf().inSingletonScope(); | ||
|
||
bind(QuickOpenService).toSelf(); | ||
bind(VariableQuickOpenService).toSelf(); | ||
|
||
bind(VariableResolverFrontendContribution).toSelf(); | ||
}); | ||
testContainer.load(module); | ||
}); | ||
|
||
after(() => { | ||
disableJSDOM(); | ||
}); | ||
|
||
beforeEach(() => { | ||
variableRegistry = testContainer.get<VariableRegistry>(VariableRegistry); | ||
|
||
const variableRegistrar = testContainer.get(VariableResolverFrontendContribution); | ||
variableRegistrar.onStart(); | ||
}); | ||
|
||
it('should register all variables from the contribution points', () => { | ||
const variables = variableRegistry.getVariables(); | ||
expect(variables.length).to.be.equal(2); | ||
expect(variables[0].name).to.be.equal('file'); | ||
expect(variables[1].name).to.be.equal('lineNumber'); | ||
}); | ||
}); | ||
|
||
export class TestVariableContribution implements VariableContribution { | ||
|
||
registerVariables(variables: VariableRegistry): void { | ||
variables.registerVariable({ | ||
name: 'file', | ||
description: 'Resolves to file name opened in the current editor', | ||
resolve: () => Promise.resolve('package.json') | ||
}); | ||
variables.registerVariable({ | ||
name: 'lineNumber', | ||
description: 'Resolves to current line number', | ||
resolve: () => Promise.resolve('5') | ||
}); | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
packages/variable-resolver/src/browser/variable-resolver-frontend-contribution.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* Copyright (C) 2018 Red Hat, Inc. and others. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
*/ | ||
|
||
import { injectable, inject, named } from 'inversify'; | ||
import { FrontendApplicationContribution } from '@theia/core/lib/browser'; | ||
import { Command, CommandContribution, CommandRegistry, ContributionProvider } from '@theia/core/lib/common'; | ||
import { VariableContribution, VariableRegistry } from './variable'; | ||
import { VariableQuickOpenService } from './variable-quick-open-service'; | ||
|
||
export const LIST_VARIABLES: Command = { | ||
id: 'variable.list', | ||
label: 'Variable: List All' | ||
}; | ||
|
||
@injectable() | ||
export class VariableResolverFrontendContribution implements FrontendApplicationContribution, CommandContribution { | ||
|
||
constructor( | ||
@inject(ContributionProvider) @named(VariableContribution) | ||
protected readonly contributionProvider: ContributionProvider<VariableContribution>, | ||
@inject(VariableRegistry) protected readonly variableRegistry: VariableRegistry, | ||
@inject(VariableQuickOpenService) protected readonly variableQuickOpenService: VariableQuickOpenService | ||
) { } | ||
|
||
onStart(): void { | ||
this.contributionProvider.getContributions().forEach(contrib => | ||
contrib.registerVariables(this.variableRegistry) | ||
); | ||
} | ||
|
||
registerCommands(commands: CommandRegistry): void { | ||
commands.registerCommand(LIST_VARIABLES, { | ||
isEnabled: () => true, | ||
execute: () => this.variableQuickOpenService.open() | ||
}); | ||
} | ||
} |
Oops, something went wrong.