forked from plexus/chemacs2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
chemacs.el
170 lines (145 loc) · 7.26 KB
/
chemacs.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
;;; 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)