Primary tabs

Настройка темы Emacs на основе внешнего освещения

Ссылка на оригинал - https://matthewbilyeu.com/blog/2018-04-09/setting-emacs-theme-based-on-ambient-l…, автор публикации - Matt Bilyeu

Я сижу рядом с окном на работе. В солнечные дни легче увидеть светлую тему редактора, а когда небо темное, темная тема становится легче для моих глаз. Поэтому я решил сделать так, чтобы мой MacBook автоматически переключал тему Emacs на основе показаний датчика внешней освещенности.

Демонстрация переключения темы в действии

Это решение состоит из двух частей: исполняемый файл командной строки для чтения данных с датчика и небольшая функция elisp для переключения тем.

Программа ниже от StackOverflow и немного изменена. Она получает AppleLMUController службу ввода-вывода, затем, когда служба готова, отправляет данные датчика освещенности на стандартный вывод и завершает работу.

// lmutracker.mm
//
// clang -o lmutracker lmutracker.mm -framework IOKit -framework CoreFoundation

#include <mach/mach.h>
#import <IOKit/IOKitLib.h>
#import <CoreFoundation/CoreFoundation.h>

static double updateInterval = 0.1;
static io_connect_t dataPort = 0;

void updateTimerCallBack(CFRunLoopTimerRef timer, void *info) {
  kern_return_t kr;
  uint32_t outputs = 2;
  uint64_t values[outputs];

  kr = IOConnectCallMethod(dataPort, 0, nil, 0, nil, 0, values, &outputs, nil, 0);
  if (kr == KERN_SUCCESS) {
    printf("%8lld", values[0]);
    exit(0);
  }

  if (kr == kIOReturnBusy) {
    return;
  }

  mach_error("I/O Kit error:", kr);
  exit(kr);
}

int main(void) {
  kern_return_t kr;
  io_service_t serviceObject;
  CFRunLoopTimerRef updateTimer;

  serviceObject = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleLMUController"));
  if (!serviceObject) {
    fprintf(stderr, "failed to find ambient light sensors\n");
    exit(1);
  }

  kr = IOServiceOpen(serviceObject, mach_task_self(), 0, &dataPort);
  IOObjectRelease(serviceObject);
  if (kr != KERN_SUCCESS) {
    mach_error("IOServiceOpen:", kr);
    exit(kr);
  }

  setbuf(stdout, NULL);

  updateTimer = CFRunLoopTimerCreate(kCFAllocatorDefault,
                  CFAbsoluteTimeGetCurrent() + updateInterval, updateInterval,
                  0, 0, updateTimerCallBack, NULL);
  CFRunLoopAddTimer(CFRunLoopGetCurrent(), updateTimer, kCFRunLoopDefaultMode);
  CFRunLoopRun();

  exit(0);
}

Прилагаемый код elisp вызовет этот исполняемый файл по таймеру и изменит тему на основе легкого чтения.

(setq current-theme "dark")
(defconst light-theme 'majapahit-light)
(defconst dark-theme 'majapahit-dark)

;; будет применять темную тему, если комната темная, и светлую тему, если комната
;; светлая
(defun change-theme-for-lighting ()
  (let* ((current-light-sensor-reading
          (string-to-number
           (shell-command-to-string "./lmutracker"))))
    (if (< current-light-sensor-reading 100000)
        (when (not (string-equal current-theme "dark"))
          (load-theme dark-theme 1)
          (setq current-theme "dark"))
      (when (not (string-equal current-theme "light"))
        (load-theme light-theme 1)
        (setq current-theme "light")))))

;; вероятно, нужно запускать реже, чем каждую секунду
(run-with-timer 0 1 #'change-theme-for-lighting)

Не нашли ответ на свой вопрос? Возможно, вы найдете решение проблемы на нашем канале в Youtube! Здесь мы собрали небольшие, но эффективные инструкции. Смотрите и подписывайтесь на наш youtube-канал!

Смотреть на Youtube