Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new prompter for meow-visit. #501

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
61 changes: 61 additions & 0 deletions meow-util.el
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,67 @@ 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
;; The below regexp was made using the below call to
;; `rx', which has gained features since Emacs 26.3.
;;
;;(rx (or (seq symbol-start (literal txt) symbol-end))
;; (seq word-start (literal txt) word-end))
(let ((qtd (regexp-quote txt)))
(concat "\\_<\\(?:" qtd "\\)\\_>\\|\\<\\(?:" qtd "\\)\\>")))
(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