aboutsummaryrefslogtreecommitdiff
path: root/config.org
blob: b82fb05e6fb93f2c9df418255fc2d9a13261ec34 (plain)
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
#+Title DNW's GNU Emacs Configuration
#+PROPERTY: header-args :tangle ./init.el
Top-level TODOs:
- Org-agenda and calendar/diary
- Better org mode in general --- org-insert-link-global
- Clean up prose on "Why Emacs"
- BBDB
- Mail
- Debug/PR Eshell visual commands over TRAMP
- Learn how to use compiling and debugging
- Generalize system package installations to non-Arch package managers
- Test eglot, consult-eglot, etc.
- More extensive display-buffer-alist integration with edwina.
- Fix bank stuff and get a ledger setup working.

* Why Emacs?

#+begin_verse
...
Reason is clouding,
Hearts are hardening,
And the result is murder.
This age is grave bound,
Likewise its aging successors.
Aging, all the while, descending
Developing an even more insatiable thirst for chaos.
Life among hyenas and asps under vultures
That pick at the corpses of the fallen.
And man will continue to suffer unto itself
Until some stand to rally the fray by firm example.
Chaos must succumb to order
Lest these days be numbered.
I cannot contribute to disarray.
I simply cannot relate.
Let this be my act of defiance.
Let this by my refusal to fit in.
Let this by my writ of misanthropy
To a thankless world of men
Who have perfected nothing.
Save the art of accusation.
...
    --- /Scornful of The Motives And Virtue of Others/, Shai Hulud, 2003

#+end_verse


Emacs and vi have long histories, each back to 1976. As editors based on them in some way have seen extensive use through all of the evolution of text and its structure (not to even mention the evolution of computers!) in the intervening 47 years, they over all newer editors can evidence the claim that their systems are capable. But what are the material grounds for this capability? In both cases, the strategy is extensibility, but the tactics could not be further apart.

The vi perspective (in line with the UNIX perspective) starts from the assertion that everything on a computer can be fundamentally identified with text. Text in the filesystem is the substance of programs and that on which programs operate; it is what they produce and consume, and that by composing individual programs that perform simple text manipulations one may arive at powerful systems from simple parts. Programs are configured through filesystem text, either with a declarative config file or by modifying and recompilng their source. Programs are accessed through (not necessarily filesystem) text, by typing their name into a shell (which can only take text input, and can only output other text and side-effects). Even hardware devices are accessed through filesystem text, by reading and writing under the =/proc= and =/dev= trees. The text editor's task is merely to present the contents of the static fraction of this text for human consumption and modification, using in no small part the extant systems for text manipulation to this end. The user's enhancements to the system then contribute jointly to the operation of the system and his prowess in the editor---vi ever-growing in functionality /precisely/ on account of its minimality and, therefore, independence of the text-manipulation tools with which it shares a system.

By contrast, it seems the Emacs perspective is that text is merely the substance of which programs and the data they operate on can be /composed/, but is not what they /are/. That text is merely a description of procedures to be performed. Therefore, we need not invoke those procedures through particular text incantations in a shell (though we may), nor must all procedures interface through the intermediary of a text terminal or terminal emulator (though, again, they may). The text editor exists more generally to describe and control computer behavior, to intercess between the user and the system---which, yes, often takes the form of reading, writing, and executing text, but which also may be keystrokes bound to functionality, pictures and animations presented to the user, or interactive graphical displays. vi people have recognized this to an extent, mercilessly abusing terminal control codes to get colors and interactive animations in their shells, polluting their textual paradise with programs graphical in all but the most distorted sense (ever tried to /write/ a TUI from scratch?). Emacs by contrast has no such philosophical restrictions, so it may be principled about drawing, using code and protocols actually /designed/ for the purpose from the ground-up.

Emacs is configured in Lisp. The language family represents a fixed point in the relationship between programs' identity and programs' composition. Homoiconicity, there being no structural distinction between a Lisp's representation of the data it operates on and the code doing the operation, enables ordinary Lisp code to reason about other Lisp code with the same primitives used for reasoning about anything else---no weird templating, interpolation, parsing, or quoting. Just =macroexpand=. It's a dead-simple language, with about 5 pieces of fundamental syntax (lists, procedure calls, quotes, quasiquotes, and namespace distinguishment). Other dialects can be implemented with about 10 primitives (see the [[https://mitp-content-server.mit.edu/books/content/sectbyfn/books_pres_0/6515/sicp.zip/full-text/book/book.html][wizard book]]). It's extremely expressive---most modern CAS (for a fact: Maple, Wolfram/Mathematica, and SageMATH) drew on theoretical advances made by the MACSYMA system, written at MIT in Maclisp for the PDP-6 starting in 1968. Sage is actually said to have some of that original mainframe Lisp code, albeit ported to CommonLisp, surviving in its core routines. Configuration in a general-purpose language like this enables the editor's functionality to change as its users' preferences, requirements, hardware, and operating systems do. The actual, runtime state of configuration variables can be inspected and changed on the fly. The entire system can be modified, replaced, extended, abused, hacked, introspected, exported, and any other passive-voice verbs you can think of, at runtime, to hearts' content. People have implemented about as complicated and diverse functionality as anyone can imagine in Emacs Lisp, from [[elisp:(describe-package 'eieio)][object systems]] to [[elisp:(describe-package 'cats)][libraries of categorical programming abstractions]] to [[elisp:(describe-package 'elforth)][Forth emulation modes]].

The vi-style editors are hardly a monolith, but on account of their heritage they err on the side of the static UNIX Conf file for extending user behavior. The original was literally this; vim has vimscript (🤣); neovim, Lua (respectable, but far from mature). Nothing like Emacs' ecosystem, where code from the times of the dinosaurs is still found in the repositories, maintained, used, and extended.

From a user perspective, the fact that all keystrokes in Emacs are user-configurably bound to Lisp functions (or Lisp wrappers of C functions) is paramount. One may attach any and all of this extensive functionality to any key combination in any way, at runtime, in any way you desire. And so it has been since Stallman's FOSS port to GNU in 1984. Programs written in Emacs Lisp, distributed and installed just as other programs, are used as substitutes for command-line alternatives, written in bash or C. To be clear, no generality or speed need be lost: Emacs can interact with the C ABI and command-line programs just as vi-based editors can. Instead, that generality and speed is made to balance against ease of development and use, a balance most seem to have struck against developing code externally first. Which, probably, would mean that more extension would have been developed for vi, had its users the same option (look no further than neovim's adoption of Lua).

Emacs is additionally self-documenting. In the Common Lisp tradition, every package, module, variable, function, and macro can be adorned with a docstring. These docstrings can be used to dynamically produce documentation pages for variables and keybinds, as you forget them in real-time. Emacs' use of prefix keys (e.g. =C-x=, after which the keystroke =b= will mean the Lisp function =switch-to-buffer= rather than insertion of a =b= character) enables packages that, by runtime-querying the current keymap, will tell you all the available next-step bindings and their functions in a key sequence if you wait too long. If you forget what a key does, or want its function to use in a script, =C-h k= will let you type it in and will present the documentation page of the function to which the key combination is bound. Similarly, under =C-h= are many other facilities to bring up documentation pages, which, after some configuration, will present the command, its arguments, its docstring, any manual/info entries about it, links to the documentation of other functions in close relation to it, any relevant key bindings and their mode map, its source definition (whether C or Emacs Lisp), other calls to it from the source (C or Emacs Lisp), options to trace calls of it, and more. I wrote my first Emacs major mode in a weekend, knowing zero Emacs Lisp beyond what I had copied verbatim from David Wilson's /Emacs from Scratch/ videos, and was distributing it among my research group the following Monday. It's difficult to overstate its power.

Finally, Emacs is comparably performant to the vi ecosystem. Implementing most of the editor's functionality as modules in a scripting language means that most of Emacs' deep functionality is simply /not present/ unless explicitly loaded, either by an explicit require or as a dependency of another module or function invoked by the user. Currently, =(emacs-uptime)= returns =2 days, 9 hours, 50 minutes, 6 seconds=. Most of this time has been spent heavily loading packages to test, evaluating at some level all 6000 that're either built-in, on ELPA, or on MELPA to craft this config. Yet a simple =free -h= from the terminal reveals usage of only 602MiB, even under X, with =eww=, several info manuals, and a several-thousand-line, rich-text org document all open, among other things. That's less than the startup, idle RAM usage of some entire desktop environments, and when you consider that Emacs /is/ my desktop environment...this old, Librebooted T60 has struggled more to run certain /package managers/ than the heaviest of tasks Emacs editing throws at it.

Emacs is, as the GNU project puts it, "/the/ extensible, customizable, self-documenting, real-time display editor." The vi ecosystem is but a pale imitation on each of those three dimensions, and so the Emacs way seems clearly the fastest towards a more principled, deeper, and enjoyable mode of human-computer interaction.

* How to Use This Configuration

If you're completely new to Emacs, drop everything and type =C-h t= (hold down =<control>=, and press =h=, and then =t= after releasing =h= and =<control>=). This will explain the basic buffer navigation and editing commands and some terminology. After finishing that (you can go back at any time by typing the same thing), type =C-h C-h= (=h= with =<control>= held down, done twice) to see all of the other places you can get help. The manual, accessed via =C-h r=, is quite helpful (if you press =u= for "up" a bunch, you can get to the top-level info directory, and read info manuals for other things on your system within Emacs!)---press =h= in the manual to get an overview of how to read it.

Place this org file under =~/.emacs.d/=. Once Emacs is up-and-running with this configuration, simply saving this file after making changes to the config snippets will result in those changes being written out to an =init.el= file in this directory, which will be loaded by Emacs at startup. However, this init file must be working in order for the setting enabling tangle-on-save to be set. The first time, you can type =M-x org-babel-tangle= (bound to =C-c C-v t=) to produce it, and it should (hopefully) work painlessly after restarting.

This is intended to be read in tandem with other sources of documentation; particularly, the manual and built-in help facilities mentioned above. =C-h r= at any time should return to the Emacs manual, and when in doubt, spam =C-g= a few times before rerunning. To see exactly what something in the configuration snippets is doing, press =C-h o= with the point near the thing in question and it should be the first completion candidate (otherwise just type it in like a plebian 😎).

If any functionality seems useless or undesirable, add =:tangle no= to the header line (after =emacs-lisp=) in the relevant source code block. To add your own functionality, create a code block by typing =<el= and pressing =TAB=; typing =C-c '= with the point in the code block should open the contents in an Emacs Lisp buffer that you can edit with nice completion and indentation, whose changes will be written back into the source block when instructed.

* Configuration Philosophy

There are a few principles this configuration follows.

- Packages that exploit built-in features usually integrate better and are more powerful and extensible than those which don't.
- However, this shouldn't induce too strong an aversion to external code---packages with substantially improved feature sets and ergonomics can offset the above.
- Modules should load lazily to reduce startup time and memory overhead (e.g. don't load a major mode until a file to which it applies is opened), and tear down when no longer needed.
- User interfaces should be mostly invisible until called-upon---the user can rely on explicit documentation and help features to learn what's available when.
- Minimize keystrokes, prevent injury.
- Mice are literally spawn of Satan: keyboard-driven workflows are preferred at all costs (hence why this is an Emacs configuration). The time taken moving keyboard-to-mouse adds up.
- Modal editing requires keeping track of which mode you're in, and doesn't seem to meaningfully reduce either keystrokes or dependence upon held modifier keys, and as such is needless complexity. The keystroke =A= should always insert the character "A", unless specifically instruced otherwise via prefixing. In a sense, these prefixes are a type of "modal editing"---and accordingly, by exploiting them in depth, the key combinations are more semantic/mnemonic and far more numerous (by default, there are 10000+ key combinations).
- In-Emacs user-interfaces are preferred to external programs, in the interest of maximizing configurability, integration, and extensibility (with the same caveat as the second bullet, /mutadis mutandis/).
- Colors, symbols, and embedded pictures enable more compact representation and faster communication of information than text alone---and this process is aided by using tools designed from the ground-up to represent this kind of information (hence GUI Emacs).
- Avoid the "customize" interface, because actual use of it clutters up the init file/process. Changes to variables should be performed first temporarily through =M-:= and then permanently via =setq= in this org file, tangled out to the actual =init.el= on save.
- Starting with more feature-complete packages, while one might not need all of their functionality immediately, prevents needing to rewrite an existing config for what would be a single =setq= otherwise. Especially true if the package in question is already built-in---there's little downside.

There are also some rules according to which this text is composed.

- Group configuration elements by their highest-level end-user purpose.
- Describe first the /why/ of the config snippet. Then describe the /what/ with comments in the actual snippet, and follow the snippet with some /how/ (useful keybindings, extra necessary system configuration etc).
- Link to package documentation, info pages, and first-party repositories as much as possible.
- Describe useful, built-in Emacs tools that might need no configuration so the reader knows what's out there.
- For similar reasons, try to describe the other packages not included in the configuration, but are worthy of evaluation, detailing the reasoning for what is chosen based on the list above.

* Startup Performance

The configuration will load faster if we let the interpreter's RAM footprint blow up on startup. To debug a bad startup time, or slow functions in general, see the [[info:elisp#Profiling][profiler]].

#+begin_src emacs-lisp

  ;; Increase garbage-collection threshold
  (setq gc-cons-threshold (* 50 1000 1000))

  ;; Tell us how fast we're going, for benchmarking
  (defun dnw/display-startup-time ()
    (message "Emacs loaded in %s with %d garbage collections."
             (format "%2f seconds"
                     (float-time
                      (time-subtract after-init-time before-init-time)))
             gcs-done))

  (add-hook 'emacs-startup-hook #'dnw/display-startup-time)

#+end_src

* Package Management

The default Emacs system, from 24 to 28, has only the [[elisp:(helpful-function 'require)][require]] interface, which is imperative and somewhat difficult to optimize load-time with. The [[elisp:(describe-package 'use-package)][use-package]] macro provides a more ergonomic, declarative way to control loading and configuration of packages, and will be in Emacs 29 (a few weeks away at time of writing). Additionally, installs are only available from the official GNU ELPA archive by default. Most third-party packages are hosted on the MELPA, so that is configured.. Currently, some alternative package managers/loaders/configurers are:
[[elisp:(describe-package 'straight)][straight]], [[elisp:(describe-package 'quelpa-use-package)][quelpa-use-package]], [[elisp:(describe-package 'elpaca)][elpaca]], [[elisp:(describe-package 'el-get)][el-get]], [[elisp:(describe-package 'elpaso)][elpaso]], [[elisp:(describe-package 'cask)][cask]], and [[elisp:(describe-package 'leaf)][leaf]]. I will not claim to be familiar with any of these, but the selection criteria few sections above ought to apply to package managers.

#+begin_src emacs-lisp

  ;; Get the good stuff from MELPA.
  (require 'package)
  (setq package-archives '(("melpa" . "https://melpa.org/packages/")
                           ("elpa" . "https://elpa.gnu.org/packages/")))

  ;; Sync the repos.
  (package-initialize)
  (unless package-archive-contents
    (package-refresh-contents))

  ;; Install and load use-package, if not done already.
  (unless (package-installed-p 'use-package)
    (package-install use-package))

  (require 'use-package)

  ;; Ensure that every package declared is installed correctly.
  (setq use-package-always-ensure t)

  ;; Allows us to make sure external binaries are available to support a particular package.
  (use-package use-package-ensure-system-package)

#+end_src

* Desktop Environment

The highest level of information management and display.

** Buffer Management

[[elisp:(describe-package 'bufler)][Bufler]] provides a replacement for the built-in [[elisp:(describe-package 'ibuffer)][ibuffer]] that's both prettier and has sane defaults; it's very useful for reclaiming space from large, unused, buried buffers. [[elisp:(describe-package 'edwina)][Edwina]] provides dwm-like window management. There exist many tab-bar-style interfaces for buffer management, but these seem to end up being little more than distracting---twixt-buffer navigation information ought not intrpude on buffer space, but present itself when called.

#+begin_src emacs-lisp

  (use-package bufler
    :bind ("C-x B" . bufler))

  (use-package edwina
    :config
    (setq display-buffer-base-action '(display-buffer-below-selected)) ;; Always create new window for buffer,
    (setq display-buffer-alist ;; except in these cases, where it's far too annoying.
          '(("\\*Help\\*" display-buffer-same-window)
            ("\\*helpful " display-buffer-same-window)
            ("\\*Backtrace\\*" display-buffer-at-bottom)))
    (edwina-setup-dwm-keys 'super)
    (edwina-mode t))

#+end_src

** Notifications

[[elisp:(describe-package 'ednc)][Ednc]] implements a decent UI for [[elisp:(describe-package 'notifications)][notifications]], an Elisp implementation of the [[https://freedesktop.org][freedesktop.org]] desktop notification spec. Perfect for EXWM.

#+begin_src emacs-lisp

  (defun dnw/stack-notifications (&optional hide)
    "Stringify only the most recent notification from each application."
    (mapconcat (lambda (notification)
                 (let ((app-name (ednc-notification-app-name notification)))
                   (unless (member app-name hide)
                     (push app-name hide)
                     (ednc-format-notification notification))))
               (ednc-notifications) ""))

  (use-package ednc
    :after exwm
    :hook (ednc-notification-presentation-functions . (lambda (&rest _) (force-mode-line-update t)))
    :config
    (ednc-mode)
    (nconc global-mode-string '((:eval (dnw/stack-notifications)))))

#+end_src

** EXWM

[[elisp:(describe-package 'exwm)][EXWM]] allows me to spawn X applications as Emacs buffers. This is great, because it allows me to use a single buffer-management scheme for windows also, extends Emacs' wonderful input modes for mathematics and CJK to all applications (fcitx is a nightmare by comparison), and remap Emacs-style keybindings to CUA equivalents. [[elisp:(describe-package 'exwm-edit)][Exwm-edit]] allows for Emacs-buffer entry of text into X applications---think editing Markdown-formatted forum posts in a Markdown-mode buffer.

#+begin_src emacs-lisp

  (defun dnw/exwm-config ()
    "My configuration of EXWM, adapted from the example."
    ;; Load modules
    (require 'exwm-xim)
    (require 'exwm-randr)
    (require 'exwm-systemtray)

    ;; Set the initial workspace number.
    (unless (get 'exwm-workspace-number 'saved-value)
      (setq exwm-workspace-number 4))
    ;; Make class name the buffer name
    (add-hook 'exwm-update-class-hook
              (lambda ()
                (exwm-workspace-rename-buffer exwm-class-name)))
    (setq exwm-randr-workspace-output-plist  '(1 "VGA-1" 2 "VGA-1" 3 "VGA-1"))
    (add-hook 'exwm-randr-screen-change-hook
              (lambda ()
                (start-process-shell-command
                 "xrandr" nil "xrandr --output VGA-1 --left-of LVDS-1 --auto")))

    ;; Global keybindings.
    (unless (get 'exwm-input-global-keys 'saved-value)
      (setq exwm-input-global-keys
            `(
              ;; 's-R': Reset (to line-mode).
              ([?\s-r] . exwm-reset)
              ;; 's-w': Switch workspace.
              ([?\s-w] . exwm-workspace-switch)
              ;; 's-p': Launch application.
              ([?\s-p] . (lambda (command)
                           (interactive (list (read-shell-command "$ ")))
                           (start-process-shell-command command nil command)))
              ;; 's-P': retrieve a password from password store
              ([?\s-P] . password-store-copy)
              ;; 's-N': Switch to certain workspace.
              ,@(mapcar (lambda (i)
                          `(,(kbd (format "s-%d" i)) .
                            (lambda ()
                              (interactive)
                              (exwm-workspace-switch-create ,i))))
                        (number-sequence 0 9)))))
    ;; Line-editing shortcuts
    (unless (get 'exwm-input-simulation-keys 'saved-value)
      (setq exwm-input-simulation-keys
            '(([?\C-b] . [left])
              ([?\C-f] . [right])
              ([?\C-p] . [up])
              ([?\C-n] . [down])
              ([?\C-a] . [home])
              ([?\C-e] . [end])
              ([?\M-v] . [prior])
              ([?\C-v] . [next])
              ([?\C-s] . [C-f])
              ([?\C-d] . [delete])
              ([?\C-g] . [ESC])
              ([?\M-b] . [C-left])
              ([?\M-f] . [C-right])
              ([?\C-k] . [S-end delete])
              ([?\C-w] . [C-x])
              ([?\M-w] . [C-c])
              ([?\C-y] . [C-v])
              ([?\C-/] . [C-z])
              ([?\C-x ?h] . [C-a]))))
    ;; Enable EXWM
    (exwm-enable)
    (exwm-xim-enable)
    (exwm-randr-enable)
    (push ?\C-\\ exwm-input-prefix-keys))

  (use-package exwm
    :config (dnw/exwm-config))

  ;; Edit selected text in org-mode-style source block. It full-screens it at the moment, not sure what that's about.
  (use-package exwm-edit
    :after exwm
    :if (eq window-system 'x))

#+end_src

The =.xinitrc= that I use to actually start Emacs is (see [[*Editing Server][Editing Server]]):

#+begin_src shell :tangle no

  setxkbmap us -option ctrl:swapcaps

  #/home/dnw/.fehbg &
  #bash /home/dnw/status.sh &
  pulseaudio --start

  # EXWM start
  # Disable access control for the current user.
  xhost +SI:localuser:$USER

  # Make Java applications aware this is a non-reparenting window manager.
  export _JAVA_AWT_WM_NONREPARENTING=1

  # Set default cursor.
  xsetroot -cursor_name left_ptr

  # Set keyboard repeat rate.
  xset r rate 200 60

  # Uncomment the following block to use the exwm-xim module.
  export XMODIFIERS=@im=exwm-xim
  export GTK_IM_MODULE=xim
  export QT_IM_MODULE=xim
  export CLUTTER_IM_MODULE=xim

  # required for GTK3 scrolling
  export GDK_CORE_DEVICE_EVENTS=1
  # Finally start Emacs

  exec dbus-run-session -- emacsclient -c -a ""

#+end_src

I then have the following =.zprofile=, so that =startx= gets called automatically upon user login on =tty2=.

#+begin_src shell :tangle no

  # Honor system-wide environment variables
  source /etc/profile

  [[ -t 0 && $(tty) == /dev/tty2 && $- =~ "l" ]]  && source ~/.zshrc && exec startx

#+end_src

* UI Glow-Up

By default, Emacs is ugly as sin.

** Better Font

Something like GNU Unifont is the default; I don't think I have a good eye for fonts generally, but Iosevka seems leaps and bounds better. Google's Noto fonts have great unicode coverage, and nice-looking emojis.

#+begin_src emacs-lisp

  (defun dnw/check-font-exists (pair)
    "Given a pair `(font-name . system-package)', check that font-name is accessible, installing its corresponding system-package,
    if non-nil and not already installed, otherwise."
    (let ((font-name (car pair))
          (system-package (cdr pair)))
      (unless (find-font (font-spec :name font-name))
        (if system-package
            (if (package-installed-p system-package)
                (message (concat "Font " font-name " installed, but not available to Emacs."))
              (message (concat "Font " font-name " not installed.")))))))

  ;; Check for the desired fonts.
  (if (eq window-system 'x)
      (mapcar #'dnw/check-font-exists
              '(("Iosevka" . ttc-iosevka)
                ("Liberation Sans" . ttf-liberation)
                ("Noto Sans" . noto-ttf)
                ("Noto Color Emoji" . noto-fonts-emoji)
                ("Symbols Nerd Font Mono" . ttf-nerd-font-symbols-mono))))

  ;; Set the default font to be monospaced Iosevka. TODO: check if this can be commented
  (add-to-list 'default-frame-alist
               '(font . "Iosevka-10"))

  ;; Set fallback fonts for Unicode characters and variable-pitch text.
  (defun dnw/unicode-fonts ()
    (setf use-default-font-for-symbols nil)
    (set-face-font 'variable-pitch (font-spec :name "Liberation Sans"))
    (set-face-font 'fixed-pitch (font-spec :name "Iosevka"))
    (set-fontset-font t 'unicode "Noto Emoji" nil 'append)
    (set-fontset-font t 'emoji "Noto Color Emoji"))

  ;; Configuring the fallbacks has some timing intricacies with the daemon:
  ;; additional frames can be made after the config finishes loading.
  (if (daemonp)
      (add-hook 'server-after-make-frame-hook #'dnw/unicode-fonts)
    (dnw/unicode-fonts))

#+end_src

** Hide Gross UI Elements

#+begin_src emacs-lisp

  ;; Everything that reeks of desktop environments must go. We know what we're doing.
  (menu-bar-mode -1)
  (tool-bar-mode -1)
  (scroll-bar-mode -1)
  (tooltip-mode -1)
  (set-fringe-mode 10)

#+end_src

** Replace W/ Good Ones

The desktop environment clutter may now be replaced with tasteful, contentual, context-dependent navigation information. The [[elisp:(describe-package 'on-screen)][on-screen]] package provides nice little margin indicators for the previously-visible buffer section after scrolls.

#+begin_src emacs-lisp

  ;; Show column number on the modeline.
  (column-number-mode)

  ;; Display line numbers in the left margin, as a general rule,
  (global-display-line-numbers-mode t)

  ;; but disable them where they just add clutter, e.g. shell.
  (dolist (mode '(org-mode-hook
                  term-mode-hook
                  vterm-mode-hook
                  eshell-mode-hook
                  Info-mode-hook
                  ement-room-mode-hook
                  elfeed-show-mode-hook
                  pdf-mode-hook))
    (add-hook mode (lambda () (display-line-numbers-mode 0))))

  ;; Enable on-screen globally.
  (use-package on-screen
    :config (global-on-screen-mode t))

#+end_src

** DOOM Features

DOOM Emacs' modeline simply looks better to me than the default or Spacemacs'. If the minor-mode list ever gets too cluttered, install the [[elisp:(describe-package 'diminish)][diminish]] package to mitigate. The DOOM themes, additionally, appear to play nicer with buffers created by external packages (I presume because these are in DOOM's distribution by default).

#+begin_src emacs-lisp

  ;; Get the modeline.
  (use-package doom-modeline
    :config (doom-modeline-mode 1))


  ;; Get the themes, and load the favorite.
  (use-package doom-themes
    :config (load-theme 'doom-tomorrow-night t))

#+end_src

To test out alternative themes, do [[elisp:(call-interactively #'load-theme)][M-x load-theme]]. Beware that sometimes artefacts of old themes persist and make new ones look bad; [[elisp:(call-interactively #'disable-theme)][M-x disable-theme]] prevents this to an extent.

** Splash Screen

The [[elisp:(describe-package 'dashboard)][dashboard]] package from Spacemacs, because it’s nice when things look pretty, and it can make navigation on startup somewhat faster.

#+begin_src emacs-lisp

  ;; Make a 1337 h@ckerman5 splash screen. TODO: debug the buffer not displaying when starting the server.
  (use-package dashboard
    :config
    (dashboard-setup-startup-hook)
    (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*")))
    (setq dashboard-banner-logo-title "Pauca Sed Matura.")
    (setq dashboard-center-content t)
    (setq dashboard-image-banner-max-width 600)
    (setq dashboard-startup-banner "~/Emacs-Config/crystals8.png")
    (setq dashboard-display-icons-p t)
    (setq dashboard-icon-type 'nerd-icons))

#+end_src

** Ligatures and Fancy Characters

Exploit Iosevka's ligature support, with the [[elisp:(describe-package 'ligature)][ligature]] package, and do other equivalent display niceties.

#+begin_src emacs-lisp

  ;; Replace e.g. lambda -> λ in Emacs Lisp mode,
  ;; or \alpha -> α in TeX-mode
  (global-prettify-symbols-mode t)

  ;; Enables fonts' ligature support---Iosevka has some good ones.
  (use-package ligature
    :if (display-graphic-p)
    :config
    (global-ligature-mode t)
    (ligature-set-ligatures
     '(prog-mode org-mode)
     '("-<<" "-<" "-<-" "<--" "<---" "<<-" "<-" "->" "->>" "-->" "--->" "->-" ">-" ">>-"
       "=<<" "=<" "=<=" "<==" "<===" "<<=" "<=" "=>" "=>>" "==>" "===>" "=>=" ">=" ">>="
       "<->" "<-->" "<--->" "<---->" "<=>" "<==>" "<===>" "<====>" "::" ":::" "__"
       "<~~" "</" "</>" "/>" "~~>" "==" "!=" "/=" "~=" "<>" "===" "!==" "!===" "=/=" "=!="
       "<:" ":=" "*=" "*+" "<*" "<*>" "*>" "<|" "<|>" "|>" "<." "<.>" ".>" "+*" "=*" "=:" ":>"
       "(*" "*)" "/*" "*/" "[|" "|]" "{|" "|}" "++" "+++" "\\/" "/\\" "|-" "-|" "<!--" "<!---")))

#+end_src

All of this can be set by-mode or by-buffer, by setting hooks with or manually invoking the non-global versions of the above.

* General Text Interaction

There are lots of ways to search, jump, move through, highlight, rearrange, display, etc. parts of text that're common across large swathes of modes.

** Basic Movement and Alteration

Not too much configuration here. The defaults are very sane, and hard to unlearn. As noted above, see the [[elisp:(call-interactively #'help-with-tutorial)][tutorial]] (accessible via =C-h t=) for the basics. The commands are documented pretty extensively in the manual:

- [[info:emacs#Moving Point][Moving the Point]]
- [[info:emacs#Scrolling][Scrolling]]
- [[info:emacs#Recentering][Recentering]]
- [[info:emacs#Inserting Text][Inserting Text]]
- [[info:emacs#Erasing][Erasing]]
- [[info:emacs#Blank Lines][Blank Lines]]
- [[info:emacs#Transpose][Transpose]]
- [[info:emacs#Fixing Case][Fixing Case]]
- [[info:emacs#Indentation][Indentation]]
- [[info:emacs#Words][Words]]
- [[info:emacs#Sentences][Sentences]]
- [[info:emacs#Paragraphs][Paragraphs]]
- [[info:emacs#Moving by Defuns][Moving by Defuns]]
- [[info:emacs#Moving by Parens][Moving by Parens]]
- [[info:emacs#Comment Commands][Comment Commands]]
- [[info:emacs#MixedCase Words][MixedCase Words]]

Additionally useful will be the various [[info:emacs#Search][Search]] features; however, we rebind the default =isearch= on =C-s= to [[elisp:(helpful-function 'consult-line)][consult-line]]. Note in the manual especially the features for modifying search/replace behavior on-the-fly.

** Regions, Yanks, Kills, (Book)Marks, and Registers

Emacs has many faculties for saving positions in buffers to refer to later. These features employ the concept of [[info:emacs#Mark][marks and regions]]. However, by default, the mark is intertwined with the region in a slightly annoying way, which makes it hard/unweildly to use the mark ring as a "scratch" poisition storage. The package [[elisp:(describe-package 'expand-region)][expand-region]] provides a very quick way to cycle the region through the usual semantic units of text.

#+begin_src emacs-lisp

  ;; Config snippet courtesy Mickey Petersen's /Mastering Emacs/.
  ;; It sets up bindings for using the mark independent from the region,
  ;; without giving up transient-mark-mode.
  (defun dnw/push-mark-no-activate ()
    "Pushes `point' to `mark-ring' and does not activate the region.
  Equivalent to \\[set-mark-command] when \\[transient-mark-mode] is disabled."
    (interactive)
    (push-mark (point) t nil)
    (message "Pushed mark to ring"))

  (defun dnw/jump-to-mark ()
    "Jumps to the local mark, respecting the `mark-ring' order.
  This is the same as using \\[set-mark-command] with prefix argument."
    (interactive)
    (set-mark-command 1))

  (defun dnw/exchange-point-and-mark-no-activate ()
    "Identical to \\[exchange-point-and-mark] but will not activate the region."
    (interactive)
    (exchange-point-and-mark)
    (deactivate-mark nil))

  ;; Bind our alternatives.
  (global-set-key (kbd "C-`") 'dnw/push-mark-no-activate)
  (global-set-key (kbd "M-`") 'dnw/jump-to-mark)
  (define-key global-map [remap exchange-point-and-mark] 'dnw/exchange-point-and-mark-no-activate)

  ;; Increases the region by reasonable, general semantic units.
  (use-package expand-region
    :bind ("C-=" . er/expand-region))

#+end_src

Many commands (even some of the ones often forgotten about, like =M-d= / =kill-word=) store the region in the [[info:emacs#Killing][kill ring]], a stack with wraparound onto which values are continually pushed. Regions and marks (among a few other things) can be stored in a common set of [[info:emacs#Registers][Registers]], one-character-named, cleared-on-exit variables. Marks can additionally be stored in [[info:emacs#Bookmarks][Bookmarks]], which are longer-named variables which may be saved to a file to persist between sessions.

Hiding among some of the documentation above are [[info:emacs#Rectangles][Rectangle]] regions: exactly what they sound like. They seem to have their own, separate kill storage, for only one rectangle at a time, but the same registers. Rectangle commands are very useful in situations where it's necessary to modify some text in the middle of an aligned, high-depth text structure.

** Undo

One of Emacs' best features is its lossless undo. Undo undoes itself---so, at least within the confines of the undo limit, the buffer never enters an unrecoverable state. Things further in the past are always just more undos away. However, this isn't very semantic. Often, it's hard to remember how many undos have been done, or what the state of the buffer was before three different bad ideas hit in some weird order. Additionally, there's lots of spamming/numeric-argumenting =C-/= through the same or similar states over and over again. The [[elisp:(describe-package 'undo-tree)][undo-tree]] package substantially improves this, realizing the edit history exactly as users think of it: a tree of states.

#+begin_src emacs-lisp

  (use-package undo-tree
    :config (global-undo-tree-mode)
    (setq undo-tree-auto-save-history nil)) ;; This litters WAY too much

#+end_src

See the documentation linked above for the set of basic keys (which align with the default =C-/= and =C-?= for the simplest stuff); there are very cool visualization and state-storage commands.

** Macros

One of the most helpful features of Emacs is its extremely deep [[info:emacs#Keyboard Macros][keyboard macro]] system. In particular, the fact these macros extend to all Emacs interfaces, e.g. =C-s=, =M-x=, and =M-:=, enables them to perform almost any repetitive task on files. Look to record one when doing any editing that feels boring; most likely there's something lurking! Save any particularly general ones for later. Note the macro queries with recursive-edits and counters; you can integrate calc commands into macro execution too. Notice the commands under =C-x C-k= allowing one to name, bind, extract as Lisp, and insert as Lisp keyboard macros. This one was useful in the preparation of this document; executing the form will recreate this macro.

#+begin_src emacs-lisp :tangle no

  (fset 'dnw/org-link-to-package
        (kmacro-lambda-form
         [?\C-c ?\C-l ?e ?l ?i ?s ?p ?: ?\( ?d ?e ?s ?c ?r ?i ?b ?e ?- ?p ?a ?c ?k ?a ?g ?e ?  ?\'
                ?\C-` ?\C-u ?\C-x ?q ?\M-` ?\C-  ?\C-e ?\M-w ?\) return ?\C-y return] 0 "%d"))


#+end_src

** Input Methods

One of Emacs' hallmark features is its level of support for non-Latin scripts. Input methods are the way it supports entry of characters from those scripts on a standard US keyboard---after enabling one, characters you type can be matched against indices into a character set, from which the actual character can be selected and inserted. I occasionally have a reason to use my high-school Chinese; it's great for that. More commonly, I use the TeX input method to embed mathematical characters where LaTeX fragments are impractical or ugly.

To select and enable an alternate input method, use =C-\=. Subsequent invocations will toggle between the "normal" input method and the alternate. In case you use more than 2, =C-x RET C-\= will present the same input-method minibuffer selection, and change the alternate to your choice.

** Delimiter Management

Stuff of the form "<begin-token> content <end-token>" is ubiquitous, and can be much improved. The [[elisp:(describe-package 'rainbow-delimiters)][rainbow-delimiters]] package makes determining which parentheses match much easier, especially in highly-nested Lisp expressions. Likewise, [[elisp:(describe-package 'paren)][paren]] will indicate the parentesis corresponding to the one under the point. The [[elisp:(describe-package 'smartparens)][smartparens]] package reduces keystrokes when typing parentheses by automatically inserting a closing delimiter behind the point whenever a corresponding opening one is typed;

#+begin_src emacs-lisp

  ;; Make each nesting level of parenthesis a different color, to avoid counting.
  (use-package rainbow-delimiters
    :commands rainbow-delimiters-mode
    :hook ((prog-mode . rainbow-delimiters-mode)
           (LaTeX-mode . rainbow-delimiters-mode)))

  ;; This will automatically create matched pairs whenever open delimiters are typed,
  ;; highlight unmatched closing delimiters, etc.
  (use-package smartparens
    :commands smartparens-mode
    :hook ((prog-mode . smartparens-mode)
           (LaTeX-mode . smartparens-mode)
           (org-mode . smartparens-mode))
    :config
    (require 'smartparens-latex))

  ;; Built-in that'll highlight the counterpart to whichever paren your cursor is over.
  (use-package paren
    :config
    (set-face-attribute 'show-paren-match-expression nil :background "#363e4a")
    (show-paren-mode t))


#+end_src

** Long-Distance Navigation

Counting and doing =C-f 57= isn't fun. Long-term, I'd like to develop eye-tracking-based mouse control, so you'd just hit a keyboard button to do mouse things where your already looking, but in the interim, [[elisp:(describe-package 'avy)][avy]], [[elisp:(describe-package 'dogears)][dogears]], and [[info:elisp#Imenu][imenu]] will do.

#+begin_src emacs-lisp

  ;; Quickly navigate to on-screen characters.
  ;; An alternative is ace-jump, but it's not maintained.
  (use-package avy
    :bind
    ("C-:" . avy-goto-char)
    ("C-'" . avy-goto-char-2)
    ("M-g g" . avy-goto-line)
    ("M-g M-g" . avy-goto-line))

  ;; Smartly navigate to past locations. NOTE: on package probation; it might be less than useful.
  (use-package dogears
    :config (dogears-mode)
    :bind (("M-g d" . dogears-go)
           ("M-g M-b" . dogears-back)
           ("M-g M-f" . dogears-forward)
           ("M-g M-d" . dogears-list)
           ("M-g M-D" . dogears-sidebar)))

#+end_src

While looking at a place you want to jump to, press =C-'= , enter two characters nearest it, and type the characters it changes to. The point will end up there when it's disambiguated fully. Use =C-:=  if you prefer to type one initial character and more subsequent ones. The =avy-goto-line= parts replace the default =goto-line= binding with a function with similar behavior: type two characters to jump to the head of any line. The original =goto-line= behavior (jump based on line number) is recovered by typing a number. The imenu allows quick navigation between top-level semantic units in a file. The [[*Consult][Consult]] replacement for it is bound to =C-c i=.

** Buffer Metrics

=M-=== counts words, and =C-x l= lines on the "page."

** Whitespace Behavior

Save space, and make things look nice (on everyone's machine). The [[elisp:(describe-package 'ws-butler)][ws-butler]] package will trim trailing whitespace on saves, which is essential for the smooth operation of navigation like =C-e=.

#+begin_src emacs-lisp

  ;; Spaces over tabs
  (setq tab-always-indent 'complete)
  (setq align-to-tab-stop nil)

  ;; Require files to end in newlines
  (setq require-final-newline t)

  ;; Enforce a line-length limit.
  (setq fill-column 140) ;; Chosen to fit nicely at my font-size on 4:3.
  (auto-fill-mode t)

  ;; Trim trailing line whitespace on save.
  (use-package ws-butler
    :hook ((text-mode . ws-butler-mode)
           (prog-mode . ws-butler-mode)))

#+end_src

Notice =M-x whitespace-mode= for inspecting exactly what's going on with whitespace.

** Better English

[[elisp:(describe-package 'ispell)][Ispell]] is the built-in package for interfacing with dictionaries. There is a [[elisp:(describe-package 'grammarly)][grammarly]] package on MELPA, but I'm squeamish about sending all my text to a nonfree network service for semantic analysis. And the FOSS, local package =languagetool= (at least, in conjunction with [[elisp:(describe-package 'langtool)][langtool]] for Emacs) is slow as can be and very unhelpful. It couldn't find a problem with "The quick fox brown jumps over the dog, lazy." [[elisp:(describe-package 'define-word)][Define-word]] interfaces with external dictionaries to get definitions, not just spelling corrections. [[elisp:(describe-package 'le-thesaurus)][Le-thesaurus]] uses the [[https:thesaurus.com][thesaurus.com]] API to provide synonyms for the word at point. See [[elisp:(describe-package 'mw-thesaurus)][mw-thesaurus]], [[elisp:(describe-package 'synonymous)][synonomous]], [[elisp:(describe-package 'synosaurus)][synosaurus]], for other less-complete, less-well-maintained, or requiring-API-key thesaurus packages. See [[elisp:(describe-package 'smog)][smog]] and [[elisp:(describe-package 'proselint)][proselint]] for more complete style analysis.

#+begin_src emacs-lisp

  (use-package ispell
    ;; Could use ispell, hunspell, aspell, or enchant.
    :ensure-system-package (aspell ("/usr/lib/aspell/american.alias" . aspell-en)))

  ;; Gets wordnik definition of the word at point.
  (use-package define-word
    :commands define-word
    :bind ("M-D" . define-word-at-point))

  ;; Use the thesaurus.com API
  (use-package le-thesaurus
    :commands (le-thesaurus-get-synonyms le-thesaurus-get-antonyms)
    :bind (("C-c t s" . le-thesaurus-get-synonyms)
           ("C-c t a" . le-thesaurus-get-antonyms)))

#+end_src

Use =M-$= to spell-check a word. Use =M-x ispell= to spell-check the whole buffer. =flyspell-mode= and =flyspell-prog-mode= can be enabled for a traditional red-squiggly-line experience, though if one uses enough technical words and spell well enough it can get annoying. Ensure you have a good word-list available.

** Rendering LaTeX Inline

By default, there's an org command I bind globally to =C-c C-x C-l= that renders LaTeX snippets. There's a [[elisp:(describe-package 'math-preview)][math-preview]] package using MathJax, which may be faster. The package [[elisp:(describe-package 'texfrag)][texfrag]] hooks into AUCTeX's preview functionality, and has the advantage that putting the point over inside the rendered snippet expands it to the source and permits editing. Additionally, the preamble used may be modified, and the TeX buffer used to generate the snippet changed by-hand for one-off things.

#+begin_src emacs-lisp

  (use-package texfrag
    :commands texfrag-mode)

#+end_src

See the results with =C-c C-p C-p= after activating =texfrag-mode=: $e^{i\pi} + 1 = 0$

** Readable Numbers

Puts graphical-only underscores between triple-digit groups of large numbers, e.g. 10000. Interacts a little oddly with long decimals, e.g. 0.0031232.

#+begin_src emacs-lisp

  (use-package readable-numbers
    :hook ((text-mode . readable-numbers-mode)
           (prog-mode . readable-numbers-mode)))

#+end_src

** Outlining

While it's hard to see a use for it, Emacs provides [[info:emacs#Outline Mode][Outline Mode]] (and a glow-up [[elisp:(describe-package 'allout)][allout]])  for essentially emulating org-mode in arbitrary text-mode buffers.

** Translation

[[elisp:(describe-package 'go-translate)][Go-translate]] can de-obfuscate non-English human languages.

#+begin_src emacs-lisp

  (use-package go-translate
    :commands gts-do-translate
    :config
    (setq gts-translate-list '(("en" "zh"))) ;; Add more languages here.
    (setq gts-default-translator
          (gts-translator
           :picker (gts-prompt-picker)
           :engines (list (gts-google-engine) (gts-google-rpc-engine)) ;; There are other engines available.
           :render (gts-buffer-render))))

#+end_src

** Comments

[[elisp:(describe-package 'hl-todo)][Hl-todo]] highlights =TODO= etc. in comments and provides commands to jump between them.

#+begin_src emacs-lisp

  ;; TODO: demonstration purposes.
  (use-package hl-todo
    :config (global-hl-todo-mode)
    :bind (("C-c t p" . hl-todo-previous)
           ("C-c t n" . hl-todo-next)
           ("C-c t o" . hl-todo-occur)
           ("C-c t i" . hl-todo-insert)))

#+end_src

The commands bound above do exactly what they say on the box for navigating between highlighted elements.

** Confusable Characters

TODO: configure =textsec= in Emacs 29.

** Ugly, Repetitive Headers

The built-in [[elisp:(describe-package 'elide-head)][elide-head]] can be used to surpress fixed, relatively useless content at the top of files.

* Completion and Templating

Sometimes, you're programming and forget what things are called. Or you don't want to keep typing a long, overly-descriptive Java name in someone else's code. Or, you forget what the full name of the function you want to type into the minibuffer is, but you know it was something to do with "doom." Enter completion. There are two places where it operates: when the point is in an ordinary buffer, and when it's in the minibuffer. The default system has the unfortunate quality of opening a whole buffer with completion candidates, and does so only after you explicitly prompt it for completions via a keypress. There are many systems which instead populate the minibuffer with completion candidates off the bat, and provide IDE-style small-window popups in-buffer. However, many are very heavy and use their own, entirely separate system for completion.

The =vertico= stack instead alters the built-in =completing-read= for minibuffer completions. It's small, modular, lightweight, and well-integrated with the default Emacs facilities, and therefore other packages that use those by extension. It's all made by the same guy, so its well-integration is expected. In Emacs 29, there will be an upgraded =icomplete= that has a similar UI to vertico itself. We'll see if it works as well.

** Vertico

The starting place of it all only modifies the minibuffer UI, by presenting a [[elisp:(describe-package 'vertico)][VERTical list of COmpletions]] in the minibuffer. [[elisp:(describe-package 'nerd-icons-completion)][Nerd-icons-completion]] uses the nerd icons font installed wiith the DOOM themes for complection candidate icons.

#+begin_src emacs-lisp

  (use-package vertico
    :config (vertico-mode)
    :custom
    ;; Wrap completions at the top and bottom of the list.
    (vertico-cycle t))

  ;; Add nice icons from DOOM's nerd-fonts from earlier to minibuffer completions.
  (use-package nerd-icons-completion)

#+end_src

** Corfu

[[elisp:(describe-package 'corfu)][Corfu]] only modifies the UI for completion in the region, by popping up a small frame instead of a completions buffer. Should integrate very well with vertico.

#+begin_src emacs-lisp

  (use-package corfu
    :custom (corfu-cycle t)
    :config (global-corfu-mode))

#+end_src

*** Kind Icon

[[elisp:(describe-package 'kind-icon)][Kind-icon]] adds type-based icon annotations in the left margin of the Corfu buffer, so you can tell if the candidate is a function etc.

#+begin_src emacs-lisp

  (use-package kind-icon
    :after corfu
    :custom
    (kind-icon-default-face 'corfu-default) ;; to compute blended backgrounds correctly
    :config
    (add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter))

#+end_src

** Orderless

[[elisp:(describe-package 'orderless)][Orderless]] changes the way the completion prompt is used to search for candidates to enable fuzzy matching, regexes etc. This is very flexible, and can be used independent of the above.

#+begin_src emacs-lisp

  (use-package orderless
    :config
    (setq completion-styles '(orderless basic) ;; basic is required for TRAMP hostname completion
          completion-category-defaults nil
          completion-category-overrides '((file (styles . (partial-completion))))))

#+end_src

The prompt (e.g. what you type into =M-x=) is divided into space-separated components. Each component is interpreted as either a regexp or a literal match. Any candidate that matches the all of the components in any order, possibly with some intervening characters, is preserved.

** Consult

A lot of the default navigation commands are pretty clumsy. [[elisp:(describe-package 'consult)][Consult]] provides a lot of alternative UIs to commands, such as search and history that shows the context around the match.
[[elisp:(describe-package 'consult-eglot)][Consult-eglot]] provides the same for eglot symbol search.

#+begin_src emacs-lisp

  (use-package consult
    :bind (("C-s" . consult-line)
           ("C-r" . consult-history)
           ("C-c i" . consult-imenu)
           ("C-x b" . consult-buffer)
           ("C-x r b" . consult-bookmark)
           ("C-x r i" . consult-register)
           ("C-+" . consult-mark)
           ("C-x C-@" . consult-pop-global-mark))
    :custom (completion-in-region-function #'consult-completion-in-region))

  (use-package consult-eglot
    :commands consult-eglot-symbols
    :after eglot)

#+end_src

** Marginalia

[[elisp:(describe-package 'marginalia)][Marginalia]] is like Corfu, but for the minibuffer. Can display things like documentation, file permissions, etc. alongside each candidate in the minibuffer.

#+begin_src emacs-lisp

  (use-package marginalia
    :custom
    (marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
    (marginalia-mode))

#+end_src

** Embark

[[elisp:(describe-pacakge 'embark)][Embark]]is kind of like right-click, but for the keyboard, and better than rebinding the mouse key (which you can do!). =embark-act= pops up a completion prompt based on whatever content is under or near the point. [[elisp:(describe-package 'embark-consult)][Embark-consult]] provides an Embark-like ehancement for the UI.

#+begin_src emacs-lisp

  ;; From the recommended config. TODO: figure out how to prevent it from shoving whole paragraphs into the minibuffer.
  (use-package embark
    :bind
    (("C-." . embark-act)
     ("C-;" . embark-dwim)
     ("C-h B" . embark-bindings))
    :init (add-hook 'eldoc-documentation-functions #'embark-eldoc-first-target)
    :config
    (setq prefix-help-command #'embark-prefix-help-command) ;; No idea what this does, but they said to add it.
    (setq embark-prompter #'embark-completing-read-prompter)
    (setq embark-indicators
          '(embark-minimal-indicator
            embark-highlight-indicator
            embark-isearch-highlight-indicator)))

  ;; Consult integration.
  (use-package embark-consult
    :hook
    (embark-collect-mode . consult-preview-at-point-mode))

#+end_src

** Abbreviations

When typing a long something repetitively, Emacs’ built-in [[info:emacs#Abbrevs][Abbrevs]] can help.

Sometimes, you want completion, but you don't have anything providing the completion. =dabbrev= helps provide that by looking through the words in the buffer for things you've already typed to u se as candidates.[[elisp:(describe-package 'tempel)][Tempel]] extends [[elisp:(describe-package 'tempo)][tempo]] style template expansion to other modes, and with better integration with modern Emacs features, e.g. completion. See also the built-in [[elisp:(describe-package 'expand)][expand]] for interactively expanded abbreviations.

#+begin_src emacs-lisp

  ;; Notify when a defined abbrev is missed.
  (setq abbrev-suggest t)

  ;; Map the more-useful function to the more-ergonomic key.
  (use-package dabbrev
    :bind (("M-/" . dabbrev-completion)
           ("C-M-/" . dabbrev-expand)))

  ;; TODO: setup some tempel templates
  (use-package tempel
    ;; Require trigger prefix before template name when completing.
    :custom
    (tempel-trigger-prefix "<")
    :init
    ;; Setup completion at point
    (defun tempel-setup-capf ()
      ;; Add the Tempel Capf to `completion-at-point-functions'.
      ;; `tempel-expand' only triggers on exact matches. Alternatively use
      ;; `tempel-complete' if you want to see all matches, but then you
      ;; should also configure `tempel-trigger-prefix', such that Tempel
      ;; does not trigger too often when you don't expect it. NOTE: We add
      ;; `tempel-expand' *before* the main programming mode Capf, such
      ;; that it will be tried first.
      (setq-local completion-at-point-functions
                  (cons #'tempel-expand
                        completion-at-point-functions)))

    (add-hook 'prog-mode-hook 'tempel-setup-capf)
    (add-hook 'text-mode-hook 'tempel-setup-capf))

#+end_src

Note the ways to customize what =dabbrev= considers a word, and distinct words.

** Auto-Insert

The built-in [[elisp:(describe-package 'autoinsert)][autoinsert]] package makes filling out boilerplate easy. I currently use it extensively for choosing between a few LaTeX preambles.

#+begin_src emacs-lisp

  ;; Let the user enter a due date (very buggy).
  (defun dnw/prompt-date ()
    (let ((date (read-string "Due date: "))
          (now  (split-string (format-time-string "%e %B %Y" (current-time)))))
      (cond ((equal date "")
             (concat now))
            ((equal (substring date 0 1) "+")
             (concat (number-to-string (+ (string-to-number (car now))
                                          (string-to-number (substring date 1))))
                     " "
                     (cadr now)
                     " "
                     (caddr now)))
            ((= (length date) 2)
             (concat date
                     " "
                     (cadr now)
                     " "
                     (caddr now))))))

  ;; Some assorted preambles.
  (setq dnw/autoinsert-latex-presets
        '(("Physics" . (nil "\\documentclass{article}\n\n"

                            "\\usepackage[letterpaper]{geometry}\n"
                            "\\usepackage{tgpagella}\n"
                            "\\usepackage{amsmath}\n"
                            "\\usepackage{amssymb}\n"
                            "\\usepackage{amsthm}\n"
                            "\\usepackage{tikz}\n"
                            "\\usepackage{minted}\n"
                            "\\usepackage{physics}\n"
                            "\\usepackage{siunitx}\n\n"

                            "\\sisetup{detect-all}\n"
                            "\\newtheorem{plm}{Problem}\n"
                            "\\renewcommand*{\\proofname}{Solution}\n\n"


                            "\\title{" (read-string "Title: ") "}\n"
                            "\\author{Duncan Wilkie}\n"
                            "\\date{" (dnw/prompt-date) "}\n\n"

                            "\\begin{document}\n\n"

                            "\\maketitle\n\n"

                            -

                            "\n\n\\end{document}"))
          ("Math" . (nil "\\documentclass{article}\n\n"

                            "\\usepackage[letterpaper]{geometry}\n"
                            "\\usepackage{tgpagella}\n"
                            "\\usepackage{amsmath}\n"
                            "\\usepackage{amssymb}\n"
                            "\\usepackage{amsthm}\n"
                            "\\usepackage{tikz}\n"
                            "\\usepackage{minted}\n"
                            "\\usepackage{physics}\n"
                            "\\usepackage{siunitx}\n\n"

                            "\\sisetup{detect-all}\n"
                            "\\newtheorem{plm}{Problem}\n\n"


                            "\\title{" (read-string "Title: ") "}\n"
                            "\\author{Duncan Wilkie}\n"
                            "\\date{" (dnw/prompt-date) "}\n\n"

                            "\\begin{document}\n\n"

                            "\\maketitle\n\n"

                            -

                            "\n\n\\end{document}"))
          ("Default" . ("options, RET: " "\\documentclass[" str & 93 | -1 123
                        (read-string "class: ")
                        "}\n"
                        ("package, %s: " "\\usepackage["
                         (read-string "options, RET: ")
                         & 93 | -1 123 str "}\n")
                        _ "\n\\begin{document}\n"
                        _ "\n\\end{document}"))))

  ;; Configure the autoinsert package to use the above.
  (use-package autoinsert
    :hook (find-file . auto-insert)
    :config
    (setq auto-insert t)
    (setq auto-insert-query nil)
    (auto-insert-mode t)
    (assoc-delete-all 'latex-mode auto-insert-alist)
    (define-auto-insert 'latex-mode
      (lambda ()
        (let* ((presets (mapcar (lambda (pair) (car pair))
                                dnw/autoinsert-latex-presets))
               (choice (completing-read "Preset:" presets)))
          (skeleton-insert (assoc choice dnw/autoinsert-latex-presets))))))


#+end_src

** Language Server Protocol

VSCode's Language Server Protocol helps provide editors with completions, documentation, project-wide renaming, etc. based on more detailed semantic analyses performed by an externally-installed language server.

There are three choices: =lsp-mode=, =eglot=, and =lsp-bridge=. [[elisp:(describe-package 'lsp-mode)][lsp-mode]] has an obnoxious UI, and [[elisp:(describe-package 'lsp-bridge)][lsp-bridge]] is lightning-fast but cantankerous (requiring you use its completion framework). [[elisp:(describe-package 'eglot)][eglot]] is servicable on both fronts, and will be built-in to 29.

#+begin_src emacs-lisp

  (use-package eglot
    :commands eglot
    :hook ((python-mode . eglot-ensure)
           (haskell-mode . eglot-ensure)
           (c-mode . eglot-ensure)
           (c++-mode . eglot-ensure)))
    ;; :ensure-system-package (python-lsp-server haskell-lsp ccls)

#+end_src

=eglot= plugs in to Emacs' built-in =xref= utilities. To:

- Find definition -> =xref-find-definitions= / =M-.=
- Find references -> =xref-find-references= / =M-?=

* Environmental Concerns

Emacs has to interact with the rest of the system at some point, unfortunately.

** Files

Emacs editing facilities technically manipulate only buffers. It's via [[info:emacs#Files][file handling commands]], which populate buffers with file contents and /vice versa/, that Emacs actually edits text in a normal sense. The [[elisp:(describe-package 'vlf)][vlf]] package enables editing of abnormally large files.

#+begin_src emacs-lisp

    ;; Better long-line support.
    (global-so-long-mode t)

    ;; Better large-file viewing: call M-x vlf.
    (use-package vlf
      :commands vlf)

    ;; Saving a file with a shebang will make it executable.
    (add-hook 'after-save-hook
              #'executable-make-buffer-file-executable-if-script-p)

#+end_src

Interesting features people often gloss over: [[info:emacs#Filesets][Filesets]], =C-x i=, and =C-x C-r=.

** Dired

[[info:emacs#Dired][Dired]] is Emacs' file management system. If there's ever need for opening files in external programs, [[elisp:(describe-package 'dired-open)][dired-open]] will help with that. [[elisp:(describe-package 'dired-single)][Dired-single]] prevents Dired from creating buffers for each directory it visits; [[elisp:(describe-package 'nerd-icons-dired)][nerd-icons-dired]] uses the same nerd-fonts needed for DOOM modeline to display file type icons; and [[elisp:(describe-package 'diredfl)][diredfl]] colorizes the buffer more richly.
The built-in [[elisp:(describe-package 'image-dired)][image-dired]] provides excellent support for tagging, querying, and viewing thumbnails of images; similarly, [[elisp:(describe-package 'wdired)][wdired]] allows for usual buffer editing commands' use for modifying filenames.

#+begin_src emacs-lisp

  ;; Mostly configuring C-x C-j to open dired at the pwd.
  (use-package dired
    :ensure nil
    :commands (dired dired-jump)
    :bind (("C-x C-j" . dired-jump))
    :custom ((dired-listing-switches "-ahgo --group-directories-first")))

  ;; Prevents dired from dirtying the buffer list with directories.
  (use-package dired-single
    :after dired)

  ;; Use the nerd-fonts installed with the DOOM UI elements for file icons.
  (use-package nerd-icons-dired
    :after dired)

  ;; Nice colors.
  (use-package diredfl
    :after dired
    :config (diredfl-global-mode))

#+end_src

Invoke it with =M-x dired= or the =C-x C-j= bound above. Use =C-h m= as always to see the keybindings if you forget; interesting features people neglect are: the =%= prefix, =image-dired=, =w=, =A=, compression with =Z= / =c=, and =epa='s dired integration under =:=.

** TRAMP

[[info:tramp#Top][Transparent Remote Access, Multiple Protocols]] allows you to access files, shells, etc. on remote machines over an absurd variety of protocols as if they were local. No need to learn the *Editor of the Beast* because the remote doesn't have Emacs; you can just use your Emacs, with no copying-of-config necessary. Also useful for editing files owned by root, via the sudo protocol. To use it, just =C-x C-f /protocol:user@remote:port/path/to/file=

** Vterm

[[elisp:(describe-package 'vterm)][vterm]] is a full-featured terminal. Emacs has built-in eshell, shell, and (ansi-)term, ordered roughly in order of the number of programs' output they break. I like eshell for its Emacs integration, so I use that as a rule. However, it does break a lot; luckily, it provides a facility for using another terminal (external to Emacs or otherwise) to run certain commands known to break it. =vterm=, unlike any of the built-ins, handles everything, even including ncurses programs. It has no Windows compatibility, but then again the only thing that shines there is eshell, so the config is covered for such misfortune.

#+begin_src emacs-lisp

  (use-package vterm
    :config (define-key vterm-mode-map (kbd "C-q") #'vterm-send-next-key)
    :ensure-system-package (cmake ("/usr/lib/libvterm.so.0" . libvterm) libtool))

#+end_src

There is a shell config snippet needed to make the integration work well:

#+begin_src shell :tangle no

  vterm_printf() {
      if [ -n "$TMUX" ] && ([ "${TERM%%-*}" = "tmux" ] || [ "${TERM%%-*}" = "screen" ]); then
          printf "\ePtmux;\e\e]%s\007\e\\" "$1"
      elif [ "${TERM%%-*}" = "screen" ]; then
          printf "\eP\e]%s\007\e\\" "$1"
      else
          printf "\e]%s\e\\" "$1"
      fi
  }

#+end_src

** Eshell

[[elisp:(describe-pacakge 'eshell)][Eshell]] is a shell writen entirely in Emacs Lisp, which supports execution of Elisp forms on the command line and integration thereof into shell workflows. The integration with the rest of Emacs is second-to-none.[[elisp:(describe-package 'eshell-vterm)][Eshell-vterm]] enables the functionality described above: using =vterm= to execute commands too visual for =eshell=. The package [[elisp:(describe-package 'eshell-syntax-highlighting)][eshell-syntax-highlighting]] provides rich Elisp and shell/binary fontification.

#+begin_src emacs-lisp

  (require 'eshell) ;; Not a package, so use-package niceness doesn't work...

  ;; Use last two components of the pwd, excepting the home directory, as the pre-prompt text.
  ;; Pretty flaky.
  (setq dnw/user-account "dnw")
  (defun dnw/prompt-prefix ()
    (let ((guess (apply
		  'concat
		  (-map
		   (lambda (x)
		     (if (string= x dnw/user-account)
			 "~/"
		       (concat x "/")))
		   (seq-subseq
		    ;; extra ""'s are to prevent slicing errors
		    (cons "" (cons "" (split-string (eshell/pwd) "/")))
		    -2)))))
      (if (string= guess "home/~/")
	  "~"
	(string-remove-suffix "/" guess))))

  ;; Change the way the buffer is scrolled on output.
  (remove-hook 'eshell-output-filter-functions
	       'eshell-postoutput-scroll-to-bottom)

  ;; Customize the interface---motd, prompt, etc
  (defun dnw/prompt ()
    (concat
     (propertize
      (dnw/prompt-prefix)
      'font-lock-face '(:foreground "#4068A3"))
     (propertize " ᛋ" 'font-lock-face '(:foreground "#CB77F9"))
     (propertize " " 'font-lock-face "default")))

  (setq eshell-prompt-regexp "^[^ᛋ\n]* ᛋ ")

  (setq eshell-highlight-prompt nil
	eshell-prompt-function #'dnw/prompt)

  ;; Set motd message.
  (setq eshell-banner-message "Formal methods are merely sufficiently good documentation. 🗿\n\n")

  ;; Patch to use vterm rather than term for visual commands.
  (use-package eshell-vterm
    :after eshell
    :config (eshell-vterm-mode))

  (require 'em-tramp) ;; So passwords don't end up in the buffer in plaintext.
  (require 'em-term) ;; So the setting below works out.

  ;; TODO: currently, visual commands called over TRAMP don't work;
  ;; this is apparently a known upstream bug.

  ;; Additional commants for which to use vterm.
  (add-to-list 'eshell-visual-commands "pacman")

  ;; Use the better-integrated elisp command versions over the binaries'---be careful, they might be slow.
  ;; Enables sudo integration below; alias sudo to eshell/sudo if you want to change.
  (setq eshell-prefer-lisp-functions t)
  (setq eshell-prefer-lisp-variables t)

  (use-package eshell-syntax-highlighting
    :hook (eshell-mode . eshell-syntax-highlighting-mode))

#+end_src

** Building Programs

There's extensive, well-integrated, built-in support for compiling and debugging programs; see [[info:emacs#Building][Building]]. The [[elisp:(describe-package 'realgud)][realgud]] package extends the debugging functionality to a more modern set of external debuggers. See also the [[elisp:(describe-package 'fancy-compilation)][fancy-compilation]] package.

#+begin_src emacs-lisp

  (use-package realgud
    :commands (realgud:gdb realgud:pdb))

#+end_src

** Editing Server

There are many ways to start Emacs as a [[info:emacs#Emacs Server][server/daemon/service]]. This allows external shell programs to use =emacsclient= to do Emacs things without the overhead of spinning up a second interpreter and running the init file a second time. I start the daemon by putting =emacsclient -c -a ""= in my =.xinitrc= and as =$EDITOR= / =$VISUAL=, the first option of which spawns a frame and the second of which will start the server if it's not up and running already.

** Being a Good UNIX Citizen

By default, Emacs doesn't get its information about available binaries from the shell, but from an exec-path somewhere, and creates annoying
auto-save files in the same directory as the file being edited. [[elisp:(describe-package 'no-littering)][No-littering]] changes the latter to store all auto-saved versions under =~/.emacs.d/auto-save=, and
[[elisp:(describe-package 'exec-path-from-shell)][exec-path-from-shell]] fixes the former by allowing selection of environment variables from the shell Emacs was called from.

#+begin_src emacs-lisp

  ;; Write backups and autosaves to .emacs.d, instead of strewing them across the filesystem.
  (use-package no-littering)
  (setq auto-save-file-name-transforms
        `((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))

  ;; Binaries on the shell path become accessible to Emacs automatically.
  (use-package exec-path-from-shell
    :init
    (setq exec-path-from-shell-variables '("PATH" "MANPATH" "PHITSPATH"))
    (when (memq window-system '(mac ns x))
      (exec-path-from-shell-initialize)))

#+end_src

** System Status

Emacs has many features to relay information about the state of the system.

#+begin_src emacs-lisp

  ;; Mode-line battery% indicator.
  (display-battery-mode)

#+end_src

** Collaborative Editing

[[elisp:(describe-package 'crdt)][Conflict-free Replicated Data Types]] enable Google docs-like collaboration on arbitrary Emacs buffers.

#+begin_src emacs-lisp

  (use-package crdt
    :commands (crdt-share-buffer crdt-connect))

#+end_src

** Pastebins

Useful for getting help on IRC/Matrix, [[elisp:(describe-package 'webpaste)][webpaste]] integrates wtih many pastebin services for uploading regions, buffers, etc.

#+begin_src emacs-lisp

  (use-package webpaste
    :bind (("C-c w b" . webpaste-paste-buffer)
           ("C-c w r" . webpaste-paste-region)
           ("C-c w p" . webpaste-paste-buffer-or-region))
    :config
    (progn
      (setq webpaste-provider-priority '("ix.io" "dpaste.org"))))

#+end_src

** "The" ""Real"" """"World""""

Map viewer, weather, etc. Every map I've tried needs bignum support, so no worky on x86.

#+begin_src emacs-lisp

  ;; Weather. Need to figure out how to configure location right.
  ;; (use-package noaa)

  ;; OpenStreetMap viewer. Need to figure out overflow errors.
  ;; (use-package osm
  ;;   :custom (osm-server 'default)
  ;;   :bind (("C-c m h" . osm-home)
  ;; 	 ("C-c m s" . osm-search)
  ;; 	 ("C-c m v" . osm-server)
  ;; 	 ("C-c m t" . osm-goto)
  ;; 	 ("C-c m x" . osm-gpx-show)
  ;; 	 ("C-c m j" . osm-bookmark-jump)))

#+end_src

** Daemons

The [[elisp:(describe-package 'daemons)][daemons]] package lists all of the daemons running, and provides ways to interact with them. The [[elisp:(describe-package 'systemd)][systemd]] package simply provides a mode for editing =systemd= services, with good documentation features.

#+begin_src emacs-lisp

    (use-package daemons
      :commands daemons)

    (use-package systemd
      :mode "\\.service\\'")

#+end_src

* Secrets

Emacs can do all the nasty password and authentication management for us.

** UNIX Pass

The command-line [[elisp:(woman "pass")][pass]] program interacts neatly with GnuPG and the clipboard to enable storage and access of secrets in an elegant, minimal manner.
[[elisp:(describe-package 'password-store)][Password-store]] provides Emacs tools for interacting with it. See [[elisp:(describe-package 'password-store-otp)][password-store-otp]] for fun extensions.

#+begin_src emacs-lisp

  ;; Unlock keys via gpg-agent on the modeline.
  (use-package pinentry
    :config (pinentry-start))

  ;; Access pass via Emacs.
  (use-package password-store
    :commands (password-store-copy
               password-store-edit
               password-store-init
               password-store-insert
               password-store-remove
               password-store-rename
               password-store-generate)
    :ensure-system-package pass)

#+end_src

The pinentry requires the following in =~/.gnupg/gpg-agent.conf= to work correctly.

#+begin_src shell :tangle no

  allow-emacs-pinentry
  allow-loopback-pinentry

#+end_src

** EasyPA

Built-in to Emacs, [[info:epa#Top][epa]] enables all the usual GnuPG interaction features with =M-x= functions starting with =epa-=. Integrates very well with mail etc.; especially note the Dired integration under the colon prefix by default.

#+begin_src emacs-lisp

    (use-package epa
      :config (setq epa-pinentry-mode 'loopback)) ;; This seems required for the Emacs gpg-agent to be integrated.

#+end_src

** Auth-Sources

[[info:auth#Top][Auth-source]] is Emacs' built-in library for cleanly managing authentication to servers---including the local machine, via TRAMP's =sudo::=. It is set to only use =pass= as a source of authentication to enable platform-independent credential storage.

#+begin_src emacs-lisp

  ;; Only use pass for credentials.
  (use-package auth-source
    :config
    (auth-source-pass-enable)
    (setq auth-sources '(password-store)))

#+end_src

* Time Management
** Calendar and Diary

The built-in [[info:emacs#Calendar/Diary][Calendar/Diary]] is nice, but doesn't integrate as completely as org-mode's tools. See [[elisp:(describe-package 'excorporate)][excorporate]] and [[elisp:(describe-package 'gmail2bbdb)][gmail2bbdb]] for tools that aid the transition away from proprietary alternatives.

** Data Entry

This didn't /quite/ fit cleanly anywhere else, but it sort of counts as time management: the built-in [[elisp:(describe-package 'forms)][forms]] can be used to create interactive data-entry systems.

* Help

Knowing things is better than not knowing things. And the WWW is a bit of a footgun in that respect.

** With Internals

[[elisp:(describe-package 'helpful)][Helpful]] provides more colorful and informative alternatives to much of the built-in help facilities. [[elisp:(describe-pacakge 'which-key)][Which-key]] displays possible continuations of an incomplete prefix key combination if idle too long.

#+begin_src emacs-lisp

  ;; Souped-up `C-h` interface.
  (use-package helpful
    :bind
    ([remap describe-function] . helpful-function)
    ([remap describe-command] . helpful-command)
    ([remap describe-variable] . helpful-variable)
    ([remap describe-key] . helpful-key)
    ([remap describe-symbol] . helpful-symbol)
    :config
    (setq helpful-max-buffers 1)) ;; Otherwise, litters buffer list way too much.


  ;; In case of brain fart: display possible prefix key follow-ups if idle for too long.
  (use-package which-key
    :config
    (which-key-mode)
    (setq which-key-idle-delay 1))

#+end_src

** WIth Externals

[[elisp:(describe-package 'inform)][Inform]] integrates Emacs' info viewer with the help system by linking to symbol documentation.

#+begin_src emacs-lisp

  ;; I don't like the navigation display at the top of Info buffers
  (setq Info-use-header-line nil)

  ;; Turns symbols in Info mode into links to their documentation
  (use-package inform)

#+end_src

* Source Control

Things related to git, cvs, /et. al/. There are some built-in features under =C-x p=; see [[info:emacs#Projects][Projects]].

** Projectile

[[elisp:(describe-package 'projectile)][Projectile]] helps make Emacs aware of project structure via source-control files, and provides commands that operate on and with respect to that structure.

#+begin_src emacs-lisp

  (use-package projectile
    :diminish projectile-mode
    :config (projectile-mode)
    :custom ((projectile-completion-system 'vertico))
    :bind-keymap
    ("C-c p" . projectile-command-map)
    :init
    (when (file-directory-p "~")
      (setq projectile-project-search-path '("~")))
    (setq projectile-switch-project-action #'projectile-dired))

#+end_src

** Git

[[elisp:(describe-package 'magit)][Magit]] is the only tool that makes =git= bearable most of the time. [[elisp:(describe-package 'dired-git-info)][Dired-git-info]] displays source control information and commit messages alongside folders and files in Dired, and  [[elisp:(describe-package 'browse-at-remote)][browse-at-remote]] opens the current file at the remote repository in the browser.

#+begin_src emacs-lisp

    (use-package magit
      :commands (magit-status magit-get-current-branch)
      :custom
      (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1))

    ;; Display Git modification dates and commit messages in dired.
    (use-package dired-git-info
      :after dired
      :bind (:map dired-mode-map
                  (")" . dired-git-info-mode))
      :config (setq dgi-auto-hide-details-p nil)
      :hook (dired-after-readin . dired-git-info-auto-enable))

    ;; Open current file in a remote repository.
    (use-package browse-at-remote
      :bind ("C-c g g" . browse-at-remote))

#+end_src

* Org Mode

[[info:org#Top][Org]] is a markup language, like Markdown or HTML, for which =org-mode= is an extensive set of tooling. It is so extensive that said description drastically undersells its awesomeness; it's unclear whether to file it under "Computation Environments," "Documentation Modes," or "Time Management"

** Beautification

Even though Org is pretty readable as-is, we can get basically WYSIWYG levels with a little effort. [[elisp:(describe-package 'visual-fill-column)][Visual-fill-column]] adds margins to the buffer that resize based on the windows; [[elisp:(describe-package 'org-appear)][org-appear]] makes hidden emphasis markers appear again when the point is adjacent to or between them (so you don't lose track of them); and [[elisp:(describe-package 'org-link-beautify)][org-link-beautify]] puts iconified link type indicators on every link.

#+begin_src emacs-lisp

  ;; Makes the org-mode buffer look like rich text.
  (defun dnw/org-mode-setup ()
    (org-indent-mode)
    (variable-pitch-mode 1)
    (visual-line-mode 1))

  (use-package org
    :commands (org-capture org-agenda)
    :hook (org-mode . dnw/org-mode-setup)
    :bind
    ("C-c C-x C-l" . org-latex-preview) ;; This is an awesome function that works outside of org-mode.
    ("C-c l" . org-store-link)
    ("C-c a" . org-agenda)
    ("C-c c" . org-capture)
    :config
    (setq org-ellipsis " ▼")
    (setq org-latex-create-formula-image-program 'imagemagick)
    :ensure-system-package ("/usr/lib/ImageMagick-7.1.1" . imagemagick))

  ;; Prevent text from getting uncomfortably wide on widescreen monitors.
  (defun dnw/org-mode-visual-fill ()
    (setq visual-fill-column-width 140
          visual-fill-column-center-text t)
    (visual-fill-column-mode 1))

  ;; ibid.
  (use-package visual-fill-column
    :hook (org-mode . dnw/org-mode-visual-fill))

  ;; Fancy bullet points in headings.z

  ;; Adjust heading sizes and things' fonts
  (with-eval-after-load
      'org-faces (dolist (face '((org-level-1 . 1.2)
                                 (org-level-2 . 1.1)
                                 (org-level-3 . 1.05)
                                 (org-level-4 . 1.0)
                                 (org-level-5 . 1.0)
                                 (org-level-6 . 1.0)
                                 (org-level-7 . 1.0)
                                 (org-level-8 . 1.0)))
                   (set-face-attribute (car face) nil :font "Liberation Sans" :weight 'regular :height (cdr face)))

      (set-face-attribute 'fixed-pitch nil :font "Iosevka" :weight 'regular :height 1.0)
      (set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch)
      (set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch))
      (set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch))
      (set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
      (set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
      (set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
      (set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch))

  ;; Hide e.g. the /italics/ delimiters.
  (setq org-hide-emphasis-markers t)

  ;; Make them appear again when the point is near them, so you don't get lost in things unseen.
  (use-package org-appear
    :hook (org-mode . org-appear-mode))

  ;; Some wizardry that converts list indicators (normally -) to nice circumpunct characters.
  (font-lock-add-keywords 'org-mode
                          '(("^ *\\([-]\\) "
                             (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))

  (use-package org-link-beautify
    :hook (org-mode . org-link-beautify-mode))

#+end_src

** Babel


=org-babel= is a subsystem that allows actual /execution/ of code blocks embedded in org documents. The results of these code blocks can be composed for a Jupyter-like experience. It's a very beautiful thing---a great trick for data analysis is to yank plaintext data into an org-mode buffer, use =C-c |= to turn it into an org table, and then give that table a name and feed it into SQL, Python, R, or Julia source blocks to do analysis on it. =org-tempo= is a built-in way to quickly insert code blocks for particular languages.

#+begin_src emacs-lisp

  ;; Load the modules for the languages desired.
  (with-eval-after-load 'org
    (org-babel-do-load-languages
     'org-babel-load-languages
     '((emacs-lisp . t)
       (python . t)
       (fortran . t)
       (gnuplot t)
       (R . t)
       (sqlite . t)
       (haskell . t)
       (lua . t)
       (shell . t)
       (C . t)))

    ;; Disable annoying prompt.
    (setq org-confirm-babel-evaluate nil)

    ;; Typing e.g. =<el <TAB>= will automatically produce all the boilerplate for a source block.
    (require 'org-tempo)
    (add-to-list 'org-structure-template-alist '("sh" . "src shell"))
    (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
    (add-to-list 'org-structure-template-alist '("py" . "src python3"))
    (add-to-list 'org-structure-template-alist '("ft" . "src fortran"))
    (add-to-list 'org-structure-template-alist '("gp" . "src gnuplot"))
    (add-to-list 'org-structure-template-alist '("sql" . "src sqlite"))
    (add-to-list 'org-structure-template-alist '("r" . "src R"))
    (add-to-list 'org-structure-template-alist '("hs" . "src haskell"))
    (add-to-list 'org-structure-template-alist '("lu" . "src lua"))
    (add-to-list 'org-structure-template-alist '("sys" . "src C")))

#+end_src

** Tangle


Code blocks in org-mode can be written out to files on the disk. This is quite useful for literate configuration like this, especially for code snippets that don't depend on each other much or for languages like Haskell with great referential transparency, so that order doesn't matter.

#+begin_src emacs-lisp

  ;; Set up this file and this file alone to auto-tangle on save.
  (defun dnw/org-babel-tangle-config ()
    (when (string-equal (buffer-file-name)
                        (expand-file-name "~/.emacs.d/config.org"))

      (let ((org-confirm-babel-evaluate nil))
        (org-babel-tangle))))

  (add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'dnw/org-babel-tangle-config)))

#+end_src

** Roam

[[elisp:(describe-package 'org-roam)][Org-roam]] is a system whereby notes can be briefly captured in a database, before refiling into a more complete ontology structure at a later date with tags and links, allowing the database to be queried at-will. I ended up just storing all my files flatly in the database and not linking between them at all, and so didn't really realize its full potential.

#+begin_src emacs-lisp

    (use-package org-roam
      :ensure t
      :init
      (setq org-roam-v2-ack t)
      :custom
      (org-roam-directory "/home/dnw/Roam")
      (org-roam-completion-everywhere t)
      (org-roam-db-node-include-function
       (defun dnw/org-roam-include ()
         (not (member "drill" (org-get-tags)))))
      (org-roam-capture-templates
       '(("d" "default" plain
          "%?"
          :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
          :unnarowed t)
         ("i" "idea" plain
          "* Motivation\n\n%?\n\n* Similar Work\n\n* Feasibility\n\n* Implementation"
          :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+filetags: Idea")
          :unnarrowed t)
         ("p" "project" plain
          "* Description\n\n%?\n\n** Collaborators\n\n** Stack\n\n* Tasks"
          :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+filetags: Project")
          :unnarrowed t)
         ("a" "article" plain
          "* Summary\n\n%?\n\n* Context"
          :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+filetags: Article")
          :unnarrowed t)
         ("m" "musing" plain
          "* %?"
          :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+filetags: Musing")
          :unnarrowed t)))
      :bind (("C-c n l" . org-roam-buffer-toggle)
             ("C-c n f" . org-roam-node-find)
             ("C-c n i" . org-roam-node-insert)
             :map org-mode-map
             ("C-M-i" . completion-at-point))
      :config
      (org-roam-db-autosync-mode))

#+end_src

** Drill

[[elisp:(describe-package 'org-drill)][Org-drill]] is a simple mechanism for creating org-formatted note-cards and memorizing them via spaced-repitition. It's much nicer than e.g. Quizlet, because 1. offline and FOSS, and 2. =org-latex-preview=.

#+begin_src emacs-lisp

  (use-package org-drill)

#+end_src

** Present

[[elisp:(describe-package 'org-present)][Org-present]] produces simple, elegant presentations from top-level org-mode headings.

#+begin_src emacs-lisp

  (use-package org-present)

#+end_src

** Archive

See [[elisp:(describe-package 'org-board)][org-board]].

** Hyperscheduler

[[elisp:(describe-package 'org-hyperscheduler)][Org-hyperscheduler]] shows org-agenda in a web calendar.

** Org-Noter

[[elisp:(describe-package 'org-noter)][Org-noter]] integrates org-mode notes external to a document that are nevertheless attached to positions in a document.

** PDF integration

[[elisp:(describe-package 'org-pdftools)][Org-pdftools]] enables links to PDFs in org-mode

#+begin_src emacs-lisp

  (use-package org-pdftools
    :hook (org-mode . org-pdftools-setup-link))

#+end_src

* Computation Environments

Setups for making the smart rock serve your whims, in different ways.

** PHITS

A mode I wrote/am writing for interacting with JAEA's PHITS.

#+begin_src emacs-lisp

  (setq phits-set-up nil)
  (if phits-set-up
      (progn
        (add-to-list 'load-path "/home/dnw/Code/PyPHITS/phits-mode")
        (require 'phits-mode)
        (add-to-list 'auto-mode-alist '("\\.inp\\'" . phits-mode))
        (add-to-list 'auto-mode-alist '("\\.out\\'" . phits-mode))))

#+end_src

** Calc

The built-in [[https://www.gnu.org/software/emacs/manual/html_mono/calc.html][Calc]] is hands-down the best calculator I've ever used that wasn't built to be a CAS from the ground-up. As examples: it has inbuilt, default support for [[https://en.wikipedia.org/wiki/Mobius_function][Möbius functions]], computing Taylor series, and doing IO on LaTeX-formatted algebraic expressions. The package [[elisp:(describe-package 'literate-calc-mode)][literate-calc-mode]] enables using it to evaluate computations embedded in normal buffers.

#+begin_src emacs-lisp

  ;; Use calc inline in more than just LaTeX-mode.
  (use-package literate-calc-mode
    :commands (literate-calc-eval-line
               literate-calc-eval-buffer
               literate-calc-insert-results
               literate-calc-clear-overlays
               literate-calc-remove-results
               literate-calc-set-radix))

#+end_src

** Haskell

[[elisp:(describe-package 'haskell-mode)][Haskell-mode]] for the purely-functional, lazy, ML-inspired programming language. It's the stuff of category-laden dreams.

#+begin_src emacs-lisp

  (use-package haskell-mode
    :commands haskell-mode
    :mode "\\.hs\\'"
    :bind ("C-c C-h" . hoogle)) ;; figure out how to defer loading until .hs is opened?

#+end_src

** Lean

[[elisp:(describe-package 'lean-mode)][Lean-mode]], the best interface to a based proof verifier/dependently-typed functional programming language.

#+begin_src emacs-lisp

  (use-package lean-mode
    :commands lean-mode
    ;; the quail-completion buffer for the input mode is annoying
    :config (with-eval-after-load 'quail (defun quail-completion ()))
    :mode "\\.lean\\'")

#+end_src

** Racket

A [[elisp:(describe-package 'racket-mode)][racket-mode]] for the language language.

#+begin_src emacs-lisp

  (use-package racket-mode
    :commands racket-mode
    :mode "\\.rkt\\'")

#+end_src

** Guile

The [[elisp:(describe-package 'geiser)][geiser]] Guile REPL integration, useful for configuring GNU programs that have adopted the official configuration language, e.g. guix and GIMP.

#+begin_src emacs-lisp

  (use-package geiser
    :commands (geiser run-geiser geiser-connect)
    :hook scheme-mode
    :config (require 'geiser-guile))

#+end_src

** Python

The default python-mode is quite good, but if colleagues are not similarly-enlightened, interaction with ipython notebooks may be necessary: [[elisp:(describe-package 'python)][python]] does this. See also [[elisp:(describe-package 'python-view-data)][python-view-data]].

#+begin_src emacs-lisp

  (use-package python
    :mode "\\.py\\'")

#+end_src

** Low-Level

Everything with bits, bytes, and asm. See also [[elisp:(describe-package 'x86-lookup)][x86-lookup]].

*** RMSBolt

[[elisp:(describe-package 'rmsbolt)][Rmsbolt]] is a version of godbolt/compiler-explorer that runs offline.

#+begin_src emacs-lisp

    (use-package rmsbolt
      :commands rmsbolt)

#+end_src

*** Disaster

Disassemble C/C++/Fortran code near point with [[elisp:(describe-package 'disaster)][disaster]].

#+begin_src emacs-lisp

    (use-package disaster
      :commands disaster
      :bind (:map
             c-mode-map
             ("C-c d" . disaster)
             :map
             fortran-mode-map
             ("C-c d" . disaster)))

#+end_src

*** Poke

A really awesome interface language for structured binary data; see [[elisp:(describe-package 'poke-mode)][poke-mode]] and [[elisp:(describe-package 'poke)][poke]].

#+begin_src emacs-lisp

  (use-package poke-mode
    :commands poke-mode
    :mode "\\.pk\\'")


  (use-package poke
    :after poke-mode
    :commands poke
    :ensure-system-package poke)

#+end_src

** Statistics

The [[elisp:(describe-package 'ess)][ess]]project is beyond compare for statistical environments.

* Document Modes

Anything to view, edit, or manage primarily static documents.

** TeX

Emacs' built-in TeX-editing features, via [[elisp:(describe-package 'AUCTeX)][AUCTeX]], are simply the most ergonomic ones for the macro system known to man.

#+begin_src emacs-lisp

  (use-package tex
    :ensure auctex
    :hook ((LaTeX-mode-hook . flyspell-mode) ;; Spell-check by default.
           (LaTeX-mode-hook . turn-on-reftex) ;; Bibliography integration.
           (LaTeX-mode-hook . TeX-source-correlate-mode) ;; SyncTeX integration.
           (TeX-after-compilation-fineshed-functions . TeX-revert-document-buffer)) ;; Auto-revert PDF buffer.
    :config
    ;; AUCTeX parses style files so it can extend to user-defined commands; following two forms turn that on.
    (setq TeX-auto-save t)
    (setq TeX-parse-self t)
    (setq-default TeX-master t) ;; Usually, files are their own masters.
    (setq LaTeX-command "latex -shell-escape") ;; Warning: security risk; don't compile third-party source.
    (setq reftex-plug-into-AUCTeX t) ;; Enable reftex.
    (setq TeX-electric-sub-and-superscript t) ;; really nice raising and lowering of sub- and superscripts in the source lines.
    (setq TeX-view-program-selection '((output-pdf "PDF Tools")))) ;; Use pdf-tools for output.

  ;; Easy table manipulation.
  (use-package latex-table-wizard
    :commands latex-table-wizard)

  ;; Faster template insertion.
  (use-package cdlatex
    :commands turn-on-cdlatex
    :hook (LaTeX-mode-hook . turn-on-cdlatex))


#+end_src

See the [[info:auctex#Top][manual]].

=C-c C-c= to compile. =C-c C-v= to view. Subsequent recompilation automatically updates the window. Set =TeX-engine= in a buffer-locally to avoid the command prompt each time. See [[help:latex-math-mode][LaTeX Math Mode]] for an easy way to enter symbols. For general editing, the =C-c C-s=  and =C-s C-e= commands are useful for quickly inserting sectioning and environments. Font commands are under =C-c C-f=, and folding under =C-c C-o=. Note that =smart-parens=' LaTeX support handles most of the delimiter-balancing features of AUCTeX. Also note =C-c *=, =M-<RET>=, and =C-c .=. The outline-mode integration should be noticed too, along with =C-c ?= to view LaTeX package documentation.

** PDF

Interact easily with PDFs from Emacs, with the aid of [[elisp:(describe-package 'pdf-tools)][pdf-tools]]. Great for working with AUCTeX, apparently.

#+begin_src emacs-lisp
  ;; Done from Guix
  (use-package pdf-tools
    :mode "\\.pdf\\'"
    :config
    (pdf-loader-install))

#+end_src

** ASCII Art

Play around with [[elisp:(describe-package 'artist)][artist]]. It's mind-boggling this is even possible.

** Gnuplot

[[elisp:(describe-package 'gnuplot)][Gnuplot]] is great for producing extremely high-quality vector plots. I like to use the TikZ terminal, which outputs LaTeX drawing code---and so uses all of the stylistic options I have set in my document. See also the org-mode integration.

#+begin_src emacs-lisp

  (use-package gnuplot
    :commands gnuplot-mode
    :mode ("\\.plt\\'" . gnuplot-mode))

#+end_src

** Chemtable

Can't remember atomic numbers? Enter [[elisp:(describe-package 'chemtable)][chemtable]]. There is also a [[elisp:(describe-package 'chembalance)][chembalance]] package, but they're not cool enough to integrate with =calc=, so a no-go for me.

#+begin_src emacs-lisp

  (use-package chemtable
    :commands chemtable)

#+end_src

* Amusements

See also the [[info:emacs#Amusements][built-in]] fun stuff.

** Go

😵 [[elisp:(describe-package 'gnugo)][gnugo]]

#+begin_src emacs-lisp

  (use-package gnugo
    :commands gnugo)

#+end_src

** Chess


😇 [[elisp:(describe-package 'chess)][chess]]

#+begin_src emacs-lisp

    (use-package chess
      :commands chess)

#+end_src

** Typing Speed

See [[elisp:(describe-package 'c-c-combo)][c-c-combo]] and [[elisp:(describe-package 'monkeytype)][monkeytype]].

** One-Time Pads

See [[elisp:(describe-package 'one-time-pad-encrypt)][one-time-pad-encrypt]]

* Communication

Things that involve bidirectional, person-to-person information exchange.

** Jabber/XMPP

See [[elisp:(describe-package 'jabber)][jabber]].

** ERC

Emacs' built-in IRC client. Very feature-complete, and integrates with auth-sources to save and automatically produce login credentials. There  are also [[elisp:(describe-package 'circe)][circe]] and
[[elisp:(describe-package 'rcirc)][rcirc]] (which is also built-in), but [[elisp:(describe-package 'erc)][erc]] has a very extensive feature set by comparison. Note the [[elisp:(describe-package 'erc-twitch)][erc-twitch]] package.

#+begin_src emacs-lisp

  (use-package erc
    :commands erc
    :config
    ;; Me.
    (setq
     erc-nick "FlaminWalrus"
     user-full-name "Duncan W")
    ;; Avoid M-x.
    :bind ("C-c e" . (lambda ()
                       (interactive)
                       (erc-tls :server "irc.libera.chat"
                                :port "6697"))))

#+end_src

** Ement

TODO: debug
Alphapapa's Matrix client, [[elisp:(describe-package 'ement)][ement]]. Very useful, especially as Matrix may be bridged to nonfree or primarily-mobile chat protocols via puppeting. However, currently just spits tons of errors.

#+begin_src emacs-lisp

    (use-package ement
      :commands ement-connect)

#+end_src

** Address Book

See: [[elisp:(describe-package 'bbdb)][bbdb]]

** Mastodon

See [[elisp:(describe-package 'mastodon)][mastodon]].

** Mail

TODO: finalize. Look into [[elisp:(describe-package 'gnorb)][gnorb]] and bbdb

I choose to use the built-in =gnus=, as it has the most extensive features for sorting mail, due to its heritage as primarily a newsreader. There is also the built-in native =rmail=, the built-in but requiring external binary [[elisp:(describe-package 'mh-e)][mh-e]], and completely externally [[elisp:(describe-package 'notmuch)][notmuch]], [[elisp:(describe-package 'notmuch)][notmuch]], [[elisp:(describe-package 'wanderlust)][wanderlust]], and [[elisp:(describe-package 'mew)][mew]], which appear to principally offer performance advantages, but with less extensive (?) sorting tools. See also [[elisp:(describe-package 'nndiscourse)][nndiscourse]] et. al. in the package list for various gnus backends for those other protocols. [[elisp:(describe-package 'message-attachment-reminder)][Message-attachment-reminder]] reminds you to attach things, and [[elisp:(describe-package 'org-msg)][org-msg]] lets one compose emails with org syntax.

#+begin_src emacs-lisp

    (setq user-mail-address "antigravityd@gmail.com"
          user-full-name "Duncan Wilkie")

    (setq gnus-select-method '(nnimap "gmail"
                                      (nnimap-address "imap.gmail.com")
                                      (nnimap-server-port "imaps")
                                      (nnimap-stream ssl)))
    (setq smtpmail-smtp-server "smtp.gmail.com"
          smtpmail-smtp-service 587
          gnus-ignored-newsgroups "^to\\.\\|^[0-9. ]+\\( \\|$\\)\\|^[\"]\"[#'()]")

    ;; Search for "see attached" etc. and warn if attachment is forgotten.
    (use-package message-attachment-reminder)

    ;; Send HTML messages with org-mode.
    (use-package org-msg)

#+end_src

** Telegram

See [[elisp:(describe-package 'telega)][telega]].

* Content Consumption

Things that involve mostly unidirectional, producer-to-consumer information exchange.

** Stack Exchange

Use Stack Exchange sites from Emacs via [[elisp:(describe-package 'sx)][sx]]:

#+begin_src emacs-lisp

  (use-package sx
    :commands (sx-ask sx-search sx-inbox)
    :config
    (bind-keys :prefix "C-c s"
               :prefix-map my-sx-map
               :prefix-docstring "Global keymap for SX."
               ("q" . sx-tab-all-questions)
               ("i" . sx-inbox)
               ("o" . sx-open-link)
               ("u" . sx-tab-unanswered-my-tags)
               ("a" . sx-ask)
               ("s" . sx-search)))

#+end_src

** Bibliography Management

[[elisp:(describe-package 'biblio)][Biblio]] adds citations automatically from a variety of sources. [[elisp:(describe-package 'citar)][Citar]] is a citation integration package. See also [[elisp:(describe-package 'citeproc)][citeproc]], [[elisp:(describe-package 'ebib)][ebib]], [[elisp:(describe-package 'gscholar-bibtex)][gscholar-bibtex]], [[elisp:(describe-package 'scholar-import)][scholar-import]], [[elisp:(describe-package 'slirm)][slirm]], and [[elisp:(describe-package 'zotero)][zotero]].

#+begin_src emacs-lisp

  (use-package biblio
    :commands (biblio-lookup
               crossref-lookup
               arxiv-lookup
               dlbp-lookup
               doi-insert
               dissemin-lookup))

  (use-package citar)

#+end_src

** RSS Reading

Uses Emacs' built-in RSS reader [[elisp:(describe-package 'elfeed)][elfeed]]. Currently use it for a bunch of research-level things; I believe =gnus= has the ability to replace it, so I might migrate blog reading over there eventually. Especially useful are [[elisp:(describe-package 'elfeed-tube)][elfeed-tube]], which integrates Youtube channel RSS feeds very well, and [[elisp:(describe-package 'elfeed-tube-mpv)][elfeed-tube-mpv]], which enables control of the =mpv= player from =elfeed=.

#+begin_src emacs-lisp

  ;; Borrowed from the org-mode config to make reading nicer.
  (defun dnw/elfeed-show-mode-visual-fill ()
    (setq visual-fill-column-width 130
          visual-fill-column-center-text t)
    (visual-fill-column-mode 1))

  ;; This is the only place where it seems like org-latex-preview /doesn't/ work ootb.
  (defun dnw/render-latex ()
    (let ((current-prefix-arg '(2)))
      (switch-to-buffer "*elfeed-entry*")
      (call-interactively 'org-latex-preview)))

  (use-package elfeed
    :hook ((elfeed-show-mode . dnw/elfeed-show-mode-visual-fill))
    :config
    (setq elfeed-db-directory (expand-file-name "elfeed" user-emacs-directory) ;; store articles in .emacs.d
          elfeed-show-entry-switch 'display-buffer) ;; Open articles side-along---useful for skimming abstracts.
    ;; Configure article sources.
    (setq elfeed-feeds
          '("http://feeds.aps.org/rss/allsuggestions.xml"  ;; Physics
            "http://feeds.aps.org/rss/recent/rmp.xml"

            "https://lexi-lambda.github.io/feeds/all.rss.xml" ;; CS
            "https://blog.functorial.com/feed.rss"

            "https://www.ams.org/rss/jams.rss"
            "https://jaireetschahal.substack.com/feed" ;; Math
            "https://golem.ph.utexas.edu/category/atom10.xml"
            "https://homotopytypetheory.org/feed/"

            "https://notrelated.xyz/rss")) ;; Misc

    :bind
    ("C-x w" . elfeed )) ;; Open it from anywhere.

  (use-package elfeed-tube
    :after elfeed
    :config (elfeed-tube-setup))

  (use-package elfeed-tube-mpv
    :after elfeed-tube)

#+end_src

** Videos

See =elfeed-youtube= above, and [[elisp:(describe-package 'peertube)][peertube]].

** Ebooks

See the various epub modes: [[elisp:(describe-package 'nov)][nov]], [[elisp:(describe-package 'finito)][finito]].

** Scihub

Experimental support for browsing [[elisp:(describe-package 'scihub)][scihub]].

#+begin_src emacs-lisp

  (use-package scihub
    :commands scihub
    :config
    (setq scihub-download-directory "~/.emacs.d/papers/"
         scihub-open-after-download t
         scihub-fetch-domain 'scihub-fetch-domains-lovescihub))

#+end_src

** Last.fm

See [[elisp:(describe-package 'lastfm)][lastfm]].

** Multi-Media Control

Emacs has built-in support for interacting with music players via [[elisp:(describe-package 'emms)][emms]]. Creating playlists through long folders of =youtube-dl='ed .mp3s seems to be an excellent experience. Compare to [[elisp:(describe-package 'elmpd)][elmpd]]
and [[elisp:(describe-package 'ffmpeg-player)][ffmpeg-player]].

#+begin_src emacs-lisp

  (use-package emms
    :config
    (emms-all)
    (add-to-list 'emms-player-list 'emms-player-mpd) ;; Used with the Music Player Daemon.
    :bind ;; Make Bluetooth earbud controls work with it.
    ("<XF86AudioPlay>" . emms-start)
    ("<XF86AudioPause>" . emms-pause)
    ("<XF86AudioNext>" . emms-next)
    ("<XF86AudioNext>" . emms-previous)
    :ensure-system-package mpd)

#+end_src

**  The World-Wide Web

Any sufficiently good website should have readable bare HTML. The built-in [[info:eww#Top][Emacs Web Wowser]] has great support for viewing such pages. The LibreX browser, developed by hnhx, is FOSS, federated, and designed to be JS-free and prioritize non-JS sites. Together, they make using the web for its intended purpose, i.e. accessing information, an enjoyable experience. Most of the websites for which this doesn't work ought to be replaced with client programs anyway, not least in the interest of freedom, so broken sites (usually) serve as a marker of bad digital hygene.
The [[elisp:(describe-package 'shr-tag-pre-highlight)][shr-tag-pre-highlight]] can syntax-highlight html source code tags. See also [[elisp:(describe-package 'shrface)][shrface]].

#+begin_src emacs-lisp

  (use-package eww
    :config
    (setq browse-url-browser-function 'eww-browse-url)
    (setq eww-search-prefix "https://librex.devol.it/search.php?q="))

  ;; Source-code highlighting for EWW et. al.
  (use-package shr-tag-pre-highlight
    :after shr
    :config
    (add-to-list 'shr-external-rendering-functions
                 '(pre . shr-tag-pre-highlight)))

#+end_src

Extremely useful is the function =eww-readable= / =U=, which attempts to strip out cluttered navigation information from poorly-designed sites. It somewhat works most of the time, up to sites as complex as StackOverflow.

** Gopher and Gemini

Two alternative, minimal, BASED alternatives to the Web, via one client, [[elisp:(describe-package 'elpher)][elpher]].

#+begin_src emacs-lisp

  (use-package elpher
    :commands elpher)

#+end_src

** Torrenting

See the [[elisp:(describe-package 'mentor)][mentor]] rTorrent client.

* Finance

Use =hledger= to manage money, and [[elisp:(describe-package 'ledger-import)][ledger-import]] to automatically manage its plaintext double-entry book files.

* Runtime Performance

Take the time to clean up the absurd amount of garbage accumulated now that Emacs is usable. Enable the Garbage Collector Magic Hack with [[elisp:(describe-package 'gcmh)][gcmh]].

#+begin_src emacs-lisp

  (use-package gcmh)

  (setq gc-cons-threshold (* 2 1000 1000))

#+end_src