如何快速浏览Emacs中的大量文件?

时间:2013-11-11 13:46:07

标签: emacs dired

有没有办法快速浏览Emacs(24.3)中的大量文件?更具体地说:

让我们假设一个Emacs框架被分成两个窗口。假设焦点位于左侧窗口中,该窗口具有打开的“dired”缓冲区,其中包含大量文本文件(或代码)。我想在文件列表中上下移动(例如使用光标键),同时当前文件显示在右侧窗口中。更好的是,只有当我将dired缓冲区移动到下一个文件时,文件才会被查看和关闭。这将非常有用,特别是与某些“省略”模式一起使用。

这可以在'dired'中完成吗?我也无法在dired-x或者日出指挥官中找到这个功能。有可能吗?

我尝试过的最佳候选人(以及为什么他们没有解决问题):

'v'显示当前文件,但也引起注意

'C-o'显示当前文件,但在向上或向下移动后,我必须再次按C-o,它还会生成大量缓冲区

非常感谢你的帮助!

6 个答案:

答案 0 :(得分:4)

非常感谢所有这些答案。总结我创建了以下解决方案(扩展了“abo-abo”的答案):

;; little modification to dired-mode that let's you browse through lots of files
(add-hook 'dired-mode-hook
  (lambda()
    (define-key dired-mode-map (kbd "C-o") 'dired-view-current)     ; was dired-display-file
    (define-key dired-mode-map (kbd "n")   'dired-view-next)           ; was dired-next-line
    (define-key dired-mode-map (kbd "p")   'dired-view-previous))) ; was dired-previous-line

(defun dired-view-next ()
  "Move down one line and view the current file in another window."
  (interactive)
  (dired-next-line)
  (dired-view-current))

(defun dired-view-previous ()
  "Move up one line and view the current file in another window."
  (interactive)
  (dired-previous-line)
  (dired-view-current))

(defun dired-view-current ()
  "View the current file in another window (possibly newly created)."
  (interactive)
  (if (not (window-parent))
      (split-window))                                   ; create a new window if necessary
  (let ((file (dired-get-file-for-visit))
        (dbuffer (current-buffer)))
    (other-window 1)                                          ; switch to the other window
    (unless (equal dbuffer (current-buffer))                 ; don't kill the dired buffer
      (if (or view-mode (equal major-mode 'dired-mode))   ; only if in view- or dired-mode
          (kill-buffer)))                                                    ; ... kill it
    (let ((filebuffer (get-file-buffer file)))
      (if filebuffer                              ; does a buffer already look at the file
          (switch-to-buffer filebuffer)                                    ; simply switch 
        (view-file file))                                                    ; ... view it
      (other-window -1))))                   ; give the attention back to the dired buffer

更改了三个键:

  1. C-o查看另一个窗口中的当前项目(可能创建一个)。
  2. n查看另一个窗口中的下一个项目。
  3. p查看另一个窗口中的上一个项目。
  4. 这可以在dired缓冲区中使用。请注意,只有dired-mode缓冲区和视图模式缓冲区在向上和向下移动时被杀死。如果显示另一个缓冲区正在访问的文件(不在视图模式下),则也会显示该缓冲区,但在移动到下一个缓冲区时不会被杀死。另一个细微之处在于,被动显示的缓冲区是用于遍历列表的dired缓冲区(当进入具有RET的文件夹时,这很容易发生)。为了处理这种情况,我们首先检查是否正在尝试终止初始的dired缓冲区。

答案 1 :(得分:3)

以下是我使用view-mode执行此操作的方法:

(add-hook 'view-mode-hook
      (lambda()
        (define-key view-mode-map (kbd "n") 'dired-view-next)
        (define-key view-mode-map (kbd "p") 'dired-view-prev)))

(defun dired-view-next ()
  "Move to next dired line and view ."
  (interactive)
  (quit-window)
  (dired-next-line 1)
  (dired-view-file))

(defun dired-view-prev ()
  "Move to next dired line and view ."
  (interactive)
  (quit-window)
  (dired-next-line -1)
  (dired-view-file))

UPD:

这个有两个窗格:

(defun dired-view-next-pane ()
  (interactive)
  (other-window 1)
  (if view-mode
      (kill-buffer))
  (other-window -1)
  (dired-next-line 1)
  (view-file-other-window
   (dired-get-file-for-visit))
  (other-window -1))

答案 2 :(得分:2)

  1. 加载Icicles

  2. 定义此命令:

  3.     (defun my-find-file ()
          "Like `icicle-find-file', but alt action views file temporarily.
        Alternate action keys such as `C-S-down' visit the candidate file in
        `view-mode' and kill the buffer of the last such viewed candidate."
          (interactive)
          (let ((icicle-candidate-alt-action-fn
                 (lambda (file)
                   (when (and my-last-viewed
                              (get-file-buffer my-last-viewed))
                     (kill-buffer (get-file-buffer my-last-viewed)))
                   (setq my-last-viewed  (abbreviate-file-name file))
                   (view-file file)
                   (select-frame-set-input-focus
                      (window-frame (active-minibuffer-window))))))
            (icicle-find-file-of-content)))
    
        (defvar my-last-viewed nil
          "Last file viewed by alternate action of `my-find-file'.")
    

    然后你可以:

    1. 使用M-x my-find-file(或将其绑定到密钥 - 例如C-x C-f)。
    2. (可选)键入文件名的一部分,以限制匹配的名称。
    3. (可选)使用downup在文件名之间循环。
    4. 使用C-S-down按顺序访问下一个文件。
    5. 重复#4按顺序查看其他文件。
    6. 重复#2或#3以查看其他文件集。
    7. RET结束,选择要访问的文件或C-g取消。
    8. 您使用C-S-down访问的每个文件缓冲区都被您杀死了 看了下一个。您也可以将C-downC-RET混合到一起 还访问您不想杀死其缓冲区的文件 自动。 (如果不这样做,请将view-file更改为find-file 想要访问view-mode,这是只读的。)

      [默认情况下,icicle-find-file的备用操作是 icicle-alt-act-fn-for-type,提示您输入文件 - 适用于所选择的特定候选人的适当行动 那个行动。命令my-find-file只是替代不同的 备用动作功能(适用于您选择的所有候选人)。]

      另见help-gnu-emacs@gnu.org中的this thread。我认为这与你的问题差不多。 My replies与我的回复几乎相同,但也有其他人的回复也可能对您有所帮助。

答案 3 :(得分:1)

尝试

M-x speedbar

这可能会吸引你

答案 4 :(得分:1)

一个简单而通用(虽然不是最佳)解决方案可以通过 C-x()机制。

首先打开Emacs中的两个窗格,其中一个是 dired

  • o 打开2 nd 窗格中的第一个文件。

然后你可以启动重复机制:

  • 执行 C-x(开始录制宏
  • 执行 C-x k 返回以关闭缓冲区
  • 再次 o 返回 dired
  • 执行 down 键转到下一个文件
  • 执行 o 打开底部窗格中的下一个文件
  • 执行 C-x)以结束宏

从那时起(在底部窗格中, dired 在顶部窗格中),仅仅做

  • C-x e (如果之间没有其他操作,则只有 e

会自动

  • 关闭底部窗格文件,转到顶部窗格,向下到下一个文件,在底部窗格中打开它

有一种更具体的方法可以做到这一点,但是知道宏机制在Emacs中无论如何都非常有用。

答案 5 :(得分:0)

另一种基于ag模式列表的视图模式解决方案。我无法找到ag模式的问题,也许这有助于某人为任何模式推广ffap预览。

(defun directory-ag-results ()
  (save-excursion
    (goto-char (point-min))
    (search-forward "\"")
    (setq a (point))
    (search-forward "\"")
    (setq b (- (point) 1))
    (buffer-substring-no-properties a b)))

(defun search-item-path ()
  (let ((dir (directory-ag-results))
        (file-parts (split-string (substring-no-properties (thing-at-point 'filename)) ":")))
    (concat dir (nth 0 file-parts))))

(defun search-item-line ()
  (let ((file-parts (split-string (substring-no-properties (thing-at-point 'filename)) ":")))
    (- (string-to-number (nth 1 file-parts)) 1)))

(defun view-current ()
  "Quickly view the current file in another window."
  (if (not (window-parent))
      (split-window))                        ; create a new window if necessary
  (let ((file (search-item-path))
        (line (search-item-line))
        (dbuffer (current-buffer)))
    (other-window 1)                         ; switch to the other window
    (unless (equal dbuffer (current-buffer)) ; don't kill the dired buffer
      (if (or view-mode (equal major-mode 'dired-mode)) ; only if in view- or dired-mode
          (kill-buffer)))                               ; ... kill it
    (let ((filebuffer (get-file-buffer file)))
     (if filebuffer                     ; does a buffer already look at the file
          (switch-to-buffer filebuffer) ; simply switch
        (progn
          (view-file file)              ; ... view it
          (goto-char (point-min))
          (next-line line)))
      (other-window -1))))

(defun next-view-current ()
  (interactive)
  (next-line)
  (view-current))
(defun previous-view-current ()
  (interactive)
  (previous-line)
  (view-current))

(define-key ag-mode-map (kbd "M-p") 'previous-view-current)
(define-key ag-mode-map (kbd "M-n") 'next-view-current)

这是我认为Sublime比Emacs更好的 one 。亵渎,我知道!我喜欢视图模式的“q退出”感觉,而不是基于计时器的解决方案,以及滚动预览文件。此代码段会导航到搜索结果中找到的行号,以优化浏览速度。

关于代码的注意事项:我尝试从Emacs 25中填充vc-root-dir,但它对ag模式没有意义,因为ag-mode的缓冲区在你正在搜索的repo之外。我最终了从“ag搜索”缓冲区的顶部拉出根目录。

早期阶段。欢迎改进。

Demo

编辑:它适用于ag模式,而不是直接模式。演示gif。

致谢:abo-abo,user2979331