如何自定义 org roam node 排序

我用doom eamcs自定义的 doom-hierarchy 层级化显示 org roam node 列表,但是发现它如果在一个文件里有子标题也是节点的时候,会把最低层级的节点显示在最上面,而文件标题作为最高层级反而显示在最下面。

  (setq org-roam-node-display-template
        (format "%s %s ${doom-hierarchy:*} "
                (propertize "${doom-type:15}" 'face 'font-lock-keyword-face)
                (propertize "${doom-tags:30}" 'face '(:inherit org-tag :box nil))))

因此我想调整一下排序,根据 org-roam-node 源码,自己搞了如下定义,但没起作用,请教如何解决:

  (defun org-roam-node-read-sort-by-level (completion-a completion-b)
    "Sort nodes such that nodes with higher levels are shown first.
COMPLETION-A and COMPLETION-B are items in the form of
\(node-title org-roam-node-struct)."
    (let ((node-a (cdr completion-a))
          (node-b (cdr completion-b)))
      (< (org-roam-node-level node-a)
         (org-roam-node-level node-b))))

  (setq org-roam-node-default-sort 'level)

我试了 > < 不同方向,都不起作用

这个函数适用于补全时节点排序的,不是用于节点层级排序的

你要改的是 org-roam-node-doom-hierarchy 这个函数 参考 User contributed Tricks · org-roam/org-roam Wiki · GitHub[V2] [Feature Request] Show file/heading context of nodes · Issue #1565 · org-roam/org-roam · GitHub

照着 org-roam-node-hierarchy 写了一版

(cl-defmethod org-roam-node-reverse-hierarchy ((node org-roam-node))
  (let ((title (org-roam-node-title node))
        (filetitle (org-roam-node-file-title node))
        (olp (org-roam-node-olp node))
        (level (org-roam-node-level node)))
    (concat title
            (when (> level 1) (concat " < "  (string-join (nreverse olp) " < ")))
            (when (> level 0) (concat " < " filetitle)))))
1 个赞

doom 自定义的就是在这上面优化了一些界面显示。我试着新建了一个测试笔记文件,发现可以正序层次化显示。然后我又尝试重新建 roam db,结果一些笔记可以文件标题排前面,一些还是倒着的。

这个 work around 可行,多谢!

org-roam issue 中有大牛给了这个定义,看程序逻辑非常合理。但我还是没能用起来,是如下的 setq 方式不对吗?

  (defun org-roam-node-read-sort-by-mtime-level (completion-a completion-b)
    "Sort Org-roam nodes first by modification time, then by level if needed.

Arguments COMPLETION-A and COMPLETION-B are items in the form of
(NODE-TITLE . ORG-ROAM-NODE-STRUCT),
where ORG-ROAM-NODE-STRUCT is an instance of the `org-roam-node` struct.

Returns t if COMPLETION-A should come before COMPLETION-B, nil otherwise."
    (let* ((node-a (cdr completion-a))
           (node-b (cdr completion-b))
           (mtime-a (org-roam-node-file-mtime node-a))
           (mtime-b (org-roam-node-file-mtime node-b))
           (level-a (org-roam-node-level node-a))
           (level-b (org-roam-node-level node-b)))
      (cond
       ((time-less-p mtime-b mtime-a) t)
       ((equal mtime-a mtime-b) (> level-a level-b))
       (t nil))))
  (setq org-roam-node-default-sort 'mtime-level)