7

当我在 emacs 中使用增量搜索时,我不知道我在整个匹配项中的位置。在 Chrome 浏览器中,它使用“2 of 30”表示位置。我怎样才能在 Emacs 中做到这一点?

4

4 回答 4

7

这是我第一次尝试实现这一点。

它使用isearch实现的惰性突出显示,并强制突出显示覆盖整个缓冲区(不仅仅是可见部分)——这会减慢对大缓冲区的搜索。然后它更新显示以包括相对于突出显示的搜索结果的当前位置(总计)。

这样做的缺点是它依赖于被搜索和突出显示的整个缓冲区。而且,有时当您进行下一场比赛时,即使亮点仍然明显存在C-s,显示也会更改。(0 of 1)

但是,这似乎是一个合理的第一次削减。

准备大切割/粘贴:

(require 'isearch)
(defun lazy-highlight-cleanup (&optional force)
  "Stop lazy highlighting and remove extra highlighting from current buffer.
FORCE non-nil means do it whether or not `lazy-highlight-cleanup'
is nil.  This function is called when exiting an incremental search if
`lazy-highlight-cleanup' is non-nil."
  (interactive '(t))
  (if (or force lazy-highlight-cleanup)
      (while isearch-lazy-highlight-overlays
        (delete-overlay (car isearch-lazy-highlight-overlays))
        (setq isearch-lazy-highlight-overlays
              (cdr isearch-lazy-highlight-overlays))))
  (when isearch-lazy-highlight-timer
    (cancel-timer isearch-lazy-highlight-timer)
    (setq isearch-message-suffix-add "")
    (setq isearch-lazy-highlight-timer nil)))

(defun isearch-lazy-highlight-search ()
  "Search ahead for the next or previous match, for lazy highlighting.
Attempt to do the search exactly the way the pending Isearch would."
  (condition-case nil
      (let ((case-fold-search isearch-lazy-highlight-case-fold-search)
            (isearch-regexp isearch-lazy-highlight-regexp)
            (search-spaces-regexp isearch-lazy-highlight-space-regexp)
            (isearch-word isearch-lazy-highlight-word)
            (search-invisible nil)  ; don't match invisible text
            (retry t)
            (success nil)
            (isearch-forward isearch-lazy-highlight-forward)
            (bound (if isearch-lazy-highlight-forward
                       (min (or isearch-lazy-highlight-end-limit (point-max))
                            (if isearch-lazy-highlight-wrapped
                                isearch-lazy-highlight-start
                              (isearch-window-end)))
                     (max (or isearch-lazy-highlight-start-limit (point-min))
                          (if isearch-lazy-highlight-wrapped
                              isearch-lazy-highlight-end
                            (isearch-window-start))))))
        ;; Use a loop like in `isearch-search'.
        (while retry
          (setq success (isearch-search-string
                         isearch-lazy-highlight-last-string bound t))

          ;; Clear RETRY unless the search predicate says
          ;; to skip this search hit.
          (if (or (not success)
                  (= (point) bound) ; like (bobp) (eobp) in `isearch-search'.
                  (= (match-beginning 0) (match-end 0))
                  (funcall isearch-filter-predicate
                           (match-beginning 0) (match-end 0)))
              (setq retry nil)))
        success)
    (error nil)))

(defun isearch-find-current-overlay ()
  (let ((total 0)
        (count 1)
        (olist isearch-lazy-highlight-overlays))
    (while olist
      (setq total (1+ total))
      (if (< (overlay-end (car olist)) (point))
          (setq count (1+ count)))
      (setq olist
            (cdr olist)))
    (cons count total)))

(add-hook 'isearch-update-post-hook 'isearch-count-message)

(defun isearch-count-message ()
  (let ((counts (isearch-find-current-overlay)))
    (setq isearch-message-suffix-add (format " (%d of %d)" (car counts) (cdr counts)))))

(defun isearch-window-start ()
  "force highlight entire buffer"
  (point-min))

(defun isearch-window-end ()
  "force highlight entire buffer"
  (point-max))

(defun isearch-lazy-highlight-update ()
  "Update highlighting of other matches for current search."
  (let ((max lazy-highlight-max-at-a-time)
        (looping t)
        nomore)
    (with-local-quit
      (save-selected-window
        (if (and (window-live-p isearch-lazy-highlight-window)
                 (not (eq (selected-window) isearch-lazy-highlight-window)))
            (select-window isearch-lazy-highlight-window))
        (save-excursion
          (save-match-data
            (goto-char (if isearch-lazy-highlight-forward
                           isearch-lazy-highlight-end
                         isearch-lazy-highlight-start))
            (while looping
              (let ((found (isearch-lazy-highlight-search)))
                (when max
                  (setq max (1- max))
                  (if (<= max 0)
                      (setq looping nil)))
                (if found
                    (let ((mb (match-beginning 0))
                          (me (match-end 0)))
                      (if (= mb me) ;zero-length match
                          (if isearch-lazy-highlight-forward
                              (if (= mb (if isearch-lazy-highlight-wrapped
                                            isearch-lazy-highlight-start
                                          (isearch-window-end)))
                                  (setq found nil)
                                (forward-char 1))
                            (if (= mb (if isearch-lazy-highlight-wrapped
                                          isearch-lazy-highlight-end
                                        (isearch-window-start)))
                                (setq found nil)
                              (forward-char -1)))

                        ;; non-zero-length match
                        (let ((ov (make-overlay mb me)))
                          (push ov isearch-lazy-highlight-overlays)
                          ;; 1000 is higher than ediff's 100+,
                          ;; but lower than isearch main overlay's 1001
                          (overlay-put ov 'priority 1000)
                          (overlay-put ov 'face lazy-highlight-face)
                          (overlay-put ov 'window (selected-window))))
                      (if isearch-lazy-highlight-forward
                          (setq isearch-lazy-highlight-end (point))
                        (setq isearch-lazy-highlight-start (point)))))

                ;; not found or zero-length match at the search bound
                (if (not found)
                    (if isearch-lazy-highlight-wrapped
                        (setq looping nil
                              nomore  t)
                      (setq isearch-lazy-highlight-wrapped t)
                      (if isearch-lazy-highlight-forward
                          (progn
                            (setq isearch-lazy-highlight-end (isearch-window-start))
                            (goto-char (max (or isearch-lazy-highlight-start-limit (point-min))
                                            (isearch-window-start))))
                        (setq isearch-lazy-highlight-start (isearch-window-end))
                        (goto-char (min (or isearch-lazy-highlight-end-limit (point-max))
                                        (isearch-window-end))))))))
            (unless nomore
              (setq isearch-lazy-highlight-timer
                    (run-at-time lazy-highlight-interval nil
                                 'isearch-lazy-highlight-update)))))))))
于 2013-02-08T06:59:33.580 回答
7

前几天我看到了这个:

https://github.com/syohex/emacs-anzu

anzu.el 是 anzu.vim 的 Emacs 端口。anzu.el 提供了一种次要模式,该模式在各种搜索模式下的模式行中显示当前匹配和总匹配信息。

github页面上的截图是其功能的gif动画。

于 2014-08-31T10:29:39.747 回答
2

开箱即用,您可以使用M-sowhile isearch 来至少查看匹配的总数(即使不幸的是它还不够聪明,无法跟踪您在原始缓冲区中的匹配)。

于 2013-02-08T05:41:00.623 回答
1

将以下内容添加到您的 emacs 初始化文件中。尽管使用了计数匹配,但它在我的笔记本电脑上运行得非常快。我还没有尝试过非常大的文件。

(defun my-isearch-update-post-hook()
  (let (suffix num-before num-after num-total)
    (setq num-before (count-matches isearch-string (point-min) (point)))
    (setq num-after (count-matches isearch-string (point) (point-max)))
    (setq num-total (+ num-before num-after))
    (setq suffix (if (= num-total 0)
                     ""
                   (format " [%d of %d]" num-before num-total)))
    (setq isearch-message-suffix-add suffix)
    (isearch-message)))

(add-hook 'isearch-update-post-hook 'my-isearch-update-post-hook)
于 2016-03-30T00:10:03.477 回答