;;; multi-emacs-config.el --- A tool to use multiple emacs configurations -*- lexical-binding: t; -*- ;; ;; Author: Rongsong Shen ;; ;;; Commentary: ;; ;; This package will enable us to use multiple EMACS startup ;; configuration(startkit in this package) and switch between ;; these configuration just by change a single environment ;; variable (EMACS_STARTKIT). ;; ;; Currently, we have test it with following: ;; - doom-emacs ;; - spacemacs ;; - frontmacs ;; - ohai-emacs ;; - graphene ;; - prelude ;; - radian emacs ;; ;;; Code: (require 'cl-lib) (require 'comint) (defvar emacs-start-kit (split-string (let ((start-kit (getenv "EMACS_STARTKIT"))) (if start-kit start-kit "easy-emacs")) ":") "The name of emacs startkit we will use") (defvar startkit-name (car emacs-start-kit) "The name of Emacs startkit") (defvar startkit-branch (let ((branch (cadr emacs-start-kit))) (if branch branch "master")) "The branch of emacs startkit") (defvar emacs-config-name startkit-name "The directory name of emacs startkit") (defvar emacs-config-directory (let ((config-dir (getenv "EMACS_CONFIG_DIR"))) (if config-dir (format "%s/%s.%s" config-dir startkit-name startkit-branch) (format "%s/.config/emacs/%s.%s" (getenv "HOME") startkit-name startkit-branch))) "The based directory of emacs start configuration") (defvar startkit-info nil "Information to install emacs startkit") (defvar emacs-base-directory (format "%s/Emacs/%s.%s" (getenv "HOME") startkit-name startkit-branch) "The base directory which Emacs startkit will be put") (defvar emacs-init-file (concat emacs-base-directory "/" "/init.el") "The full path of emacs start file") (unless (file-exists-p emacs-config-directory) (make-directory emacs-config-directory t)) ;; setup customization directory for emacs (custom.el) (unless custom-file (setq custom-file (expand-file-name "custom.el" emacs-config-directory))) ;; Setup default directory which package will be installed (setq package-user-dir (concat emacs-config-directory "/elpa")) ;; setup directory of spacemacs customization (when (string= startkit-name "spacemacs") (let ((spacemacs-dir (concat emacs-config-directory "/.local/etc"))) (progn (setenv "SPACEMACSDIR" spacemacs-dir)))) (defun my-doom-dir (config-dir) (concat config-dir "/doom")) (defun my-doom-local-dir (config-dir) (concat config-dir "/local")) (defun gen-doom-install-script (branch install-dir config-dir) (if (string= branch "master") (list (format "git clone https://github.com/hlissner/doom-emacs.git %s" install-dir) (format "cd %s" install-dir) (format "./bin/doom -y --doomdir %s --localdir %s install" (my-doom-dir config-dir) (my-doom-local-dir config-dir))) (list (format "git clone -b %s https://github.com/hlissner/doom-emacs.git %s" branch install-dir) (format "cd %s" install-dir) (format "./bin/doom -y --doomdir %s --localdir %s install" (my-doom-dir config-dir) (my-doom-local-dir config-dir))))) (defun doom-load (install-dir config-dir) (progn (setenv "DOOMDIR" (my-doom-dir config-dir)) (setenv "DOOMLOCALDIR" (my-doom-local-dir config-dir)) (load-file emacs-init-file))) (defun gen-easy-install-script (branch install-dir config-dir) (if (string= branch "master") (list (format "git clone git@shenrs.eu:rshen/easy-emacs.git %s" install-dir)) (list (format "git clone -b %s git@shenrs.eu:rshen/easy-emacs.git %s" branch install-dir)))) (defun easy-emacs-load (install-dir config-dir) (progn (setenv "EASYEMACSDATA" config-dir) (setenv "EASYEMACSDIR" install-dir) (load-file emacs-init-file))) (setq startkit-info '((doom-emacs . (gen-doom-install-script . doom-load)) (easy-emacs . (gen-easy-install-script . easy-emacs-load)))) (defun get-startkit-installer-gen-fn (name startkit-info) (car (cdr (assoc name startkit-info)))) (defun get-startkit-loader (name startkit-info) (cdr (cdr (assoc name startkit-info)))) (defun load-emacs () ;; use emacs config directory as user-emacs-directory (setq user-emacs-directory emacs-config-directory) (funcall (get-startkit-loader (intern startkit-name) startkit-info) emacs-base-directory emacs-config-directory)) (defun on-installer-finished (process event) "Callback function when uinstaller process has finished. We use this function to load startkit initialization file" (cond ((string= event "finished\n") (load-emacs)) (t (message "Event %s has been ignored" event)))) (defun install-emacs-startkit (name branch location config-dir) "Function to install EMACS startkit. NAME is the name of EMACS startkit. LOCATION is the target directory which startkit will be installed." (progn (let* ((shell-buffer (make-comint-in-buffer "installer" nil "/bin/sh")) (shell-process (get-buffer-process shell-buffer))) (progn (set-process-sentinel shell-process 'on-installer-finished) (display-buffer shell-buffer) (cl-loop for cmd in (funcall (get-startkit-installer-gen-fn (intern name) startkit-info) branch location config-dir) do (comint-simple-send shell-process (concat cmd "\n"))) (comint-simple-send shell-process "exit\n"))))) (if (not (file-exists-p emacs-init-file)) (progn (install-emacs-startkit startkit-name startkit-branch emacs-base-directory emacs-config-directory)) (load-emacs)) (provide 'multi-emacs-config) ;;; multi-emacs-config.el ends here