Initial commit

This commit is contained in:
Docker7530
2026-03-01 01:43:46 +08:00
commit c6125c117b
3840 changed files with 415340 additions and 0 deletions
@@ -0,0 +1,65 @@
# 📔 Rime YAML Custom Patch 语法笔记
## 一、 核心规则与权重
1. **权重排序**`custom.yaml` > `schema.yaml` > `default.yaml`
2. **对应关系**:修改 `xxx.schema.yaml` 需创建 `xxx.custom.yaml`。**注意:** `.dict.yaml` 无法被 patch。
3. **最终形态原则**:Patch 作用于编译后的“最终形态”(见 `build/` 文件夹)。若原方案包含 `__include`,需 patch 其引入后的结果,而非 patch `__include` 命令本身。
4. **结构限制**:一个 `custom` 文件顶层**只能有一个** `patch:` 入口。
## 二、 常用引用命令
- `__include: [路径]`:将指定段落内容引入当前位置。
- `__patch: [路径]`:功能类似 include,但可叠加使用(多个 `__include` 只有最后一个生效)。
- `__append: [列表]`:配合 patch 使用,将新列表内容追加到原列表后方实现拼接。
## 三、 语法操作符速查
| 操作类型 | 语法示例 | 说明 |
| :--- | :--- | :--- |
| **全局替换** | `key: new_value` | **慎用!** 会清空该键下的所有原有子项 |
| **局部替换** | `key/subkey: value` | 仅修改特定项,不影响同级其他项 |
| **末尾追加** | `key/+: [list]` | 在列表末尾添加新元素 |
| **特定行替换** | `key/@n: value` | 替换第 $n+1$ 行(索引从 0 开始) |
| **特定行插入** | `key/@before n: value` | 在第 $n+1$ 行前插入,原内容后移 |
| **末尾行替换** | `key/@last: value` | 直接定位并替换最后一行 |
| **删除/失效** | `key/subkey: ` | **不支持 `/-`**。通过将值设为空来使其失效 |
## 四、 关键行为解析
### 1. 局部修改 vs. 覆盖重写
- **推荐(局部)**`menu/page_size: 10` —— 只改数字,保留 `menu` 下的其他设置(如字体、颜色)。
- **危险(全局)**`menu: { page_size: 10 }` —— 会导致 `menu` 下除 `page_size` 外的所有配置被**删除**。
### 2. 列表(List)的操作细节
对于 `engine/filters` 等有严格顺序要求的模块:
- **不能直接用 `/+`**:因为 `/+` 默认加在末尾。如果某个引导器(Translator)必须排在前面,加在末尾会导致功能失效。
- **精准定位**
```yaml
patch:
engine/translators/@before 0: table_translator@custom_phrase # 插入到首行
engine/filters/@5: lua_filter@new_filter # 替换第6行
```
*注:`@` 语法后直接跟值,不需要加 `-` 横线。*
### 3. 如何“删除”配置
由于 Rime Patch 不支持 `/-` 语法,删除某行有两种方式:
1. **重写整个段落**:在 `patch` 中重新列出需要的行,剔除不需要的行(最彻底)。
2. **置空法**`key/subkey: `。虽然键还在,但值为空,通常能停止该功能。
## 五、 缩进与格式
- YAML 严格遵守 **2 空格缩进**。
- 不要在 `patch:` 段落中间插入顶层节点,否则会截断 Patch。
- 外部预设(如模糊音)建议放在文件末尾,通过 `__include` 引入到 `patch` 内部。
---
**💡 提示**:调试 Patch 时,若结果不符合预期,请第一时间检查 `build/` 文件夹下的产物,那是 Rime 真正读取的配置。
+52
View File
@@ -0,0 +1,52 @@
配置:
```
custom.yaml > schema.yaml > default.yaml
引用__include:
补丁__patch:
跟随__append:
不能patch一个__include段落
一个custom文件顶层必须只有一个patch:
```
```
1. 方案文件七大模块
阅读:wanxiang.schema.yaml:1-100
schema: # 方案元信息
switches: # 开关配置
engine: # 输入引擎(核心)
processors: # 处理器链
segmentors: # 分段器
translators: # 翻译器
filters: # 过滤器
speller: # 拼写设定
translator: # 翻译器设定
punctuator: # 标点设定
key_binder: # 按键绑定
recognizer: # 识别器
engine:
processors: # 1. 最先接收按键
- ascii_composer # 处理中英切换
- recognizer # 识别特殊模式(如反查)
- speller # 拼写处理
segmentors: # 2. 分段标记
- abc_segmentor # 标记普通文字段落为 'abc' tag
- affix_segmentor@wanxiang_reverse # 标记反查为特定 tag
translators: # 3. 翻译候选
- script_translator # 主翻译器
- table_translator@custom_phrase # 自定义短语
filters: # 4. 过滤排序
- uniquifier # 去重
```
+50
View File
@@ -0,0 +1,50 @@
快捷键(含场景与功能)
| 场景 | 按键 | 功能 | 来源 |
| ---------- | ----------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------ |
| 任意 | `Control+grave` | 打开方案选单 | `default.yaml` |
| 任意 | `Shift+space` | 切换到下一个方案 | `wanxiang.schema.yaml`, `wanxiang_english.schema.yaml` |
| 任意 | `Caps_Lock` | 清空未上屏内容并切换中英(按 ascii_composer 规则) | `default.yaml` |
| 任意 | `Shift_L` / `Shift_R` | 上屏编码并切换中英(按 ascii_composer 规则) | `default.yaml` |
| 任意 | `Control+Shift+3` / `Control+Shift+#` | 切换中英标点 | `wanxiang.schema.yaml` |
| 任意 | `Control+Shift+4` / `Control+Shift+$` | 切换简繁(s2t) | `wanxiang.schema.yaml` |
| 组合中 | `Alt+Left` / `Alt+Right` | 移动到上/下一音节(通过 Shift+Left/Right | `wanxiang.schema.yaml` |
| 组合中 | `Control+w` | 删除一个词(Control+BackSpace | `wanxiang.schema.yaml` |
| 候选存在 | `Control+e` | 切换中英翻译模式(chinese_english | `wanxiang.schema.yaml` |
| 候选存在 | `Control+a` | 切换辅助码显示(tone_hint | `wanxiang.schema.yaml` |
| 候选存在 | `Control+s` | 切换输入码音调显示(tone_display | `wanxiang.schema.yaml` |
| 候选存在 | `Control+t` | 切换 super_tips | `wanxiang.schema.yaml` |
| 候选存在 / 组合中 | `Control+g` | 切换字符集过滤(charset_filter | `wanxiang.schema.yaml` |
| 候选存在 / 组合中 | `Tab` | 跳到下一音节(Control+Right | `wanxiang.schema.yaml` |
| 组合中 | `Control+Tab` | 按序补码上屏(发送序列 `{Home}{Shift+Right}{1}{Shift+Right}` | `wanxiang.schema.yaml` |
| 候选存在 | `-` / `=` | 翻页(上一页/下一页) | `wanxiang.schema.yaml` |
| 组合中 | `Control+k` | 切换选项 `xxxxx`(配置里未定义,可能无效) | `default.yaml` |
| 组合中 | 小键盘 `0-9`/`.`/`+`/`-`/`*`/`/`/`Enter` | 映射为主键盘对应字符 | `default.yaml` |
| 排序模式 | `Control+j` / `Control+k` / `Control+l` / `Control+p` | 候选手动排序:上移/下移/重置/置顶 | `wanxiang.schema.yaml` |
编辑键(输入法编辑状态)
| 场景 | 按键 | 功能 | 来源 |
|---|---|---|---|
| 候选存在 | `Space` | 上屏当前候选 | `wanxiang.schema.yaml` |
| 组合中 | `Return` | 上屏原始输入 | `wanxiang.schema.yaml` |
| 组合中 | `Control+Return` | 上屏变换后的输入 | `wanxiang.schema.yaml` |
| 组合中 | `Control+Shift+Return` | 上屏注释(comment | `wanxiang.schema.yaml` |
| 组合中 | `BackSpace` | 撤销上次输入 | `wanxiang.schema.yaml` |
| 组合中 | `Delete` | 删除后一个字符 | `wanxiang.schema.yaml` |
| 组合中 | `Control+BackSpace` | 删除一个音节 | `wanxiang.schema.yaml` |
| 候选存在 | `Control+Delete` | 删除或降权候选 | `wanxiang.schema.yaml` |
| 任意 | `Escape` | 取消输入 | `wanxiang.schema.yaml` |
特殊引导键/前缀
| 场景 | 按键/前缀 | 功能 | 来源 |
|---|---|---|---|
| 输入引导 | `/``o` | 触发 shijian.lua(日期/时间/节气等) | `wanxiang.schema.yaml` |
| 输入引导 | `U` + 十六进制 | Unicode 码点输出 | `wanxiang.schema.yaml` |
| 输入引导 | `R` + 数字 | 数字金额大写 | `wanxiang.schema.yaml` |
| 输入引导 | `V` + 表达式 | 计算器功能 | `wanxiang.schema.yaml` |
| 输入引导 | `/` + 代码 | 符号/表情/特殊字符表(如 `/fh``/bq` 等) | `wanxiang_symbols.yaml` |
| 输入行为 | `/` 单独作为输入 | 斜杠被占用为引导键,配置里用双击 `/` 方式输入本身 | `wanxiang.schema.yaml` |
| 候选存在 | `[` / `]` | 以词定字:取首字/末字 | `wanxiang.schema.yaml` |
| 候选存在 | `,` | super_tips 上屏按键 | `wanxiang.schema.yaml` |
+123
View File
@@ -0,0 +1,123 @@
# 闪念
```
<%*
// 查找当前日期对应的文件
const file = tp.file.find_tfile(tp.date.now("YYYY-MM-DD"));
if (!file) {
// 如果没有找到对应的文件,弹出通知
new Notice("No Daily Note Found!");
return; // 早期返回,避免更深的嵌套
}
// 弹出提示框,获取用户输入的日记内容
const loggedItem = await tp.system.prompt("What's Up?");
if (loggedItem === undefined || loggedItem === null || loggedItem.trim().length === 0) {
// 如果输入为undefined、null、空串或仅包含空格,不执行任何操作,弹出通知
new Notice("Input is empty or invalid!");
return; // 早期返回,避免更深的嵌套
}
// 获取当前时间
const time = tp.date.now("HH:mm");
// 读取文件内容,并按行分割成数组
const content = (await app.vault.read(file)).split("\n");
// 找到“# 杂记”标题的位置
const index = content.indexOf("# 杂记");
// 检查“# 杂记”标题下一行是否为空行
if (content[index + 1].trim() === "") {
// 如果下一行是空行,就在空行下添加新内容
content.splice(index + 2, 0, `- ${time} - ${loggedItem}`);
} else {
// 如果下一行不是空行,就先添加一个空行,然后添加新内容
content.splice(index + 1, 0, "", `- ${time} - ${loggedItem}`);
}
// 将修改后的内容写回文件
await app.vault.modify(file, content.join("\n"));
-%>
```
# 问题记录模板
```
<%*
// 弹出提示框获取文件标题
const title = await tp.system.prompt("Enter file title");
// !!!!!!!!!!!!!!!!每个人自定义区域!!!!!!!!!!!!!!!!
// 定义待创建文件的目录
const inboxDirectory = "000-Inbox";
// 定义文档中会用到的特定标题,方便将来修改
const detailHeader = "# 问题详情";
// !!!!!!!!!!!!!!!!每个人自定义区域!!!!!!!!!!!!!!!!
// 检查用户输入的标题是否有效(非空且非纯空格)
if (!title || title.trim().length === 0) {
new Notice("Title is empty or invalid!");
return; // 如果标题为空或无效,则显示通知并停止执行
}
// 获取当前日期并格式化为 YYYY-MM-DD 用于文件属性
const currentDate = tp.date.now("YYYY-MM-DD");
// 获取当前时间并格式化为 HH:mm 用于文件属性
const currentTime = tp.date.now("HH:mm");
// 获取当前日期并格式化为 MMDD 用于文件名前缀
const datePrefix = tp.date.now("MMDD");
// 构造待写入新文件中的内容,使用 YAML front matter 和 Markdown 格式
const content = `---
日期: ${currentDate} ${currentTime}
来源:
---
# 问题详情
# 处理过程
# 总结
`;
// 根据日期前缀和用户输入的标题构造文件名
const myFilename = `${datePrefix}-${title}`;
// 尝试创建新文件并写入构造好的内容
try {
await tp.file.create_new(content, myFilename, false, app.vault.getAbstractFileByPath(inboxDirectory));
new Notice("File created successfully!"); // 如果成功,弹出通知
// 根据文件名和目录获取新创建的文件
const createdFile = app.vault.getAbstractFileByPath(`${inboxDirectory}/${myFilename}.md`);
// 获取新窗口叶节点
const leaf = app.workspace.getLeaf(true);
// 在新叶节点中打开新创建的文件
await leaf.openFile(createdFile);
// 等待新视图加载完成
await leaf.view.awaitingView;
// 获取编辑器实例
const editor = leaf.view.sourceMode.cmEditor;
// 寻找文件中的特定标题行
const line_number = editor.lastLine();
for(let i = 0; i <= line_number; i++) {
const line = editor.getLine(i);
if(line.includes(detailHeader)) { // 如果找到指定的标题行
// 将光标移动到该标题下一行的开始位置
editor.setCursor({line: i+2, ch: 0});
break;
}
}
} catch (e) { // 如果尝试创建或打开文件出现错误
new Notice("Failed to create or open file: " + e.message); // 弹出错误通知
}
-%>
```
@@ -0,0 +1,39 @@
要在 Windows 系统上测试 Obsidian 的 `x-callback-url` 功能,可以创建一个简单的场景,在该场景中,你将使用浏览器(如 Edge 或 Chrome)来构造 URL 请求,并利用 Obsidian 和一个 web 服务(比如用一些免费在线服务作为 `x-success` 回调目标)来测试。以下是一个可以直接体验的步骤:
# 准备工作:
1. **确保已安装 Obsidian** 并且已经在本地创建一个名为 `TestVault` 的笔记库。
2. **确认 Obsidian 可以处理 URL Scheme**:在 Obsidian 中,启用 `URI` 插件(如果有),确保它能接收 `obsidian://` 协议的链接。
# 测试步骤:
1. 打开浏览器,复制并粘贴以下 URL 到地址栏中,然后回车:
```
obsidian://new?vault=TestVault&name=TestNote&x-success=https://webhook.site/your-webhook-id
```
- `vault=TestVault`:这是你的笔记库名称,需要与你本地的笔记库名称一致。
- `name=TestNote`:要在 Obsidian 中创建的新笔记名称。
- `x-success=https://webhook.site/your-webhook-id``https://webhook.site/` 是一个在线工具,用于接受任何形式的 HTTP 请求。你可以在这个网站上获取一个唯一的 URL(称为 `your-webhook-id`),Obsidian 完成操作后会回调到这个地址。
2. **获取 `Webhook.site` 的 ID**
- 打开 [Webhook.site](https://webhook.site)。
- 页面上会生成一个唯一的 URL(如 `https://webhook.site/abcdefg-1234-5678`)。复制这个地址,替换上面的 `https://webhook.site/your-webhook-id` 部分。
3. **执行 URL**
- 将替换后的完整 URL 粘贴到浏览器地址栏,然后回车。这个 URL 会触发 Obsidian 创建一个名为 `TestNote` 的新笔记,并在创建完成后回调 `Webhook.site`。
4. **查看回调结果**
- 回到 `Webhook.site` 页面,你会看到 Obsidian 请求回调的详细信息,包括笔记的名称和相关信息。
# 结果:
- 如果操作成功,你应该会在 Obsidian 中的 `TestVault` 笔记库中看到一个名为 `TestNote` 的新笔记。
- 同时,在 `Webhook.site` 上可以查看到一个包含 `name` 参数的请求,比如:
```
name=TestNote&url=obsidian%3A%2F%2Fopen%3Fvault%3DTestVault%26file%3DTestNote&file=file%3A%2F%2F%2F...
```
通过这种方法,你可以很方便地在 Windows 系统上测试 `x-callback-url` 的功能,并直观地看到 Obsidian 和外部服务之间的交互结果。