# textkit.patch：精确补丁

`literal-only / unique / atomic / same-original`。本库是文件编辑工具使用的底层补丁引擎，只处理字符串、不读写文件；通过工具编辑文件时不需要直接调用。原文包含补丁标记行、需要行号或明确批量匹配时，用 `textkit.editor`。

## 最小调用

```aardio
import textkit.patch;

var text = 'old();\r\nkeep();\n';
var patchText = /******
<<<<<<< SEARCH
old();
=======
new();
>>>>>>> REPLACE
******/;

var result,err,info = textkit.patch.apply(text,patchText,{previewMaxBytes=0});
if(result === null) return {error=err;info=info};
print(result); // 'new();\r\nkeep();\n'
```

## 必须记住

- **Copy old, format new**：SEARCH 从当前原文复制，空白、大小写必须一致；不要 `trim/dedent`、手工重建或用省略号代替。
- **同一原文**：所有块都在修改前的文本上匹配，块之间不是顺序替换；SEARCH 必须非空、恰好一处且彼此不重叠。
- **只容忍行尾差别**：CRLF/LF/CR 等价；SPACE/TAB、行尾空格仍有区别。只修改最小变化区间，新片段适配局部行尾，其他字节保留。
- **显式排版**：不自动缩进。新片段需要调整缩进时，先用 `textkit.indent/dedent` 处理，不要处理旧片段。
- **插入**：SEARCH 是原锚点，REPLACE 是锚点与新增内容；**删除**：REPLACE 留空。
- 三条标记独占一行；内容自己包含标记行时使用 `textkit.editor.process`，不额外设计转义语法。

## 返回与恢复

`apply(text,patchText[,options])`：

- 成功：`newText,null,info`；`count` 是匹配数，`changedCount` 是实际变化数，`changed` 表示是否有变化。
- 失败：`null,err,info`；整单不产生部分文本。根据 `info.code`、`blockIndex`、`hint` 重新读取和修正。
- `diagnostics.approximate` 仅是候选诊断，永不用于模糊写入。
- `parse(patchText)` 只解析，返回块数组或 `null,err,info`；可接受一层外围 Markdown 围栏。

`options.previewMaxBytes` 默认 1024，范围 0..4096，0 关闭文本回显；`changePreview=false` 关闭成功预览。预览最多 4 处、定位最多 6 处。字节预算只限制回显，不限制实际编辑，也不包含固定有界元数据。`*Bytes` 都是字节预算或统计，不是字符位置。

此库只处理字符串，不负责文件 BOM、备份、编译或写入；文件工具负责这些步骤。

[textkit 主库](../index.html)
