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

can you add swiper-the-thing-with-same-fontface #288

Closed
redguardtoo opened this Issue Nov 9, 2015 · 3 comments

Comments

Projects
None yet
2 participants
@redguardtoo
Contributor

redguardtoo commented Nov 9, 2015

That's useful when I want to replace all the things in text, but I don't want to wrongly replace sub-string of function or variable name.

@abo-abo

This comment has been minimized.

Show comment
Hide comment
@abo-abo

abo-abo Nov 9, 2015

Owner

There's already swiper-query-replace bound to M-q for that, exactly because the-thing-with-same-fontface is a very vague idea.

Swiper works line-wise, can't change that. So the thing could be in two places on a single line, with two different faces. That's one problem.

Additionally, faces apply to each character separately. Thing-at-point can have a different face for every single char. Suppose we restrict ourselves to only the cases where each entire match has face (plist-get (text-properties-at (point)) 'face). Then it can be done.

One more thing, the faces don't get assigned if the buffer is huge. See the code of swiper-font-lock-ensure. You can advise it to also work for huge buffers, but then you'll have to wait for a few seconds for swiper to start up.

Have a look at this code that's supposed to work, if we accept the above assumptions/restrictions:

(defvar swiper-like-this-face nil)

(defun swiper-like-this (&optional initial-input)
  "`isearch' with an overview using `ivy'.
When non-nil, INITIAL-INPUT is the initial search pattern."
  (interactive)
  (swiper--init)
  (setq swiper-like-this-face
        (plist-get (text-properties-at (point)) 'face))
  (let ((candidates (swiper--candidates))
        (preselect (buffer-substring-no-properties
                    (line-beginning-position)
                    (line-end-position)))
        (minibuffer-allow-text-properties t))
    (unwind-protect
         (ivy-read
          "Swiper: "
          candidates
          :initial-input initial-input
          :keymap swiper-map
          :preselect preselect
          :require-match t
          :update-fn #'swiper--update-input-ivy
          :unwind #'swiper--cleanup
          :action #'swiper--action
          :re-builder #'swiper--re-builder
          :matcher #'swiper--like-this-matcher
          :history 'swiper-history
          :caller 'swiper)
      (when (null ivy-exit)
        (goto-char swiper--opoint)))))

(defun swiper--like-this-matcher (regexp candidates)
  "Return REGEXP-matching CANDIDATES.
Skip some dotfiles unless `ivy-text' requires them."
  (cl-remove-if-not
   (lambda (x)
     (and
      (string-match regexp x)
      (let ((s (match-string 0 x))
            (i 0))
        (while (and (< i (length s))
                    (text-property-any
                     i (1+ i)
                     'face swiper-like-this-face
                     s))
          (cl-incf i))
        (eq i (length s)))))
   candidates))

If you like the code, I'll integrate it.

Owner

abo-abo commented Nov 9, 2015

There's already swiper-query-replace bound to M-q for that, exactly because the-thing-with-same-fontface is a very vague idea.

Swiper works line-wise, can't change that. So the thing could be in two places on a single line, with two different faces. That's one problem.

Additionally, faces apply to each character separately. Thing-at-point can have a different face for every single char. Suppose we restrict ourselves to only the cases where each entire match has face (plist-get (text-properties-at (point)) 'face). Then it can be done.

One more thing, the faces don't get assigned if the buffer is huge. See the code of swiper-font-lock-ensure. You can advise it to also work for huge buffers, but then you'll have to wait for a few seconds for swiper to start up.

Have a look at this code that's supposed to work, if we accept the above assumptions/restrictions:

(defvar swiper-like-this-face nil)

(defun swiper-like-this (&optional initial-input)
  "`isearch' with an overview using `ivy'.
When non-nil, INITIAL-INPUT is the initial search pattern."
  (interactive)
  (swiper--init)
  (setq swiper-like-this-face
        (plist-get (text-properties-at (point)) 'face))
  (let ((candidates (swiper--candidates))
        (preselect (buffer-substring-no-properties
                    (line-beginning-position)
                    (line-end-position)))
        (minibuffer-allow-text-properties t))
    (unwind-protect
         (ivy-read
          "Swiper: "
          candidates
          :initial-input initial-input
          :keymap swiper-map
          :preselect preselect
          :require-match t
          :update-fn #'swiper--update-input-ivy
          :unwind #'swiper--cleanup
          :action #'swiper--action
          :re-builder #'swiper--re-builder
          :matcher #'swiper--like-this-matcher
          :history 'swiper-history
          :caller 'swiper)
      (when (null ivy-exit)
        (goto-char swiper--opoint)))))

(defun swiper--like-this-matcher (regexp candidates)
  "Return REGEXP-matching CANDIDATES.
Skip some dotfiles unless `ivy-text' requires them."
  (cl-remove-if-not
   (lambda (x)
     (and
      (string-match regexp x)
      (let ((s (match-string 0 x))
            (i 0))
        (while (and (< i (length s))
                    (text-property-any
                     i (1+ i)
                     'face swiper-like-this-face
                     s))
          (cl-incf i))
        (eq i (length s)))))
   candidates))

If you like the code, I'll integrate it.

@redguardtoo

This comment has been minimized.

Show comment
Hide comment
@redguardtoo

redguardtoo Nov 11, 2015

Contributor

Yes, I like every line you wrote ;)

Contributor

redguardtoo commented Nov 11, 2015

Yes, I like every line you wrote ;)

@abo-abo abo-abo closed this in 7cf7575 Nov 11, 2015

@abo-abo

This comment has been minimized.

Show comment
Hide comment
@abo-abo

abo-abo Nov 11, 2015

Owner

Thanks for the suggestion and the testing. The C-c C-f toggle is now available for swiper.

Owner

abo-abo commented Nov 11, 2015

Thanks for the suggestion and the testing. The C-c C-f toggle is now available for swiper.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment