(想法)解决 swiper 在超长行的文件中卡死的问题

swiper搜索会有三个问题

  • 超长行 (存在一些行过分多的字符)
  • 大文件 (buffer 的字符数过多或者行数过多)
  • 一些mode不能使用

尝试使用 counsel-grep, counsel-grep-or-swiperisearch来解决

  ;; 确保counsel, ivy, swiper已经加载

  (defvar my-line-length-threshold 500
    "行字符数阈值,超过该值使用counsel-grep.")

  (defvar my-line-count-threshold 50000
    "缓冲行数阈值,超过该值直接使用counsel-grep.")

  (defun buffer-has-long-line-p (&optional threshold)
    "检查当前buffer是否存在超过THRESHOLD字符的行."
    (let ((threshold (or threshold my-line-length-threshold))
          (found nil))
      (save-excursion
	(goto-char (point-min))
	(while (and (not found)
                    (re-search-forward (format "^.\\{%d\\}" threshold) nil t))
          (setq found t)))
      found))
 
  (setq my-line-count-threshold 50000)  ; 行数阈值
  (setq my-line-length-threshold 500)   ; 行长度阈值
  (setq counsel-grep-swiper-limit 300000) ;字符数阈值

  (defun my-smart-grep ()
    "智能搜索策略:
1. 缓冲区行数超过50000时使用counsel-grep
2. 存在超过500字符的行时使用counsel-grep
3. 其他情况使用counsel-grep-or-swiper."
    (interactive)
    (cond
     ((> (count-lines (point-min) (point-max)) my-line-count-threshold)
      (counsel-grep))
     ((buffer-has-long-line-p)
      (counsel-grep))
     (t
      (counsel-grep-or-swiper))))

  ;; 绑定到C-s
  (global-set-key (kbd "C-s") 'my-smart-grep)

一些mode的无法使用:pdf-view-mode等

  (define-key pdf-view-mode-map (kbd "C-s") 'isearch-forward)
  (define-key pdf-view-mode-map (kbd "C-r") 'isearch-backward)

这里就直接用isearch

何必呢?直接用 grep 不好吗?emacs 已经内置了:

感觉挺有用的,我swiper和isearch都在用,因为我的org 文件里链接太多 ,swiper会把链接里的内容也进行搜索,而我只需要搜索链接显示出的提示文字就可,这时用iserach,好像也可以写个函数来判断页面中链接太多时自动切到iserach

swiper 自带一个命令叫 swiper-isearch, 不知道是不是性能好一些. 这是 swiper 作者本人绑定在 C-s 上的命令, 原因他解释在他自己的博客里了 https://oremacs.com/2019/04/07/swiper-isearch/, 但是目前好像挂了, 我也忘了他当年具体解释了啥, 依稀记得好像可以提高性能

我试了一下,性能确实提高了不少,而且高亮也保持的不错。但似乎与在文件中的位置有关,当在大文件末尾时,要卡上一会。

针对超长行的处理,也有性能的提高,比counsel-grep要好(可以在同一行中上下选择位置)。