扩展类型
由于 Org element API 只能处理特定的元素类型, 当我们想隐藏位于 heading 的 tags 时, Org element API 无该元素类型的定义。为此,org-visibility 提供了可自定义元素类型的接口,这些元素类型被称为扩展类型。
内置扩展类型: tags, drawer-delimiter, sharp-line, headline-star, logbook, meta&mark, xtype.
xtype: tags
#+name: 2025-07-26-20-22
#+begin_src emacs-lisp :eval no
(lambda (&optional ele)
(cond
(ele
(save-excursion
(save-match-data
(goto-char (org-element-begin ele))
(forward-line 0)
(when (re-search-forward
org-tag-group-re
(line-end-position) t)
`((;; 1+: 留一个空格编辑用
,(1+
(- (point)
(length (match-string 0))))
,(point)))))))
(t '(tags headline))))
#+end_src
xtype: drawer-delimiter
诸如 :DRAWERNAME:, :END: 之类的元素。
#+name: 2025-07-26-20-23
#+begin_src emacs-lisp :eval no
(lambda (&optional ele)
(cond
(ele
(let (regions)
(save-excursion
(goto-char (org-element-begin ele))
(org-fold-hide-drawer-toggle 'off)
(push
`(,(point) ,(1+ (line-end-position)))
regions)
<<@([[id:org-visibility::drawer-delimiter-xtype--end]])>>
(nreverse regions))))
(t '(drawer-delimiter drawer))))
#+end_src
xtype: drawer-delimiter 之 drawer-delimiter-xtype–end
#+name: 2025-08-24-23-35
#+begin_src emacs-lisp :eval no
(if (org-element-contents-end ele)
(goto-char
(org-element-contents-end ele))
(forward-line))
;; :end: 隐藏时不含换行符。
(goto-char (line-end-position))
(push `(,(line-beginning-position)
,(min
(+ (line-end-position)
(if (looking-at-p "\n[^\n]")
0 1))
(point-max)))
regions)
#+end_src
xtype: sharp-line
诸如 #+begin_src, #+end_src, #+header 等 # 打头的行。
#+name: 2025-07-26-20-24
#+begin_src emacs-lisp :eval no
(lambda (&optional ele)
(cond
(ele
(let* ((beg (org-element-begin ele))
(end (org-element-end ele))
(line "")
(regions nil))
(save-excursion
(goto-char beg)
(save-match-data
(while (re-search-forward
"^#.*$" end t)
(setq line (match-string 0))
(save-excursion
(ignore-errors
(org-fold-hide-block-toggle
'off)))
(goto-char (line-end-position))
<<@([[id:org-visibility::sharp-line-xtype--add-region]])>>)))
(nreverse regions)))
(t '(sharp-line
<<@([[id:org-visibility::sharp-line-xtype--parents]])>>))))
#+end_src
xtype: sharp-line 之 sharp-line-xtype–end
#+name: 2025-08-24-23-37
#+begin_src emacs-lisp :eval no
(push
`(,(line-beginning-position)
,(min
(+ (line-end-position)
;; 若 #+end_ 后无空行
;; 我们不吞其换行符。
(if (and
(string-match-p
"#[+]end[:_]" line)
(looking-at-p "\n[^\n]"))
0 1))
(point-max)))
regions)
#+end_src
xtype: sharp-line 之 sharp-line-xtype–parents
#+name: 2025-08-24-23-38
#+begin_src emacs-lisp :eval no
src-block dynamic-block
comment comment-block example-block
table fixed-width keyword babel-call
#+end_src
xtype: headline-star
Org 标题前的星号。
#+name: 2025-08-24-23-40
#+begin_src emacs-lisp :eval no
(lambda (&optional ele)
(cond
(ele
(save-excursion
(save-match-data
(goto-char (org-element-begin ele))
(forward-line 0)
(when (re-search-forward
org-heading-regexp
(line-end-position) t)
`((,(line-beginning-position)
,(+
1 (line-beginning-position)
(length (match-string 1)))))))))
(t '(headline-star headline))))
#+end_src
xtype: logbook
整个 LOGBOOK drawer.
#+name: 2025-08-24-23-41
#+begin_src emacs-lisp :eval no
(lambda (&optional ele)
(cond
(ele
(when (member-ignore-case
(org-element-property :drawer-name ele)
'("LOGBOOK"))
`((,(org-element-begin ele)
,(org-element-end ele)))))
(t '(logbook drawer))))
#+end_src
xtype: meta&mark
#+name: 2025-08-24-23-42
#+begin_src emacs-lisp :eval no
'(meta&mark property-drawer timestamp logbook
xtype)
#+end_src