150 lines
4.4 KiB
EmacsLisp
150 lines
4.4 KiB
EmacsLisp
;;; isearch-olc.el --- In-buffer overlay for Isearch's lazy count -*- lexical-binding: t -*-
|
|
|
|
;; Copyright (C) 2022 Free Software Foundation, Inc.
|
|
|
|
;; Author: Jai Flack <jflack@disroot.org>
|
|
;; Version: 2022-03-24
|
|
;; URL: https://git.disroot.org/jflack/isearch-olc
|
|
;; Package-Requires: ((emacs "29"))
|
|
;; Keywords: Isearch matching
|
|
|
|
;; This file is NOT part of GNU Emacs.
|
|
|
|
;; This program is free software: you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
;; (at your option) any later version.
|
|
|
|
;; This program is distributed in the hope that it will be useful,
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;; GNU General Public License for more details.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
;;; Commentary:
|
|
|
|
;; This package provides an in-buffer overlay of Isearch's lazy counting
|
|
;; facility. This count is displayed at the end of the current matches
|
|
;; line with configurable formatting similar to
|
|
;; `lazy-count-suffix-format'.
|
|
|
|
;; To use the package, activate `isearch-olc-mode'. Requires both
|
|
;; `isearch-lazy-highlight' and `isearch-lazy-count' to be non-nil.
|
|
|
|
;;; Configuration:
|
|
|
|
;; The defaults should be acceptable for most users however it can be
|
|
;; customised for aesthetic purposes.
|
|
|
|
;; Available options:
|
|
;; - `isearch-olc-format'
|
|
|
|
;; Available faces:
|
|
;; - `isearch-olc'
|
|
|
|
|
|
;;; Code:
|
|
|
|
(require 'isearch)
|
|
|
|
(defgroup isearch-olc nil
|
|
"In-buffer overlay for Isearch's lazy count."
|
|
:group 'isearch)
|
|
|
|
(defcustom isearch-olc-format " %s/%s"
|
|
"Format of the current and total number of matches for the
|
|
in-buffer display. Requirements are the same as
|
|
`lazy-count-suffix-format'.
|
|
|
|
See `isearch-olc-mode'."
|
|
:type 'string
|
|
:group 'isearch-olc)
|
|
|
|
(defface isearch-olc
|
|
'((t (:inherit isearch)))
|
|
"Face for the in-buffer count overlay.
|
|
|
|
See `isearch-olc-mode'."
|
|
:group 'isearch-olc)
|
|
|
|
|
|
(defvar isearch-olc--overlay nil)
|
|
|
|
(defun isearch-olc--format ()
|
|
(if (and isearch-olc-format
|
|
isearch-lazy-count
|
|
isearch-lazy-count-current
|
|
(not isearch-error)
|
|
(not isearch-suspended))
|
|
(format isearch-olc-format
|
|
(if isearch-lazy-highlight-forward
|
|
isearch-lazy-count-current
|
|
(if (eq isearch-lazy-count-current 0)
|
|
0
|
|
(- isearch-lazy-count-total
|
|
isearch-lazy-count-current
|
|
-1)))
|
|
(or isearch-lazy-count-total "?"))
|
|
""))
|
|
|
|
(defun isearch-olc--display ()
|
|
;; Try to reuse the overlay as much as possible to remove flickering.
|
|
(unless isearch-olc--overlay
|
|
(let ((ov (make-overlay 0 0)))
|
|
(setq isearch-olc--overlay ov)
|
|
;; see `isearch-lazy-highlight-match'
|
|
(overlay-put ov 'priority 1001)
|
|
(overlay-put ov 'face 'isearch-olc)
|
|
(unless isearch-lazy-highlight-buffer
|
|
(overlay-put ov 'window (selected-window)))))
|
|
|
|
;; TODO: test more thoroughly with RTL text
|
|
(let ((ov isearch-olc--overlay)
|
|
(pae
|
|
(if isearch-match-data
|
|
(save-excursion
|
|
(goto-char (car isearch-match-data))
|
|
(point-at-eol))
|
|
(point-at-eol)))
|
|
(count (propertize (isearch-olc--format)
|
|
'cursor t)))
|
|
(unless (and (= (overlay-end ov)
|
|
pae)
|
|
(eq (overlay-buffer ov)
|
|
(current-buffer)))
|
|
(move-overlay ov pae pae (current-buffer)))
|
|
;; TODO: could this be eq?
|
|
(unless (string= (overlay-get ov 'after-string)
|
|
count)
|
|
(overlay-put ov 'after-string count))))
|
|
|
|
(defun isearch-olc--cleanup ()
|
|
(when isearch-olc--overlay
|
|
(delete-overlay isearch-olc--overlay)
|
|
(setq isearch-olc--overlay nil)))
|
|
|
|
|
|
(defun isearch-olc--setup ()
|
|
(add-hook 'lazy-count-update-hook #'isearch-olc--display)
|
|
(add-hook 'isearch-mode-end-hook #'isearch-olc--cleanup))
|
|
|
|
(defun isearch-olc--packup ()
|
|
(remove-hook 'lazy-count-update-hook #'isearch-olc--display)
|
|
(remove-hook 'isearch-mode-end-hook #'isearch-olc--cleanup))
|
|
|
|
(define-minor-mode isearch-olc-mode
|
|
"Display the current isearch's match number and total number of
|
|
matches just after the currently matched line.
|
|
|
|
Requires both `isearch-lazy-highlight' and `isearch-lazy-count'
|
|
to be non-nil."
|
|
:global t
|
|
(if isearch-olc-mode
|
|
(isearch-olc--setup)
|
|
(isearch-olc--packup)))
|
|
|
|
(provide 'isearch-olc)
|
|
;;; isearch-olc.el ends here
|