扩展类型
由于 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