以树状图展示 Git 项目

我一直不太清楚怎么像 tree(1) 那样画目录结构,今天上午发现了一个专门处理树状结构数据的库:

我用它以树状图的方式展示 Git 项目,比如我的 Emacs 配置:

(上图中的 lisp 目录被我折叠了,因为其下的文件太多了,不方便截图)

代码

(defun chunyang-git-tree ()
  (interactive)
  (require 'hierarchy)
  (let ((files (split-string
                (shell-command-to-string "git ls-files -z")
                (string 0) t))
        (hierarchy (hierarchy-new)))
    ;; Fill the hierarchy
    (hierarchy-add-trees
     hierarchy
     ;; Set . as the root since tree-widget.el requires only one root
     (mapcar (lambda (f) (concat "./" f)) files)
     (lambda (f)
       "Return parent directory of F."
       (if (directory-name-p f)
           (file-name-directory (directory-file-name f))
         (file-name-directory f))))
    ;; Draw the hierarchy
    (switch-to-buffer
     (hierarchy-tree-display
      hierarchy
      (lambda (f _)
        "Insert basename of F."
        (insert
         (if (directory-name-p f)
             (file-name-nondirectory (directory-file-name f))
           (file-name-nondirectory f))))))
    ;; Unfold
    (goto-char (point-min))
    (while (progn (widget-button-press (point))
                  (widget-forward 1)
                  (/= (point) (point-min))))))

目前的实现就是这样,但还有不少值得改进的地方,比如:

  • 一个 Git 项目对应一个独立 Buffer
  • 用 Side Window 展示这个 Buffer,像 IDE 那样
  • 设置 Tree Widget 中的 Action,即打开文件
  • 排序(上图中貌似正好是倒着排的)
5 个赞