2013-02-08 13 views

risposta

6

Ecco il mio primo tentativo di implementare questo.

Utilizza l'evidenziazione pigro che isearch implementa e forza l'evidenziazione a coprire l'intero buffer (non solo le porzioni visibili), il che può rallentare la ricerca su buffer di grandi dimensioni. Aggiorna quindi la visualizzazione per includere una posizione corrente (totale) relativa ai risultati della ricerca evidenziati.

Questo ha lo svantaggio di dipendere dall'intero buffer ricercato ed evidenziato. E, a volte quando si aggiunge C-s alla corrispondenza successiva, il display diventa (0 of 1) anche se i punti salienti sono chiaramente ancora presenti.

Ma, sembra essere un primo taglio ragionevole.

Preparare per grande taglia/incolla:

(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

Ah, è molto carino. – phils

+0

Perché non chiamare '[re] -search- [forward | backward]' in 'isearch-count-message()'? Non riesco a vedere la necessità di scansionare gli overlay per questo. –

+0

Nel punto in cui viene chiamato 'isearch-count-message', la ricerca è già stata eseguita in tutto il buffer, quindi l'aggiunta di un'altra chiamata alla ricerca potrebbe rallentare drasticamente le cose - mentre gli overlay erano presenti e avevano le informazioni necessarie per determinare il conteggio. Pensa al caso in cui ci sono molte occorrenze del termine cercato, se salti alla ricorrenza successiva per 50 volte, avresti dovuto scansionare il buffer dall'inizio alla Nth, 50 volte. '1 + 2 + 3 + ... + 50 = 1275' - tante ricerche per determinare se sei al 50 ° evento. –

1

Fuori dalla scatola, è possibile utilizzare Mso mentre isearching almeno visualizzare il numero totale di partite (anche se purtroppo non è abbastanza intelligente per seguire il match che si è in in buffer originale).

5

ho saw questo l'altro giorno:

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

anzu.el è un porto di Emacs anzu.vim. anzu.el fornisce una modalità minore che visualizza la corrispondenza corrente e le informazioni di partite totali nella linea della modalità in varie modalità di ricerca.

Lo screenshot sulla pagina github è un'animazione gif delle sue funzionalità.

0

Aggiungere quanto segue al file init di emacs. Nonostante l'uso di count-matches, funziona molto velocemente sul mio portatile. Non l'ho provato con file molto grandi.

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