“1 of n” result for Emacs search

前端 未结 4 1586
梦毁少年i
梦毁少年i 2021-01-02 22:16

When I use incremental search in emacs I can\'t know where I am in whole matches. In Chrome browser it says location using \"2 of 30\". How can I do that in Emacs?

相关标签:
4条回答
  • 2021-01-02 22:41

    I saw this the other day:

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

    anzu.el is an Emacs port of anzu.vim. anzu.el provides a minor mode which displays current match and total matches information in the mode-line in various search modes.

    The screenshot on the github page is a gif animation of its functionality.

    0 讨论(0)
  • 2021-01-02 22:43

    Add the following to your emacs init file. Despite the use of count-matches, it works very fast on my laptop. I have not tried it with very large files.

    (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)
    
    0 讨论(0)
  • 2021-01-02 22:51

    Out of the box, you can use M-so while isearching to at least see the total number of matches (even if it unfortunately isn't smart enough to track the match that you're on in the original buffer).

    0 讨论(0)
  • 2021-01-02 22:56

    Here's my first attempt to implement this.

    It uses the lazy highlighting that isearch implements, and forces the highlighting to cover the entire buffer (not just the visible portions) - which can slow down the search on large buffers. It then updates the display to include a current position (of total) relative to the highlighted search results.

    This has the drawback that it is dependent on the entire buffer being searched and highlighted. And, sometimes when you C-s to the next match, the display changes to (0 of 1) even though the highlights are clearly still present.

    But, it seems to be a reasonable first cut.

    Prepare for big cut/paste:

    (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)))))))))
    
    0 讨论(0)
提交回复
热议问题