关于emacs-28的新选项dired-kill-when-opening-new-dired-buffer, 如何在分隔窗口时临时禁用。

如题,这个新选项不会生成大量的重复buffer,还是很有用的, 但是有一个例外。 我有时有一个频繁的操作,就是打开一个 dired buffer。 浏览一会, 然后比如在当前文件夹下建一个子文件,左右分隔视图把一部分父文件夹下的文件移动或复制到子文件夹中。

我一般使用:vs % 这个evil命令来做这个事情。

启用新选项之后带来的问题就是。这个操作现在不可能了。

只要在右侧打开子文件夹,左侧的父文件夹会被杀掉。

大家有什么好的思路来解决这个问题么,或者都是什么来进行这种文件操作的?

因为我注意到你前两天还在讨论 dirvish 的问题,所以我假定你目前还在使用 dirvish, 如果已经没有使用了你可以忽略我的回答。

dired 管理自己 buffers 的方式很粗暴, 唯一的相关选项 dired-kill-when-opening-new-dired-buffer 无论设置成 t 还是 nil 都有不可接受的副作用。我在这一楼详细说明过 这个问题。

dirvish 可以让你更直接地进行主题中描述的操作。

  1. 标记想复制或者剪切的文件 (dired-mark)
  2. 新建文件夹 (dired-create-directory)
  3. 进入这个文件夹 (dired-find-file)
  4. 把标记好的文件粘贴进来 (dirvish-yank, 加个 C-u 是剪贴,默 认是复制)
  5. 返回之前的目录 (dirvish-other-buffer)

第1步和第2步可以颠倒没影响。第5步可选,视情况而定。

当然你也可以分屏操作。用 dired-other-window 这个命令打开另一个 dirvish 会话,这两个会话相互独立,其余的操作和 dired 一样。我自己自从用了 dirvish 以后从不这么操作,因为没有上面描述的有效率。

感谢回复,我起初只是想用dirvish代替neotree, 而且比较尴尬的是,上次请教过几个问题之后,还是有不少问题没有解决,我就想先用回dired。

如果dired那个管理buffer的问题是比较本质的问题的话,还可以继续试图把dirvish的几个配置都解决掉。同时彻底的把dired也代替掉。

我试了一下,如果开启用dirvish代替dired,在这个使用场景下, 有几个问题。

操作流程.

  1. 打开一个文件 config.el
  2. \ e x(自定义evil快捷键)进入 当前目录的dirvish.
  3. :vs % 这时右侧窗口配置的是仍然是config.el的分屏, 即不是光标当下选中的文件分屏,也不是当前复制的 dirvish分屏。

这是因为 :vs %的buffer列表中没有 dirvish是么?

(defun dired--find-possibly-alternative-file@dont-kill-split-buffer (&rest args)
  "Advice around original function with ARGS to avoid killing the split buffer."
  (let ((dired-kill-when-opening-new-dired-buffer
         (and dired-kill-when-opening-new-dired-buffer
              (not (memq (current-buffer)
                         (mapcar #'window-buffer
                                 (remove
                                  (get-buffer-window (current-buffer))
                                  (window-list))))))))
    (apply args)))

(advice-add 'dired--find-possibly-alternative-file
            :around 'dired--find-possibly-alternative-file@dont-kill-split-buffer)
3 个赞

试了一下,太棒了。感激!

向上游提交一下?我感觉跟 dired-dwim-target 有点相像,都是改善在使用 2 个窗口时的行为。

1 个赞

有一家餐厅,菜做的不错,但是有个破毛病: 它要求顾客吃完以后自己收拾饭桌。这当然很烦,于是越来越多顾客要求餐厅改规矩。餐厅给出了一个方案: 顾客可以选择一个很小的桌子,只放得下一个盘子。即使你点了 10 个菜,面前永远就一盘,每次要换菜,就做盘新的把你面前这盘换掉。餐厅说这样你收拾桌子就方便多了。

dired 就是这家餐厅,dired-kill-when-opening-new-dired-buffer 和相关的函数就是小桌方案。

许多不想收拾桌子的顾客选择了小桌方案,餐厅却接到了许多新的抱怨。

  • 顾客A: 我刚那盘菜加了很多辣椒调味,怎么端上来一盘新的? (文件标记等状态丢失)
  • 顾客B: 我点的火锅,小桌子放了锅,我要另一个小桌子放食材 (主帖所描述的双屏操作)。
  • 顾客C: 佛跳墙每次等太久了,能不能别不停的重新做 (远程目录,大目录)。 …

我一开始也是写了和 @twlzOne 功能差不多的东西,但是使用中不断发现问题,于是涂涂改改 kill buffer 的条件,最终变得无比丑陋。因此我认定这种随用随杀的方式是一个错误思路,就和小桌子一样。这问题应该怎么解决呢? 当然是餐厅把自己那个破毛病改了: 顾客用餐结束后,餐厅负责收拾饭桌。

1 个赞

同意,似乎是这么个理,杀掉会带来很多副作用。不过dired buffer不断增加使用起来也是很不爽。

我很少用 dired,不知道这样处理是否合适。

把多余的 dired buffer 隐藏起来,眼不见为净。

可以考虑写个 dired buffer ring,不知道是不是已经有现成的包。

何不换一个思路,你之所以希望保留两个dired窗口(A和B),是因为dired (A) 中在执行Copy/Rename 等操作时,如果发现另一个窗口(B)也是dired-mode,那么它会优先以B为target ,从而方便的实现两个目录间copy/rename.

但利用 GitHub - karthink/consult-dir: Insert paths into the minibuffer prompt in Emacs 这个package 再加额外的一些配置,可以实现记住你最近访问过的directory, 然后方便的从列表中选择你最近访问过的directory, 不过consult-dir 有几个小问题

  1. 它记录recent dir 是使用recentf 这个内置包实现的,recentf-mode 只能记录file列表,然后以file所在的目录作为candidates 如果你单纯在dired 里访问,它并不会记住,我在这个issue里有提到 it seems a dired buffer is not added to recentf-list,any plan to support directory visited by dired-mode · Issue #17 · karthink/consult-dir · GitHub 并提供了解决方案, 大家可以copy 过去(如果作者不想实现的话)
(setq-default consult-dir-sources
              '(consult-dir--source-dired
                consult-dir--source-default
                consult-dir--source-project
                consult-dir--source-recentf
                consult-dir--source-bookmark))
(define-key minibuffer-local-completion-map (kbd "C-M-s-j") #'consult-dir)
(define-key minibuffer-local-completion-map (kbd "C-M-s-l") #'consult-dir-jump-file) ;locate
(define-key global-map (kbd "C-x d") #'consult-dir)
(define-key dired-mode-map (kbd ",") #'consult-dir)
(setq consult-dir-shadow-filenames nil)
;;使用dired 打开candidate 而不是默认的find-file
(setq consult-dir-default-command #'(lambda () (interactive)(dired default-directory)))

我之前也用helm/ivy 实现了相应的版本,转到consult 之后,发现已经有人实现了功能类似的 consult-dir了,如果你是consult/helm/ivy 的用户的话,可以研究下 适不适全你 GitHub - jixiuf/ivy-dired-history GitHub - jixiuf/helm-dired-history: show dired histories you have visited on emacs.

1 个赞

感谢你这样坦诚的安利, 我作为一个小白,刚开始用dirvish的时候眼前一亮,觉得它速度快体验也更现代一些,不过当时用的时候有很多问题,一直没转过去。这几天一点点的它已经趋于完善。目前似乎已经完全可以把dired和neotree替代掉了。我今天再试一试。

同时你也提到开源社区中的一个挺重要的问题,大家觉得这种文化好在于,都会基于一个共同的base代码做修改,于是很快这个base就可以变得功能完备同时极富可定制性。但是如果这个base有一些比较内生的问题的话,这可能反倒是个拖累。这个问题比较大,我还没有能力去评价dired的设计好坏。只是联想到vim和neovim,同时也感慨一下 。

1 个赞

感觉这个问题跟浏览器的 Tab 页有点类似,很可能加个 N 分钟没有访问且 Dired Buffer 没有 MARK 项则自动关闭会是一个很实用的设定

dired主要的问题是,它内部没有当前文件的结构体,比如一个文件的名称、路径、修改时间、权限和标记状态等。

正常的实现是,这些值都应该是每个文件对象的属性,所有文件的操作基于文件对象和属性进行逻辑处理,同时文件管理器的界面布局应该和文件对象是解偶的。

但是整个 dired 生态都是基于文本的正则表达式 hacking, 不管是逻辑功能还是界面布局都是一大堆正则表达式搜索、匹配和替换,每个基于dired的插件本身还有自己的正则表达式,很难保证两个 dired 插件的代码不会相互干扰和冲突,这种冲突会随着用户加载 dired 插件数量增多而更加复杂,甚至 dired 插件的作者也很难解决,因为他不知道用户端还装了哪些 dired 插件。

dired 要修复这些问题,需要基于库的形式读取文件各维度信息,文件逻辑处理和界面布局代码要完全分开,这个基本上就是要重写 dired, 所以我最后删除了所有 dired 插件,自己重写了 EAF File Manager.

3 个赞