Preferences
{ // Enable/Disable the line numbers in the monaco editor "monaco.lineNumbers": "off", // Tab width in the editor "monaco.tabWidth": 4, "fs.watcherExcludes": "path/to/file" }
我们以filesystem作为示例,它是使用preference service的一个模块。
使用inversity创建具有默认preferences的模块
为了提供preference的值,模块必须提供一个有效的json schema,用来验证所提供的值。模块必须像下面这样将PreferenceContributton绑定到值:
export interface PreferenceSchema {
[name: string]: Object,
properties: {
[name: string]: object
}
}
export interface PreferenceContribution {
readonly schema: PreferenceSchema;
}
例如,filesystem中的代码:
export const filesystemPreferenceSchema: PreferenceSchema = { "type": "object", "properties": { "files.watcherExclude": { "description": "List of paths to exclude from the filesystem watcher", "additionalProperties": { "type": "boolean" } } } }; bind(PreferenceContribution).toConstantValue( { schema: filesystemPreferenceSchema });
通过配置监听preference的更改
要使用preference的值,只需从容器中获得注入的PreferenceService。
const preferences = ctx.container.get(PreferenceService);
对filesystem而言,服务在一开始绑定的时候获取。这里,你可以使用onPreferenceChanged方法来注册preference更改的回调。
constructor(@inject(PreferenceService) protected readonly prefService: PreferenceService
prefService.onPreferenceChanged(e => { callback }
这里,事件接收到的对象e是下面这种类型:
export interface PreferenceChangedEvent { readonly preferenceName: string; readonly newValue?: any; readonly oldValue?: any; }
虽然我们可以在类中直接这样使用,不过filesystem提供了一个特定于filesystem preferences的代理preference服务(该服务在后台运行),这样可以更快、更有效地搜索preference(因为它在filesystem preference service中进行搜索,而不是通过更通用的preference service搜索所有的内容)。从某种意义上来说,它也更高效,因为只有那些监视与某个模块相关的特定preferences的模块才会得到通知。要做到这一点,可以看看有关filesystem配置的代理接口是如何绑定使用preference代理接口的:
export type PreferenceProxy<T> = Readonly<T> & Disposable & PreferenceEventEmitter<T>; export function createPreferenceProxy<T extends Configuration>(preferences: PreferenceService, configuration: T): PreferenceProxy<T> { /* Register a client to the preference server When a preference is received, it is validated against the schema and then fired if valid, otherwise the default value is provided. This proxy is also in charge of calling the configured preference service when the proxy object is called i.e editorPrefs[‘preferenceName‘] It basically forwards methods to the real object, i.e dispose/ready etc. }
要使用这个代理,只需要将它绑定到一个新类型X = PreferenceProxy<CONFIGURATION_INTERFACE>,然后使用上面的方法bind(X)到一个代理。
export interface FileSystemConfiguration { ‘files.watcherExclude‘: { [globPattern: string]: boolean } } export const FileSystemPreferences = Symbol(‘FileSystemPreferences‘); export type FileSystemPreferences = PreferenceProxy<FileSystemConfiguration>; export function createFileSystemPreferences(preferences: PreferenceService): FileSystemPreferences { return createPreferenceProxy(preferences, defaultFileSystemConfiguration, filesystemPreferenceSchema); } export function bindFileSystemPreferences(bind: interfaces.Bind): void { bind(FileSystemPreferences).toDynamicValue(ctx => { const preferences = ctx.container.get(PreferenceService); return createFileSystemPreferences(preferences); }); bind(PreferenceContribution).toConstantValue({ schema: filesystemPreferenceSchema }); }
最后,在模块中使用filesystem配置,只需要将它注入到你需要的地方。你可以像这样访问preference(以filesystem为例):
const patterns = this.preferences[‘files.watcherExclude‘];
你也可以像这样监听preference的更改:
this.toDispose.push(preferences.onPreferenceChanged(e => { if (e.preferenceName === ‘files.watcherExclude‘) { this.toRestartAll.dispose(); } }));
constructor(..., @inject(FileSystemPreferences) protected readonly preferences: FileSystemPreferences) { ... this.toDispose.push(preferences.onPreferenceChanged(e => { if (e.preferenceName === ‘files.watcherExclude‘) { this.toRestartAll.dispose(); } })); ... }
Preference的修改流程
.theia/settings.json -> JsonPreferenceServer -> CompoundPreferenceServer -> PreferenceService -> PreferenceProxy<FileSystemConfiguration> -> FileSystemWatcher
获取preference的值
对于filesystem来说,我们可以使用与上面相同的代理配置来访问preference的内容。
if (this.prefService[‘preferenceName‘]) { ... } if (this.prefService[‘preferenceName2‘]) { ... } })
它能正常工作,正如我们在上面所看到的那样,代理将简单地调用prefService.get(‘preferenceName‘)。
TODO/FIXME
-
在CompoundPreferenceServer中添加server优先级
-
当在theia的settings.json中修改内容时添加自动完成和描述功能