NINJA是新出的Python的IDE工具,全称是NINJA is not just anther IDE,主要由Python语言用PyQt作为底层核心进行开发的,非常容易做扩展。目前放出的版本,功能相对很简单,但启动速度还是蛮快的。
NINJA-IDE目前只是2.0的beta版本,plugin方式可能会被修改。
总结:
NINJA-IDE功能可以很容易通过插件扩展,可以通过下面的方式添加:
1、插件描述,因此NINJA-IDE可以被应用集成
2、插件源码
3、ServiceLocator对象,插件通过这个与IDE进行交互。
注意:最好的方式是通过理解内部的源码。
最新的NINJA-IDE构架允许插件通过下面两种方式与NINJA-IDE核心交互
- 直接方式:插件启动交互
- 间接方式:核心NINJA-IDE启动插件交互监听然后与之交互
插件描述:
一个文件后缀为".plugin"的json描述文件。下面的信息必须在插件描述中:
{
"module": "my_plugin",
"class": "MyPluginExample",
"authors": "Martin Alderete <malderete@gmail.com>",
"version": "0.1",
"url": "http://code.google.com/p/ninja-ide",
"description": "Este plugin es de prueba"
}
module:模块名称,插件代码放置位置,被NINJA-IDE初始化实例
class : 提示实现插件的类名称
authors:作者数组
version:插件版本
url : 插件url可能的doc文档位置
description:插件描述
注意,插件是一个文件夹,必须创建__init__.py文件,在__init__.py文件必须导入主要实现类,如下:
from my_plugin import MyPluginExample
(译注:其实就是python的package,在原文中为init.py,与从网上下载的__init__.py有差别)
需要NINJA-IDE插件基础
因为是通过PyQt小件,如QMenu,QAction,QEvent等构建插件
插件
ninja_ide.core.plugin.Plugin: 每个插件的基类,提供两个函数用来覆盖,initialize, finish。
Instance attributes | Description |
locator | ServiceLocator类的实例 |
metadata | 插件描述,会被NINJA-IDE自动设置 |
Instance methods | Description |
initialize(self) | 插件被载入时调用 |
finish(self) | 插件被卸载时调用 |
get_preferences_widget(self) | 当配置打开时调用,必须反悔一个QWidget的子类实例,使用IPluginPreferences接口 |
ServiceLocator
ninja_ide.core.plugin_manager.ServiceLocator: 对象给插件提供服务
Instance attributes | Description |
get_availables_services(self) | 所有可用服务的名字列表 |
get_service(self, service_name) | 返回服务 |
Plugin Interfaces
ninja_ide.core.plugin_interfaces: 文件包含了USEFUL接口,不需要一些行为,例如添加一个“新的工程类型"
IProjectTypeHandler: 创建工程类型处理句柄
ISmbolsHandler:创建符号句柄
IPluginPreferences:配置小件插件
NINJA-IDE Services
通过PLUGINS和NINJA-IDE交互的服务。
可以使用的服务有:
- editor
- toolbar
- menuApp
- misc
- explorer
editor: 允许与Editor交互
Events(事件) | Description(描述) |
editorKeyPressEvent(QEvent) | 键按下时发送 |
fileSaved(fileName) | 文件保存时发送 |
currentTabChanged(fileName) | 当前tab更改时发送 |
executeFile(fileName) | 文件被执行时发送 |
executeProject(projectName) | 工程被执行时发送 |
Instance methods(实例方法) | Description(描述) | Returns(返回值) |
add_menu(self, menu, lang="py") | 在上下文上添加菜单 | |
get_editor(self) | 获取获得焦点的编辑器 | Editor or None |
get_editor_path(self) | 获取当前文件路径 | String |
add_editor(self, fileName="") | 添加一个editor到IDE中 | |
get_text(self) | 获取编辑器中的纯文本 | String or None |
insert_text(self, text) | 插入文本到当前位置 | |
jump_to_line(self, lineno) | 跳到某一行 | |
get_lines_count(self) | 获取当前编辑器的行数 | Integer or None |
toolbar:允许与工具条交互
Instance methods(实例方法) | Description(描述) |
add_action(self, action) | 在工具条中添加action |
menuApp: 允许与菜单插件交互
Instance methods(实例方法) | Description(描述) |
add_menu(self, menu) | NINJA-IDE中添加一个菜单 |
add_action(self, action) | NINJA-IDE中添加一个菜单行为 |
misc:与MiscContainer交互(ninja底部panel,console所在的panel)
Instance methods(实例方法) | Description(描述) |
add_widget(self, widget, icon_path, description) | 用给定的icon和提示在容器中添加一个widget |
explorer:允许与Explorer交互
Instance methods(实例方法) | Description(描述) | Returns(返回值) |
get_tree_projects(self) | 获取树工程对象(如果数可视) | gui.explorer.tree_projects_widget.TreeProjectsWidget or None |
get_current_project_item(self) | 从树工程中获取当前节点 | gui.explorer.tree_projects_widget.ProjectTree or gui.explorer.tree_projects_widget.ProjectItem |
get_tree_symbols(self) | 获取树符号(如果可视) | gui.explorer.tree_symbols_widget.TreeSymbolsWidget or None |
set_symbols_handler(self, file_extension, symbols_handler) | 为给定文件添加一个新的符号句柄,符号句柄必须有一个特殊的接口ninja_ide.core.plugin_interfaces | None |
set_project_type_handler(self, project_type, project_type_handler) | 给新的工程累i系那个添加一个句柄,project_type_handler必须有一个特殊的接口,见 ninja_ide.core.plugin_interfaces | None |
add_tab(self, tab, title) | 用给定名称添加一个tab | None |
get_actual_project(self) | 返回打开工程的路径 | String |
add_project_menu(self, menu, lang='all') | 为给定文件后缀,添加额外的菜单当到工程explorer中, | None |
ok,熟悉完所有的接口信息后,可以编写插件了
首先创建一个josn插件文件描述符。my_plugin.plugin
{
"module": "my_plugin",
"class": "ExamplePlugin",
"authors": "Martin Alderete <malderete@gmail.com>",
"version": "0.1",
"description": "Example of NINJA-IDE plugin"
}
注意:与Python不一样,此处的json用的是Python的json包进行解析,因此最后的一个描述后面,一定不要添加 , 否则会出现NINJA-IDE启动不了。
最小的插件代码
from ninja_ide.core import plugin
class ExamplePlugin(plugin.Plugin):
def initialize(self):
print "This message go to the console when the plugins is loaded"
是的,我们创建自己的插件,这个插件不能够做任何事情。
更高级的插件
首先,我们给NINJA-IDE添加一个插件菜单行为,然后连接单击事件
from ninja_ide.core import plugin
from PyQt4.QtGui import QAction
from PyQt4.QtGui import QDialog
class ExamplePlugin(plugin.Plugin):
def initialize(self):
self.menuapp_s = self.locator.get_service('menuApp')
self.action = QAction("Example plugin menu action", self)
self.connect(self.action, SIGNAL("triggered()"), self.action_click)
self.menuapp_s.add_action(self.action)
def action_click(self):
d = Dialog()
d.exec_()
class Dialog(QDialog):
def __init_(self):
QDialog.__init__(self)
接下来,我们可以处理Editor的keyPressEvent事件
from ninja_ide.core import plugin
from PyQt4.QtCore import Qt
class ExamplePlugin(plugin.Plugin):
def initialize(self):
self.editor_s = self.locator.get_service('editor')
self.editor_s.editorKeyPressEvent.connect(self.handle_keyPress)
def handle_keyPress(self, event):
if event.key() in (Qt.Key_Enter, Qt.Key_Return):
print "Someone has pressed the return key"
至此,一个完整的NINJA-IDE工程插件结束