2013-02-08 34 views
5

當我在emacs中使用增量搜索時,我無法知道我在哪裏進行全部匹配。在Chrome瀏覽器中,它表示使用「2/30」的位置。我該如何在Emacs中做到這一點?Emacs搜索的「n of 1」結果

回答

6

這是我第一次嘗試實現這一點。

它使用惰性突出顯示isearch實現,並強制突出顯示覆蓋整個緩衝區(而不僅僅是可見部分) - 這可能會減慢大緩衝區上的搜索速度。然後它更新顯示以包括相對於突出顯示的搜索結果的當前位置(總數)。

這有一個缺點,它依賴於正在搜索和突出顯示的整個緩衝區。而且,有時當您下一場比賽時,即使高光顯然仍然存在,顯示屏也會變爲(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))))))))) 
+0

啊,這很整齊。 – phils

+0

爲什麼不在'isearch-count-message()'中調用'[re] -search- [forward | backward]'?我看不到爲此需要掃描疊加層。 –

+0

在調用'isearch-count-message'的時候,搜索已經在整個緩衝區完成了,因此添加另一個搜索調用可能會顯着減慢搜索速度 - 而疊加層已經存在並且有必要的信息來確定伯爵。 考慮到搜索到的詞語出現次數很多的情況,如果您跳到下一個出現次數爲50次,您將不得不從緩衝區開始到第N次掃描50次。 '1 + 2 + 3 + ... + 50 = 1275' - 許多搜索只是爲了確定你是在第50次出現。 –

1

開箱即用,你可以使用女士Ø而isearching至少看比賽的總人數(即使不幸的是,沒有足夠的智慧來追蹤你的是在比賽原始緩衝區)。

5

saw這前些天:

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

anzu.el是anzu.vim的Emacs的端口。 anzu.el提供了一種次要模式,可以在各種搜索模式下顯示模式行中的當前匹配和總匹配信息。

github頁面上的屏幕截圖是其功能的gif動畫。

0

將以下內容添加到您的emacs init文件中。儘管使用了計數匹配,但筆記本電腦的工作速度非常快。我還沒有用非常大的文件來試用它。

(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)