PyForge Studio 插件开发文档
欢迎来到 PyForge Studio 的插件开发世界!本文档将指导你从零开始,为 PyForge 编写功能强大的插件。 无论你是想增加一个快捷键、添加一个代码格式化工具,还是集成网络服务,PyForge 的插件系统都能让你轻松扩展 IDE 的功能。
1. 概述
PyForge Studio 的插件系统基于 微内核架构 设计:
- 内核(主程序):负责加载插件、管理菜单、提供核心 API(如编辑器访问、日志、线程工具等)。主程序代码闭源,但插件接口完全开放。
- 插件(Plugin):一个
.zip压缩包,内含Include.json(元数据)和init.py(入口脚本)。插件可以:- 添加菜单项到“插件”菜单
- 注册快捷键
- 修改编辑器行为
- 调用其他插件提供的 API
- 使用主程序提供的工具库(如
editor.utils)
2. 插件文件结构
一个标准的插件压缩包(.zip)内部应包含以下文件:
YourPlugin.zip ├── Include.json # 必须,元数据文件 └── init.py # 必须,插件入口脚本
插件安装后,主程序会将其解压到 .plugin/extracted/ 目录,并以 UUID 作为唯一标识。
3. Include.json 详细说明
Include.json 是一个 JSON 格式的元数据文件,用于声明插件的身份、依赖和 API 信息。
所有字段均区分大小写。
3.1 基础字段
{
"plugin_uuid": "com.yourstudio.yourplugin", // 必填,全局唯一标识符
"name": "Your Plugin Name", // 必填,显示名称
"version": "1.0.0", // 必填,语义化版本号
"provides_api": false, // 可选,是否提供 API
"dependencies": { // 可选,依赖声明
"pip": [], // pip 依赖列表
"plugins": [] // 前置插件依赖列表
}
}
3.2 字段详解
| 字段 | 类型 | 说明 |
|---|---|---|
plugin_uuid |
字符串 | 必填。全局唯一标识符,建议使用反向域名格式(如 com.yourstudio.plugin)。 |
name |
字符串 | 必填。插件在 UI 中显示的名称。 |
version |
字符串 | 必填。语义化版本号(如 1.2.3)。 |
provides_api |
false 或 {"version":"..."} |
可选,默认 false。若提供 API,需指定版本号,如 {"version":"1.0"}。
其他插件可通过依赖此插件并指定所需 API 版本来调用。
|
dependencies |
对象 |
可选,默认为 {"pip": [], "plugins": []}。· pip:Python 包列表(如 ["requests"]),加载时自动安装。· plugins:前置插件列表,每个对象包含 uuid 和 api_version。
|
4. init.py – 插件入口脚本
init.py 是插件的核心执行文件,主程序会在满足所有依赖后动态加载它。
必须包含一个 register(editor) 函数,作为插件的入口点。
import tkinter as tk from tkinter import messagebox def register(editor): """ 插件注册函数 :param editor: PythonEditor 实例,提供核心 API """ # 在这里编写你的插件逻辑 pass
5. editor API 参考
在 register 函数中,你获得的 editor 对象提供了以下常用属性和方法:
| API | 类型 | 说明 |
|---|---|---|
editor.root | tk.Tk | 主窗口对象 |
editor.code_editor | ScrolledText | 代码编辑器控件 |
editor.current_file | str / None | 当前打开的文件路径 |
editor.log_info(msg) | 方法 | 打印信息日志(控制台) |
editor.log_error(msg) | 方法 | 打印错误日志 |
editor.add_plugin_menu_item(label, cmd) | 方法 | 在“插件”菜单添加菜单项 |
editor.run_in_thread(func, *args) | 方法 | 在后台线程运行函数,避免阻塞 UI |
editor.save_file() | 方法 | 保存当前文件 |
editor.run_code() | 方法 | 运行当前文件 |
editor.get_plugin_dir() | 方法 | 获取插件根目录路径 |
editor.utils | 对象 | 工具库(需依赖 com.rauto.utils) |
editor.utils 仅在依赖插件 com.rauto.utils 已加载时可用。
如需使用,请在 Include.json 的 dependencies.plugins 中声明。
6. editor.utils 工具库
需要依赖 com.rauto.utils 插件(UUID: com.rauto.utils)。
| 方法 | 说明 |
|---|---|
utils.read_text(path) | 读取文本文件,返回字符串 |
utils.write_text(path, content) | 写入文本文件 |
utils.read_json(path) | 读取并解析 JSON 文件 |
utils.write_json(path, data) | 将数据写入 JSON 文件 |
utils.http_get(url, params, headers, timeout) | 发起 GET 请求(需 requests) |
utils.http_post(url, data, json, headers, timeout) | 发起 POST 请求 |
utils.show_info(title, message) | 显示信息提示框 |
utils.show_error(title, message) | 显示错误提示框 |
utils.show_yesno(title, message) | 显示“是/否”对话框,返回 True/False |
utils.get_string(title, prompt, initialvalue) | 显示输入框,返回用户输入 |
utils.show_progress(title, maximum) | 显示进度条窗口,返回 (update, close) |
utils.run_in_thread(func, *args, callback) | 后台运行函数,完成后通过回调更新 UI |
utils.run_in_main_thread(func, *args) | 在主线程执行函数(用于更新 UI) |
utils.subscribe(event, callback) | 订阅事件(跨插件通信) |
utils.publish(event, *args, **kwargs) | 发布事件,触发所有订阅者 |
utils.get_timestamp() | 返回当前时间字符串 |
utils.get_plugin_dir() | 返回当前插件的目录 |
示例:添加一个菜单项
def register(editor): def say_hello(): editor.utils.show_info("问候", "你好,世界!") editor.add_plugin_menu_item("👋 问候", say_hello) editor.log_info("问候插件加载成功")
示例:访问编辑器内容
def register(editor): def count_lines(): content = editor.code_editor.get("1.0", tk.END) lines = content.count('\n') messagebox.showinfo("行数统计", f"当前文件共有 {lines} 行") editor.add_plugin_menu_item("📊 统计行数", count_lines)
7. 依赖管理与版本兼容性
7.1 声明依赖
在 Include.json 中可声明两种依赖:
- Python 包(pip):在
dependencies.pip数组中列出包名,加载器自动检查并安装。 - 前置插件:在
dependencies.plugins中指定uuid和api_version。
7.2 版本比较规则
主程序使用 语义化版本 比较(>=)。要求 "1.2",前置插件提供 "1.3" 则兼容;若提供 "1.1" 则不兼容并提示错误。
7.3 加载流程
- 扫描
.plugin目录下所有.zip文件。 - 解压每个插件,读取
Include.json,注册 UUID 和元数据。 - 对每个插件检查
dependencies.plugins:- 若前置插件 UUID 不存在 → 弹出“缺少前置插件”
- 若前置插件未声明
provides_api→ 不兼容 - 若 API 版本不满足要求 → 弹出“API 版本不兼容”
- 依赖检查通过后,执行
init.py中的register。
8. 插件管理窗口
用户可以通过菜单 “插件” → “管理插件” 打开插件管理窗口,查看所有已注册插件的 UUID、名称、版本、是否提供 API 以及状态(已加载/错误)。用户还可以在此窗口卸载插件。
9. 开发与调试建议
9.1 日志输出
使用 editor.log_info() 和 editor.log_error() 输出日志,这些信息会显示在控制台(如果从命令行启动)或日志文件中。
9.2 热重载
修改插件代码后,无需重启 IDE,只需点击 “插件” → “刷新插件” 即可重新加载所有插件(注意:已注册的菜单项可能需要手动刷新)。
9.3 测试依赖
建议先安装 RautoStudio_Universal_utils(UUID: com.rauto.utils)作为基础工具库。
9.4 常见错误及解决
| 错误现象 | 可能原因 | 解决方法 |
|---|---|---|
| 插件未被加载 | Include.json 缺少 plugin_uuid | 添加 UUID |
| 状态显示“错误” | init.py 缺少 register 或语法错误 | 检查并修正 |
| 提示“缺少前置插件” | 依赖的插件未安装 | 安装对应的 .zip 插件 |
| 提示“API版本不兼容” | 前置插件提供的 API 版本低于要求 | 更新前置插件或降低版本要求 |
| 菜单项未出现 | 未调用 editor.add_plugin_menu_item | 在 register 中添加调用 |
10. 完整插件示例(带依赖)
以下是一个完整的插件示例,它依赖 com.rauto.utils 工具库,并添加一个“显示当前时间”的菜单项。
Include.json
{
"plugin_uuid": "com.rauto.clock",
"name": "时钟插件",
"version": "1.0.0",
"provides_api": false,
"dependencies": {
"pip": [],
"plugins": [
{ "uuid": "com.rauto.utils", "api_version": "1.0" }
]
}
}
init.py
import datetime def register(editor): def show_time(): now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") editor.utils.show_info("当前时间", now) editor.add_plugin_menu_item("🕒 显示时间", show_time) editor.log_info("时钟插件已加载")
打包为 clock.zip 后,用户即可通过“安装插件”功能安装。
11. 发布与分发
- 插件格式:将
Include.json和init.py打包成.zip(注意:不要包含外层文件夹)。 - 分发方式:将
.zip分享给其他 PyForge 用户,他们通过 “插件” → “安装插件” 选择该文件即可安装。 - 插件市场(未来):Rauto Studio 计划建立官方插件仓库,届时插件可在线浏览并一键安装。
12. 获取帮助
- 文档更新:本文件随主程序版本更新,请以最新版为准。
- 问题反馈:可通过 Rauto Studio 官方渠道提交问题(邮箱:Rauto@outlook.com 或官网 www.rauto.p8.ink)。
- 示例插件:官方提供了两个示例插件(
RautoStudio_Universal_utils和ModernControl),可参考其实现。
—— Rauto Studio 团队