Theia APIs——Preferences

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

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的一個模塊。json

使用inversity建立具備默認preferences的模塊

  爲了提供preference的值,模塊必須提供一個有效的json schema,用來驗證所提供的值。模塊必須像下面這樣將PreferenceContributton綁定到值:api

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。ide

const preferences = ctx.container.get(PreferenceService);

   對filesystem而言,服務在一開始綁定的時候獲取。這裏,你可使用onPreferenceChanged方法來註冊preference更改的回調。this

constructor(@inject(PreferenceService) protected readonly prefService: PreferenceService
    prefService.onPreferenceChanged(e => { callback }

  這裏,事件接收到的對象e是下面這種類型:spa

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代理接口的:.net

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爲例):code

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

相關文章
相關標籤/搜索