Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion TeXmacs/packages/customize/document/three-columns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,5 @@
<\initial>
<\collection>
<associate|preamble|true>
<associate|stem-doc-id|1BBE8D65-51A6-4730-888B-09E3E033E540>
</collection>
</initial>
54 changes: 38 additions & 16 deletions TeXmacs/plugins/autosave/progs/autosave/plugin.scm
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(texmacs-module (autosave plugin)
(:use (utils library cursor) (texmacs texmacs tm-collab))
(:use (utils library cursor)
(texmacs texmacs tm-collab)
(texmacs texmacs tm-files)
) ;:use
) ;texmacs-module

(import (liii uuid))
Expand Down Expand Up @@ -96,6 +99,7 @@
(not (url-rooted-tmfs? name))
(not (auto-backup-texmacs-path-buffer? name))
(in? (url-format name) '("texmacs" "stm" "tmu" "stem"))
(not (style-buffer? name))
) ;and
) ;tm-define

Expand All @@ -106,20 +110,22 @@
(tm-define (auto-backup-buffer-doc-id name)
(catch #t
(lambda ()
;; First try to get from init-env (memory), then from document tree (file)
(with-buffer name
(let* ((from-env (get-init-env "stem-doc-id"))
(doc-id (if (and (string? from-env) (!= from-env ""))
from-env
(let* ((doc (buffer-get name)) (initial (tmfile-extract doc 'initial)))
(and initial (collection-ref initial "stem-doc-id"))
) ;let*
) ;if
) ;doc-id
) ;
doc-id
) ;let*
) ;with-buffer
(and (not (style-buffer? name))
;; First try to get from init-env (memory), then from document tree (file)
(with-buffer name
(let* ((from-env (get-init-env "stem-doc-id"))
(doc-id (if (and (string? from-env) (!= from-env ""))
from-env
(let* ((doc (buffer-get name)) (initial (tmfile-extract doc 'initial)))
(and initial (collection-ref initial "stem-doc-id"))
) ;let*
) ;if
) ;doc-id
) ;
doc-id
) ;let*
) ;with-buffer
) ;and
) ;lambda
(lambda args #f)
) ;catch
Expand Down Expand Up @@ -180,6 +186,22 @@
) ;catch
) ;tm-define

(tm-define (auto-backup-clear-buffer-doc-id! name)
(catch #t
(lambda () (with-buffer name (init-default "stem-doc-id")))
(lambda args #f)
) ;catch
) ;tm-define

;; 「样式 buffer 清除、文档 buffer 补齐」的 doc id 策略统一收口在这里,
;; 各保存路径只需无条件调用本函数。
(tm-define (auto-backup-sync-buffer-doc-id! name)
(if (style-buffer? name)
(auto-backup-clear-buffer-doc-id! name)
(auto-backup-ensure-buffer-doc-id! name)
) ;if
) ;tm-define

(tm-define (auto-backup-trig-payload name kind)
(let* ((collab? (collab-buffer? name))
;; 协作文档:path 指向本地不可见备份文件(collab-silent-backup 已在 save-buffer-save
Expand Down Expand Up @@ -338,7 +360,7 @@
(tm-define (save-all-buffers)
(for-each (lambda (buf)
(when (buffer-modified? buf)
(auto-backup-ensure-buffer-doc-id! buf)
(auto-backup-sync-buffer-doc-id! buf)
(buffer-save buf)
) ;when
) ;lambda
Expand Down
1 change: 0 additions & 1 deletion TeXmacs/plugins/bash/doc/bash.en.tmu
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,5 @@
<associate|page-medium|paper>
<associate|page-screen-margin|false>
<associate|preamble|false>
<associate|stem-doc-id|BCAFEF72-F99D-4000-896F-74714384F260>
</collection>
</initial>
82 changes: 81 additions & 1 deletion TeXmacs/progs/texmacs/texmacs/tm-files-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(texmacs-module (texmacs texmacs tm-files-test)
(:use (texmacs texmacs tm-files) (autosave plugin))
(:use (texmacs texmacs tm-files) (autosave plugin) (utils library cursor))
) ;texmacs-module

(import (liii check))
Expand Down Expand Up @@ -139,6 +139,85 @@
) ;let*
) ;define

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tests for style-buffer? and stem-doc-id eligibility
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define (test-style-buffer-and-doc-id)
;; 1. .ts 后缀 buffer 属于样式 buffer,不生成 stem-doc-id
(let* ((orig (current-buffer))
(buf (new-buffer ".tmu"))
(ts-url (system->url "/tmp/test_custom_style.ts"))
) ;
(buffer-rename buf ts-url)
(check (style-buffer? ts-url) => #t)
(check (auto-backup-buffer-eligible? ts-url) => #f)
(check (auto-backup-ensure-buffer-doc-id! ts-url) => #f)
(buffer-close ts-url)
(switch-to-buffer orig)
) ;let*

;; 2. 实际为样式的 .stem buffer(style 为 source)不生成 stem-doc-id
(let* ((orig (current-buffer))
(stem-style-buf (new-buffer ".stem"))
(style-doc '(document (TeXmacs "2.1.4")
(style (tuple "source"))
(body (document (active* (src-title (document (src-package "my-pkg"
"1.0")))))))
) ;style-doc
) ;
(buffer-set stem-style-buf style-doc)
(check (style-buffer? stem-style-buf) => #t)
(check (auto-backup-buffer-eligible? stem-style-buf) => #f)
(check (auto-backup-ensure-buffer-doc-id! stem-style-buf) => #f)
;; 验证若环境中已存在 doc-id,clear 会将其清除
(with-buffer stem-style-buf (init-env "stem-doc-id" "test-uuid"))
(auto-backup-clear-buffer-doc-id! stem-style-buf)
(with-buffer stem-style-buf (check (get-init-env "stem-doc-id") => #f))
(check (auto-backup-buffer-doc-id stem-style-buf) => #f)
(buffer-close stem-style-buf)
(switch-to-buffer orig)
) ;let*

;; 3. 普通文档 buffer(.stem / .tmu,style 为 generic)生成 stem-doc-id
(for-each (lambda (suffix)
(let* ((orig (current-buffer))
(buf (new-buffer suffix))
(doc '(document (TeXmacs "2.1.4")
(style (tuple "generic"))
(body (document "Hello document")))
) ;doc
) ;
(buffer-set buf doc)
(check (style-buffer? buf) => #f)
(check (auto-backup-buffer-eligible? buf) => #t)
(let ((doc-id (auto-backup-ensure-buffer-doc-id! buf)))
(check (string? doc-id) => #t)
(check (!= doc-id "") => #t)
(check (auto-backup-buffer-doc-id buf) => doc-id)
) ;let
(buffer-close buf)
(switch-to-buffer orig)
) ;let*
) ;lambda
'(".stem" ".tmu")
) ;for-each

;; 4. 导出样式包生成的草稿 buffer 属于样式 buffer,不生成 stem-doc-id
(let ((orig-buf (current-buffer)))
(when (defined? 'extract-style-package)
(extract-style-package)
(let ((style-draft (current-buffer)))
(check (style-buffer? style-draft) => #t)
(check (auto-backup-buffer-eligible? style-draft) => #f)
(check (auto-backup-ensure-buffer-doc-id! style-draft) => #f)
(buffer-close style-draft)
(switch-to-buffer orig-buf)
) ;let
) ;when
) ;let
) ;define

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Test entry point
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Expand All @@ -151,5 +230,6 @@
(test-scratch-buffer-title-stem)
(test-scratch-buffer-title-old-and-new-stamp)
(test-scratch-buffer-title-legacy-one-underscore-this-week)
(test-style-buffer-and-doc-id)
(check-report)
) ;tm-define
51 changes: 49 additions & 2 deletions TeXmacs/progs/texmacs/texmacs/tm-files.scm
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,53 @@
) ;with
) ;tm-define

(define (source-markup-tag? t)
(and (pair? t) (in? (car t) '(src-title src-package src-style-file)))
) ;define

(define (body-has-source-markup? doc)
(let ((body (and doc (tmfile-extract doc 'body))))
(and (pair? body)
(== (car body) 'document)
(pair? (cdr body))
;; 导出样式包的草稿把 src-* 标记包在 active* 里,其内还可能再套一层 document
(let* ((first (cadr body))
(inner (if (and (pair? first) (== (car first) 'active*) (pair? (cdr first)))
(cadr first)
first
) ;if
) ;inner
) ;
(or (source-markup-tag? inner)
(and (pair? inner)
(== (car inner) 'document)
(pair? (cdr inner))
(source-markup-tag? (cadr inner))
) ;and
) ;or
) ;let*
) ;and
) ;let
) ;define

(tm-define (style-buffer? name)
(catch #t
(lambda ()
(and (url? name)
(buffer-exists? name)
(or (== (url-suffix name) "ts")
(and (defined? 'style-package-target-url)
(url? (style-package-target-url name))
) ;and
(with-buffer name (has-style-package? "source"))
(body-has-source-markup? (buffer-get name))
) ;or
) ;and
) ;lambda
(lambda args #f)
) ;catch
) ;tm-define

(tm-define (buffer-set-default-style)
(init-style "generic")
(with lan
Expand Down Expand Up @@ -428,8 +475,8 @@
;; (display* "save-buffer-save " name "\n")
(with vname
`(verbatim ,(utf8->cork (url->system name)))
(when (defined? 'auto-backup-ensure-buffer-doc-id!)
(auto-backup-ensure-buffer-doc-id! name)
(when (defined? 'auto-backup-sync-buffer-doc-id!)
(auto-backup-sync-buffer-doc-id! name)
) ;when
(if (buffer-save name)
(begin
Expand Down
57 changes: 57 additions & 0 deletions devel/1297.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# [1297] 仅对文档缓冲区生成 stem-doc-id

## 1 相关文档
- [dddd.md](dddd.md) - 任务文档模板
- [1104.md](1104.md) - 修复新建文档未写入 stem-doc-id 的问题
- [1131.md](1131.md) - 添加 stem 格式并全量迁移 plugins 下 .ts → .stem
- [1293.md](1293.md) - 草稿文件后缀放开为 .tmu 与 .stem 并导出样式包为 .stem 草稿
- [200_33.md](200_33.md) - stem-doc-id 自动备份标识机制说明

## 2 任务相关的代码文件
- `TeXmacs/progs/texmacs/texmacs/tm-files.scm` — 定义 `style-buffer?` 谓词;保存文件时统一调用 `auto-backup-sync-buffer-doc-id!`
- `TeXmacs/plugins/autosave/progs/autosave/plugin.scm` — `auto-backup-buffer-eligible?` 排除样式 buffer;新增 `auto-backup-clear-buffer-doc-id!` 与 `auto-backup-sync-buffer-doc-id!`(样式 buffer 清除、文档 buffer 补齐的策略收口);`auto-backup-buffer-doc-id` 对样式 buffer 返回 `#f`
- `TeXmacs/progs/texmacs/texmacs/tm-files-test.scm` — 单元测试:验证样式 buffer 与文档 buffer 判定,以及 `stem-doc-id` 生成与清除
- `TeXmacs/packages/customize/document/three-columns.ts`、`TeXmacs/plugins/bash/doc/bash.en.tmu` — 移除历史遗留误写入的 `stem-doc-id`

## 3 如何测试

### 3.1 单元测试
```bash
xmake b stem
xmake b tm-files-test && xmake r tm-files-test
```
预期:
1. `.ts` 文件被判定为样式 buffer(`style-buffer?` 为 `#t`),不具备自动备份与 `stem-doc-id` 绑定资格;
2. 实际为样式的 `.stem` 文件(包含 `source` 样式或样式声明标记)被判定为样式 buffer,不填入 `stem-doc-id`;
3. 作为普通文档的 `.stem` 文件(非 `source` 样式)被判定为文档 buffer,正常绑定 `stem-doc-id`;
4. 普通 `.tmu`/`.tm` 文档正常保持绑定 `stem-doc-id` 的行为;
5. 单元测试全部通过。

### 3.2 手动测试
1. 打开一个 `.ts` 样式文件或 `.stem` 样式包(如 `std.stem`),修改后保存:
- 检查保存后的文件内容,确认没有写入 `<associate|stem-doc-id|...>` 或 `(associate "stem-doc-id" ...)`.
2. 新建或打开一个 `.stem` 文档(如 `test.stem`,样式为 `generic` 或 `article`),修改后保存:
- 检查保存后的文件内容,确认包含 `stem-doc-id`.
3. 新建或打开普通 `.tmu` 文档并保存:
- 确认正常包含 `stem-doc-id`.

## 4 为什么(Why)
1. `stem-doc-id` 是用于文档追踪和自动备份的稳定唯一标识,仅应存在于文档缓冲区。
2. `.ts` 文件是 TeXmacs 样式文件,不属于文档;而 `.stem` 扩展名既可用于样式文件(作为 `.ts` 的 S-expression 继任格式),也可用于保存普通文档。
3. 此前 `auto-backup-buffer-eligible?` 仅依据格式 `in? '("texmacs" "stm" "tmu" "stem")` 进行判断,导致 `.ts` 以及实际上是样式的 `.stem` 在保存或触发自动备份时被误填入 `stem-doc-id`(例如 `three-columns.ts` 中就遗留了误写入的 doc id)。
4. 不能单纯依靠文件后缀区分样式与文档,需要根据缓冲区实际内容与样式属性(如是否具备 `source` 样式、是否包含宏包标记、是否关联样式包导出目标等)准确判定。

## 5 怎么做(How)
1. 在 `tm-files.scm` 中实现 `style-buffer?`:
- 识别 `.ts` 后缀;
- 识别通过「导出样式包」创建的关联草稿(`style-package-target-url`);
- 检查缓冲区是否具备 `source` 样式包(`has-style-package?`,读取 buffer 的样式环境);
- 检查缓冲区文档树首部是否包含 `src-title` / `src-package` / `src-style-file` 等样式文件特征标记(`body-has-source-markup?`)。
2. 在 `plugin.scm` 中:
- 将 `auto-backup-buffer-eligible?` 调整为要求 `(not (style-buffer? name))`;
- 实现 `auto-backup-clear-buffer-doc-id!`,在样式缓冲区保存时调用 `(init-default "stem-doc-id")` 重置环境中的 doc id;
- 新增 `auto-backup-sync-buffer-doc-id!`,把「样式 buffer 清除、文档 buffer 补齐」的策略收口到一处,各保存路径无条件调用;
- `auto-backup-buffer-doc-id` 对样式缓冲区直接返回 `#f`。
3. `tm-files.scm` 的 `save-buffer-save-file` 与 `plugin.scm` 的 `save-all-buffers` 均通过 `auto-backup-sync-buffer-doc-id!` 同步 doc id。
4. 清理 `three-columns.ts` 与 `bash.en.tmu` 中残留的 `stem-doc-id`。
5. 在 `tm-files-test.scm` 中增加针对样式判定与 doc id 行为的单元测试。
Loading