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中修改內容時添加自動完成和描述功能