minibuffer里面的搜索结果如何二次过滤

使用projectile-rg搜索在整个项目里搜索字符串,显示的结果在一个minibuffer里面,如果结果特别多,比如驱动文件,按翻页都要按好久,有没有办法能够对搜索结果二次过滤,或者像vscode里面那样折叠成文件夹树,点击展开。 配置文件如下:

;; packages
(setq package-archives '(("gnu" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/gnu/")
                         ("melpa" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/melpa/")
                         ("nongnu" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/nongnu/")))
(package-initialize)
(setq package-check-signature nil)
(require 'package)
(unless (bound-and-true-p package--initialized)
  (package-initialize))
(unless package-archive-contents
  (package-refresh-contents))
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

;; global var
(defconst *is-mac* (eq system-type 'darwin))
(defconst *is-linux* (eq system-type 'gnu/linux))
(defconst *is-windows* (or (eq system-type 'ms-dos) (eq system-type 'windows-nt)))

;; global settings
(menu-bar-mode -1)
(tool-bar-mode -1)
;;(scroll-bar-mode -1)
(xterm-mouse-mode 1)
(mouse-wheel-mode 1)
(if (display-graphic-p) (scroll-bar-mode -1))
(setq menu-bar-open-mouse t)
(setq auto-save-default nil)
(setq make-backup-files nil)
(setq backup-directory-alist (quote ((".*" . "~/.emacs_backups/"))))
;;(setq blink-cursor-mode nil)
;;(setq mouse-wheel-progressive-speed t)
;;(setq mouse-wheel-scroll-amount 3)
(setq initial-major-mode 'text-mode)
(setq inhibit-startup-screen t)
(setq-default cursor-type 'box)
(setq initial-scratch-message "")
(setq use-package-always-ensure t)
(setq use-package-always-defer t)
(setq use-package-always-demand nil)
(setq use-package-expand-minimally t)
(delete-selection-mode)
(setq use-package-verbose t)
(setq newsticker-url-list-defaults nil)
(setq enable-recursive-minibuffers t)
;;(use-package doom-themes
;;  :ensure t
;;  :init (load-theme 'doom-gruvbox t))
(if (display-graphic-p)
    (load-theme 'modus-operandi t))
;;(setq max-mini-window-height 10)
;;(add-to-list 'default-frame-alist '(width . 120))
;;(add-to-list 'default-frame-alist '(height . 40))
;;(setq completion-category-overrides '((file (styles basic partial-completion))))
;;(add-to-list 'default-frame-alist '(fullscreen . maximized))
;;(modify-syntax-entry ?_ "w")
;;(setq dictionary-server "localhost")

;; dired
;;(setq dired-kill-when-opening-new-dired-buffer t)

;; buff map
(global-set-key (kbd "S-<left>") 'previous-buffer)
(global-set-key (kbd "S-<right>") 'next-buffer)

;; custom-file
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(when (file-exists-p custom-file)
  (load-file custom-file))

;; font
(when (eq system-type 'darwin)
  (setq fonts '("SF Mono" "冬青黑体简体中文"))
  (set-fontset-font t 'unicode "Apple Color Emoji" nil 'prepend)
  (set-face-attribute 'default nil :font
                      (format "%s:pixelsize=%d" (car fonts) 16)))

(when (eq system-type 'windows-nt)
  (setq fonts '("Consolas" "微软雅黑"))
  (set-fontset-font t 'unicode "Segoe UI Emoji" nil 'prepend)
  (set-face-attribute 'default nil :font
                      (format "%s:pixelsize=%d" (car fonts) 24)))

(when (eq system-type 'gnu/linux)
  (setq fonts '("Consolas" "FZLanTingHei-M-GBK"))
  (set-fontset-font t 'unicode "FZLanTingHei-M-GBK" nil 'prepend)
  (set-face-attribute 'default nil :font
                      (format "%s:pixelsize=%d" (car fonts) 16)))

(if (display-graphic-p)
    (dolist (charset '(kana han symbol cjk-misc bopomofo))
      (set-fontset-font (frame-parameter nil 'font) charset
                        (font-spec :family (car (cdr fonts))))))

;; coding
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(setq default-buffer-file-coding-system 'utf-8)

;; garbage collection
(setq gc-cons-threshold most-positive-fixnum)

;; use y/n instead of yes/no
(defalias 'yes-or-no-p 'y-or-n-p)

;; line-number relative/visual/t
(setq display-line-numbers-type 't)
;(unless *is-windows* (global-display-line-numbers-mode t))
(global-display-line-numbers-mode t)

;; packages
(require 'use-package)
(use-package restart-emacs)
(use-package rg)
(use-package ag)
(use-package fzf)
(use-package yasnippet)

(use-package ivy
  :defer 1
  :demand
  :hook (after-init . ivy-mode)
  :config
  (ivy-mode 1)
  (setq ivy-use-virtual-buffers nil
	ivy-initial-inputs-alist nil
	ivy-count-format "%d%d "
	enable-recursive-minibuffers nil
	ivy-re-builders-alist '((t . ivy--regex-ignore-order))
	ivy-height 25
	ivy-wrap t))

(use-package counsel
  :after (ivy)
  :init (counsel-mode)
  :bind (("M-x" . counsel-M-x)
	 ("C-x C-f" . counsel-find-file)
	 ("C-c f" . counsel-recentf)
	 ("C-c g" . counsel-git)))

(use-package counsel-projectile
  :after (projectile)
  :init (counsel-projectile-mode)
  :config
  (setq counsel-projectile-sort-directories t))

(use-package counsel-at-point
  :bind (("C-c r" . counsel-at-point-rg)
	 ("C-S-c r" . projectile-ripgrep)))

(use-package swiper
  :after ivy
  :bind (("C-S-s" . swiper-all-thing-at-point)
	 ("C-s" . swiper))
  :config (setq swiper-action-recenter t
		swiper-include-line-number-in-search t))

(use-package projectile
  :init (projectile-mode +1)
  :bind (("C-c p" . projectile-command-map)
	 ("C-c o" . projectile-find-file))
  :config
  (setq projectile-indexing-method 'alien)
  (setq projectile-sort-order 'access-time)
  (setq projectile-mode-line "Projectile")
  (setq projectile-track-known-projects-automatically nil))

(use-package smart-mode-line
  :init
  (setq sml/no-confirm-load-theme t)
  (setq sml/theme 'dark)
  (setq sml/shorten-directory nil)
  (setq sml/shorten-modes t)
  ;;(setq sml/name-width 40)
  ;;(setq sml/mode-width 'full)
  (sml/setup))

(use-package benchmark-init
  :init (benchmark-init/activate)
  :hook (after-init . benchmark-init/deactivate))

(use-package drag-stuff
  :bind (("<M-up>" . drag-stuff-up)
	 ("<M-down>" . drag-stuff-down)))

(use-package company
  :config
  (setq company-dabbrev-code-everywhere t
	company-dabbrev-code-modes t
	company-dabbrev-code-other-buffers 'all
	company-dabbrev-downcase nil
	company-dabbrev-ignore-case t
	company-dabbrev-other-buffers 'all
	company-require-match nil
	company-minimum-prefix-length 2
	company-show-numbers t
	company-tooltip-limit 20
	company-idle-delay 0
	company-echo-delay 0
	company-tooltip-offset-display 'scrollbar
	company-begin-commands '(self-insert-command)
	company-backends '((company-capf company-dabbrev-code company-dabbrev company-files)))
  ;;(push '(company-semantic :with company-yasnippet) company-backends)
  :hook ((after-init . global-company-mode)))

(use-package crux
  :bind (("C-a" . crux-move-beginning-of-line)
	 ("C-c ^" . crux-top-join-line)
	 ("C-x ," . crux-find-user-init-file)
	 ("C-S-d" . crux-duplicate-current-line-or-region)
	 ("C-S-k" . crux-smart-kill-line)
	 ("C-c n" . crux-create-scratch-buffer)))

(use-package which-key
  :defer nil
  :config (which-key-mode))

(use-package rainbow-delimiters
  :init (add-hook 'prog-mode-hook 'rainbow-delimiters-mode))

(use-package highlight-parentheses
  :init (add-hook 'prog-mode-hook 'highlight-parentheses-mode))

(use-package auto-highlight-symbol
  :init (global-auto-highlight-symbol-mode))

(use-package ace-window
  :config
  (setq aw-background nil)
  (setq aw-minibuffer-flag t)
  :bind (("C-x o" . 'ace-window)))

(unless *is-windows* (use-package magit
		     :ensure t))

(use-package format-all
  :diminish
  :hook (prog-mode . format-all-ensure-formatter)
  :bind ("C-c f" . 'format-all-region))

(use-package youdao-dictionary)
(if (display-graphic-p)
    (global-set-key (kbd "C-c d") 'youdao-dictionary-search-at-point-posframe)
    (global-set-key (kbd "C-c d") 'youdao-dictionary-search-at-point+))

(use-package expand-region
  :bind ("C-q" . er/expand-region))

(use-package avy
  :bind ("C-c a" . avy-goto-word-1))

(use-package markdown-mode
  :mode ("*\\.md\\'" . gfm-mode))

(use-package color-theme-approximate
  :init (color-theme-approximate-on))

(use-package ranger
  :init (ranger-override-dired-mode t)
  :config
  (setq ranger-parent-depth 0)
  (setq ranger-cleanup-on-disable t)
  (setq ranger-show-hidden t)
  (setq ranger-preview-file nil)
  :bind ("C-c b" . ranger))

(use-package multiple-cursors
  :bind ("C-c c" . mc/edit-lines))

(use-package better-jumper
  :init (better-jumper-mode +1)
  :bind
  ("C-c C-s" . better-jumper-set-jump)
  ("C-c C-c" . better-jumper-clear-jumps)
  ("C-c C-f" . better-jumper-jump-backward)
  ("C-c C-b" . better-jumper-jump-forward))

(use-package vlf)

(use-package ascii-table)

embark-export ?

不用projectile,不过看截图,projectile-rg像是用的ivy,如果是,可以在候选项展示出来后按Shift+空格(ivy-restrict-to-matches),然后就可以继续输入来过滤候选项了。

1 个赞

装上试了下不行:

(use-package embark
  :ensure t
  :bind (("C-e" . embark-act))
  )

最下一行后面蓝绿色提示出错:

用buffer list试了下就导出了,是我没配置好吗?

Shift+空格,在我这里只是在“start_kernel”后面加了一个空格,用的确实是ivy, ivy-restrict-to-matches这个命令没有,我ivy的版本:

另外,大佬你不用projectile,用的是什么呢?

shift和空格是同时按的,这个绑定在ivy-minibuffer-map里,你可以检查确认一下。 我用的是自带的project.el,但其实不太直接用到project的功能。平时搜索项目用counsel-rg。

方法太多了

这种场景下可以用 deadgrep 或者 rg.el

或者用 embark 之类的也应该可以达到在 minibuffer isearch 的效果

或者 ivy 本身就应该有这种功能吧

我知道了,相当于再调用swiper,前提是ivy里enable-recursive-minibuffers选项试打开的。 但是在我这里行为很奇怪,比如在内核源码里先用projectile-rg搜索start_kernel,在结果里按Shift+空格,然后输入init来过滤init/目录下的匹配项,但是输入i之后光标会自动跳到i前面,再输入n的话,n会插入i的前面,除非每次输入一个字母之后按上/下键,光标才会回到最后面。 而且如果projectile-rg的搜索结果有好几十页,这个第二次调出来的swiper好像只是对第一页的结果进行搜索。。

那什么,ivy不是可以直接按C-c C-o,然后就可以各种玩耍了吗,搜索当然也可以

不敢相信这个技巧我今天才习得。。

我并没有手动打开enable-recursive-minibuffers,用着没啥问题。

你这个确实有点奇怪,但是我也想不到可能因为啥,你自己再研究研究吧。

我应该也是从论坛里学到的,不过我用的其实不多,需要再次过滤的时候都是在原来的输入后面空格然后继续输入新的过滤内容。

好吧,谢谢~

@rua @oxsard @yangyingchao 刚发现有at功能诶~统一回一下吧,用其他工具,我觉得要么会打乱布局,要么按键太多,还会产生很多临时buffer,跟踪内核驱动模型那种层层嵌套,一会就晕了~_~#,我不知道你们是怎么用的。