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

Candidates with font-lock-face properties. #1293

Closed
TonCherAmi opened this issue Nov 19, 2017 · 9 comments
Closed

Candidates with font-lock-face properties. #1293

TonCherAmi opened this issue Nov 19, 2017 · 9 comments

Comments

@TonCherAmi
Copy link

@TonCherAmi TonCherAmi commented Nov 19, 2017

Hey, is it currently possible to get ivy to highlight candidates with font-lock-face properties?
For example, I'd like to use ansi-color-apply on the output of some shell command and then pass the result to ivy-read:

(let* ((output (shell-command-to-string "ls -l --color=always ~/"))
       (cands (mapcar #'ansi-color-apply (split-string output "\n"))))
  (ivy-read "prompt -> " cands))

Thank you very much for this project by the way, it is absolutely fantastic.

@abo-abo
Copy link
Owner

@abo-abo abo-abo commented Nov 19, 2017

Here's how to do this normally:

(defun ivy-ls ()
  (interactive)
  (let ((cands (split-string (shell-command-to-string "ls -l --color=always ~/")  "\n")))
    (ivy-read "prompt -> " cands
              :caller 'ivy-ls)))

(defun ivy-ls-display-transformer (str)
  (ansi-color-apply str))

(ivy-set-display-transformer 'ivy-ls 'ivy-ls-display-transformer)

The only issue is that the ivy-ls-display-transformer doesn't work as it should, since ansi-color-apply applies font-lock-face and not face property.

Here's a small hack that I've found that makes it work, don't ask me how:

(defun ivy-ls-display-transformer (str)
  (ivy-append-face
   (ansi-color-apply str) 'ivy-modified-buffer))

And finally, here's a solution that isn't a hack, but a bit longer:

(defun ivy-ls-display-transformer (str)
  (ivy-map-text-property
   (ansi-color-apply str)
   'font-lock-face (lambda (x) (cons 'face x))))

(defun ivy-map-text-property (str prop fun)
  (let ((start 0)
        (end (length str))
        next prev)
    (while (/= start end)
      (setq next (next-single-property-change start prop str end))
      (setq prev (get-text-property start prop str))
      (remove-text-properties start next (list prop) str)
      (when prev
        (let ((new (funcall fun prev)))
          (put-text-property start next (car new) (cdr new) str)))
      (setq start next))
    str))

Everything would be easy if ansi-color-apply simply applied face.

Thank you very much for this project by the way, it is absolutely fantastic.

Glad to hear it, and you're welcome.

@TonCherAmi
Copy link
Author

@TonCherAmi TonCherAmi commented Nov 19, 2017

Thanks, what you've suggested works almost perfectly except for one small thing - highlighting doesn't seem to work properly for the current match:

image

I have only the background set for the ivy-current-match face and other things that use highlighting work fine:

image

Is there any way to remedy this?

@TonCherAmi TonCherAmi closed this Dec 22, 2017
@dieggsy
Copy link
Contributor

@dieggsy dieggsy commented Dec 23, 2017

highlighting doesn't seem to work properly for the current match

@TonCherAmi did you find a solution to this? @abo-abo I basically have the same problem, though I use ivy-format-function-line.

@dieggsy
Copy link
Contributor

@dieggsy dieggsy commented Dec 23, 2017

As an example of what I'm working with:

(defun nmcli-ivy ()
  (interactive)
  (let* ((str (shell-command-to-string "nmcli -f IN-USE,SSID,BARS,SECURITY dev wifi list"))
         (lines (split-string str "\n" 'omit-nulls))
         (ssid-start (string-match-p "ssid" (car lines)))
         (ssid-end (string-match-p "bars" (car lines))))
    (ivy-read "[Networks] "
              (append
               (cdr lines)
               '("Rescan"))
              :action
              (lambda (x)
                (let ((cmd
                       (cond
                        ;; First do something if wifi
                        ((string-prefix-p "*" x)
                         "nmcli dev wifi disconnect")
                        ((string= x "Rescan")
                         "nmcli dev wifi rescan")
                        (t (format
                            "nmcli con up %s"
                            (substring x ssid-start ssid-end))))))
                  (start-process-shell-command cmd nil cmd)))
              :caller 'nmcli-ivy)))

(defun nmcli-ivy-transformer (str)
  (if (string-prefix-p "*" str)
      (propertize
       (string-trim (substring str 1))
       'face
       '(:foreground "#DD6F48"))
    (s-trim str)))

(ivy-set-display-transformer 'nmcli-ivy 'nmcli-ivy-transformer)
@TonCherAmi
Copy link
Author

@TonCherAmi TonCherAmi commented Dec 24, 2017

@dieggsy no, I have not unfortunately.

@TonCherAmi TonCherAmi reopened this Dec 24, 2017
abo-abo added a commit that referenced this issue Dec 24, 2017
Test:

(progn
  (pop-to-buffer (get-buffer-create "*ivy--add-face*"))
  (erase-buffer)
  (let ((str #("One"
               0 3 (face
                    (:foreground "#DD6F48")))))
    (insert str "\n")
    (insert (ivy--add-face str 'ivy-current-match))))

Re #1293
@abo-abo
Copy link
Owner

@abo-abo abo-abo commented Dec 24, 2017

Thanks for the persistence, I can now reproduce the issue.

Here's the narrowed-down reproduction scenario:

(progn
  (pop-to-buffer (get-buffer-create "*ivy--add-face*"))
  (erase-buffer)
  (let ((str #("One"
               0 3 (face
                    (:foreground "#DD6F48")))))
    (insert str "\n")
    (insert (ivy--add-face str 'ivy-current-match))))

So the problem here is ivy--add-face will replace the face with ivy-current-match instead of blending/extending the face foreground/background.

I've added a quick hack to colir-blend-face-background to address your specific use cases. If anyone is an expert on Emacs faces, any improvements to colir-blend-face-background are welcome.

@dieggsy That's a pretty cool function. Do you want to add it to counsel maybe?

abo-abo added a commit that referenced this issue Dec 24, 2017
* colir.el (colir--blend-background): Extract.

Re #1293
@dieggsy
Copy link
Contributor

@dieggsy dieggsy commented Dec 24, 2017

@abo-abo your workaround seems to be working for me.

Regarding counsel-nmcli, I'm still working on it (most recently tweaked to handle passing in passwords, for example), and I'd have to get a copyright assignment, but I'd love to.

@abo-abo
Copy link
Owner

@abo-abo abo-abo commented Dec 24, 2017

@dieggsy Great. Take your time. Thanks in advance.

@TonCherAmi
Copy link
Author

@TonCherAmi TonCherAmi commented Dec 25, 2017

@abo-abo seems to be working for me as well, thanks a lot.

@TonCherAmi TonCherAmi closed this Dec 25, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants