(define-minor-mode search-read-target-mode
"Minor mode for `search-read-target' minibuffer.")
-(defun search--read-target (buffer beg end reg sfn init)
+(defun search--read-target (buffer beg end reg sfn init alt)
"Prompt for search target in BUFFER between BEG and END matching REG.
SFN is the search function to use for finding matches. INIT is the
(overlay-put cur 'face 'isearch)))
"search"))
(setq minibuffer-alternative-action
- (cons
- (lambda (c)
- (if-let ((n (string-to-number c))
- (d (gethash n tab)))
+ (if alt
+ (cons
+ (lambda (c)
(with-selected-window
(or (get-buffer-window buffer) (display-buffer buffer))
+ (goto-char (car (gethash (string-to-number c) tab)))
(when (overlayp cur) (overlay-put cur 'face 'lazy-highlight))
- (set-match-data d)
- (let ((ov (seq-some
+ (setq cur (seq-some
(lambda (ov) (and (overlay-get ov 'search) ov))
- (overlays-at (match-beginning 0)))))
- (unless rep
- (overlay-put ov 'face 'isearch)
- (goto-char (match-beginning 0))
- (setq rep (query-replace-read-to reg "Replace" t)))
- (setq ovs (delq ov ovs))
- (delete-overlay ov))
- (setq trs (delete c trs))
- (remhash n tab)
- (replace-match rep))
- (user-error "Already replaced")))
- "replace"))
+ (overlays-at (point))))
+ (overlay-put cur 'face 'isearch)
+ (funcall (car alt))))
+ (cdr alt))
+ (cons
+ (lambda (c)
+ (if-let ((n (string-to-number c))
+ (d (gethash n tab)))
+ (with-selected-window
+ (or (get-buffer-window buffer) (display-buffer buffer))
+ (when (overlayp cur) (overlay-put cur 'face 'lazy-highlight))
+ (set-match-data d)
+ (let ((ov (seq-some
+ (lambda (ov) (and (overlay-get ov 'search) ov))
+ (overlays-at (match-beginning 0)))))
+ (unless rep
+ (overlay-put ov 'face 'isearch)
+ (goto-char (match-beginning 0))
+ (setq rep (query-replace-read-to reg "Replace" t)))
+ (setq ovs (delq ov ovs))
+ (delete-overlay ov))
+ (setq trs (delete c trs))
+ (remhash n tab)
+ (replace-match rep))
+ (user-error "Already replaced")))
+ "replace")))
(let ((hook-fn
(lambda (input)
(unless (string-empty-p input)
(mapc #'delete-overlay ovs)
(mapc #'delete-overlay ovz))))
-(defun search-read-target (&optional beg end re-or-fn)
+(defun search-read-target (&optional beg end re-or-fn alt)
"Prompt for \\[search] target between BEG and END matching RE-OR-FN."
(let* ((buf (current-buffer))
- (beg (or beg (point-min)))
- (end (or end (point-max)))
+ (beg (or beg (use-region-beginning) (point-min)))
+ (end (or end (use-region-end) (point-max)))
reg res
(sfn (if (functionp re-or-fn)
(prog1 re-or-fn (setq reg "match"))
(lambda () (re-search-forward reg end t)))))
(deactivate-mark)
(while (stringp (setq res (catch 'search-change
- (search--read-target buf beg end reg sfn res))))
+ (search--read-target buf beg end reg sfn res alt))))
(setq reg (read-regexp "Search regular expression")
sfn (lambda () (re-search-forward reg end t))))
res))
;;;###autoload
(defun search (beg end)
"Go to and pulse region starting at BEG and ending at END."
- (interactive
- (save-excursion
- (search-read-target (use-region-beginning) (use-region-end))))
+ (interactive (save-excursion (search-read-target)))
(push-mark)
(goto-char beg)
(pulse-momentary-highlight-region beg end 'isearch))
;;;###autoload
(defun search-lines (beg end)
"Go to and pulse line starting at BEG and ending at END."
+ (interactive (save-excursion (search-read-target nil nil ".*")))
+ (search beg end))
+
+(defun search--property (prop)
+ (lambda ()
+ (when-let ((pm (text-property-search-forward prop)))
+ (set-match-data (list (prop-match-beginning pm)
+ (prop-match-end pm)))
+ (point))))
+
+;;;###autoload
+(defun search-property (beg end)
+ "`search' for region from BEG to END with a given text property."
(interactive
(save-excursion
- (search-read-target (use-region-beginning) (use-region-end) ".*")))
+ (search-read-target nil nil (search--property (read-text-property)))))
(search beg end))
+;;;###autoload
+(defun search-button (beg end)
+ "`search' for button from BEG to END."
+ (interactive
+ (save-excursion
+ (search-read-target nil nil (search--property 'button)
+ (cons #'push-button "push"))))
+ (search beg end)
+ (push-button))
+
(provide 'search)
;;; search.el ends here
(defvar read-text-property-history nil)
+(defun read-text-property (&optional prompt default)
+ (setq default (when default (symbol-name default)))
+ (intern
+ (completing-read
+ (format-prompt (or prompt "Property") default)
+ (completion-table-with-metadata
+ (let ((alist text-property-alist)
+ (plist (text-properties-at (point))))
+ (while plist
+ (unless (assq (car plist) alist)
+ (push (cons (car plist) "") alist))
+ (setq plist (cddr plist)))
+ (mapcar (compose #'symbol-name #'car) alist))
+ '((category . text-property)
+ (affixation-function . read-text-property-affixation)))
+ nil nil nil
+ 'read-text-property-history default)))
+
(defun read-text-property-and-value (&optional prompt)
- (let ((prop (intern
- (completing-read
- (format-prompt (or prompt "Property") "face")
- (completion-table-with-metadata
- (let ((alist text-property-alist)
- (plist (text-properties-at (point))))
- (while plist
- (unless (assq (car plist) alist)
- (push (cons (car plist) "") alist))
- (setq plist (cddr plist)))
- (mapcar (compose #'symbol-name #'car) alist))
- '((category . text-property)
- (affixation-function . read-text-property-affixation)))
- nil nil nil
- 'read-text-property-history "face"))))
+ (let ((prop (read-text-property prompt 'face)))
(list prop (read-text-property-value prop))))
(defun propertize-region (beg end prop val)