实战示例
下面三个示例由浅入深,覆盖菜单、侧边栏面板与 Hook 三种最常见的插件形态;最后介绍书砚内置的有声书扩展示例。
示例 1:给工具菜单加一个「字数统计」
"""字数统计扩展"""
def get_info():
return {'name': 'word_counter',
'display_name': '📊 字数统计',
'version': '1.0.0',
'author': 'me',
'description': '在工具菜单里加一个"显示全书字数"按钮'}
def activate(api):
def show_total():
chapters = api.list_chapters()
total = sum(ch.get('word_count', 0) for ch in chapters)
api.toast(f"全书共 {total:,} 字,{len(chapters)} 章")
api.add_menu('工具', '📊 显示全书字数', show_total, 'Ctrl+Shift+W')
示例 2:侧边栏面板——生成 Markdown 目录
"""Markdown 目录扩展"""
def get_info():
return {'name': 'markdown_toc',
'display_name': '📋 MD 目录',
'version': '1.0.0',
'description': '生成当前项目的 Markdown 目录'}
def activate(api):
from PySide2.QtWidgets import QWidget, QVBoxLayout, QPlainTextEdit, QPushButton
from PySide2.QtCore import Qt
panel = QWidget()
lay = QVBoxLayout(panel)
edit = QPlainTextEdit()
edit.setReadOnly(True)
btn = QPushButton("🔄 生成目录")
lay.addWidget(edit)
lay.addWidget(btn)
def gen():
chapters = api.list_chapters()
lines = ['# ' + (api.project.get('name','') or '') + ' 目录', '']
for i, ch in enumerate(chapters, 1):
lines.append(f"{i}. {ch['title']} ({ch.get('word_count',0):,} 字)")
edit.setPlainText('\n'.join(lines))
api.toast(f"生成了 {len(chapters)} 章目录")
btn.clicked.connect(gen)
api.add_side_tab(panel, "📋 MD 目录")
示例 3:用 Hook 监听保存 + 写入自定义元数据
"""保存自动记录扩展"""
def get_info():
return {'name': 'auto_log',
'display_name': '📝 保存日志',
'version': '1.0.0',
'description': '每次保存自动记录到项目日志里'}
def activate(api):
def on_saved(editor):
ch = api.db.get_chapter(editor.chapter_id)
words = ch.get('word_count', 0) if ch else 0
key = f'save_log_{api.project_id}'
import json
logs = json.loads(api.get_config(key, '[]'))
logs.append({'chapter': ch['title'] if ch else '?', 'words': words})
api.set_config(key, json.dumps(logs, ensure_ascii=False))
api.log(f"保存记录: {ch['title']} {words:,} 字")
api.on_chapter_saved(on_saved)
内置扩展:有声书
书砚内置了一个示例扩展 plugins/audiobook_plugin.py,功能是给每章填写旁白音色和预计时长,一键导出有声书描述文件。可以直接打开看源码,是学习插件开发的最佳模板。
这个插件做的事:
- 往侧边栏加一个 🎧 有声书 tab(一个
QTableWidget表格) - 每章可填:旁白音色、预计时长、是否已录、备注
- 数据持久化到 DB config(key =
audiobook_meta_{project_id}) - 一键导出 JSON / TXT 格式的有声书描述文件