summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--display-graphic-p-cl-letf-and-themes.post89
1 files changed, 89 insertions, 0 deletions
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.
+
+<!-- Local Variables: -->
+<!-- mode: markdown -->
+<!-- End: -->