Dirvish: 基于 Dired 的极简、一站式文件管理器

使用 dirvish-side :如果想最大化文件窗口,一般是最大化当前窗口,但保留side window。treemacs默认是该中行为,也是最合理的行为

你这里说的最大化命令是什么? 是说的 dirvish-toggle-fullscreen 吗?

  1. 使用 dirvish :用 ace-window 切换,默认配置下所有窗口都可被选择(如下图)。这个模式下我其实关心的就三个窗口,能快捷切换最实用,比如 M-1 M-2 M-3…

欸 好奇怪,为什么我的ace-window就直接到预览窗口了,我看看我的配置

side window 可以设置大小的 dirvish-side-display-alist

我的意思是用C-x 1

刚看到上面有个老哥在问exa预览的问题,想问下对目录为何不直接用dired buffer来显示呢?ranger好像是这么操作的。似乎这样使用dired更纯粹呀 :joy:

因为包括 exa 在内的所有文本型预览命令都是异步的,文件夹再大预览也不会卡。如果你当前目录有很多大文件夹,用 dired 直接预览没有 exa 的跟手。如果确保不会遇到大文件夹的场景 可以把 directory-exa 这个策略关了,就默认用 dired 预览了。

之所以默认 exa 就是考虑到用户会遇到这种情况,一看开预览很卡,就不用了。

我明白你的意思了, 你是说希望 side window 常驻不受 delete-other-windows 的影响是吧

很赞并且很实用的模块,我已经离不开了,在另一个帖子里也在安利dirvish哈哈,没想到竟然是论坛里的大佬做的

不敢当不敢当,非常感谢你的安利,吹的都有点过头了哈哈

对的,你理解到了。

顺便报个bug:Invalid face attribute :inherit (mode-line-active)。看了下是dirvish-core.el Line 53 有问题。

这个已经修了,你更新到最新的应该就好了

现在 dirvish-side 应该不会被 delete-other-windows 关掉了。

另外 ace-window 的问题,是因为我一直用的 ace-select-window, 这个命令是尊重 window 的 no-other-window 参数的,但是 ace-window 不会。

dirvish 会打开好多buffer。。。 buffer不能复用么? 我预览了一下我的项目后,发现打开好多buffer

其实 README 里面有写 Dirvish 的 buffer 管理机制,但是我还是详细说一下,因为你对 Dired 的 buffer 复用可能有一些误解。

Dired

Dired 的默认情况是每访问一个路径就新开一个 Dired buffer,如果重复访问某个路径,就会 复用 已经存在的 Dired buffer,这是合理的。可是要命的是这些 buffer 不会自己关掉。你要退出要不停的按 q

对这个问题 Dired 给出了 dired-kill-when-opening-new-dired-buffer (> Emacs 28) 这个选项和 dired-find-alternate-file 这个命令,意思是访问新路径时杀掉当前窗口的旧 Dired buffer,来保证你浏览文件系统的过程中只有一个 Dired buffer 存在。

不过请注意这恰恰破坏了 Dired 原本的 复用 机制。假设你在 ~/foo/bar 展开了一些文件夹,标记了一些文件,当你 dired-up-directory~/foo, ~/foo/bar 就被杀掉了。你再进去,这些标记和折叠状态就没了。如果 ~/foo/bar 是一个很大的文件夹 (比如包含 100000 个文件打开要 2 秒),那你每次访问,每次都要等 2 秒。

Dirvish

Dirvish 是以会话 (session) 的形式存在的。每一个会话包含自己独立的 dirvish-mode buffer 列表,它不会在访问新路径时杀掉旧的 buffer,所以复用机制和 Dired 在不开 dired-kill-when-opening-new-dired-buffer 这个选项的情况时是一致的。 不同的是当你按 q 退出这个会话时,这些 dirvish-mode buffer 就被杀掉了,免去你一直按 q 的麻烦。预览 buffer 的情况也是类似的,按 q 的时候一起杀掉。你也可以利用外部命令来预览文本文件,从而完全避免预览 buffer 的创建,但这是另一个话题了。

Edit: 另外值得一说的是 doom-emacs 的解决办法,它就是在你按 q 的时候不管三七二十一把所有 Dired buffer 都杀掉。好处是简单粗暴,坏处是其他 window/tab/frame 里面的 Dired buffer 也会莫名其妙的被删掉。

我在 doom-emacs 里面,按 q 的时候是会调用它自定义的方法 +dired/quit-all ,有时候就会抛错:

Debugger entered--Lisp error: (wrong-type-argument dirvish nil)
  dirvish-deactivate(nil)
  dirvish-quit-h()
  funcall(dirvish-quit-h)
  (condition-case e (funcall hook) ((debug error) (signal 'doom-hook-error (list hook e))))
  doom-run-hook(dirvish-quit-h)
  run-hook-wrapped(doom-run-hook dirvish-quit-h)
  (condition-case e (run-hook-wrapped hook #'doom-run-hook) ((debug doom-hook-error) (if debug-on-error nil (lwarn hook :error "Error running hook %S because: %s" (if (symbolp (car (cdr e))) (symbol-name (car (cdr e))) (car (cdr e))) (car (cdr (cdr e))))) (signal 'doom-hook-error (cons hook (cdr e)))))
  (let ((hook (car --dolist-tail--))) (condition-case e (run-hook-wrapped hook #'doom-run-hook) ((debug doom-hook-error) (if debug-on-error nil (lwarn hook :error "Error running hook %S because: %s" (if (symbolp (car ...)) (symbol-name (car ...)) (car (cdr e))) (car (cdr (cdr e))))) (signal 'doom-hook-error (cons hook (cdr e))))) (setq --dolist-tail-- (cdr --dolist-tail--)))
  (while --dolist-tail-- (let ((hook (car --dolist-tail--))) (condition-case e (run-hook-wrapped hook #'doom-run-hook) ((debug doom-hook-error) (if debug-on-error nil (lwarn hook :error "Error running hook %S because: %s" (if (symbolp ...) (symbol-name ...) (car ...)) (car (cdr ...)))) (signal 'doom-hook-error (cons hook (cdr e))))) (setq --dolist-tail-- (cdr --dolist-tail--))))
  (let ((--dolist-tail-- hooks)) (while --dolist-tail-- (let ((hook (car --dolist-tail--))) (condition-case e (run-hook-wrapped hook #'doom-run-hook) ((debug doom-hook-error) (if debug-on-error nil (lwarn hook :error "Error running hook %S because: %s" (if ... ... ...) (car ...))) (signal 'doom-hook-error (cons hook (cdr e))))) (setq --dolist-tail-- (cdr --dolist-tail--)))))
  doom-run-hooks(quit-window-hook)
  apply(doom-run-hooks quit-window-hook)
  run-hooks(quit-window-hook)
  apply(run-hooks quit-window-hook)
  #<subr quit-window>(nil)
  apply(#<subr quit-window> nil)
  quit-window(nil)
  apply(quit-window nil)
  +dired/quit-all(nil)
  funcall-interactively(+dired/quit-all nil)
  command-execute(+dired/quit-all)

另外,我在 doom-one-dark 主题下,预览时的颜色不适配,这个怎么解:

这个问题我没遇到,你能稳定复现这个错误吗? 我试着修复了一下,你更新到最新看还会不会遇到这个问题

要么改这个颜色

(set-face-attribute 'ansi-color-blue nil :foreground "#FFFFFF") 

要么直接用 dired 预览

(setq dirvish-preview-dispatchers (remove 'directory-exa dirvish-preview-dispatchers))
1 个赞

好的,我再试试看能不能复现

何不考虑直接用ls或者gls预览?这样不会有exa的颜色问题

也行,我就是不知道 windows 上面怎么样。目前默认是 windows 直接 dired。

你有 windows 环境吗? 有的话帮我看看这个在windows上有没有问题,没什么问题我就把默认换成这个。谢了。

(dirvish-define-preview directory-ls (file)
  "Uses `ls' to generate directory preview."
  (when (file-directory-p file)
    `(shell . ("ls" ,@(split-string dired-listing-switches) "--color=always" ,file))))

(add-to-list 'dirvish-preview-dispatchers 'directory-ls)

我目前也没有用Windows。根据经验,windows上默认用dired是最好的,默认是没有ls的。

左侧是 treemacs 中光标所在行的背景色,怎么能也设置成这种呢,dirvish 这个背景一个是在 icon 哪里不连贯,再一个选中多个时候连成一片有点刺眼,和主题不太搭。

或者未选中的时候,没有颜色,选中的时候使用 dired 选中的样式: 光标在的时候:

选中行的时候:

你的 dirvish-attributes 的值是什么啊? 如果是 nil 的话,那你这个 icon 就不是 dirvish 提供的。

我这边打开是这样的。就 doom 默认配置加上这一行

(setq! dirvish-attributes '(all-the-icons file-size))

你这个好像是自己特殊配置过 all-the-icons-dired ?