上一篇: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

Theia APIs——Preferences的更多相关文章

  1. Theia APIs——事件

    上一篇:Theia APIs——Preferences 事件 Theia中的事件或许会让你感到困惑,希望本节能阐述清楚. 来看下面的代码: (来自logger-watcher.ts) @injecta ...

  2. Theia APIs——通过JSON-RPC进行通信

    上一篇:Theia APIs——事件 通过JSON-PRC进行通信 在本节中,我将讲解如何创建后端服务并通过JSON-PRC来连接它. 我将使用debug logging system作为例子来进行讲 ...

  3. Theia APIs——命令和快捷键

    上一篇:使用Theia——创建语言支持 命令和快捷键 Theia可以通过多种不同的方式进行扩展.命令允许packages提供可以被其它包调用的唯一命令,还可以向这些命令添加快捷键和上下文,使得它们只能 ...

  4. 【起航计划 031】2015 起航计划 Android APIDemo的魔鬼步伐 30 App->Preferences->Advanced preferences 自定义preference OnPreferenceChangeListener

    前篇文章Android ApiDemo示例解析(31):App->Preferences->Launching preferences 中用到了Advanced preferences 中 ...

  5. 【起航计划 028】2015 起航计划 Android APIDemo的魔鬼步伐 27 App->Preferences->Launching preferences 其他activity获取Preference中的值

    前给例子介绍了如何使用PreferenceActivity 来显示修改应用偏好,用户对Preferences的修改自动存储在应用对应的Shared Preferences中. 本例介绍了如何从一个Ac ...

  6. Theia架构

    上一篇:Theia——云端和桌面版的IDE 架构概述 本节描述了Theia的整体架构. Theia被设计为一个可以在本地运行的桌面应用程序,也可以在浏览器和远程服务器之间工作.为了支持这两种工作方式, ...

  7. 使用Theia——构建你自己的IDE

    上一篇:Theia架构 构建你自己的IDE 本指南将教你如何构建你自己的Theia应用. 必要条件 你需要安装node 10版本(译者:事实上最新的node稳定版即可): curl -o- https ...

  8. 使用Theia——创建扩展包

    上一篇:使用Theia——构建你自己的IDE 创建Theia扩展包 本例中,我们将添加一个菜单项“Say hello”用来显示一个通知“Hello world!”.本文将指导你完成所有必要的步骤. T ...

  9. (转载)构建public APIs与CORS

    from: https://segmentfault.com/a/1190000000709909 理由:在操作层面详细的讲解了跨域的操作.尤其是对于option请求的详解.收藏. 在构建Public ...

随机推荐

  1. GitHub 上 10 款免费开源 Windows 工具

    GitHub 上 10 款免费开源 Windows 工具 GitHub 是如今所有开源事物的中央仓库, 这个网站最近发布了一个叫做<2016 Octoverse  状态报告>,详细列出了从 ...

  2. hdu 4476 Cut the rope (2-pointer && simulation)

    Problem - 4476 题意是,给出若干绳子,对同一根绳子只能切割一次,求出最多能获得多少长度相同的绳子. 代码中,s是最大切割长度,而当前切割长度为t/2. 代码如下: #include &l ...

  3. hdu 1277 全文检索 (直接映射查找 || 自动机)

    Problem - 1277 无聊做水题的时候发现的一道题目.这道题第一反应可以用自动机来解决.当然,条件是各种限制,从而导致可以用直接映射标记的方法来搜索.具体的做法就像RK算法一样,将字符串has ...

  4. js实现方块的碰撞检测

    文章地址:https://www.cnblogs.com/sandraryan/ 个人感觉.方块的碰撞检测比圆形麻烦~~ <!DOCTYPE html> <html lang=&qu ...

  5. Python--day29--logging模块(日志模块)

    重要程度六颗星,比如一个小窗口的广告如果因为你没有日志的问题导致点击量没有记录下来,几十分钟那就会损失几十万了,这责任谁负得起. 希望离开一个公司是因为有了更好的去处而不是因为各种各样的原因被开掉,那 ...

  6. Delphi的不足

    Delphi拥有C#那样的开发速度,同时运行速度也很快,而且不需要.net运行时(可以免安装直接运行).为什么还是衰落了呢? 既不是单根体系,又缺少泛型支持.导致delphi没法做map.list.v ...

  7. python进阶之异常处理

    异常处理 在代码运行时,会因为各种原因出现bug,而程序遇到bug就会中断运行,而在日常生产中程序是要长时间运行不能随意中断的.因此就需要我们提前做好异常处理. 异常 print(x) # 一般报错就 ...

  8. [php] 如何处理好autoload

    在有了诸如apc之类的cache之后,php的autoloader成为了需要认真考虑的性能点. 参见: http://stackoverflow.com/questions/4788452/does- ...

  9. P1051 八皇后问题

    题目描述 在国际象棋中,皇后是同时具备象和车的攻击范围的,它可以横竖移动,也可以斜着移动.那么在一个8*8的标准国际象棋棋盘中,我们要放入8个皇后,同时皇后之间无法互相攻击,问有多少种皇后的放置方法. ...

  10. dotnet 特性 DynamicallyInvokable 是用来做什么的

    我在 Linq 很多函数都看到 __DynamicallyInvokable 这个特性,这是一个没有官方文档的特性,也许是用来优化反射 在堆栈 网找到了以下描述 这个 __DynamicallyInv ...