forked from kaushalmodi/.emacs.d
-
Notifications
You must be signed in to change notification settings - Fork 0
/
setup-packages.el
225 lines (200 loc) · 10.5 KB
/
setup-packages.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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
;; Time-stamp: <2018-02-20 16:39:46 kmodi>
;; Package management
;; Loading of packages at startup
;; Load newer version of .el and .elc if both are available
(setq load-prefer-newer t)
(>=e "27.0"
nil
;; Lower-level `package.el' variables like `package-user-dir' need to be set
;; in early-init.el starting emacs 27.x.
;; http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=24acb31c04b4048b85311d794e600ecd7ce60d3b
(setq package-user-dir (let ((elpa-dir-name (format "elpa_%s" emacs-major-version))) ;default = "elpa"
(file-name-as-directory (expand-file-name elpa-dir-name user-emacs-directory)))))
;; Below require will auto-create `package-user-dir' it doesn't exist.
(require 'package)
(>=e "25.0"
(setq package-menu-async t)) ; If non-nil, do activities asynchronously, like refreshing menu
(defvar modi/elisp-directory (file-name-as-directory (expand-file-name "elisp" user-emacs-directory))
"Directory containing my custom elisp code.")
(add-to-list 'load-path modi/elisp-directory)
(add-to-list 'load-path (file-name-as-directory (expand-file-name "setup-files" user-emacs-directory)))
;; <prefix-dir>
;; ├── bin (`invocation-directory')
;; ├── share (`modi/default-share-directory')
;; │ ├── emacs
;; │ │ ├── site-lisp
;; │ │ ├── 27.0.50
;; │ │ │ ├── lisp (`modi/default-lisp-directory')
;; │ │ │ └── ..
;; │ │ └── ..
;; │ └── ..
;; └── ..
(defvar modi/default-share-directory nil
"Share directory for this Emacs installation.")
(defvar modi/default-lisp-directory nil
"Directory containing lisp files for the Emacs installation.
This value must match the path to the lisp/ directory of the
Emacs installation. If Emacs is installed using
--prefix=\"${PREFIX_DIR}\" this value would typically be
\"${PREFIX_DIR}/share/emacs/<VERSION>/lisp/\".")
(let* ((bin-dir (when (and invocation-directory
(file-exists-p invocation-directory))
(file-truename invocation-directory)))
(prefix-dir (when bin-dir ;Because bin-dir = prefix-dir + "bin/"
(file-name-directory (directory-file-name bin-dir))))
(share-dir (when prefix-dir
(let ((share-dir-1 (file-name-as-directory (expand-file-name "share" prefix-dir))))
(when (file-exists-p share-dir-1)
(setq modi/default-share-directory share-dir-1))
share-dir-1)))
(version-dir (when share-dir
(let* ((emacs-dir (file-name-as-directory (expand-file-name "emacs" share-dir)))
;; Possibility where the lisp dir is something like
;; ../emacs/26.0.50/lisp/. If `emacs-version' is
;; x.y.z.w, remove the ".w" portion.
;; http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=22b2207471807bda86534b4faf1a29b3a6447536
(version (replace-regexp-in-string "\\([0-9]+\\.[0-9]+\\.[0-9]+\\).*" "\\1" emacs-version))
(version-dir-1 (file-name-as-directory (expand-file-name version emacs-dir))))
(if (file-exists-p version-dir-1)
version-dir-1
;; Possibility where the lisp dir is something like
;; ../emacs/25.2/lisp/. If `emacs-version' is x.y.z,
;; remove the ".z" portion.
(setq version (replace-regexp-in-string "\\([0-9]+\\.[0-9]+\\).*" "\\1" emacs-version))
(setq version-dir-1 (file-name-as-directory (expand-file-name version emacs-dir)))
(when (file-exists-p version-dir-1)
version-dir-1))))))
;; (message "setup-packages:: bin-dir: %s" bin-dir)
;; (message "setup-packages:: prefix-dir: %s" prefix-dir)
;; (message "setup-packages:: share-dir: %s" share-dir)
;; (message "setup-packages:: version-dir: %s" version-dir)
(when version-dir
(let ((lisp-dir-1 (file-name-as-directory (expand-file-name "lisp" version-dir))))
(when (file-exists-p lisp-dir-1)
(setq modi/default-lisp-directory lisp-dir-1)))))
;; Add theme paths
(add-to-list 'custom-theme-load-path
(file-name-as-directory (expand-file-name "zenburn-emacs" modi/elisp-directory)))
(add-to-list 'custom-theme-load-path
(file-name-as-directory (expand-file-name "smyx" modi/elisp-directory)))
;; Add melpa package source when using package list
;; Fri Nov 17 17:05:12 EST 2017 - kmodi
;; The `system-type' for emacs in WSL is `gnu/linux' but it could be built
;; without TLS support. So make the below condition for `no-ssl' an OR condition
;; instead of an AND condition.
(let* ((no-ssl (or (memq system-type '(windows-nt ms-dos))
(not (gnutls-available-p))))
(protocol (if no-ssl
"http"
"https"))
(melpa-url (concat protocol "://melpa.org/packages/"))
(orgelpa-url (concat protocol "://orgmode.org/elpa/")))
(add-to-list 'package-archives (cons "melpa" melpa-url) :append)
;; Install `org-plus-contrib' only when it's set to use the Elpa version of Org.
(when (eq modi/org-version-select 'elpa)
(add-to-list 'package-archives (cons "org" orgelpa-url))
(add-to-list 'my-packages 'org-plus-contrib))) ;Latest stable version of org-mode, includes org-eww
(>=e "27.0"
nil ;`package-initialize' call is not needed in emacs 27+
;; Load emacs packages and activate them
;; This must come before configurations of installed packages.
;; Don't delete this line.
(package-initialize)
;; `package-initialize' call is required before any of the below
;; can happen.
)
;; Auto install the required packages
;; https://github.com/bbatsov/prelude/blob/master/core/prelude-packages.el
;; http://toumorokoshi.github.io/emacs-from-scratch-part-2-package-management.html
(defvar modi/missing-packages '()
"List populated at each startup that contains the list of packages that need
to be installed.")
(dolist (p my-packages)
(unless (package-installed-p p)
(add-to-list 'modi/missing-packages p :append)))
(when modi/missing-packages
(message "Emacs is now refreshing its package database...")
(package-refresh-contents)
;; Install the missing packages
(dolist (p modi/missing-packages)
(message "Installing `%s' .." p)
(package-install p))
(setq modi/missing-packages '()))
;; Mark packages to *not* to be updated
;; http://emacs.stackexchange.com/a/9342/115
(defvar modi/package-menu-dont-update-packages '(org)
"List of packages for which the package manager should not look for updates.
Example: '(org org-plus-contrib).")
;; Do not upgrade Org using the package manager if it's set to *not* use the
;; Elpa version of Org.
(unless (eq modi/org-version-select 'elpa)
(add-to-list 'modi/package-menu-dont-update-packages 'org-plus-contrib))
(defun modi/package-menu-remove-excluded-packages (orig-fun &rest args)
"Remove the packages listed in `modi/package-menu-dont-update-packages' from
the `tabulated-list-entries' variable."
(let ((included (-filter
(lambda (entry)
(let ((pkg-name (package-desc-name (car entry))))
(not (member pkg-name modi/package-menu-dont-update-packages))))
tabulated-list-entries)))
(setq-local tabulated-list-entries included)
(apply orig-fun args)))
(advice-add 'package-menu--find-upgrades :around #'modi/package-menu-remove-excluded-packages)
;; (advice-remove 'package-menu--find-upgrades #'modi/package-menu-remove-excluded-packages)
;; Inspired from paradox.el
(defun my/package-upgrade-packages (&optional no-fetch)
"Upgrade all packages. No questions asked.
This function is equivalent to `list-packages', followed by a
`package-menu-mark-upgrades' and a `package-menu-execute'. Except
the user isn't asked to confirm deletion of packages.
The NO-FETCH prefix argument is passed to `list-packages'. It
prevents re-download of information about new versions. It does
not prevent downloading the actual packages (obviously)."
(interactive "P")
(let ((package-menu-async nil)) ; This variable was introduced in emacs 25.0
(save-window-excursion
(package-list-packages no-fetch)
(package-menu-mark-upgrades)
(package-menu-execute 'noquery))))
;; http://emacs.stackexchange.com/a/26513/115
(defun modi/package-dependency-check-ignore (orig-ret)
"Remove the `black listed packages' from ORIG-RET.
Packages listed in the let-bound `pkg-black-list' will not be auto-installed
even if they are found as dependencies.
It is known that this advice is not effective when installed packages
asynchronously using `paradox'. Below is effective on synchronous
package installations."
(let ((pkg-black-list '(org))
new-ret
pkg-name)
;; (message "before %S" orig-ret)
(dolist (pkg-struct orig-ret)
(setq pkg-name (package-desc-name pkg-struct))
(if (member pkg-name pkg-black-list)
(message (concat "Package `%s' will not be installed. "
"See `modi/package-dependency-check-ignore'.")
pkg-name)
;; (message "Package to be installed: %s" pkg-name)
(push pkg-struct new-ret)))
;; Tue Apr 11 17:48:16 EDT 2017 - kmodi
;; It's *very* critical that the order of packages stays the same in NEW-RET
;; as in ORIG-RET. The `push' command flips the order, so use `reverse'
;; to flip the order back to the original.
;; Without this step, you will get errors like below when installing
;; packages with dependencies:
;; Debugger entered--Lisp error: (error "Unable to activate package ‘nim-mode’.
;; Required package ‘flycheck-28’ is unavailable")
(setq new-ret (reverse new-ret))
;; (message "after %S" new-ret)
new-ret))
(advice-add 'package-compute-transaction :filter-return #'modi/package-dependency-check-ignore)
;; (advice-remove 'package-compute-transaction #'modi/package-dependency-check-ignore)
(defun modi/byte-recompile-elpa ()
"Force byte-compile every `.el' file in `package-user-dir'.
The `.el' files are re-compiled even if the corresponding `.elc' files exist,
in all the sub-directories under `package-user-dir'.
If the `.elc' file does not exist, this function *does not* compile the
corresponding `.el' file."
(interactive)
(byte-recompile-directory package-user-dir nil :force))
(provide 'setup-packages)