时间自动加载Emacs主题颜色

17

我可以让Emacs自动加载主题吗?或者在特定时间执行某些命令?比如我想在早上9点在办公室时使用 M-x load-theme RET solarized-light,晚上8点回到家继续使用Emacs时使用M-x laod-theme RET solarized-dark

6个回答

16

在@Anton Kovalenko的答案基础上,你可以使用elisp函数current-time-string获取当前时间,并提取当前时间的小时数。

如果你想编写一个完整的实现,可以像下面这样做(警告,未调试):

;; <Color theme initialization code>
(setq current-theme '(color-theme-solarized-light))

(defun synchronize-theme ()
    (setq hour 
        (string-to-number 
            (substring (current-time-string) 11 13)))
    (if (member hour (number-sequence 6 17))
        (setq now '(color-theme-solarized-light))
        (setq now '(color-theme-solarized-dark))) 
    (if (equal now current-theme)
        nil
        (setq current-theme now)
        (eval now) ) ) ;; end of (defun ...

(run-with-timer 0 3600 synchronize-theme)

有关所使用的函数的更多信息,请参见emacs手册中的以下部分:


很好的例子。我每天都使用emacs,但从未尝试学习elisp。刚开始学习并跟随您的示例。它有效。谢谢。小提醒:应该是substring (current-time-string) 11 13)吗?没有括号?此外,在run-with-timer中在synchronize-theme之前添加'也可以。 - liuminzhao
@liuminzhao:您能否澄清需要修复什么(或直接自行修复)。 - Dan
经过一些错误修复后,它可以正常工作:(如果(eq现在current-theme)到(如果(equal now current-theme) - tangxinfa
@tangxinfa:随意编辑答案以修复错误。 - Dan

12

另一个非常优雅的解决方案是theme-changer

根据位置和昼夜色彩主题,该文件提供了一个更改主题函数,根据白天或黑夜选择适当的主题。它将在日出和日落时继续更改主题。安装方法如下:

设置位置:

(setq calendar-location-name "Dallas, TX") 
(setq calendar-latitude 32.85)
(setq calendar-longitude -96.85)

指定白天和夜间主题:

(require 'theme-changer)
(change-theme 'tango 'tango-dark)

该项目托管在Github上,可通过Melpa进行安装。


5
你可以使用这段代码来实现你想要的功能。
(defvar install-theme-loading-times nil
  "An association list of time strings and theme names.
The themes will be loaded at the specified time every day.")
(defvar install-theme-timers nil)
(defun install-theme-loading-at-times ()
  "Set up theme loading according to `install-theme-loading-at-times`"
  (interactive)
  (dolist (timer install-theme-timers)
(cancel-timer timer))
  (setq install-theme-timers nil)
  (dolist (time-theme install-theme-loading-times)
(add-to-list 'install-theme-timers
         (run-at-time (car time-theme) (* 60 60 24) 'load-theme (cdr time-theme)))))

只需根据需要自定义变量install-theme-loading-times
(setq install-theme-loading-times '(("9:00am" . solarized-light)
                ("8:00pm" . solarized-dark)))

跟随 @Dan 的代码,它可以工作。我也会通过你的代码学习elisp。谢谢。 - liuminzhao

2

我发现了一段适用于Doom Emacs的简单代码。将其放入配置文件中:

(load-theme 'solarized-light t t) ;;load light theme
(run-at-time "09:00" (* 60 60 24) (lambda () (enable-theme 'solarized-light)))
(load-theme 'solarized-dark t t) ;;load dark theme
(run-at-time "20:00" (* 60 60 24) (lambda () (enable-theme 'solarized-dark)))

您可以选择自己喜欢的亮色或暗色主题。时间格式为24小时制,可以从上午9点/下午8点进行更改。

来源和出处:https://parasurv.neocities.org/emacs/change-emacs-theme-depending-on-time.html


2
你可以从run-with-timer函数开始:
(run-with-timer SECS REPEAT FUNCTION &rest ARGS)

Perform an action after a delay of SECS seconds.
Repeat the action every REPEAT seconds, if REPEAT is non-nil.
SECS and REPEAT may be integers or floating point numbers.
The action is to call FUNCTION with arguments ARGS.

This function returns a timer object which you can use in `cancel-timer'.

安排一个函数每隔一分钟运行一次,它将检查当前时间并在适当时调用load-theme(即使重新加载当前主题,也不要每分钟切换主题)。


感谢您的指引。根据@Dan的代码,我想我已经弄清楚了。谢谢。 - liuminzhao

1

这个实现根据您提供的纬度和经度的日出和日落时间更改主题。唯一的依赖关系是 solar.el,它与Emacs一起发布(如果我没记错的话)。

(我认为这里的代码可能可以更短。)

;; theme changing at sunrises and sunsets according to lat and long
(require 'solar)

(defun today-date-integer (offset)
  "Returns today's date in a list of integers, i.e. month, date, and year, in system time."
  (let* ((date (mapcar
   (lambda (pattern)
     (string-to-number (format-time-string pattern)))
   '("%m" "%d" "%Y"))))
    (setcar
   (nthcdr
    1
    date)
   (+ offset (nth 1 date)))
    date))

(defun current-time-decimal ()
  (let* ((current-min-fraction (/ (string-to-number (format-time-string "%M")) 60.0))
    (current-hour (string-to-number (format-time-string "%H"))))
    (+ current-hour current-min-fraction)))

(defun next-alarm-time (sunrise-time sunset-time)
  (let* ((current-time (current-time-decimal)))
   (cond ((< current-time sunrise-time)
       (- sunrise-time current-time))
    ((and (>= current-time sunrise-time)
          (< current-time sunset-time))
      (- sunset-time current-time))
    ((>= current-time sunset-time)
     (let ((tomorrow-sunrise-time (car (car (solar-sunrise-sunset (today-date-integer 1))))))
       (- (+ 24 tomorrow-sunrise-time) current-time))))))

(defun to-seconds (hour) (* hour 60 60))

(defun change-theme (light-theme dark-theme coor)
  (let* ((_ (setq calendar-latitude (car coor)))
    ( _ (setq calendar-longitude (nth 1 coor)))
    (today-date (today-date-integer 0))
    (sunrise-sunset-list (solar-sunrise-sunset today-date))
    (sunrise-time (car (car sunrise-sunset-list)))
    (sunset-time (car (nth 1 sunrise-sunset-list)))
    (current-time (current-time-decimal))
    (current-theme (if (or (< current-time sunrise-time) (> current-time sunset-time))
             dark-theme
             light-theme))
    (next-alarm-t (next-alarm-time sunrise-time sunset-time)))
    (cancel-function-timers 'change-theme)
    (load-theme current-theme t)
    (run-at-time
     (to-seconds next-alarm-t) nil 'change-theme light-theme dark-theme coor)))

(change-theme 'solarized-gruvbox-light 'solarized-gruvbox-dark '(47.6062 -122.3321))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接