Theia APIs——Preferences


上一篇:Theia APIs——命令和快捷鍵

Preferences

  Theia有一個preference service,模塊可以通過它來獲取preference的值,提供默認的preferences以及監聽preference的更改。
  Preferences的內容可以保存在workspace根目錄下的 .theia/settings.json中,或者Linux系統的 $HOME/.theia/settings.json文件中。在Windows系統中,用戶設置默認保存在 %USERPROFILE%/.theia/settings.json文件中(例如 c:\Users\epatpol\.theia\settings.json)。
  所有這些文件都必須包含一個有效的JSON,其中包含preferences的名稱和值(注意下面例子中的preference不是官方指定的,這里僅作為一個示例)。如有需要,你也可以在settings.json文件中添加注釋。如:
{
    // 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 
});
  下面是一些有關提供驗證的schema的鏈接:

通過配置監聽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的修改流程

  當在${workspace}/.theia/或者 os.homedir()/.theia/中修改settings.json的內容時,JSON preference服務器會觸發一個事件。首先,CompoundPreferenceServer用來管理不同的服務器(作用域),例如workspace/user/defaults(提供上面說的contributions)。接下來,PreferenceService管理該服務器並在其上添加更多api以方便調用(例如getBoolean,getSrtring等等),它同時還允許客戶端監聽preference的修改。這個PreferenceService可以直接或通過特定的代理(如上面這個filesystem配置)被注入到模塊中。
  當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中修改內容時添加自動完成和描述功能

 

原文地址:https://theia-ide.org/docs/preferences


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM