1

How can I let-bound a face-attribute locally. E.g. I want to:

(set-face-attribute 'query-replace nil :background "OrangeRed3")
(perform-replace "bar" "foo" t t nil 1 nil (point-min) (point-max))

and then restore the default query-replace background color. Is the a way to use let to do that?

EDIT. I need a solution that will restore the default value even if I quit the command perform-replace.

2 Answers 2

3

No, the attributes of a face are global. Using face-remapping-alist you can make them buffer local, which won't make you happy.

In your case, I would recommend that you define a new face, say my-performed-replacements with your preferred background.

When replacing text, you could remap all occurrences of query-replace with my-performed-replacements. It would take some non-trivial elisp, but it is certainly doable.

5
  • +1 to the answer and to the question (even if misstated in terms of let binding - that's in fact how the question would naturally be posed).
    – Drew
    Commented Jun 7, 2017 at 17:11
  • 1
    +1 I completely agree with your advice, I just wish to point out a technicality. Face attributes are indeed global, but so are all dynamically scoped variables. Against your best advice, they can still be temporarily modified: (let* ((face 'default) (bg (face-background face))) (set-face-background face "OrangeRed3") (sit-for 2) (set-face-background face bg))
    – Basil
    Commented Jun 7, 2017 at 17:18
  • @Basil I tried you solution but the problem is that, if I keyboard-quit (C-g) the perform-replacement, the default value will not be restored. I need a solution that will restore the default value if I quit the replacement.
    – Gabriele
    Commented Jun 7, 2017 at 17:59
  • @GabrieleNicolardi I think you can handle that using unwind-protect, though I haven't tested this and there could be a better way: (let ((bg ...)) (unwind-protect <body> (set-face-background <face> bg)))
    – Basil
    Commented Jun 7, 2017 at 18:59
  • @Basil Thank you! This now works fine and does exactly what I need. I think you should write a complete answer to my question. I'd accept it.
    – Gabriele
    Commented Jun 7, 2017 at 20:14
0

OK, I accepted the Lindydancer answer but I also got what I need from Basil's comments. I want to share the solution that fit my needs:

(let* ((face 'query-replace)
       (bg   (face-background face)))
  (set-face-background face "OrangeRed3")
  (unwind-protect
      (perform-replace "bar" "foo" t t nil 1 nil (point-min) (point-max))
    (set-face-background face bg)))
1
  • If this is what you were after, I'm fine with you accepting this answer instead of mine. (I must admit that I misunderstood the question, I though you were asking for a permanent change for faces inserted in the block.) Commented Jun 19, 2017 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.