90 lines
3.3 KiB
Text
90 lines
3.3 KiB
Text
|
;;;;;
|
||
|
title: display-graphic-p, cl-letf and themes
|
||
|
tags: emacs, elisp
|
||
|
date: 2014-10-27 21:18
|
||
|
format: md
|
||
|
;;;;;
|
||
|
|
||
|
I had a problem with my
|
||
|
[theme](https://github.com/ryuslash/yoshi-theme) a while where the
|
||
|
colors would be different depending on whether I was starting Emacs as
|
||
|
a daemon or not. The `colors` module has some code that changes the
|
||
|
way it works depending on whether a graphical or non-graphical display
|
||
|
is run. This was messing with some of the colors in my theme.
|
||
|
|
||
|
My first thought was that it should just wait until the first frame is
|
||
|
created before setting the theme. For a while this worked.
|
||
|
|
||
|
``` emacs-lisp
|
||
|
(if (daemonp)
|
||
|
(add-hook 'after-make-frame-functions
|
||
|
(lambda (frame) (load-theme 'yoshi t)))
|
||
|
(add-hook 'emacs-startup-hook (lambda () (load-theme 'yoshi t))))
|
||
|
```
|
||
|
|
||
|
Some time later, that stopped working, because apparently
|
||
|
`display-graphic-p` stopped returning true during the execution of the
|
||
|
`after-make-frame-functions` hook. So I set out to change it so it
|
||
|
would work again. This would have been easy in earlier versions of
|
||
|
Emacs, where `flet` wasn't yet deprecated.
|
||
|
|
||
|
``` emacs-lisp
|
||
|
(if (daemonp)
|
||
|
(add-hook 'after-make-frame-functions
|
||
|
(lambda (frame)
|
||
|
(flet ((display-graphic-p () t))
|
||
|
(load-theme 'yoshi t))))
|
||
|
(add-hook 'emacs-startup-hook (lambda () (load-theme 'yoshi t))))
|
||
|
```
|
||
|
|
||
|
Unfortunately, as stated, `flet` is deprecated. Whenever you compile
|
||
|
it you're warned and told that you should use `cl-flet` or `cl-letf`
|
||
|
instead. I couldn't quite figure out how, though. `cl-flet` does
|
||
|
almost the same thing as `flet`, but lexically, so you can't
|
||
|
dynamically rebind `display-graphic-p` that way. `cl-letf` did't seem
|
||
|
to be anything like `flet` at all, so I didn't know how to ever use
|
||
|
that to accomplish this.
|
||
|
|
||
|
Thankfully, there was
|
||
|
[noflet](https://github.com/nicferrier/emacs-noflet). This, for my
|
||
|
purposes at least, works the same way as `flet` did. It is not part of
|
||
|
Emacs, however. But in this case I didn't know what else to do.
|
||
|
|
||
|
``` emacs-lisp
|
||
|
(if (daemonp)
|
||
|
(add-hook 'after-make-frame-functions
|
||
|
(lambda (frame)
|
||
|
(noflet ((display-graphic-p (&optional display) t))
|
||
|
(load-theme 'yoshi t))))
|
||
|
(add-hook 'emacs-startup-hook (lambda () (load-theme 'yoshi t))))
|
||
|
```
|
||
|
|
||
|
This worked perfectly, but I really don't like depending on external
|
||
|
packages for starting up emacs.
|
||
|
|
||
|
Then Artur Malabarba wrote a
|
||
|
[post](http://endlessparentheses.com/understanding-letf-and-how-it-replaces-flet.html)
|
||
|
about using `cl-letf` and things became very clear.
|
||
|
|
||
|
``` emacs-lisp
|
||
|
(if (daemonp)
|
||
|
(add-hook 'after-make-frame-functions
|
||
|
(lambda (frame)
|
||
|
(cl-letf (((symbol-function 'display-graphic-p))
|
||
|
(lambda (&optional display) t))
|
||
|
(load-theme 'yoshi-theme t))))
|
||
|
(add-hook 'emacs-startup-hook (lambda () (load-theme 'yoshi-theme t))))
|
||
|
```
|
||
|
|
||
|
It's a bit more involved than the `noflet` solution, but it does
|
||
|
remove a requirement from my `init.el`. What I failed to realize
|
||
|
before reading Artur's post is that `cl-letf` works a lot like Emacs'
|
||
|
new `setf`, which works a lot like Common Lisp's `setf`, which makes
|
||
|
it very powerful.
|
||
|
|
||
|
By now, my theme doesn't use the colors module anymore.
|
||
|
|
||
|
<!-- Local Variables: -->
|
||
|
<!-- mode: markdown -->
|
||
|
<!-- End: -->
|