tvl-depot/configs/shared/emacs/.emacs.d/elpa/cycle-themes-20150402.2009/cycle-themes.el
William Carroll 17ee0e400b Support Vim, Tmux, Emacs with Stow
After moving off of Meta, Dotfiles has a greater responsibility to
manage configs. Vim, Tmux, and Emacs are now within Stow's purview.
2018-09-10 14:53:23 -04:00

155 lines
5.4 KiB
EmacsLisp

;;; cycle-themes.el --- A global minor mode to make switching themes easier
;; Copyright (C) 2015 Katherine Whitlock
;;
;; Authors: Katherine Whitlock <toroidalcode@gmail.com>
;; URL: http://github.com/toroidal-code/cycle-themes.el
;; Package-Version: 20150402.2009
;; Version: 1.0
;; Package-Requires: ((cl-lib "0.5"))
;; Keywords: Themes, Utility, Global Minor Mode
;; This file is not part of GNU Emacs.
;;; Commentary:
;; Allows switching between themes easily.
;;; Installation
;; In your Emacs config, define a list of themes you want to be
;; able to switch between. Then, enable the global minor mode.
;;
;; (setq cycle-themes-theme-list
;; '(leuven monokai solarized-dark))
;; (require 'cycle-themes)
;; (cycle-themes-mode)
;;
;; `cycle-themes' is bound to 'C-c C-t' by default.
;;
;; You can optionally add hooks to be run after switching themes:
;;
;; (add-hook 'cycle-themes-after-cycle-hook
;; #'(lambda () (Do-something-fn ...)))
;;
;;; License:
;; This program is free software; you can redistribute it and/or modify it under
;; the terms of the GNU General Public License as published by the Free Software
;; Foundation; either version 3 of the License, or (at your option) any later
;; version.
;;
;; This program is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
;; details.
;;
;; You should have received a copy of the GNU General Public License along with
;; GNU Emacs; see the file COPYING. If not, write to the Free Software
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
;; USA.
;;; Code:
(eval-when-compile
(require 'cl-lib))
(defgroup cycle-themes nil
"The cycle-themes group"
:group 'appearance
:prefix "cycle-themes-")
(defcustom cycle-themes-after-cycle-hook nil
"Hooks that are run after switching themes."
:group 'cycle-themes
:type 'hook)
(defcustom cycle-themes-theme-list (custom-available-themes)
"The list of themes to cycle through on calling `cycle-themes'."
:group 'cycle-themes
:type '(list symbol))
(defcustom cycle-themes-allow-multiple-themes nil
"Whether to allow the application of more than one theme at once."
:group 'cycle-themes
:type 'boolean)
(defconst cycle-themes-last-theme-set custom-enabled-themes
"Used with multiple theme layering.")
(defconst cycle-themes-first-start t
"load-theme reapplies all minor-modes, so we need this to avoid a stack overflow.")
(defun cycle-themes-get-next-valid-theme ()
"Get the next valid theme from the list."
;; save our starting theme for a infinite-loop check
;; if there's no theme applied,
(let* ((start-theme (or (first custom-enabled-themes)
(car (last cycle-themes-theme-list))))
(current-theme start-theme))
;; do-while
(while
(progn
;; Fancy way to move to the next theme
;; with modular arithmetic so we never reach the end.
(setq current-theme
(nth (mod (1+ (cl-position current-theme cycle-themes-theme-list))
(length cycle-themes-theme-list))
cycle-themes-theme-list))
;; Make sure we didn't loop all the way through
(when (eq current-theme start-theme)
(error "No valid themes in cycle-themes-theme-list"))
(not (custom-theme-p current-theme))))
current-theme))
(defun cycle-themes ()
"Cycle to the next theme."
(interactive)
(let ((new-theme (cycle-themes-get-next-valid-theme))
(current-theme (first custom-enabled-themes))
(current-theme-set custom-enabled-themes))
;; disable the current theme only if we want multiple themes
;; and we had it before
(unless (and cycle-themes-allow-multiple-themes
(member current-theme cycle-themes-last-theme-set))
(disable-theme current-theme))
(load-theme new-theme t)
(setq cycle-themes-last-theme-set current-theme-set)
(run-hooks 'cycle-themes-after-cycle-hook)))
;;;###autoload
(define-minor-mode cycle-themes-mode
"Minor mode for cycling between themes."
:lighter ""
:keymap (let ((map (make-sparse-keymap)))
(define-key map (kbd "C-c C-t") 'cycle-themes)
map)
:global t
(progn
;; remove any lingering themes other than the primary
(dolist (theme (cl-set-difference (custom-available-themes)
custom-enabled-themes))
(disable-theme theme))
;; If we _aren't_ already trying to start up
(when cycle-themes-first-start
(setq cycle-themes-first-start nil)
;; if there are no themes enabled, enable
;; the first one in the list
(if (null custom-enabled-themes)
(add-hook 'emacs-startup-hook
#'(lambda ()
(load-theme (car cycle-themes-theme-list))
(run-hooks 'cycle-themes-after-cycle-hook)))
;; otherwise, ensure they're _actually_ loaded
(add-hook 'emacs-startup-hook #'(lambda ()
(dolist (theme (reverse custom-enabled-themes))
(load-theme theme))
(run-hooks 'cycle-themes-after-cycle-hook)))))))
(provide 'cycle-themes)
;;; cycle-themes.el ends here