Branckets 如何开发插件

有个功能Brackets一直没有, 也没有找到相关的插件, 所以转载官方的这篇关于如何开发Brackets插件的wiki, 方便自己有空的时候来学习下.

如何开发Brackets插件

开发一个插件需要三个步骤:

  1. 创建基本的插件模板。
  2. 开发插件并调试
  3. 打包并发布插件以供其他人使用

通过以上链接阅读这些章节的详细内容!

创建插件

*注意:因为通过Brackets的插件管理器很容易删除正在开发的插件,所以更安全的方式是把插件文件夹新建在Brackets安装目录下的src/extensions/dev目录下。可通过修改权限保证文件夹是可写的,or by cloning the Brackets source and using that copy.

测试或调试

  • 编辑main.js文件。
  • 保存文件并通过Brackets的”Debug>Reload Brackets”重启Brackets,以进行测试。
  • 通过Brackets的”Debug>Show Developer Tools”(依赖于Chrome浏览器),并可使用Chrome浏览器的控制台。
    • 在首次打开Developer Tools时,必须设置为禁用缓存,否则在Developer Tools打开的状态下重新加载Brackets,不能反映出插件修改之后的变化。

查看Debugging Brackets获取更完善描述。

还可以为插件编写单元测试。

发布插件

  1. 向main.js所在的目录中添加package.json文件。
  2. 打包整个插件目录为ZIP格式(更快捷的使用GitHub的“Download ZIP”按钮下载ZIP包)或通过命令git archive –format zip -o yourextension.zip master生成ZIP包。
  3. 通过上传ZIP包到Brackets Extension Registry,以发布插件

更多信息,参见Extension Registry Help

常见操作

使用模块

  • 从插件的文件夹树中加载模块,使用require()方法,传入相对于插件根目录的相对路径做为参数。
  • 加载Brackets的核心模块,使用brackets.getModule()方法,传入相对于Brackets的src目录的相对路径做为参数。
  • 不能到其他插件中加载模块(暂时还不支持)

也可以插件中使用其他的文件,例如下文的“Load a CSS file”。

添加菜单项与键盘快捷键

查看Simple “Hello World” extension代码示例。

对于任何一个新的行为,都要通过CommandManager.resiger()方法注册一个Command以实现它。Command通过Command Id(字符串类型)映射到实现行为的函数。使用包命名的方式为Command Id命名(例如:myorg.myextendsion.mycommand)以避免与其他插件冲突。(参见:higher-level overview of command architecture)。

添加菜单项: 通过Menus.getMenu()方法,传入Menus.AppMenuBar常量(当前包含FILE_MENU,EDIT_MENU, VIEW_MENU, NAVIGATE_MENU或HELP_MENU),获取顶级菜单。再通过theMenu.addMenuItem()方法,传入要执行的Command Id以添加菜单项。这样就把菜单项与Command关联起来,Command被创建后,它的名称将被显示为菜单项标签。

约定,调用addMenuItems()方法的同时为Command创建键盘快捷键。

1
2
3
4
5
6
7
8
// 获取顶级的菜单
var editorMenu = Menus.getMenu(Menus.AppMenuBar.EDIT_MENU);
// 以包命名风格命名Command Id
var commandId = "com.wanggit.commandId";
// 注册Command
CommandManager.register("Custom Command", commandId, customFunction);
// 添加菜单项,并指菜单项执行commandId的命令,快捷键为Ctrl-Shift-O
editorMenu.addMenuItem(commandId, "Ctrl-Shift-O");

添加上下文菜单项: 通过Menus.getContextMenu()方法,传入Menus.ContextMenuIds常量(目前包含EDITOR_MENU, INLINE_EDITOR_MENU, PROJECT_MENU或WORKING_SET_MENU),可获取上下文菜单。通过theContextMenu.addMenuItem()方法,传入要执行的Command Id以添加上下文菜单项,上下文菜单项标签的显示与菜单项相同。

1
2
3
4
5
6
// 获取编辑器的上下文菜单
var contextMenu = Menu.getContextMenu(Menus.ContextMenuIds.EDITOR_MENU);
// 省略Command的定义
// ...
// 添加上下文菜单,并指定要执行的Command,指定快捷键
contextMenu.addMenuItem(commandId, "Ctrl-Shift-L");

添加菜单分隔线: 依据以上的说明获取顶级菜单或上下文菜单,再通过theMenu.addMenuDivider()添加菜单分隔线。这个方法总要把分隔线添加到菜单当前状态的最后一个位置。通过传入first与last参数,指分隔线的位置。另外,还可以通过传入before或after与相对那个菜单的Command Id,以指定分隔线显示的某菜单项之前或之后。

1
2
3
4
5
6
// 添加一个分隔线到菜单当前状态的最后一个位置
menu.addMenuDivider();
// 添加到最前面,相关参数还有FIRST,LAST,BEFORE,AFTER
menu.addMenuDivider(Menus.FIRST);
// 在Commands.EDIT_FIND命令对应的菜单前添加分隔线
menu.addMenuDivider(Menus.before, Commands.EDIT_FIND);

添加快捷键: 通过KeyBindingManager.addBinding()方法,传入快捷键要执行的Command Id与快捷键组合,可以在不关联菜单项的情况下新建快捷键。务必在Brackets Shortcuts页面查看那些快捷键是没被占用,并把自定义的快捷键添中到此页面列表中。

1
2
CommandManager.register("Handler Enter", commandId, handlerEnter);
KeyBindingManager.addBinding(commandId, "Ctrl-Enter", "linux");

通过拒绝(decline)键盘事件,并允许其他功能处理这个键盘事件,那么就一定要在Command的执行方法中返回一个已reject()的$.Promise对象。(如果想要光标在某个位置时重写Enter的事件,那么这就非常有用处)(此功能在Sprint 18及以上的版本有效)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var commandId = "wanggit.test";
// 捕捉Enter事件
function handlerEnter(){
console.log("Handler Enter");
// 创建Deferred对象
var deferred = new $.Deferred();
// 拒绝Enter事件,在调用reject方法之后,并返回$.Promise对象,那么此时Enter事件,还可以被其他功能捕捉。
deferred.reject();
// 返回$.Promise对象。如果不返回一个已调用过reject方法的$.Promise对象,那么其他功能就不能再捕捉到Enter事件了。
return deferred.promise();
}
CommandManager.register("Handler Enter", commandId, handlerEnter);
// 绑定键盘事件
KeyBindingManager.addBinding(commandId, "Enter", "linux");

添加新UI元素

向Edtior的下面添加Panel:首先Panel要添加.bottom-panel,具体可以参见JSLint bottom-panel.html的例子。通过PanelManager.createBottomPanel(“yourExtension.name”, $(panelHtml))可以在状态栏之上新建一个Panel。You may see Resizer.makeResizable()and manual DOM insertion of panels in some extensions but this parctice is being phased out since the introduction of PanelManager.

参考资料

如何开发插件