[分享] 模仿ranger(lf)制作的简单org mode漫游方案

我想要像ranger一样漫游我的org mode中的outline。

具体来说,就是把每个outline看成一个文件夹。

“左” 回到上一级文件夹

“右” 进入下一级文件夹

“上” 浏览同级前一个文件夹

“下” 浏览同级后一个文件夹

并且,同时仅预览同一个文件夹下的内容。

我发现,实现起来非常简单(也就花了我俩小时吧)


(defun my/outline-left ()
  (interactive)
  (hide-subtree)
  (outline-up-heading 1)
  (hide-subtree)
  (outline-show-children)
  (outline-show-entry))

(defun my/outline-up ()
  (interactive)
  (hide-subtree)
  (outline-backward-same-level 1)
  (outline-show-children)
  (outline-show-entry))

(defun my/outline-down ()
  (interactive)
  (hide-subtree)
  (outline-forward-same-level 1)
  (outline-show-children)
  (outline-show-entry))

(defun my/outline-right ()
  (interactive)
  (if (outline-has-subheading-p)
      (progn  (outline-next-heading)
              (outline-show-children)
              (outline-show-entry))
      ))

你可以把这四个方程绑定到比如 C-h, C-j, C-k, C-l 上,然后你就能体验到惊人的效果!

因为太简单了,太有效了,我怀疑早就有人做过了,或者有类似的东西了。

5 个赞

“四个方程” :grin:

2 个赞

想起来了,这玩意儿在中文里应该叫函数不是 :thinking:

词本无意,意由境生 :grinning:

可以联立求解了是不是 :grin:

挺有意思的(不过印象中好像有个org包就是做这个事,也可能是记岔了x

效果不错,查看outline发现有个outline-minor-mode,开启后以C-c @为前辍,有以下可以用:

(defvar outline-mode-prefix-map
  (let ((map (make-sparse-keymap)))
    (define-key map "@" 'outline-mark-subtree)
    (define-key map "\C-n" 'outline-next-visible-heading)
    (define-key map "\C-p" 'outline-previous-visible-heading)
    (define-key map "\C-i" 'outline-show-children)
    (define-key map "\C-s" 'outline-show-subtree)
    (define-key map "\C-d" 'outline-hide-subtree)
    (define-key map "\C-u" 'outline-up-heading)
    (define-key map "\C-f" 'outline-forward-same-level)
    (define-key map "\C-b" 'outline-backward-same-level)
    (define-key map "\C-t" 'outline-hide-body)
    (define-key map "\C-a" 'outline-show-all)
    (define-key map "\C-c" 'outline-hide-entry)
    (define-key map "\C-e" 'outline-show-entry)
    (define-key map "\C-l" 'outline-hide-leaves)
    (define-key map "\C-k" 'outline-show-branches)
    (define-key map "\C-q" 'outline-hide-sublevels)
    (define-key map "\C-o" 'outline-hide-other)
    (define-key map "\C-^" 'outline-move-subtree-up)
    (define-key map "\C-v" 'outline-move-subtree-down)
    (define-key map [(control ?<)] 'outline-promote)
    (define-key map [(control ?>)] 'outline-demote)
    (define-key map "\C-m" 'outline-insert-heading)
    map))

可以试试这个

(defun org-current-heading-has-children-p ()
  (save-excursion
    (org-goto-first-child)))

;;;###autoload
(defun ded/org-show-next-heading-tidily ()
  "Show next entry, keeping other entries closed."
  (if (save-excursion (end-of-line) (outline-invisible-p))
      (progn (org-show-entry) (show-children))
    (outline-next-heading)
    (unless (and (bolp) (org-on-heading-p))
      (org-up-heading-safe)
      (outline-hide-subtree)
      (error "Boundary reached"))
    (org-overview)
    (org-reveal t)
    (org-show-entry)
    (org-show-children)
    (unless (org-current-heading-has-children-p)
      (org-with-wide-buffer
       (org-narrow-to-subtree)
       (org-display-inline-images t nil (point-min) (point-max))))
    (recenter-top-bottom 1)))

;;;###autoload
(defun ded/org-show-previous-heading-tidily ()
  "Show previous entry, keeping other entries closed."
  (let ((pos (point)))
    (outline-previous-heading)
    (unless (and (< (point) pos) (bolp) (org-on-heading-p))
      (goto-char pos)
      (outline-hide-subtree)
      (error "Boundary reached"))
    (org-overview)
    (org-reveal t)
    (org-show-entry)
    (show-children)
    (unless (org-current-heading-has-children-p)
      (org-with-wide-buffer
       (org-narrow-to-subtree)
       (org-display-inline-images t nil (point-min) (point-max))))
    (recenter-top-bottom 1)))

配合org-speed使用会更方便。

(setq org-speed-commands
      (append '(("n" . ded/org-show-next-heading-tidily)
                ("p" . ded/org-show-previous-heading-tidily))
			  org-speed-commands))
2 个赞