更新
表项覆盖;构建时间嵌入(附带更新)。
1 表项覆盖
在使用的过程中,常常会遇到这种场景[S]:个别文本块需要更新,进而联动到复制一份映射表,然后更新映射表中的 “个别” 表项。同样地,为了减少更新量,我们期望能够复用先前的映射表,或者说,在先前映射表的基础上,覆盖掉个别需要更新的表项。
原先 org-id-remap
的调用设计是为了实现一对多映射,即某个 id 存在多条映射链接(出于数据冗余考虑),具体来说:
映射表:
(org-id-remap
"id1" "link1"
"id1" "link2"
"id1" "link3")
可以让我们具有多份 id1 的映射,以便某个 link 损毁的情况下能使用其他 links.
现在,场景[S]对映射表提出了另一种需求:同一 id 不同版本。
为此,最简单且直观的实现方式为:新增一个特性,使得 “每次” 调用 org-id-remap
建立表项时,覆盖已存在的表项。具体来说:
某次调用:
(org-id-remap
"id1" "link1"
"id1" "link2"
"id2" "link3"
"id3" "link4")
后跟有调用:
(org-id-remap
"id2" "link6"
"id2" "link5")
此时,旧的 id2 将被覆盖,即当前映射表为:
id1->{link1,link2}, id2->{link5,link6}, id3->{link4}
.
实现
分裂 cmd-impl, 剥离 set-mapping.
#+name: 2025-07-25-21-30
#+begin_src emacs-lisp :eval no
(!def enable?
(lambda ()
(get remap 'org-link-abbrev-safe)))
(!def enable
(lambda ()
(put remap 'org-link-abbrev-safe t)
(setf (alist-get
"id" org-link-abbrev-alist
nil nil #'equal)
remap)
(push `(t . ,open-file-link)
org-file-apps)
(add-hook
'org-execute-file-search-functions
search)
(message "Org ID remap enable.")))
(!def disable
(lambda ()
(put remap 'org-link-abbrev-safe nil)
(setq org-link-abbrev-alist
(assoc-delete-all
"id" org-link-abbrev-alist
#'equal))
(setq org-file-apps
(seq-filter
(lambda (it)
(not
(equal
it `(t . ,open-file-link))))
org-file-apps))
(remove-hook
'org-execute-file-search-functions
search)
(message "Org ID remap disable.")))
(!def reset
(lambda ()
(clrhash mapping)
(message "Org ID mapping reset.")))
<<@([[id:org-id-remap::set-mapping]])>>
(!def get-mapping
(lambda ()
(!let (r)
(maphash
(lambda (k vs)
(mapc
(lambda (v) (push (list k v) r)) vs))
mapping)
(flatten-list r))))
#+end_src
更新 set-mapping. 实现旧表项覆盖。
#+name: 2025-07-25-21-31
#+begin_src emacs-lisp :eval no
(!def set-mapping
(lambda (mappings)
(let ((mappings
(seq-partition mappings 2)))
;; 覆盖已有的映射表项,以用新表项变更文本版本。
(mapcar
(lambda (kv)
(setf (gethash (car kv) mapping) nil))
mappings)
;; 建立映射。
(mapcar
(lambda (kv)
(let ((k (car kv)) (v (cadr kv)))
(unless
(member v (gethash k mapping))
(push v (gethash k mapping)))))
mappings))))
#+end_src
2 构建时间嵌入(附带更新)
新增 build-time 命令,以识别不同的 build.
#+name: 2025-07-25-21-32
#+begin_src emacs-lisp :results silent
(format-time-string "%FT%T%z")
#+end_src
:2025-07-25-21-33:
将 Org ID 链接重映射为其他链接。
重映射仅在“打开链接”的上下文中有效。
零参时, toggle org-id-remap.
单参时:
'reset 重置重映射;
'enable? 查询使能情况;
nil 禁用重映射;其他使能。
其他情况时,建立 id 映射,调用形式如下:
(org-id-remap
\"id1\" \"id:real-target1\"
\"id2\" \"id:real-target2\"
...)
:end:
#+name: 2025-07-25-21-34
#+begin_src emacs-lisp :eval no
(lambda (&rest args)
"Org ID 重映射。
<<@([[id:org-id-remap::cmd-doc]],rm-ws-p=1)>>"
(interactive)
(declare (indent 0))
(cond
((length= args 0)
(if (enable?) (disable) (enable)))
((length= args 1)
(setq args (car args))
(cond
((eq 'enable? args) (enable?))
((eq 'reset args) (reset))
((eq 'get-mapping args) (get-mapping))
((eq 'build-time args)
"<<2025-07-25-21-32()>>")
((null args) (disable))
(t (enable))))
(t (set-mapping args))))
#+end_src
构建配置
映射表:
#+name: 2025-07-25-21-38
#+begin_src emacs-lisp :eval no
"org-id-remap::cmd-impl"
"emacs-china/org-id-remap:29814::2025-07-25-21-30"
"org-id-remap::set-mapping"
"emacs-china/org-id-remap:29814::2025-07-25-21-31"
"org-id-remap::cmd-entry"
"emacs-china/org-id-remap:29814::2025-07-25-21-34"
"org-id-remap::cmd-doc"
"emacs-china/org-id-remap:29814::2025-07-25-21-33"
;; 未变更部分
"org-id-remap::org-id-remap"
"emacs-china/org-id-remap:29814::2025-07-25-20-48"
"org-id-remap::link-verify"
"emacs-china/org-id-remap:29814::2025-07-25-20-49"
"org-id-remap::drawer-search"
"emacs-china/org-id-remap:29814::2025-07-25-20-50"
"org-id-remap::open-file-link"
"emacs-china/org-id-remap:29814::2025-07-25-20-51"
"org-id-remap::remap"
"emacs-china/org-id-remap:29814::2025-07-25-20-52"
"org-id-remap::remap-sort-links"
"emacs-china/org-id-remap:29814::2025-07-25-20-53"
"org-id-remap::cache-http-link"
"emacs-china/org-id-remap:29814::cache-http-link"
"org-id-remap::cmd-set"
"emacs-china/org-id-remap:29814::cmd-set"
"org-id-remap::log"
"emacs-china/org-id-remap:29814::log"
"org-id-remap::private"
"emacs-china/org-id-remap:29814::private"
#+end_src
Eval 及 Tangle入口
#+name: 2025-07-25-21-36
#+begin_src emacs-lisp :eval no
(org-id-remap
"org-id-remap::2025-07-25-21-38"
"https://emacs-china.org/t/org-id-remap/29814::2025-07-25-21-38"
)
#+end_src
#+name: 2025-07-25-21-37
#+header: :depend (org-sbe "2025-07-25-21-36" ":eval yes")
#+header: :depend (org-id-remap t)
#+begin_src emacs-lisp :results silent :noweb yes
(org-id-remap 'reset)
(org-id-remap
<<@([[id:org-id-remap::2025-07-25-21-38]])>>
)
(org-with-wide-buffer (org-sbe "2025-07-25-20-39" ":eval yes"))
#+end_src