"1 из n" результат поиска Emacs
Когда я использую добавочный поиск в emacs, я не могу знать, где я нахожусь в целых совпадениях. В браузере Chrome он говорит местоположение, используя "2 из 30". Как я могу сделать это в Emacs?
4 ответа
Вот моя первая попытка реализовать это.
Он использует ленивую подсветку, которая isearch
реализует и заставляет подсветку покрывать весь буфер (не только видимые части), что может замедлить поиск в больших буферах. Затем он обновляет отображение, чтобы включить текущую позицию (всего) относительно выделенных результатов поиска.
Это имеет тот недостаток, что он зависит от всего буфера, который ищется и подсвечивается. И, иногда, когда вы Cs к следующему совпадению, дисплей меняется на (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)))))))))
Я видел это на днях:
https://github.com/syohex/emacs-anzu
anzu.el - это порт Emacs для anzu.vim. anzu.el предоставляет второстепенный режим, который отображает информацию о текущем совпадении и общем совпадении в строке режима в различных режимах поиска.
Снимок экрана на странице GitHub представляет собой анимацию его функциональности.
Из коробки вы можете использовать Mso во время поиска, чтобы хотя бы увидеть общее количество совпадений (даже если, к сожалению, оно недостаточно умное, чтобы отследить совпадение в исходном буфере).
Добавьте следующее в ваш файл инициализации 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)