From 19fbe64c38b19227291bc236021daa56cadc49f8 Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Fri, 2 Jan 2015 20:08:44 +0100 Subject: Add old post --- display-graphic-p-cl-letf-and-themes.post | 89 +++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 display-graphic-p-cl-letf-and-themes.post diff --git a/display-graphic-p-cl-letf-and-themes.post b/display-graphic-p-cl-letf-and-themes.post new file mode 100644 index 0000000..6796f0a --- /dev/null +++ b/display-graphic-p-cl-letf-and-themes.post @@ -0,0 +1,89 @@ +;;;;; +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. + + + + -- cgit v1.2.3-54-g00ecf