-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path.emacs.el
More file actions
7538 lines (6975 loc) · 283 KB
/
.emacs.el
File metadata and controls
7538 lines (6975 loc) · 283 KB
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;;;; -*-coding: utf-8;-*-
;;;;
;;;; .emacs.el
;;;;
;;;;#ident "@(#)HOME:.emacs.el 37.26 25/09/16 18:24:16 (woods)"
;;;;
;;;; per-user start-up functions for GNU-emacs v24.1 or newer (with Xft)
;;;;
;;;; primarily tested on v27.2 (previously 26.3), and sometimes the Git "master"
;;;; branch (v31.0.50 most recently)
;;;;
;;;; (someday support for versions prior to v24.x should just be removed)
;;;;
;; A simple 1-based ruler (note the column indicator in the mode line is 0-based)
;; 10: 20: 30: 40: 50: 60: 70: 80: 90: 100: 110: 120: 130:
;;3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12
;;; This file should be stored in "~/.emacs.el".
;;; Saving it will normally compile it into "~/.emacs.elc".
;;; You need to compile it with the oldest version you use in the same $HOME.
;;; Make a (symbolic) link from "~/.emacs" pointing to "~/.emacs.elc" to use it.
;;;
;;; Use something like the following to compile it from the command line:
;;;
;;; cd $HOME && emacs -batch -q -no-site-file -f batch-byte-compile .emacs.el
;;; N.B.: Run `my-packages-install' after first installing, or upgrading, Emacs.
;;;
;;; XXX but first hack in a working markdown-mode:
;;;
;;; cd ~/.emacs.d/packages-$(emacs-version-nobuild) # the current one!
;;; cp -R ../packages-26.1/markdown-mode-* .
;;;
;;; XXX gnu-elpa-keyring-update may have to be manually installed and used first!
;;;
;;; From https://elpa.gnu.org/packages/gnu-elpa-keyring-update.html
;;;
;;; Download: http://elpa.gnu.org/packages/gnu-elpa-keyring-update-2022.12.1.tar
;;; Run: `package-install-file' and select the downloaded .tar file....
;;;
;;; xxx you may have to make some buffers writeable for the install to complete
;;; if you also have gnupg2 installed!
;;;
;;; N.B.: Also if on X then after `ucs-utils' and `unicode-fonts' are installed
;;; you need to start emacs fresh, then quit it after their cache files are
;;; built so that those files get saved (they are only saved on quit!!!)
;;; NOTES:
;;;
;;; `calendar-latitude' and `calendar-longitude' are customized to my home
;;; location somewhere down below.
;;;
;;; Don't use (function (lambda () ...)) for hook functions
;;; -- it makes it difficult to change them without a full restart....
;;;
;;; Don't use `cl' or anything that uses it (e.g. `seq'), at least not in
;;; anything that might be evaluated before all the `after-init-hook' functions
;;; have been called. The exception being `package' -- it must be loaded and
;;; initialized before any installed packages can be detected and set up herein.
;;; TODO:
;;;
;;; Use `eval-after-load' (or when available `with-eval-after-load'?) more....
;;;
;;; Use `password-store' (package) with 27.7 and pkgsrc/security/password-store
;;;
;;; Think about using `emacs-everywhere' (package) (needs 26.3)
;;; to debug, eval (^X^E) these after starting with "emacs -q":
;;;
;;; (setq debug-on-error t)
;;; (load-file "~/.emacs.el")
;;;
;;; [note: newer emacs have a "--debug-init" command-line option]
;;;
;;; See also: https://svn.red-bean.com/repos/kfogel/trunk/.emacs
;;; more goodies for debug:
;;;
;;; (setq debug-on-error nil)
;;; (setq stack-trace-on-error t)
;;; (setq stack-trace-on-error nil)
;;; (setq debug-on-quit t)
;;; (setq debug-on-quit nil)
;;; (debug-on-entry 'byte-compile) ; this will detect use of 'cl
;;; (list-load-path-shadows)
;;; helpers for calendar session
;;;
;;; eval this to stop appt-check:
;;; (cancel-timer appt-timer)
;;;
;;; eval this to re-start appt-check:
;;; (setq appt-timer (run-at-time t 60 'appt-check))
;;;
;;; eval this to prevent the diary update at midnight
;;; (setq appt-display-diary nil) ; do not display diary at midnight
;; I don't want that annoying startup message.
(setq inhibit-startup-message t)
;; but knowing this is (re)loading is useful....
(message "Loading ~/.emacs.el...")
;;;; ----------
;;;; What to do before we get too far along...
;; set a different name for the custom-file
;;
;; (For newer Emacs with `early-init-file', perhaps in theory this could/should
;; go in this so-called Early Init File and then I think the explicit load could
;; be avoided, but this way we can keep everything in one place.)
;;
(setq custom-file "~/.emacs-custom.el")
;;
;; doing this first allows this file to over-ride `customize', and in particular
;; `custom-save-all', which is what I think I want to do for now, as the default
;; value (of nil) means "use your init file as specified by `user-init-file'",
;; which is THIS FILE!
;;
;; `customize' is probably only really useful for settings which are specific to
;; a given host environment, such as `magit-repo-dirs' (and even then there's
;; potential for confusion with a network-shared $HOME)
;;
;; Also there's the issue of version control for `custom-file', which
;; `custom-save-all' currently has no support for....
;;
(if (file-exists-p custom-file)
(load custom-file))
;;;; ----------
;;;; Let's make sure we're "home"....
;; If that's where we should be. See the call to `list-buffers' at the end.
;;
(if (<= (safe-length command-line-args) 1)
(cd "~"))
;;;; ----------
;;;; stolen from cl.el -- find out what and where we are!
(eval-and-compile
(defvar init-emacs-type
(cond ((boundp 'emacs-major-version) ; first available in 19.23
emacs-major-version)
((or (and (fboundp 'epoch::version)
(symbol-value 'epoch::version))
(string-lessp emacs-version "19"))
18) ; was there ever anything less?
(t 19)) ; what else could it be?
"*Emacs major version for testing compatibility.")
)
;; XXX string-to-int is apparently obsolete since 22.1
(eval-and-compile
(if (not (fboundp 'string-to-number))
(defalias 'string-to-number 'string-to-int)))
;;; stolen by way of Len Tower from Noah Freidman from /home/fsf/friedman/etc/init/emacs/init.el
(eval-and-compile
(defun emacs-version-get-component (component)
(let ((old-match-data (match-data))
(version 0)
(regexp (cond
((eq 'major component) "^\\([0-9]+\\)")
((eq 'minor component) "^[0-9]+\\.\\([0-9]+\\)")
((eq 'build component) "^[0-9]+\\.[0-9]+\\.\\([0-9]+\\)"))))
(unwind-protect
(and (string-match regexp emacs-version)
(setq version
(string-to-number (substring emacs-version
(match-beginning 1)
(match-end 1)))))
(store-match-data old-match-data))
version))
)
;; note the "official" variables are named like emacs-*-version, but they
;; didn't appear until 19.23
(eval-and-compile
(defconst emacs-version-major (emacs-version-get-component 'major)
"Major version number for this Emacs.")
(defconst emacs-version-minor (emacs-version-get-component 'minor)
"Minor version number for this Emacs.")
(defconst emacs-version-nobuild (string-to-number
(concat
(number-to-string (emacs-version-get-component 'major)) "."
(number-to-string (emacs-version-get-component 'minor))))
"Version number for this Emacs (as a floating point number).")
(defconst emacs-version-build (emacs-version-get-component 'build)
"Build number for this Emacs.")
)
;;; end by Noah Freidman from /home/fsf/friedman/etc/init/emacs/init.el
;; This init file may still "work" for even the ancient 22.1, but will be
;; missing some important features and some feature-specific configurations may
;; not actually work.
;;
(if (< emacs-version-nobuild 24.1)
(progn
(message "Not running emacs v24.1 or newer I see -- you may have trouble with this .emacs!")
(sit-for 2)))
;;;; ----------
;;;; things to do for coding systems, MULE, etc.
;; XXX N.B.: display-graphic-p etc.
;;
;; Use of `window-system' as a predicate is deprecated. Instead, use
;; `display-graphic-p' or any of the other `display-*-p' predicates which report
;; frame's specific UI-related capabilities.
;; XXX should this actually be done in the `after-init-hook' function?
(if (>= init-emacs-type 20)
(setq inhibit-eol-conversion t)) ; show M$ crap for what it is....
;; xxx some/all of the following may also be useful:
;;
;; (setq locale-coding-system 'utf-8)
;; (set-terminal-coding-system 'utf-8)
;; (set-keyboard-coding-system 'utf-8)
;; (set-selection-coding-system 'utf-8)
;; (prefer-coding-system 'utf-8)
;;
(eval-when-compile
(defvar manual-program))
(if (>= init-emacs-type 20)
(if (not window-system)
(set-locale-environment nil) ; xxx assume environment is correct
; (LC_ALL, LC_CTYPE, or LANG) (the
; parameter is optional in version 22,
; but not in version 21.4)
(set-language-environment "UTF-8") ; xxx assume all window systems are
; full UTF-8, since all of the ones I
; use are, and I do this here because
; emacs may have been started from a
; non-UTF-8 capable command environment
; (i.e. not a uxterm/xterm -u8)
(setq manual-program "LC_CTYPE=en_US.UTF-8 man")) ; also tell 'man'...
(standard-display-european 1))
;; xxx we don't seem to need this -- it should "Do The Right Thing(tm)" based
;; on the locale settings.
;;
;(if (and (>= init-emacs-type 20)
; (not window-system))
; (set-terminal-coding-system 'iso-8859-1)) ; force the issue
;; XXX this may rely on v20 or even v21 features....
;;
;; XXX sadly this does not work for uxterm (xterm -u8)
;;
(if (not window-system)
(set-input-mode nil nil t)) ; Turn on 8'th-bit META handling
(eval-when-compile
(defvar mac-command-modifier)
(defvar mac-option-modifier))
(if (eq window-system 'ns)
(progn
;; XXX unfortunately this doesn't steal the key entirely from macOS Cocoa
;; one I'm sure to trip over in confusion many times is M-tab, thus see
;; setting of s-tab in `my-function-key-map` by
;; `my-fix-emacs-function-key-brain-damage':
;;
(setq mac-command-modifier 'meta)
;;
;; xxx apparently this interferes with international keyboard input, but
;; we can configure the "fn" key to "Show Emoji & Symbols" (in "Keyboard"
;; under System Settings)
;;
(setq mac-option-modifier 'super)
))
;;;; ----------
;;;; get ready to load stuff
;; detect potential problems with `list-load-path-shadows'
(defvar load-path-ORIGINAL load-path "The original value at startup.")
;; You may need to install subdirs.el into each of the following "site-lisp" or
;; "elisp" directories. It should contain the following:
;;
;; (if (fboundp 'normal-top-level-add-subdirs-to-load-path)
;; (normal-top-level-add-subdirs-to-load-path))
;;
;; It can usually be copied from the emacs default site-lisp directory:
;;
;; cp $PKG/share/emacs/$VERSION/site-lisp/subdirs.el DESTDIR/site-lisp/
;; prepend the $LOCAL version's site-lisp dir
;;
;; Note this may already be included with defaults specified in the file
;; `epaths.h' used when Emacs was built. `add-to-list' avoids duplicates.
;; (`add-to-list' is in 19.29 and newer)
;;
(eval-and-compile
(if (file-exists-p (concat (getenv "LOCAL")
"/share/emacs/site-lisp/subdirs.el"))
(progn
(defvar local-site-lisp-dir
(concat (getenv "LOCAL") "/share/emacs/site-lisp")
"Location of the site-lisp directory for local packages.")
(add-to-list 'load-path local-site-lisp-dir)))
)
;; append the $PKG version's site-lisp dir if we're running the local version.
;;
;; Note this may already be included with defaults specified in the file
;; `epaths.h' used when Emacs was built.
;;
(eval-and-compile
(if (and (file-exists-p (concat (getenv "PKG")
"/share/emacs/site-lisp/subdirs.el"))
(not (fboundp 'local-site-lisp-dir)))
(progn
(defvar pkg-site-lisp-dir
(concat (getenv "PKG") "/share/emacs/site-lisp")
"Location of the site-lisp directory for add-on packages.")
(add-to-list 'load-path pkg-site-lisp-dir 'append)))
)
;; finally prepend our private elisp library (even if it does not exist!)
;;
(eval-and-compile
(defvar private-lisp-dir
(expand-file-name "~/lib/elisp")
"*The location of the user's private e-lisp library.")
(add-to-list 'load-path private-lisp-dir)
)
(eval-after-load 'info
'(progn
(eval-and-compile
(require 'info))
;; xxx unfortunately the compiler isn't smart enough to notice the
;; matching 'info tags above and still gives us the lame "Warning: the
;; following functions might not be defined at runtime". The only fix
;; would seem to be to use `eval-and-compile' and bite the bullet on doing
;; the `require' at every startup.
(info-initialize)
(add-to-list 'Info-directory-list (expand-file-name "~/lib/info"))))
;; By default this is only done in `normal-top-level' before ~/.emacs is loaded.
;;
;; So, we must do it all again here now to get any new load-path directories
;; added just above....
;;
;; Look in each dir in load-path for a subdirs.el file.
;; If we find one, load it, which will add the appropriate subdirs
;; of that dir into load-path,
;; Look for a leim-list.el file too. Loading it will register
;; available input methods.
(let ((tail load-path) dir)
(while tail
(setq dir (car tail))
(let ((default-directory dir))
(message (concat "~/.emacs.el: loading " (expand-file-name "subdirs.el")))
(load (expand-file-name "subdirs.el") t t t))
(let ((default-directory dir))
(message (concat "~/.emacs.el: loading " (expand-file-name "leim-list.el")))
(load (expand-file-name "leim-list.el") t t t))
;; We don't use a dolist loop and we put this "setq-cdr" command at
;; the end, because the subdirs.el files may add elements to the end
;; of load-path and we want to take it into account.
(setq tail (cdr tail))))
(eval-and-compile
(defun file-in-pathlist-p (file-name path-list)
"Returns t if the string FILENAME is a file name which occurs in a
directory in the list PATHLIST, otherwise nil."
(let (try-path (file-found-in-path-p nil))
(while (not (or file-found-in-path-p (null path-list)))
(setq try-path (car path-list)
path-list (cdr path-list))
(if (file-exists-p (concat try-path "/" file-name)) ; path-separator :-)
(setq file-found-in-path-p t)))
(eval 'file-found-in-path-p)))
)
(eval-and-compile
(defun file-in-loadpath-p (file-name)
"Returns t if the string argument FILENAME is a file name present in a
directory in the load-path list, otherwise returns nil."
(file-in-pathlist-p file-name load-path))
)
;;; This could probably be rewritten to use mapcar
;;;
;;; see also `locate-library'
;;;
(eval-and-compile
(defun elisp-file-in-loadpath-p (file-name)
"Returns t if there is an emacs lisp-library of the name FILENAME in the
load-path list. Matching is first done by looking for the file with an .elc
extension, an .el extension, and finally with no extension at all, and
returning t if any of the three are found. Nil is returned otherwise."
(let ((extension-list (list ".elc" ".el" ""))
(file-found-p nil)
name-to-try)
(while (and (not file-found-p) (not (null extension-list)))
(setq name-to-try (concat file-name (car extension-list)))
(setq extension-list (cdr extension-list))
(setq file-found-p (file-in-loadpath-p name-to-try)))
(eval 'file-found-p)))
)
;;;; ----------
;;;; Some helper functions needed early and possibly during compile
(eval-and-compile
(if (elisp-file-in-loadpath-p "s")
(require 's)
(defun s-replace (old new s)
"Replaces OLD with NEW in S."
(declare (pure t) (side-effect-free t))
(replace-regexp-in-string (regexp-quote old) new s t t)))
)
;; like `delete-dups', but non-destructive
(defun strip-duplicates (list)
"Non-destructively remove duplicates, using `equal' for
comparison, from LIST."
(let ((new-list nil))
(while list
(when (and (car list)
(not (member (car list) new-list)))
(setq new-list (cons (car list) new-list)))
(setq list (cdr list)))
(nreverse new-list)))
;;;; ----------
;;;; What to do after this file has been loaded...
(eval-and-compile
(if (>= emacs-version-nobuild 20.1)
(require 'time)
(if (elisp-file-in-loadpath-p "time")
(load-library "time")))
)
(eval-when-compile
(defvar display-time-24hr-format)) ; was not always defvar'ed!
(eval-when-compile
(defvar resize-minibuffer-mode))
(defun my-main-after-init-func ()
"Functions to call after loading the init file (`~/.emacs').
The call is not protected by a condition-case, so you can set `debug-on-error'
in `.emacs', and put all the actual code on `after-init-hook'."
(progn
;;
;;(setq debug-on-error t) ; need this to debug in here...
;;
(message "Doing main after-init setup...")
;;
(require 'fontset) ; for `xlfd-regexp-spacing-subnum'
(defconst xlfd-regexp-spacing-subnum 9) ; fix a 20-year-old typo!
(setq display-time-day-and-date t) ; what day is it again?
(setq display-time-24hr-format t) ; time in 24hour-mode
(if (or (string-equal (system-name) "robohack")
(string-equal (system-name) "almost.weird.com")
(string-equal (system-name) "always.weird.com"))
(setq display-time-interval 300)) ; ease off for poor little machines....
;; xxx why did I clear `process-connection-type' for `display-time'???
(let ((process-connection-type nil)) ; pty's are limited, pipes are not
(display-time)) ; display-time is autoload'ed
;; xxx what is the difference between `display-time' and `display-time-mode' again?
(if (fboundp 'display-time-mode)
(if (not display-time-mode)
(if (>= emacs-version-nobuild 23.0)
(display-time-mode nil)
(display-time-mode 1))))
;; (see below for the `require' of jka-compr to provide this)
(if (fboundp 'auto-compression-mode)
(if (not auto-image-file-mode)
(if (>= emacs-version-nobuild 23.0)
(auto-compression-mode nil)
(auto-compression-mode 1))))
(if (fboundp 'auto-image-file-mode)
(if (not auto-image-file-mode)
(if (>= emacs-version-nobuild 23.0)
(auto-image-file-mode nil)
(auto-image-file-mode 1))))
;;
;; Message-Id: <9601081816.AA07579@alex.x.org>
;; From: Stephen Gildea <gildea@x.org>
;; To: bug-gnu-emacs@prep.ai.mit.edu
;; Date: Mon, 08 Jan 1996 13:16:19 EST
;; Subject: resize-minibuffer-mode should be on by default
;;
;; I just stumbled upon resize-minibuffer-mode (in Emacs 19.26-19.30);
;; it is very nice.
;;
;; XXX but it's gone (and mostly automatic) in Emacs 22 and newer
;;
(if (fboundp 'resize-minibuffer-mode)
(if (not resize-minibuffer-mode) ; xxx avoid calling again if already enabled
(resize-minibuffer-mode)))
(message "Doing main after-init setup... Done.")))
(add-hook 'after-init-hook
'my-main-after-init-func)
;;;; ----------
;;;; some default packages we'd like, if we can get them...
(eval-when-compile
(when (fboundp 'declare-function) ; (>= emacs-version-nobuild 23.0)
(require 'simple) ; squelch warnings
(declare-function package-initialize "package" t t)
(declare-function package-install "package" t t)
(declare-function package-installed-p "package" t t)
(declare-function package-refresh-contents "package" t t)))
;;
;; N.B.: gnutls-cli needs a CA bundle, install security/mozilla-rootcerts,
;; and dont' forget to run (as root):
;;
;; mozilla-rootcerts install
;;
(eval-when-compile
(defvar gnutls-trustfiles) ; xxx it's also a function...
(defvar gnutls-algorithm-priority))
(eval-when-compile
(when (fboundp 'declare-function) ; (>= emacs-version-nobuild 23.0)
(require 'simple) ; squelch warnings
(declare-function gnutls-trustfiles "gnutls" t t))) ; xxx it's also a variable...
(eval-after-load 'gnutls
'(progn
;; N.B.: This is a list, and the function `gnutls-trustfiles' prunes any
;; that don't exist, but even then only the `car' entry is ever used!!!!!
;;
(add-to-list 'gnutls-trustfiles "/etc/openssl/certs/ca-certificates.crt")
(add-to-list 'gnutls-trustfiles "/etc/openssl/certs/weird-ca.pem")
;;
;; So, make sure to add any self-signed certs or private CAs to a new
;; merged file as the tls-checktrust stuff doesn't actually work.
;;
;; I.e. this must come last (so it's at the head of the list) for the call
;; to `tls-program' (normally "gnutls-cli") to work:
;;
(add-to-list 'gnutls-trustfiles "/etc/openssl/certs/merged-ca.crt")
;; https://www.reddit.com/r/emacs/comments/cdei4p/failed_to_download_gnu_archive_bad_request/
(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")))
(eval-after-load 'starttls
'(progn
;; here "gnutls" means run `starttls-gnutls-program' instead of
;; `starttls-program' (nothing in `starttls' uses built-in GNUtls)
(setq starttls-use-gnutls t)
(setq starttls-extra-args '("--x509cafile")) ; "--crlf" causes problems with end-of-DATA!
(add-to-list 'starttls-extra-args (car (gnutls-trustfiles)) t)
(setq starttls-success "\\(^- Compression:\\|^- Options:\\)")
(setq starttls-connect "^- Simple Client Mode:")))
;; TLS helpers for package fetching in older (and non-gnutls) releases...
;;
;;
;; XXX including a redefinition of `open-tls-stream' is a bit of a hack to aid
;; in debugging....
;;
;; N.B.: This is not used in 26.x or newer IFF emacs is built to use gnutls....
;;
(eval-when-compile
(defvar tls-program)
(defvar tls-process-connection-type)
(defvar tls-success)
(defvar tls-end-of-info)
(defvar tls-checktrust)
(defvar tls-untrusted)
(defvar tls-hostmismatch)
(when (fboundp 'declare-function) ; (>= emacs-version-nobuild 23.0)
(require 'simple) ; squelch warnings
(declare-function format-spec "format-spec" t t)
(declare-function format-spec-make "format-spec" t t)))
(eval-and-compile
;; xxx hmmm.... this does not seem to avoid compiling `open-tls-stream' unless
;; `gnutls-available-p'
;;
(unless (and (fboundp 'gnutls-available-p)
(gnutls-available-p))
(require 'tls)
(require 'format-spec)
;;
;; N.B.: Each of the `tls-program' commands are tried until one works. If
;; gnutls-cli is installed and in the path, but we end up running openssl,
;; that probably means the merged certificate file isn't available!
;;
(setq tls-program
;; n.b.: "[-]-crlf" is necessary for Gmail on command-line but
;; seemingly not in Wanderlust. On the other hand it would break
;; interactions with Cyrus!
;;
'("gnutls-cli --x509cafile %t -p %p %h"
;; XXX remove "--protocols ssl3" variant, it's deprecated since 3.?
;;
;; more optional ways to work around broken connections....
;;
; "gnutls-cli --verify-allow-broken --x509cafile %t -p %p %h"
; "gnutls-cli --insecure --x509cafile %t -p %p %h"
; "gnutls-cli --verify-allow-broken --insecure --x509cafile %t -p %p %h"
;;
;; (xxx "-no_ssl2" might still be required for older openssl......
;; XXX but it isn't available in newer)
"openssl s_client -quiet -verify 3 -CAfile %t -connect %h:%p"
))
;;
;; XXX as of OpenSSL 1.1.1a 20 Nov 2018 there's a new ending to the noise
;; c_client prints before real data starts.
;;
;; (XXX debugging this was HARD! No clues -- emacs just "hung" without responding)
;;
;; XXX thus the included version of `open-tls-stream' above...
;;
(setq tls-end-of-info
"\\(^verify return:.+
\\|^\s*Verify return code: .+
---
\\|^ Extended master secret: .+
---
\\|^- Simple Client Mode:
\\(
\\|^\\*\\*\\* Starting TLS handshake
\\)*\\)")
;; XXX fixing this doesn't actually make the `tls-checktrust' thing work....
(setq tls-untrusted
"- Status: The certificate is NOT trusted.
\\|- Peer's certificate is NOT trusted
\\|Verify return code: \\([^0] \\|.[^ ]\\)")
(defun open-tls-stream (name buffer host port)
"Open a TLS connection for a port to a host.
Returns a subprocess-object to represent the connection.
Input and output work as for subprocesses; `delete-process' closes it.
Args are NAME BUFFER HOST PORT.
NAME is name for process. It is modified if necessary to make it unique.
BUFFER is the buffer (or buffer name) to associate with the process.
Process output goes at end of that buffer, unless you specify
a filter function to handle the output.
BUFFER may be also nil, meaning that this process is not associated
with any buffer
Third arg is name of the host to connect to, or its IP address.
Fourth arg PORT is an integer specifying a port to connect to."
(let ((cmds tls-program)
(use-temp-buffer (null buffer))
process cmd done)
(if use-temp-buffer
(setq buffer (generate-new-buffer " TLS"))
;; BUFFER is a string but does not exist as a buffer object.
(unless (and (get-buffer buffer)
(buffer-name (get-buffer buffer)))
(generate-new-buffer buffer)))
(with-current-buffer buffer
(message "Opening TLS connection to `%s'..." host)
(while (and (not done) (setq cmd (pop cmds)))
(let ((process-connection-type tls-process-connection-type)
(formatted-cmd
(format-spec
cmd
(format-spec-make
?t (car (gnutls-trustfiles)) ; XXX bogus! How to use the whole list!?!?!?
?h host
?p (if (integerp port)
(int-to-string port)
port)))))
(message "Opening TLS connection with `%s'..." formatted-cmd)
(setq process (start-process
name buffer shell-file-name shell-command-switch
formatted-cmd))
(message "Searching for tls-success pattern...")
;; XXX this should probably time out....
(while (and process
(memq (process-status process) '(open run))
(progn
(goto-char (point-min))
(not (setq done (re-search-forward
tls-success nil t)))))
(message "Still Searching for tls-success pattern....")
(unless (accept-process-output process 1)
(sit-for 1)))
(message "Opening TLS connection with `%s'...%s" formatted-cmd
(if done "done" "failed"))
(if (not done)
(delete-process process)
;; advance point to after all informational messages that
;; `openssl s_client' and `gnutls' print
;;
;; XXX WARNING XXX: If the `tls-end-of-info' pattern is not found
;; in the output from the process command then this simply hangs
;; waiting with no indication whatsoever about what's happening!
;;
(message "Searching for tls-end-of-info pattern...")
;;
(let ((start-of-data nil))
(while
(not (setq start-of-data
;; the string matching `tls-end-of-info'
;; might come in separate chunks from
;; `accept-process-output', so start the
;; search where `tls-success' ended
(save-excursion
(if (re-search-forward tls-end-of-info nil t)
(match-end 0)))))
(accept-process-output process 1))
(if start-of-data
;; move point to start of client data
(goto-char start-of-data)
(message "WARNING: did not find tls-end-of-info pattern!!!")))
(setq done process))))
(when (and done
(or
(and tls-checktrust
(save-excursion
(message "Searching for tls-untrusted pattern...")
(goto-char (point-min))
(re-search-forward tls-untrusted nil t))
(or
(and (not (eq tls-checktrust 'ask))
(message "The certificate presented by `%s' is \
NOT trusted." host))
;; XXX shouldn't something be dnoe if "yes"!?!?!?
(not (yes-or-no-p
(tls-format-message "\
The certificate presented by `%s' is NOT trusted. Accept anyway? " host)))))
(and tls-hostmismatch
(save-excursion
(message "Searching for tls-hostmismatch pattern...")
(goto-char (point-min))
(re-search-forward tls-hostmismatch nil t))
;; XXX shouldn't something be dnoe if "yes"!?!?!?
(not (yes-or-no-p
(format "Host name in certificate doesn't \
match `%s'. Connect anyway? " host))))))
(setq done nil)
(delete-process process))
;; Delete all the informational messages that could confuse
;; future uses of `buffer'.
(delete-region (point-min) (point)))
(message "Opening TLS connection to `%s'...%s"
host (if done "done" "failed"))
(when use-temp-buffer
(if done (set-process-buffer process nil))
(kill-buffer buffer))
done))
) ;; gnutls-available-p
)
(eval-and-compile
;; n.b.: note the chicken&egg situation IFF `package' is installed by itself!
(if (or (elisp-file-in-loadpath-p "package")
(elisp-file-in-loadpath-p "package-23"))
(progn
(eval-when-compile ; not really needed, but for consistency....
(defvar package-archives)
(defvar package-archive-contents)
(defvar epg-gpg-program))
;;
;; xxx for emacs-23 a limited version is available:
;;
;; ftp 'http://git.savannah.gnu.org/gitweb/?p=emacs.git;a=blob_plain;hb=ba08b24186711eaeb3748f3d1f23e2c2d9ed0d09;f=lisp/emacs-lisp/package.el'
;;
;;diff -u /home/woods/lib/elisp/package.el\~ /home/woods/lib/elisp/package.el
;;--- /home/woods/lib/elisp/package.el~ Thu Dec 18 16:41:54 2014
;;+++ /home/woods/lib/elisp/package.el Sat Dec 20 15:08:04 2014
;;@@ -1034,9 +1034,12 @@
;; (file-name-as-directory
;; (expand-file-name package-user-dir)))
;; (progn
;;- (delete-directory dir t t)
;;+ (if (stringp dir)
;;+ (message "Deleting package `%s-%s'...." name version)
;;+ (message "May not be able to delete non-string-dir package `%s-%s'...." name version))
;;+ (delete-directory dir t)
;; (message "Package `%s-%s' deleted." name version))
;;- ;; Don't delete "system" packages
;;+ ;; Don't (try to) delete "system" packages
;; (error "Package `%s-%s' is a system package, not deleting"
;; name version))))
;;
;;diff -u /home/woods/lib/elisp/package.el\~ /home/woods/lib/elisp/package.el
;;--- /home/woods/lib/elisp/package.el~ Sat Dec 20 15:08:04 2014
;;+++ /home/woods/lib/elisp/package.el Sat Dec 20 15:30:03 2014
;;@@ -1056,6 +1056,9 @@
;; (let* ((dir (expand-file-name "archives" package-user-dir))
;; (dir (expand-file-name (car archive) dir)))
;; (package--with-work-buffer (cdr archive) file
;;+ (save-excursion
;;+ (switch-to-buffer buffer)
;;+ (replace-regexp "\\([0-9]\\{8\\}\\)\\([0-9]+\\)" "\\1.\\2"))
;; ;; Read the retrieved buffer to make sure it is valid (e.g. it
;; ;; may fetch a URL redirect page).
;; (when (listp (read buffer))
;;
;;
;;
;; N.B.: to manually update the GNU ELPA key run the `shell-command' below!
;;
;; XXX this should not be necessary if the first setup used the versioned
;; directory name
;;
(defun my-package-user-dir-cleanup ()
"Fix up old `package-user-dir' to match the new regime."
(interactive)
(unless (file-exists-p package-user-dir)
(make-directory package-user-dir t))
(if (and (string-equal package-user-dir-ORIGINAL "~/.emacs.d/elpa")
(file-accessible-directory-p package-user-dir-ORIGINAL))
(if (yes-or-no-p (concat "Rename '"
package-user-dir-ORIGINAL
"' to '"
package-user-dir "'?"))
(progn
(beep)
(rename-file package-user-dir-ORIGINAL package-user-dir))))
;; xxx this might fail -- key servers are notoriously unreliable these days!
(unless (file-exists-p package-gnupghome-dir)
(with-file-modes #o0700
(make-directory package-gnupghome-dir t))
;; XXX key servers are notoriously unreliable these days!
;; xxx hkp://ipv4.pool.sks-keyservers.net
;; xxx hkps://keys.openpgp.org
;; xxx hkp://keys.gnupg.net
;; hkp://keyserver.ubuntu.com
(require 'epg-config)
(shell-command (concat epg-gpg-program
" --keyserver hkp://keyserver.ubuntu.com"
" --homedir " package-gnupghome-dir
" --receive-keys 066DAFCB81E42C40 474F05837FBDEF9B"))))
(defun my-package-menu-mode-setup ()
"Setup for `package-menu-mode'."
(setq case-fold-search t)
(cd package-user-dir))
;;
(add-hook 'package-menu-mode-hook 'my-package-menu-mode-setup)
;;
(require 'package)
;; Note that after 24.x "gnu" should be in the list by default, but
;; it is there with "http" instead of "https", so we clear it first
(defvar package-archives-ORIGINAL package-archives "The original value at startup.")
(setq package-archives nil)
(defun my-package-setup ()
"Function to set up the `package' package."
(let ((proto "https")) ; M$ systems need gnutls built-in for HTTPS
;; For important compatibility libraries like cl-lib
(add-to-list 'package-archives `("gnu" . ,(concat proto "://elpa.gnu.org/packages/")))
(add-to-list 'package-archives `("nongnu" . ,(concat proto "://elpa.gnu.org/nongnu/")))
;; Comment/uncomment the next two expressions to enable/disable MELPA
;; or MELPA-Stable as desired -- with `package-archive-priorities'
;; set as below though it seems to work with both, for now.
(add-to-list 'package-archives
(cons "melpa" (concat proto "://melpa.org/packages/")) t)
;; XXX melpa-stable is not recommended: "Note that the MELPA
;; maintainers do not use MELPA Stable themselves, and do not
;; particularly recommend its use."
;;
;; xxx however having both works OK so long as
;; `package-archive-priorities' is set properly below
;;
(add-to-list 'package-archives
(cons "melpa-stable" (concat proto "://stable.melpa.org/packages/")) t)
;; XXX WARNING XXX: marmalade is apparently defunct....
;;(add-to-list 'package-archives
;; (cons "marmalade" (concat proto "://marmalade-repo.org/packages/")) t)
;;
;; "When higher versions are available from archives with lower
;; priorities, the user has to select those manually."
(setq package-archive-priorities
'(("melpa-stable" . 10)
("gnu" . 5)
("nongnu" . 5)
("melpa" . 0)
;("marmalade" . 0)
))
)
;;
;; Set `package-user-dir' to include `emacs-version' so that multiple
;; Emacs versions can be used. The default value is stupid and can
;; also be confusing, especially if multiple Emacs versions are used,
;; e.g. with a $HOME shared to multiple systems.
;;
;; (For newer Emacs with `early-init-file', perhaps in theory this
;; part could/should go in this so-called Early Init File and then I
;; think the explicit `eval-after-load' that calls this could be
;; avoided, but this way we can keep everything in one place.)
;;
(defvar package-user-dir-ORIGINAL package-user-dir "The original value at startup.")
(setq package-user-dir (concat user-emacs-directory "packages-"
(number-to-string emacs-version-major) "."
(number-to-string emacs-version-minor)
"/"))
;; we must also reset things that depend on `package-user-dir'
;;
;; XXX maybe also `pcache-directory' too -- would simplify setup for
;; `ucs-utils' and `unicode-fonts'
;;
(if (boundp 'package-gnupghome-dir)
(progn
(defvar package-gnupghome-dir-ORIGINAL package-gnupghome-dir "The original value at startup")
(setq package-gnupghome-dir (expand-file-name "gnupg" package-user-dir))))
;;
;; make packages read-only by default (i.e. for viewing from help)
;;
;; (a programmatic way of doing what a .dir-locals.el file would do)
;;
; (dir-locals-set-class-variables
; 'packages
; '((nil . ((buffer-read-only . t)))))
; (dir-locals-set-directory-class package-user-dir 'packages)
;;
;; but do allow `package-install' to write to such files
;;
;; (from https://emacs.stackexchange.com/a/46655)
;;
(advice-add
'package-install-from-archive
:around (lambda (orig-fun &rest args)
(let ((inhibit-read-only t))
(apply orig-fun args))))
(advice-add
'package-install-file
:around (lambda (orig-fun &rest args)
(let ((inhibit-read-only t))
(apply orig-fun args))))
;;
;; xxx this has to come before `package-initialize'
;;
(my-package-user-dir-cleanup)
(package-initialize)
;;
;; xxx and this of course has to come _after_ `package-initialize'
;;
;; Hmmm.... this doesn't work for emacs-23 at all
;;
;; See also these packages: req-package, el-get, and use-package-el-get
;;
;; XXX Hmmm... this didn't work with a fresh 26.1 install....
;;
;; had to do `list-packages' then install use-package by hand first
;; and still `package-install' fails with "bad request", while
;; manual installs from the *Pacakges* menu work OK.
;;
;; XXX This is possibly due to the `gnutls-algorithm-priority' bug
;; affecting 26.[12].... Or maybe it needs gnu-elpa-keyring-update?
;;
; XXX SO, this currently just causes more trouble than it is worth, and is not
; really used properly anyway -- just call `my-packages-install' to get
; everything the first time....
; (when (>= emacs-major-version 24)
; (if (package-installed-p 'use-package)
; (when (null package-archive-contents)
; (package-refresh-contents))
; (package-install 'use-package))
; (require 'use-package))
)
;;
;; N.B.: `package' must be initialized before its dir is in `load-path'!
(eval-after-load 'package
'(progn
(my-package-setup)))
;;
;; XXX unfortunately we cannot avoid this during init. It loads `seq',
;; which then does some common-lisp generic setup which calls
;; `byte-compile', and thus takes much longer to start. However we need
;; to have `package-user-dir' set and `package-initialize' called before
;; we can continue to detect and set up any installed packages!
;;
(if (< emacs-major-version 24)
(progn
(require 'package-23)
(require 'package)) ; xxx this doesn't/didn't trigger `eval-after-load'?
(require 'package))
)
(message "No package support!")
)
)
;; Essential packages -- many more are useful, but this is a minimum set?
;;
;; Note also that `package-selected-packages', typically defined and
;; automatically maintained in `custom-file', aka ~/.emacs-custom.el for this
;; init file, contains the list of manually installed packages.
;;
;; Hint to filter dependencies that might be locally handled or uneeded:
;;
;; https://emacs.stackexchange.com/questions/24290/how-to-install-package-without-install-dependencies-through-package