Skip to content

Commit

Permalink
Add a new prompter for meow-visit.
Browse files Browse the repository at this point in the history
- Add user option `meow-vist-prompter`.

- Add `meow--prompt-buffer-highlight`, which highlights matches in the buffer
  similar to Isearch, and highlights all matches in the secondary selection
  while in Beacon Mode and point is in the secondary selection.
  • Loading branch information
okamsn committed Sep 3, 2023
1 parent f553db1 commit b9e9747
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 7 deletions.
39 changes: 33 additions & 6 deletions meow-command.el
Original file line number Diff line number Diff line change
Expand Up @@ -1349,18 +1349,45 @@ Argument REVERSE if selection is reversed."
The input will be pushed into `regexp-search-ring'. So
\\[meow-search] can be used for further searching with the same condition.
A list of words and symbols in the current buffer will be provided for completion.
To search for regexp instead, set `meow-visit-sanitize-completion' to nil.
In that case, completions will be provided in regexp form, but also covering
When `meow-prompter' is `completion' (the default), a list of
words and symbols in the current buffer will be provided for
completion. To search for a regexp instead, set
`meow-visit-sanitize-completion' to nil. In that case,
completions will be provided in regexp form, but also covering
the words and symbols in the current buffer.
When `meow-prompter' is `buffer-highlight', matches are
highlighted in the current buffer from point until then end of
the visible text. When `meow-visit-sanitize-completion' is
non-nil, only whole words and symbols are highlighted, and the
input is treated literally. When `meow-beacon-mode' is active
and point is inside the secondary selection, matches back to the
start or end of the selection are highlighted, depending on whether
`meow-visit' is searching backward or forward.
To search backward, use \\[negative-argument]."
(interactive "P")
(let* ((reverse arg)
(pos (point))
(text (meow--prompt-symbol-and-words
(if arg "Visit backward: " "Visit: ")
(point-min) (point-max)))
(prompt (if reverse "Visit backward: " "Visit: "))
(text (pcase meow-visit-prompter
('buffer-highlight
(apply #'meow--prompt-buffer-highlight
prompt
(let* ((ov-start (overlay-start mouse-secondary-overlay))
(ov-end (overlay-end mouse-secondary-overlay))
(use-sec (and (meow-beacon-mode-p)
(secondary-selection-exist-p)
(>= pos ov-start)
(< pos ov-end))))
(if reverse
(list (window-start (selected-window))
(if use-sec ov-end pos))
(list (if use-sec ov-start pos)
(window-end (selected-window)))))))
((or 'completion _)
(meow--prompt-symbol-and-words prompt
(point-min) (point-max)))))
(visit-point (meow--visit-point text reverse)))
(if visit-point
(let* ((m (match-data))
Expand Down
64 changes: 64 additions & 0 deletions meow-util.el
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,70 @@ Looks up the state in meow-replace-state-name-list"
(regexp-quote selected))
selected))))

(defun meow--prompt-buffer-highlight (prompt beg end)
"PROMPT from the minibuffer while highlighting matches between BEG and END.
When `meow-visit-sanitize-completion' is non-nil, matches are
literal instead of regexps and only words and symbols are
matched.
Highlights are only visible in the selected window."
(let ((current-buffer (current-buffer))
(selected-window (selected-window))
(timer)
(overlays)
(prompter-minibuffer))
(cl-labels ((transform-text (txt &optional quote-regexp)
(cond (meow-visit-sanitize-completion
;; To support Emacs 26.3, we need to use RX's `regexp'
;; form with `regexp-quote' instead of the `literal'
;; form, which was added in Emacs 27.
(let ((qtd (regexp-quote txt)))
(rx (or (seq symbol-start
(regexp qtd)
symbol-end)
(seq word-start
(regexp qtd)
word-end)))))
(quote-regexp (regexp-quote txt))
(t txt)))
(delete-overlays ()
(mapc #'delete-overlay overlays)
(setq overlays nil))
(highlight-matches ()
;; Before highlighting the minibuffer contents, we need to
;; check that we are still in the prompter's minibuffer, not
;; some other minibuffer.
(when (or (not enable-recursive-minibuffers)
(equal prompter-minibuffer (current-buffer)))
(delete-overlays)
(let ((regexp (transform-text (minibuffer-contents))))
(unless (string-empty-p regexp)
(save-excursion
(with-current-buffer current-buffer
(goto-char beg)
(while (ignore-error invalid-regexp
;; If the user is still typing the regexp it
;; might not be valid. In that case, we
;; treat it as valid but not matching.
(re-search-forward regexp end t))
(let ((ov (make-overlay (match-beginning 0)
(match-end 0))))
(overlay-put ov 'face 'lazy-highlight)
;; Same priority as Isearch lazy-highlight.
(overlay-put ov 'priority 1000)
(overlay-put ov 'window selected-window)
(push ov overlays)))))))))
(make-hl-timer ()
(run-with-idle-timer 0.01 'repeat #'highlight-matches)))
(unwind-protect
(minibuffer-with-setup-hook
(lambda () (setq timer (make-hl-timer)
prompter-minibuffer (current-buffer)))
(transform-text (read-from-minibuffer prompt) t))
(cancel-timer timer)
(delete-overlays)))))

(defun meow--on-window-state-change (&rest _args)
"Update cursor style after switching window."
(meow--update-cursor)
Expand Down
23 changes: 22 additions & 1 deletion meow-var.el
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,29 @@ This will affect how selection is displayed."
:group 'meow
:type '(repeat function))

(defcustom meow-visit-prompter 'completion
"How `meow-visit' should prompt for a target.
- `completion' (the default) means to present a lists of regexps
in the minibuffer, respecting the value of
`meow-visit-sanitize-completion'.
- `buffer-highlight' means to highlight in the buffer the region
matching the text in the minibuffer, whether after or before
point. If point is within the secondary selection and
`meow-beacon-mode' is active, then matches within the
secondary selection are also highlighted. When
`meow-visit-sanitize-completion' is non-nil, this treats the
input literally and only matches whole words and symbols.
Any other value is treated as `completion'."
:group 'meow
:type '(choice (const :tag "Show regexps in the minibuffer" completion)
(const :tag "Highlight text in the buffer" buffer-highlight)))

(defcustom meow-visit-collect-min-length 1
"Minimal length when collecting symbols for `meow-visit'."
"Minimal length when collecting symbols for `meow-visit' in the default prompter.
See also `meow-visit-prompter'."
:group 'meow
:type 'integer)

Expand Down

0 comments on commit b9e9747

Please sign in to comment.