
Setting Emacs theme based on ambient light - mbil
https://matthewbilyeu.com/blog/2018-04-09/setting-emacs-theme-based-on-ambient-light
======
auxym
I've had this in my vimrc for a little while:

    
    
      let hr = (strftime('%H'))
      if hr >= 17
          set background=dark
      elseif hr >= 7
          set background=light
      elseif hr >= 0
          set background=dark
      endif
    

Using a light sensor would be cool, but I actually work from a desktop PC most
of the time, so no sensor. I guess the next best thing would be something like
f.lux does: query some web service for the sunset time at your current
location.

~~~
TwistedWave
It is possible to purchase a small USB lux meter:

[http://www.yoctopuce.com/EN/products/usb-environmental-
senso...](http://www.yoctopuce.com/EN/products/usb-environmental-
sensors/yocto-light-v3)

I use one to automatically adjust the brightness of my Dell display.

~~~
tobyhinloopen
what display and how do you control your display from your PC?

~~~
TwistedWave
I have a Dell P4317Q, a great 43 inch display, and control it from my Mac with
ddcctl: [https://github.com/kfix/ddcctl](https://github.com/kfix/ddcctl)

------
neic
There is also circadian.el to change themes based on sunset and sunrise.

[https://github.com/guidoschmidt/circadian.el](https://github.com/guidoschmidt/circadian.el)

------
kfoley
I really like this idea, it's something I've been wanting to try out for a
while now.

I'm curious if using `run-with-timer` causes any performance issues in emacs.
If so one option is to watch the value outside of emacs and then change the
theme using `emacsclient -d "(load-theme 'my-dark-theme t)"` from the script.

~~~
TeMPOraL
It looks like it could; the timer isn't the problem (they're just entries in a
queue), but #'shell-command-to-string call might be. It's a synchronous,
blocking call (at least on my Emacs 26, running (shell-command-to-string
"sleep 5") hangs the whole Emacs nicely for 5 seconds).

Personally, I'd reimplement it the way you suggest - I'd put the timer loop in
C code to save on repeatedly starting a process, and then make it run
emacsclient -e "(change-theme-for-lighting %d)", where %d is a sensor value,
whenever that value crosses a threshold.

Alternatively, if you want to keep the entire business logic within Emacs Lisp
code, there's some way to make it work too. I'd look into documentation of
#'make-process[0]. There's an argument :FILTER that would let you set a
function that receives stdout from that process. Alternatively, #'start-
process-shell-command with NIL for buffer, + #'set-process-filter should
achieve the same thing. So the C program would be barfing out the sensor value
every second or so, and the process filter would read it.

(You might also want to read through the sources of #'shell-command to see how
it uses the above facilities to handle asynchronous shell processes - the ones
you invoke with M-x async-shell-command - but I think it'll work out of the
box, and the process filter will only be executed as new output arrives.)

\--

[0] - in Emacs, type: C-h f make-process. Gotta love the self-documenting
features of this editor. Actually, half of my comment is based on what I just
read in docs of various Emacs functions. Also, hint: make sure you install
Emacs with sources - then you can easily jump from help buffer directly into
code implementing the thing you're reading about.

------
temp0198209812
You can leverage the existing sunrise-sunset function to determine if it is
day on night and change your theme accordingly.

(defun daytime? () (sunrise-sunset) (let ((range (mapcar 'car (butlast (solar-
sunrise-sunset (calendar-current-date)))))) (let ((sunrise (car range))
(sunset (cadr range)) (now (string-to-number (format-time-string "%H")))) (<
sunrise now sunset))))

(if (daytime?) (light) (dark))

------
Scarbutt
is the background color really the problem? I though screen brightness was a
more issue, for example: continue using your light theme but lower down the
brightness, most of your websites are going to be white backgrounds, switch
between dark and light background frequently strains more the eyes, looking
for the link where I read this.

~~~
avhon1
In my own experience, many devices either:

* do not offer granular enough control of the brightness on the low end (the backlight is either kind of dim, or nearly/completely off, with no in-between setting), or they

* do not have enough contrast at low brightness to read easily.

In either case, the display is more readable by having the backlight on
bright, and darkening most of the display (by changing the background color).

Of course, this does not apply to all displays, but _every_ display has pretty
fine control its total light output by changing the colors it is displaying.

------
avcdsuia
That's why we need OLED displays to save our eyes. With OLED's pixels actually
produce their own light and dark pixels are just not glowing pixels, pure dark
background still provide maximum contrast on sunny days.

~~~
w0m
always-dark is the answer :)

------
todda7
How to do it on linux? there's a package iio-sensor-proxy but who knows how to
read out the ambient light from terminal.

~~~
shakna
Only way I've managed is using pillow's ImageStat against a webcam image.

If Gnome can read your ambient sensor then monitor-sensor is the cli tool from
that package to look at.

------
mattdemon
I sometimes do this manually:

M-x set-background-color snow2, snow3, or snow4

or wheat2, wheat3, wheat4. or MistyRose1, MistyRose2, MistyRose3.

------
atheriel
This is really neat, but I'm wondering if you are better off triggering the
change by sending SIGUSR1 to the Emacs process [0]. This would remove the need
to run the function in a timer every 1s.

[0]:[https://www.gnu.org/software/emacs/manual/html_node/elisp/Mi...](https://www.gnu.org/software/emacs/manual/html_node/elisp/Misc-
Events.html)

------
ddavis
Thanks for sharing, this is really cool. I often struggle with my Emacs theme
switching between light and dark traveling in and out of my windowless office
which is filled with intense unnatural night. I once tried to write some Elisp
for determining my theme based on the network I was connected to, didn’t work
out. I’ll definitely try using this!

------
mixmastamyk
Neat. I've done that on the occasional web site, although matched to time of
sunrise/sunset. I imagine reading from a light sensor is more accurate, but it
isn't available everywhere yet:

[https://caniuse.com/#search=ambient](https://caniuse.com/#search=ambient)

~~~
willtim
If you are running Linux, iio-sensor-proxy might be worth a try.

------
lprd
I'm not an Emacs user, but this is really cool. Are there any equivalents for
vim? Typically, I just set my theme for my shell and vim through base16.

------
newusertoday
Off-topic, is there a way to control chrome/firefox through emacs or elisp?
something similar to [https://github.com/ChromeDevTools/awesome-chrome-
devtools#ch...](https://github.com/ChromeDevTools/awesome-chrome-
devtools#chrome-devtools-protocol).

------
saagarjha
I have something similar, except it's based on sunrise/sunset. It hooks into
my Mac's Night Shift timer to also enable dark mode and a darker color scheme
in all my text editors when it's getting close to sunset, and undo it when the
sun rises.

