mirror of https://github.com/Flinner/dots.git
				
				
				
			
		
			
				
	
	
		
			171 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
	
;;; chemacs.el --- -*- lexical-binding: t; -*-
 | 
						|
;;; Commentary:
 | 
						|
;; ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 | 
						|
;;
 | 
						|
;;       ___           ___           ___           ___           ___           ___           ___
 | 
						|
;;      /  /\         /__/\         /  /\         /__/\         /  /\         /  /\         /  /\
 | 
						|
;;     /  /:/         \  \:\       /  /:/_       |  |::\       /  /::\       /  /:/        /  /:/_
 | 
						|
;;    /  /:/           \__\:\     /  /:/ /\      |  |:|:\     /  /:/\:\     /  /:/        /  /:/ /\
 | 
						|
;;   /  /:/  ___   ___ /  /::\   /  /:/ /:/_   __|__|:|\:\   /  /:/~/::\   /  /:/  ___   /  /:/ /::\
 | 
						|
;;  /__/:/  /  /\ /__/\  /:/\:\ /__/:/ /:/ /\ /__/::::| \:\ /__/:/ /:/\:\ /__/:/  /  /\ /__/:/ /:/\:\
 | 
						|
;;  \  \:\ /  /:/ \  \:\/:/__\/ \  \:\/:/ /:/ \  \:\~~\__\/ \  \:\/:/__\/ \  \:\ /  /:/ \  \:\/:/~/:/
 | 
						|
;;   \  \:\  /:/   \  \::/       \  \::/ /:/   \  \:\        \  \::/       \  \:\  /:/   \  \2.0 /:/
 | 
						|
;;    \  \:\/:/     \  \:\        \  \:\/:/     \  \:\        \  \:\        \  \:\/:/     \__\/ /:/
 | 
						|
;;     \  \::/       \  \:\        \  \::/       \  \:\        \  \:\        \  \::/        /__/:/
 | 
						|
;;      \__\/         \__\/         \__\/         \__\/         \__\/         \__\/         \__\/
 | 
						|
;;
 | 
						|
;; ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 | 
						|
;;
 | 
						|
;; Chemacs - Emacs Profile Switcher
 | 
						|
;;
 | 
						|
;; See README.md for instructions.
 | 
						|
 | 
						|
;; NOTE Don't require any libraries in this file. When emacs loads a library that
 | 
						|
;; is byte compiled, it may start native-compiling it, so if we require anything
 | 
						|
;; here, native compilation can start before the user has had a chance to configure
 | 
						|
;; it in their init files.
 | 
						|
 | 
						|
;;; Code:
 | 
						|
(defvar chemacs-version "2.0")
 | 
						|
(defvar config-home (or (getenv "XDG_CONFIG_HOME") "~/.config"))
 | 
						|
(defvar chemacs-profiles-paths (list "~/.emacs-profiles.el" (format "%s/%s" config-home "chemacs/profiles.el" )))
 | 
						|
(defvar chemacs-default-profile-paths (list "~/.emacs-profile" (format "%s/%s" config-home "chemacs/profile")))
 | 
						|
 | 
						|
;; Copy `seq' library's `seq-filter' to avoid requiring it, see note above.
 | 
						|
(defun chemacs--seq-filter (pred sequence)
 | 
						|
  (let ((exclude (make-symbol "exclude")))
 | 
						|
    (delq exclude (mapcar (lambda (elt)
 | 
						|
                            (if (funcall pred elt)
 | 
						|
                                elt
 | 
						|
                              exclude))
 | 
						|
                          sequence))))
 | 
						|
 | 
						|
(defvar chemacs-profiles-path (or (car (chemacs--seq-filter #'file-exists-p chemacs-profiles-paths))
 | 
						|
                                  (car chemacs-profiles-paths)))
 | 
						|
(defvar chemacs-default-profile-path (or (car (chemacs--seq-filter #'file-exists-p chemacs-default-profile-paths))
 | 
						|
                                         (car chemacs-default-profile-paths)))
 | 
						|
 | 
						|
(defun chemacs-handle-command-line (args)
 | 
						|
  (when args
 | 
						|
    ;; Handle either --with-profile profilename or
 | 
						|
    ;; --with-profile=profilename
 | 
						|
    (let ((s (split-string (car args) "=")))
 | 
						|
      (cond ((equal (car args) "--with-profile")
 | 
						|
             ;; This is just a no-op so Emacs knows --with-profile
 | 
						|
             ;; is a valid option. If we wait for
 | 
						|
             ;; command-switch-alist to be processed then
 | 
						|
             ;; after-init-hook has already run.
 | 
						|
             (add-to-list 'command-switch-alist
 | 
						|
                          '("--with-profile" .
 | 
						|
                            (lambda (_) (pop command-line-args-left))))
 | 
						|
             (cadr args))
 | 
						|
 | 
						|
            ;; Similar handling for `--with-profile=profilename'
 | 
						|
            ((equal (car s) "--with-profile")
 | 
						|
             (add-to-list 'command-switch-alist `(,(car args) . (lambda (_))))
 | 
						|
             (mapconcat 'identity (cdr s) "="))
 | 
						|
 | 
						|
            (t (chemacs-handle-command-line (cdr args)))))))
 | 
						|
 | 
						|
(defvar chemacs--with-profile-value
 | 
						|
  (let* ((value (chemacs-handle-command-line command-line-args))
 | 
						|
         (read-value (read value)))
 | 
						|
    (when value
 | 
						|
      (if (listp read-value)
 | 
						|
          read-value
 | 
						|
        value))))
 | 
						|
 | 
						|
(defvar chemacs-literal-profile-provided
 | 
						|
  (and chemacs--with-profile-value
 | 
						|
       (listp chemacs--with-profile-value)))
 | 
						|
 | 
						|
(unless (or (file-exists-p chemacs-profiles-path)
 | 
						|
            (and chemacs--with-profile-value
 | 
						|
                 (listp chemacs--with-profile-value)))
 | 
						|
  (error "[chemacs] %s does not exist." chemacs-profiles-path))
 | 
						|
 | 
						|
(defvar chemacs-default-profile-name
 | 
						|
  (if (file-exists-p chemacs-default-profile-path)
 | 
						|
      (with-temp-buffer
 | 
						|
        (insert-file-contents chemacs-default-profile-path)
 | 
						|
        (goto-char (point-min))
 | 
						|
        ;; (buffer-string))
 | 
						|
        (symbol-name (read (current-buffer)) ))
 | 
						|
    "default"))
 | 
						|
 | 
						|
 | 
						|
(defvar chemacs-profile-name
 | 
						|
  (if (and chemacs--with-profile-value
 | 
						|
           (stringp chemacs--with-profile-value))
 | 
						|
      chemacs--with-profile-value
 | 
						|
    chemacs-default-profile-name))
 | 
						|
 | 
						|
(defvar chemacs-profile
 | 
						|
  (if (and chemacs--with-profile-value
 | 
						|
           (listp chemacs--with-profile-value))
 | 
						|
      chemacs--with-profile-value
 | 
						|
      (let ((profiles
 | 
						|
         (with-temp-buffer
 | 
						|
           (insert-file-contents chemacs-profiles-path)
 | 
						|
           (goto-char (point-min))
 | 
						|
           (read (current-buffer)))))
 | 
						|
    (cdr (assoc chemacs-profile-name profiles)))))
 | 
						|
 | 
						|
(unless chemacs-profile
 | 
						|
  (error "No profile `%s' in %s" chemacs-profile-name chemacs-profiles-path))
 | 
						|
 | 
						|
(defun chemacs-profile-get (key &optional default)
 | 
						|
  (alist-get key chemacs-profile default))
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
(setq user-emacs-directory (file-name-as-directory
 | 
						|
                            (chemacs-profile-get 'user-emacs-directory)))
 | 
						|
 | 
						|
;; Allow multiple profiles to each run their server
 | 
						|
;; use `emacsclient -s profile_name' to connect
 | 
						|
(let ((name (chemacs-profile-get 'server-name)))
 | 
						|
  (when name (setq server-name name)))
 | 
						|
 | 
						|
;; Set environment variables, these are visible to init-file with
 | 
						|
;; getenv
 | 
						|
(mapcar (lambda (env)
 | 
						|
          (setenv (car env) (cdr env)))
 | 
						|
        (chemacs-profile-get 'env))
 | 
						|
 | 
						|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
						|
 | 
						|
(defun chemacs-load-user-early-init ()
 | 
						|
  (let ((early-init-file (expand-file-name "early-init.el" user-emacs-directory)))
 | 
						|
    (load early-init-file t t)))
 | 
						|
 | 
						|
(defun chemacs-load-user-init ()
 | 
						|
  (when (chemacs-profile-get 'straight-p) (chemacs-load-straight))
 | 
						|
  (let ((init-file (expand-file-name "init.el" user-emacs-directory)))
 | 
						|
    (setq package-user-dir (expand-file-name "elpa" user-emacs-directory))
 | 
						|
    (load init-file t t)
 | 
						|
    ;; Prevent customize from changing ~/.emacs (this file), but if
 | 
						|
    ;; init.el has set a value for custom-file then don't touch it.
 | 
						|
    (let ((chemacs-custom-file (chemacs-profile-get 'custom-file init-file)))
 | 
						|
      (when (not custom-file)
 | 
						|
        (setq custom-file chemacs-custom-file)
 | 
						|
        (unless (equal custom-file init-file)
 | 
						|
          (unless (file-exists-p custom-file)
 | 
						|
            (with-temp-buffer (write-file custom-file)))
 | 
						|
          (load custom-file))))))
 | 
						|
 | 
						|
(defun chemacs-load-straight ()
 | 
						|
  (defvar bootstrap-version)
 | 
						|
  (let ((bootstrap-file (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
 | 
						|
        (bootstrap-version 5))
 | 
						|
    (unless (file-exists-p bootstrap-file)
 | 
						|
      (with-current-buffer
 | 
						|
          (url-retrieve-synchronously
 | 
						|
           "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
 | 
						|
           'silent 'inhibit-cookies)
 | 
						|
        (goto-char (point-max))
 | 
						|
        (eval-print-last-sexp)))
 | 
						|
    (load bootstrap-file nil 'nomessage)))
 | 
						|
 | 
						|
(provide 'chemacs)
 |