[emacs] silence ivy-initial-inputs-alist related warning
[~bandali/configs] / init.org
CommitLineData
5fece105
AB
1#+title: =aminb='s Literate Emacs Configuration
2#+author: Amin Bandali
3#+babel: :cache yes
4#+property: header-args :tangle yes
5
6* About
7:PROPERTIES:
8:CUSTOM_ID: about
9:END:
10
11This org file is my literate configuration for GNU Emacs, and is
12tangled to [[./init.el][init.el]]. Packages are installed and managed using
13[[https://github.com/emacscollective/borg][Borg]]. Over the years, I've taken inspiration from configurations of
14many different people. Some of the configurations that I can remember
15off the top of my head are:
16
17- [[https://github.com/dieggsy/dotfiles][dieggsy/dotfiles]]: literate Emacs and dotfiles configuration, uses
18 straight.el for managing packages
19- [[https://github.com/dakra/dmacs][dakra/dmacs]]: literate Emacs configuration, using Borg for managing
20 packages
21- [[http://pages.sachachua.com/.emacs.d/Sacha.html][Sacha Chua's literate Emacs configuration]]
22- [[https://github.com/dakrone/eos][dakrone/eos]]
23- Ryan Rix's [[http://doc.rix.si/cce/cce.html][Complete Computing Environment]] ([[http://doc.rix.si/projects/fsem.html][about cce]])
24- [[https://github.com/jwiegley/dot-emacs][jwiegley/dot-emacs]]: nix-based configuration
25- [[https://github.com/wasamasa/dotemacs][wasamasa/dotemacs]]
26- [[https://github.com/hlissner/doom-emacs][Doom Emacs]]
27
28I'd like to have a fully reproducible Emacs setup (part of the reason
29why I store my configuration in this repository) but unfortunately out
30of the box, that's not achievable with =package.el=, not currently
31anyway. So, I've opted to use Borg. For what it's worth, I briefly
32experimented with [[https://github.com/raxod502/straight.el][straight.el]], but found that it added about 2 seconds
33to my init time; which is unacceptable for me: I use Emacs as my
34window manager (via EXWM) and coming from bspwm, I'm too used to
35having fast startup times.
36
37** Installation
38
39To use this config for your Emacs, first you need to clone this repo,
40then bootstrap Borg, tell Borg to retrieve package submodules, and
41byte-compiled the packages. Something along these lines should work:
42
43#+begin_src sh :tangle no
44git clone https://github.com/aminb/dotfiles ~/.emacs.d
45cd ~/.emacs.d
46make bootstrap-borg
47make bootstrap
48make build
49#+end_src
50
51* Contents :toc_1:noexport:
52
53- [[#about][About]]
54- [[#header][Header]]
55- [[#initial-setup][Initial setup]]
56- [[#core][Core]]
673d5faa
AB
57- [[#borg-essentials][Borg's =layer/essentials=]]
58- [[#editing][Editing]]
59- [[#syntax-spell-checking][Syntax and spell checking]]
60- [[#programming-modes][Programming modes]]
61- [[#emacs-enhancements][Emacs enhancements]]
62- [[#email][Email]]
63- [[#blogging][Blogging]]
5fece105
AB
64- [[#post-initialization][Post initialization]]
65- [[#footer][Footer]]
66
67* Header
68:PROPERTIES:
69:CUSTOM_ID: header
70:END:
71
72** First line
73
74#+begin_src emacs-lisp :comments none
f1149591 75;;; init.el --- Amin Bandali's Emacs config -*- lexical-binding: t; eval: (view-mode 1) -*-
5fece105
AB
76#+end_src
77
78Enable =view-mode=, which both makes the file read-only (as a reminder
79that =init.el= is an auto-generated file, not supposed to be edited),
80and provides some convenient key bindings for browsing through the
81file.
82
83** License
84
85#+begin_src emacs-lisp :comments none
86;; Copyright (C) 2018 Amin Bandali <bandali@gnu.org>
87
88;; This program is free software: you can redistribute it and/or modify
89;; it under the terms of the GNU General Public License as published by
90;; the Free Software Foundation, either version 3 of the License, or
91;; (at your option) any later version.
92
93;; This program is distributed in the hope that it will be useful,
94;; but WITHOUT ANY WARRANTY; without even the implied warranty of
95;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
96;; GNU General Public License for more details.
97
98;; You should have received a copy of the GNU General Public License
99;; along with this program. If not, see <https://www.gnu.org/licenses/>.
100#+end_src
101
102** Commentary
103
104#+begin_src emacs-lisp :comments none
105;;; Commentary:
106
c5d8bb25
AB
107;; Emacs configuration of Amin Bandali, computer scientist, functional
108;; programmer, and free software advocate.
5fece105
AB
109
110;; THIS FILE IS AUTO-GENERATED FROM `init.org'.
111#+end_src
112
5fece105
AB
113* Initial setup
114:PROPERTIES:
115:CUSTOM_ID: initial-setup
116:END:
117
5fece105
AB
118** Emacs initialization
119
120I'd like to do a couple of measurements of Emacs' startup time. First,
121let's see how long Emacs takes to start up, before even loading
122=init.el=, i.e. =user-init-file=:
123
124#+begin_src emacs-lisp
c5d8bb25 125(defvar a/before-user-init-time (current-time)
5fece105
AB
126 "Value of `current-time' when Emacs begins loading `user-init-file'.")
127(message "Loading Emacs...done (%.3fs)"
c5d8bb25 128 (float-time (time-subtract a/before-user-init-time
5fece105
AB
129 before-init-time)))
130#+end_src
131
132Also, temporarily increase ~gc-cons-threshhold~ and
133~gc-cons-percentage~ during startup to reduce garbage collection
134frequency. Clearing the ~file-name-handler-alist~ seems to help reduce
135startup time as well.
136
137#+begin_src emacs-lisp
c5d8bb25
AB
138(defvar a/gc-cons-threshold gc-cons-threshold)
139(defvar a/gc-cons-percentage gc-cons-percentage)
140(defvar a/file-name-handler-alist file-name-handler-alist)
5fece105
AB
141(setq gc-cons-threshold (* 400 1024 1024) ; 400 MiB
142 gc-cons-percentage 0.6
143 file-name-handler-alist nil
144 ;; sidesteps a bug when profiling with esup
145 esup-child-profile-require-level 0)
146#+end_src
147
148Of course, we'd like to set them back to their defaults once we're
149done initializing.
150
151#+begin_src emacs-lisp
152(add-hook
153 'after-init-hook
154 (lambda ()
c5d8bb25
AB
155 (setq gc-cons-threshold a/gc-cons-threshold
156 gc-cons-percentage a/gc-cons-percentage
157 file-name-handler-alist a/file-name-handler-alist)))
5fece105
AB
158#+end_src
159
160Increase the number of lines kept in message logs (the =*Messages*=
161buffer).
162
163#+begin_src emacs-lisp
164(setq message-log-max 20000)
165#+end_src
166
167Optionally, we could suppress some byte compiler warnings like below,
168but for now I've decided to keep them enabled. See documentation for
169~byte-compile-warnings~ for more details.
170
171#+begin_src emacs-lisp
172;; (setq byte-compile-warnings
173;; '(not free-vars unresolved noruntime lexical make-local))
174#+end_src
175
176** whoami
177
178#+begin_src emacs-lisp
179(setq user-full-name "Amin Bandali"
180 user-mail-address "amin@aminb.org")
181#+end_src
182
183** Package management
184
185*** No =package.el=
186
187I can do all my package management things with Borg, and don't need
188Emacs' built-in =package.el=. Emacs 27 lets us disable =package.el= in
189the =early-init-file= (see [[https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=24acb31c04b4048b85311d794e600ecd7ce60d3b][here]]).
190
191#+begin_src emacs-lisp :tangle early-init.el
192(setq package-enable-at-startup nil)
193#+end_src
194
195But since Emacs 27 isn't out yet (Emacs 26 is just around the corner
196right now), and even when released it'll be long before most distros
197ship in their repos, I'll still put the old workaround with the
198commented call to ~package-initialize~ here anyway.
199
200#+begin_src emacs-lisp
201(setq package-enable-at-startup nil)
202;; (package-initialize)
203#+end_src
204
205*** Borg
206
207#+begin_quote
208Assimilate Emacs packages as Git submodules
209#+end_quote
210
211[[https://github.com/emacscollective/borg][Borg]] is at the heart of package management of my Emacs setup. In
212short, it creates a git submodule in =lib/= for each package, which
213can then be managed with the help of Magit or other tools.
214
215#+begin_src emacs-lisp
216(setq user-init-file (or load-file-name buffer-file-name)
217 user-emacs-directory (file-name-directory user-init-file))
218(add-to-list 'load-path
219 (expand-file-name "lib/borg" user-emacs-directory))
220(require 'borg)
221(borg-initialize)
222
223;; (require 'borg-nix-shell)
224;; (setq borg-build-shell-command 'borg-nix-shell-build-command)
225
226(with-eval-after-load 'bind-key
227 (bind-keys
228 :package borg
229 ("C-c b A" . borg-activate)
230 ("C-c b a" . borg-assimilate)
231 ("C-c b b" . borg-build)
232 ("C-c b c" . borg-clone)
233 ("C-c b r" . borg-remove)))
234#+end_src
235
236*** =use-package=
237
238#+begin_quote
239A use-package declaration for simplifying your .emacs
240#+end_quote
241
242[[https://github.com/jwiegley/use-package][use-package]] is an awesome utility for managing and configuring
243packages (in our case especially the latter) in a neatly organized way
244and without compromising on performance.
245
246#+begin_src emacs-lisp
247(require 'use-package)
248(if nil ; set to t when need to debug init
249 (setq use-package-verbose t
250 use-package-expand-minimally nil
251 use-package-compute-statistics t
252 debug-on-error t)
253 (setq use-package-verbose nil
254 use-package-expand-minimally t))
255#+end_src
256
257*** Epkg
258
259#+begin_quote
260Browse the Emacsmirror package database
261#+end_quote
262
263Epkg provides access to a local copy of the [[https://emacsmirror.net][Emacsmirror]] package
264database, low-level functions for querying the database, and a
265=package.el=-like user interface for browsing the available packages.
266
267#+begin_src emacs-lisp
268(use-package epkg
269 :defer t
270 :bind
271 (("C-c b d" . epkg-describe-package)
272 ("C-c b p" . epkg-list-packages)
d568ebac
AB
273 ("C-c b u" . epkg-update))
274 :config
2b34d6dd 275 (eval-when-compile (defvar ivy-initial-inputs-alist))
d568ebac
AB
276 (with-eval-after-load 'ivy
277 (add-to-list
278 'ivy-initial-inputs-alist '(epkg-describe-package . "^") t)))
5fece105
AB
279#+end_src
280
281** No littering in =~/.emacs.d=
282
283#+begin_quote
284Help keeping ~/.emacs.d clean
285#+end_quote
286
287By default, even for Emacs' built-in packages, the configuration files
288and persistent data are all over the place. Use =no-littering= to help
289contain the mess.
290
291#+begin_src emacs-lisp
292(use-package no-littering
293 :demand t
294 :config
295 (savehist-mode 1)
296 (add-to-list 'savehist-additional-variables 'kill-ring)
297 (save-place-mode 1)
298 (setq auto-save-file-name-transforms
299 `((".*" ,(no-littering-expand-var-file-name "auto-save/") t))))
300#+end_src
301
302** Custom file (=custom.el=)
303
304I'm not planning on using the custom file much, but even so, I
305definitely don't want it mixing with =init.el=. So, here; let's give
306it it's own file. While at it, treat themes as safe.
307
308#+begin_src emacs-lisp
309(use-package custom
310 :no-require t
311 :config
312 (setq custom-file (no-littering-expand-etc-file-name "custom.el"))
313 (when (file-exists-p custom-file)
314 (load custom-file))
315 (setf custom-safe-themes t))
316#+end_src
317
318** Secrets file
319
320Load the secrets file if it exists, otherwise show a warning.
321
322#+begin_src emacs-lisp
323(with-demoted-errors
324 (load (no-littering-expand-etc-file-name "secrets")))
325#+end_src
326
327** Better =$PATH= handling
328
329Let's use [[https://github.com/purcell/exec-path-from-shell][exec-path-from-shell]] to make Emacs use the =$PATH= as set up
330in my shell.
331
332#+begin_src emacs-lisp
333(use-package exec-path-from-shell
334 :defer 1
335 :init
336 (setq exec-path-from-shell-check-startup-files nil)
337 :config
338 (exec-path-from-shell-initialize)
339 ;; while we're at it, let's fix access to our running ssh-agent
340 (exec-path-from-shell-copy-env "SSH_AGENT_PID")
341 (exec-path-from-shell-copy-env "SSH_AUTH_SOCK"))
342#+end_src
343
21ad71fa 344** COMMENT Only one custom theme at a time
5fece105
AB
345
346#+begin_src emacs-lisp
21ad71fa
AB
347(defadvice load-theme (before clear-previous-themes activate)
348 "Clear existing theme settings instead of layering them"
349 (mapc #'disable-theme custom-enabled-themes))
5fece105
AB
350#+end_src
351
352** Server
353
354Start server if not already running. Alternatively, can be done by
355issuing =emacs --daemon= in the terminal, which can be automated with
356a systemd service or using =brew services start emacs= on macOS. I use
357Emacs as my window manager (via EXWM), so I always start Emacs on
358login; so starting the server from inside Emacs is good enough for me.
359
360See [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html#Emacs-Server][Using Emacs as a Server]].
361
362#+begin_src emacs-lisp
363(use-package server
364 :defer 1
365 :config (or (server-running-p) (server-mode)))
366#+end_src
367
21ad71fa 368** COMMENT Unicode support
5fece105
AB
369
370Font stack with better unicode support, around =Ubuntu Mono= and
371=Hack=.
372
373#+begin_src emacs-lisp
21ad71fa
AB
374(dolist (ft (fontset-list))
375 (set-fontset-font
376 ft
377 'unicode
378 (font-spec :name "Source Code Pro" :size 14))
379 (set-fontset-font
380 ft
381 'unicode
382 (font-spec :name "DejaVu Sans Mono")
383 nil
384 'append)
385 ;; (set-fontset-font
386 ;; ft
387 ;; 'unicode
388 ;; (font-spec
389 ;; :name "Symbola monospacified for DejaVu Sans Mono")
390 ;; nil
391 ;; 'append)
392 ;; (set-fontset-font
393 ;; ft
394 ;; #x2115 ; ℕ
395 ;; (font-spec :name "DejaVu Sans Mono")
396 ;; nil
397 ;; 'append)
398 (set-fontset-font
399 ft
400 (cons ?Α ?ω)
401 (font-spec :name "DejaVu Sans Mono" :size 14)
402 nil
403 'prepend))
5fece105
AB
404#+end_src
405
406** Gentler font resizing
407
408#+begin_src emacs-lisp
409(setq text-scale-mode-step 1.05)
410#+end_src
411
412** Focus follows mouse
413
414I’d like focus to follow the mouse when I move the cursor from one
415window to the next.
416
417#+begin_src emacs-lisp
418(setq mouse-autoselect-window t)
419#+end_src
420
421Let’s define a function to conveniently disable this for certain
422buffers and/or modes.
423
424#+begin_src emacs-lisp
c5d8bb25 425(defun a/no-mouse-autoselect-window ()
5fece105
AB
426 (make-local-variable 'mouse-autoselect-window)
427 (setq mouse-autoselect-window nil))
428#+end_src
429
430** Libraries
431
432#+begin_src emacs-lisp
433(require 'cl-lib)
434(require 'subr-x)
435#+end_src
436
437** Useful utilities
438
5fece105
AB
439Convenience macro for =setq='ing multiple variables to the same value:
440
441#+begin_src emacs-lisp
c5d8bb25 442(defmacro a/setq-every (value &rest vars)
5fece105
AB
443 "Set all the variables from VARS to value VALUE."
444 (declare (indent defun) (debug t))
445 `(progn ,@(mapcar (lambda (x) (list 'setq x value)) vars)))
446#+end_src
447
448* Core
449:PROPERTIES:
450:CUSTOM_ID: core
451:END:
452
5fece105
AB
453** Defaults
454
455*** Time and battery in mode-line
456
457Enable displaying time and battery in the mode-line, since I'm not
458using the Xfce panel anymore. Also, I don't need to see the load
459average on a regular basis, so disable that.
460
461Note: using =i3status= on sway at the moment, so disabling this.
462
463#+begin_src emacs-lisp :tangle no
464(use-package time
465 :init
466 (setq display-time-default-load-average nil)
467 :config
468 (display-time-mode))
469
470(use-package battery
471 :config
472 (display-battery-mode))
473#+end_src
474
475*** Smaller fringe
476
477Might want to set the fringe to a smaller value, especially if using
478EXWM. I'm fine with the default for now.
479
480#+begin_src emacs-lisp
481;; (fringe-mode '(3 . 1))
482(fringe-mode nil)
483#+end_src
484
485*** Disable disabled commands
486
487Emacs disables some commands by default that could persumably be
488confusing for novice users. Let's disable that.
489
490#+begin_src emacs-lisp
491(setq disabled-command-function nil)
492#+end_src
493
494*** Kill-ring
495
496Save what I copy into clipboard from other applications into Emacs'
497kill-ring, which would allow me to still be able to easily access it
498in case I kill (cut or copy) something else inside Emacs before
499yanking (pasting) what I'd originally intended to.
500
501#+begin_src emacs-lisp
502(setq save-interprogram-paste-before-kill t)
503#+end_src
504
505*** Minibuffer
506
507#+begin_src emacs-lisp
508(setq enable-recursive-minibuffers t
509 resize-mini-windows t)
510#+end_src
511
512*** Lazy-person-friendly yes/no prompts
513
514Lazy people would prefer to type fewer keystrokes, especially for yes
515or no questions. I'm lazy.
516
517#+begin_src emacs-lisp
518(defalias 'yes-or-no-p #'y-or-n-p)
519#+end_src
520
521*** Startup screen and =*scratch*=
522
523Firstly, let Emacs know that I'd like to have =*scratch*= as my
524startup buffer.
525
526#+begin_src emacs-lisp
527(setq initial-buffer-choice t)
528#+end_src
529
530Now let's customize the =*scratch*= buffer a bit. First off, I don't
531need the default hint.
532
533#+begin_src emacs-lisp
534(setq initial-scratch-message nil)
535#+end_src
536
537Also, let's use Text mode as the major mode, in case I want to
538customize it (=*scratch*='s default major mode, Fundamental mode,
539can't really be customized).
540
541#+begin_src emacs-lisp
542(setq initial-major-mode 'text-mode)
543#+end_src
544
545Inhibit the buffer list when more than 2 files are loaded.
546
547#+begin_src emacs-lisp
548(setq inhibit-startup-buffer-menu t)
549#+end_src
550
551I don't really need to see the startup screen or echo area message
552either.
553
554#+begin_src emacs-lisp
555(advice-add #'display-startup-echo-area-message :override #'ignore)
556(setq inhibit-startup-screen t
557 inhibit-startup-echo-area-message user-login-name)
558#+end_src
559
560*** More useful frame titles
561
562Show either the file name or the buffer name (in case the buffer isn't
563visiting a file). Borrowed from Emacs Prelude.
564
565#+begin_src emacs-lisp
566(setq frame-title-format
567 '("" invocation-name " - "
568 (:eval (if (buffer-file-name)
569 (abbreviate-file-name (buffer-file-name))
570 "%b"))))
571#+end_src
572
573*** Backups
574
575Emacs' default backup settings aren't that great. Let's use more
576sensible options. See documentation for the ~make-backup-file~
577variable.
578
579#+begin_src emacs-lisp
580(setq backup-by-copying t
581 version-control t
582 delete-old-versions t)
583#+end_src
584
585*** Auto revert
586
587Enable automatic reloading of changed buffers and files.
588
589#+begin_src emacs-lisp
590(global-auto-revert-mode 1)
591(setq auto-revert-verbose nil
592 global-auto-revert-non-file-buffers nil)
593#+end_src
594
595*** Always use space for indentation
596
597#+begin_src emacs-lisp
598(setq-default
599 indent-tabs-mode nil
600 require-final-newline t
601 tab-width 4)
602#+end_src
603
604*** Winner mode
605
606Enable =winner-mode=.
607
608#+begin_src emacs-lisp
609(winner-mode 1)
610#+end_src
611
f79ed7c6
AB
612*** Don’t display =*compilation*= on success
613
614Based on https://stackoverflow.com/a/17788551, with changes to use
615=cl-letf= instead of the now obsolete =flet=.
c44ace12
AB
616
617#+begin_src emacs-lisp
f1516d51 618(with-eval-after-load 'compile
c5d8bb25 619 (defun a/compilation-finish-function (buffer outstr)
5e07a091
AB
620 (unless (string-match "finished" outstr)
621 (switch-to-buffer-other-window buffer))
622 t)
f79ed7c6 623
c5d8bb25 624 (setq compilation-finish-functions #'a/compilation-finish-function)
f79ed7c6 625
5e07a091 626 (require 'cl-macs)
f79ed7c6 627
5e07a091
AB
628 (defadvice compilation-start
629 (around inhibit-display
630 (command &optional mode name-function highlight-regexp))
631 (if (not (string-match "^\\(find\\|grep\\)" command))
0571b240 632 (cl-letf (((symbol-function 'display-buffer) #'ignore))
5e07a091
AB
633 (save-window-excursion ad-do-it))
634 ad-do-it))
635 (ad-activate 'compilation-start))
5fece105
AB
636#+end_src
637
638*** Search for non-ASCII characters
639
640I’d like non-ASCII characters such as ‘’“”«»‹›áⓐ𝒶 to be selected when
641I search for their ASCII counterpart. Shoutout to [[http://endlessparentheses.com/new-in-emacs-25-1-easily-search-non-ascii-characters.html][endlessparentheses]]
642for this.
643
644#+begin_src emacs-lisp
645(setq search-default-mode #'char-fold-to-regexp)
646
647;; uncomment to extend this behaviour to query-replace
648;; (setq replace-char-fold t)
649#+end_src
650
96b3e55d
AB
651*** Cursor shape
652
653#+begin_src emacs-lisp
654(setq-default cursor-type 'bar)
655#+end_src
656
5fece105
AB
657** Bindings
658
659#+begin_src emacs-lisp
660(bind-keys
661 ("C-c a i" . ielm)
662
663 ("C-c e b" . eval-buffer)
664 ("C-c e r" . eval-region)
665
666 ("C-c F m" . make-frame-command)
667 ("C-c F d" . delete-frame)
668 ("C-c F D" . delete-other-frames)
669
670 ("C-c o" . other-window)
671
672 ("C-c Q" . save-buffers-kill-terminal)
673
674 ("C-S-h C" . describe-char)
675 ("C-S-h F" . describe-face)
676
677 ("C-x K" . kill-this-buffer)
678
679 ("s-p" . beginning-of-buffer)
680 ("s-n" . end-of-buffer))
681#+end_src
682
683** Packages
684
685The packages in this section are absolutely essential to my everyday
686workflow, and they play key roles in how I do my computing. They
687immensely enhance the Emacs experience for me; both using Emacs, and
688customizing it.
689
690*** [[https://github.com/emacscollective/auto-compile][auto-compile]]
691
692#+begin_src emacs-lisp
693(use-package auto-compile
694 :demand t
695 :config
696 (auto-compile-on-load-mode)
697 (auto-compile-on-save-mode)
698 (setq auto-compile-display-buffer nil
699 auto-compile-mode-line-counter t
700 auto-compile-source-recreate-deletes-dest t
701 auto-compile-toggle-deletes-nonlib-dest t
702 auto-compile-update-autoloads t)
703 (add-hook 'auto-compile-inhibit-compile-hook
704 'auto-compile-inhibit-compile-detached-git-head))
705#+end_src
706
707*** [[https://orgmode.org/][Org mode]]
708
709#+begin_quote
710Org mode is for keeping notes, maintaining TODO lists, planning
711projects, and authoring documents with a fast and effective plain-text
712system.
713#+end_quote
714
715In short, my favourite way of life.
716
717#+begin_src emacs-lisp
718(use-package org
719 :defer 1
720 :config
721 (setq org-src-tab-acts-natively t
722 org-src-preserve-indentation nil
723 org-edit-src-content-indentation 0
724 org-email-link-description-format "Email %c: %s" ; %.30s
725 org-highlight-latex-and-related '(entities)
815c338b
AB
726 org-use-speed-commands t
727 org-startup-folded 'content
728 org-catch-invisible-edits 'show-and-error
5fece105
AB
729 org-log-done 'time)
730 (add-to-list 'org-structure-template-alist '("L" . "src emacs-lisp") t)
731 (font-lock-add-keywords
732 'org-mode
733 '(("[ \t]*\\(#\\+\\(BEGIN\\|END\\|begin\\|end\\)_\\(\\S-+\\)\\)[ \t]*\\([^\n:]*\\)"
734 (1 '(:foreground "#5a5b5a" :background "#292b2b") t) ; directive
735 (3 '(:foreground "#81a2be" :background "#292b2b") t) ; kind
736 (4 '(:foreground "#c5c8c6") t))) ; title
737 t)
738 :bind (:map org-mode-map ("M-L" . org-insert-last-stored-link))
739 :hook ((org-mode . org-indent-mode)
740 (org-mode . auto-fill-mode)
741 (org-mode . flyspell-mode))
742 :custom
743 (org-latex-packages-alist '(("" "listings") ("" "color")))
744 :custom-face
745 '(org-block-begin-line ((t (:foreground "#5a5b5a" :background "#1d1f21"))))
746 '(org-block ((t (:background "#1d1f21"))))
747 '(org-latex-and-related ((t (:foreground "#b294bb")))))
748
749(use-package ox-latex
750 :after ox
751 :config
752 (setq org-latex-listings 'listings
753 ;; org-latex-prefer-user-labels t
754 )
755 (add-to-list 'org-latex-packages-alist '("" "listings"))
756 (add-to-list 'org-latex-packages-alist '("" "color"))
757 (add-to-list 'org-latex-classes
758 '("IEEEtran" "\\documentclass[11pt]{IEEEtran}"
759 ("\\section{%s}" . "\\section*{%s}")
760 ("\\subsection{%s}" . "\\subsection*{%s}")
761 ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
762 ("\\paragraph{%s}" . "\\paragraph*{%s}")
763 ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
764 t))
765
766(use-package ox-beamer
767 :after ox)
768
769(use-package orgalist
770 :after message
771 :hook (message-mode . orgalist-mode))
772#+end_src
773
774**** asynchronous tangle
775
c5d8bb25 776=a/async-babel-tangle= is a function closely inspired by [[https://github.com/dieggsy/dotfiles/tree/cc10edf7701958eff1cd94d4081da544d882a28c/emacs.d#dotfiles][dieggsy's
5fece105
AB
777d/async-babel-tangle]] which uses [[https://github.com/jwiegley/emacs-async][async]] to asynchronously tangle an org
778file.
779
780#+begin_src emacs-lisp
ab6781dd 781(with-eval-after-load 'org
c5d8bb25 782 (defvar a/show-async-tangle-results nil
5fece105
AB
783 "Keep *emacs* async buffers around for later inspection.")
784
c5d8bb25 785 (defvar a/show-async-tangle-time nil
5fece105
AB
786 "Show the time spent tangling the file.")
787
c5d8bb25 788 (defvar a/async-tangle-post-compile "make ti"
5fece105
AB
789 "If non-nil, pass to `compile' after successful tangle.")
790
c5d8bb25 791 (defun a/async-babel-tangle ()
5fece105
AB
792 "Tangle org file asynchronously."
793 (interactive)
794 (let* ((file-tangle-start-time (current-time))
795 (file (buffer-file-name))
796 (file-nodir (file-name-nondirectory file))
0571b240
AB
797 ;; (async-quiet-switch "-q")
798 )
5fece105
AB
799 (async-start
800 `(lambda ()
801 (require 'org)
802 (org-babel-tangle-file ,file))
c5d8bb25 803 (unless a/show-async-tangle-results
5fece105
AB
804 `(lambda (result)
805 (if result
806 (progn
807 (message "Tangled %s%s"
808 ,file-nodir
c5d8bb25 809 (if a/show-async-tangle-time
5fece105
AB
810 (format " (%.3fs)"
811 (float-time (time-subtract (current-time)
812 ',file-tangle-start-time)))
813 ""))
c5d8bb25
AB
814 (when a/async-tangle-post-compile
815 (compile a/async-tangle-post-compile)))
5fece105
AB
816 (message "Tangling %s failed" ,file-nodir))))))))
817
818(add-to-list
819 'safe-local-variable-values
c5d8bb25 820 '(eval add-hook 'after-save-hook #'a/async-babel-tangle 'append 'local))
5fece105
AB
821#+end_src
822
823*** [[https://magit.vc/][Magit]]
824
825#+begin_quote
826It's Magit! A Git porcelain inside Emacs.
827#+end_quote
828
829Not just how I do git, but /the/ way to do git.
830
831#+begin_src emacs-lisp
832(use-package magit
833 :defer 1
834 :bind (("C-x g" . magit-status)
835 ("s-g s" . magit-status)
836 ("s-g l" . magit-log-buffer-file))
837 :config
838 (magit-add-section-hook 'magit-status-sections-hook
839 'magit-insert-modules
840 'magit-insert-stashes
841 'append)
842 (setq
843 magit-repository-directories '(("~/.emacs.d/" . 0)
844 ("~/src/git/" . 1)))
845 (nconc magit-section-initial-visibility-alist
846 '(([unpulled status] . show)
847 ([unpushed status] . show)))
848 :custom-face (magit-diff-file-heading ((t (:weight normal)))))
849#+end_src
850
851*** [[https://github.com/abo-abo/swiper][Ivy]] (and friends)
852
853#+begin_quote
854Ivy - a generic completion frontend for Emacs, Swiper - isearch with
855an overview, and more. Oh, man!
856#+end_quote
857
858There's no way I could top that, so I won't attempt to.
859
860**** Ivy
861
862#+begin_src emacs-lisp
863(use-package ivy
864 :defer 1
865 :bind
866 (:map ivy-minibuffer-map
867 ([escape] . keyboard-escape-quit)
868 ([S-up] . ivy-previous-history-element)
869 ([S-down] . ivy-next-history-element)
870 ("DEL" . ivy-backward-delete-char))
871 :config
872 (setq ivy-wrap t)
873 (ivy-mode 1)
874 ;; :custom-face
875 ;; (ivy-minibuffer-match-face-2 ((t (:background "#e99ce8" :weight semi-bold))))
876 ;; (ivy-minibuffer-match-face-3 ((t (:background "#bbbbff" :weight semi-bold))))
877 ;; (ivy-minibuffer-match-face-4 ((t (:background "#ffbbff" :weight semi-bold))))
878)
879#+end_src
880
881**** Swiper
882
883#+begin_src emacs-lisp
884(use-package swiper
f2a57944
AB
885 :bind (("C-s" . swiper)
886 ("C-r" . swiper)
887 ("C-S-s" . isearch-forward)))
5fece105
AB
888#+end_src
889
890**** Counsel
891
892#+begin_src emacs-lisp
893(use-package counsel
894 :defer 1
895 :bind (([remap execute-extended-command] . counsel-M-x)
896 ([remap find-file] . counsel-find-file)
897 ("s-r" . counsel-recentf)
898 ("C-c x" . counsel-M-x)
899 ("C-c f ." . counsel-find-file)
900 :map minibuffer-local-map
901 ("C-r" . counsel-minibuffer-history))
902 :config
903 (counsel-mode 1)
904 (defalias 'locate #'counsel-locate))
905#+end_src
906
907*** eshell
908
909#+begin_src emacs-lisp
910(use-package eshell
911 :defer 1
912 :commands eshell
23cd3185 913 :bind ("C-c a s e" . eshell)
5fece105
AB
914 :config
915 (eval-when-compile (defvar eshell-prompt-regexp))
c5d8bb25 916 (defun a/eshell-quit-or-delete-char (arg)
5fece105
AB
917 (interactive "p")
918 (if (and (eolp) (looking-back eshell-prompt-regexp nil))
919 (eshell-life-is-too-much)
920 (delete-char arg)))
921
c5d8bb25 922 (defun a/eshell-clear ()
5fece105
AB
923 (interactive)
924 (let ((inhibit-read-only t))
925 (erase-buffer))
926 (eshell-send-input))
927
c5d8bb25 928 (defun a/eshell-setup ()
5fece105 929 (make-local-variable 'company-idle-delay)
0571b240 930 (defvar company-idle-delay nil)
5fece105 931 (bind-keys :map eshell-mode-map
c5d8bb25
AB
932 ("C-d" . a/eshell-quit-or-delete-char)
933 ("C-S-l" . a/eshell-clear)
5fece105
AB
934 ("M-r" . counsel-esh-history)
935 ([tab] . company-complete)))
936
c5d8bb25 937 :hook (eshell-mode . a/eshell-setup)
5fece105
AB
938 :custom
939 (eshell-hist-ignoredups t)
940 (eshell-input-filter 'eshell-input-filter-initial-space))
941#+end_src
942
943*** Ibuffer
944
945#+begin_src emacs-lisp
946(use-package ibuffer
947 :defer t
948 :bind
949 (("C-x C-b" . ibuffer-other-window)
950 :map ibuffer-mode-map
951 ("P" . ibuffer-backward-filter-group)
952 ("N" . ibuffer-forward-filter-group)
953 ("M-p" . ibuffer-do-print)
954 ("M-n" . ibuffer-do-shell-command-pipe-replace))
955 :config
956 ;; Use human readable Size column instead of original one
957 (define-ibuffer-column size-h
958 (:name "Size" :inline t)
959 (cond
960 ((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0)))
961 ((> (buffer-size) 100000) (format "%7.0fk" (/ (buffer-size) 1000.0)))
962 ((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0)))
963 (t (format "%8d" (buffer-size)))))
964 :custom
965 (ibuffer-saved-filter-groups
966 '(("default"
967 ("dired" (mode . dired-mode))
968 ("org" (mode . org-mode))
4e0afb99
AB
969 ("gnus"
970 (or
971 (mode . gnus-group-mode)
972 (mode . gnus-summary-mode)
973 (mode . gnus-article-mode)
974 ;; not really, but...
975 (mode . message-mode)))
5fece105
AB
976 ("web"
977 (or
978 (mode . web-mode)
979 (mode . css-mode)
980 (mode . scss-mode)
981 (mode . js2-mode)))
982 ("shell"
983 (or
984 (mode . eshell-mode)
4e0afb99
AB
985 (mode . shell-mode)
986 (mode . term-mode)))
5fece105
AB
987 ("programming"
988 (or
989 (mode . python-mode)
4e0afb99 990 (mode . c-mode)
5fece105 991 (mode . c++-mode)
4e0afb99
AB
992 (mode . emacs-lisp-mode)
993 (mode . scheme-mode)
994 (mode . haskell-mode)
995 (mode . lean-mode)))
5fece105
AB
996 ("emacs"
997 (or
998 (name . "^\\*scratch\\*$")
4e0afb99 999 (name . "^\\*Messages\\*$"))))))
5fece105
AB
1000 (ibuffer-formats
1001 '((mark modified read-only locked " "
1002 (name 18 18 :left :elide)
1003 " "
1004 (size-h 9 -1 :right)
1005 " "
1006 (mode 16 16 :left :elide)
1007 " " filename-and-process)
1008 (mark " "
1009 (name 16 -1)
1010 " " filename)))
1011 :hook (ibuffer . (lambda () (ibuffer-switch-to-saved-filter-groups "default"))))
1012#+end_src
1013
1014*** Outline
1015
1016#+begin_src emacs-lisp
1017(use-package outline
1018 :defer t
1019 :hook (prog-mode . outline-minor-mode)
1020 :bind
1021 (:map
1022 outline-minor-mode-map
1023 ("<s-tab>" . outline-toggle-children)
1024 ("M-p" . outline-previous-visible-heading)
1025 ("M-n" . outline-next-visible-heading)
c5d8bb25 1026 :prefix-map a/outline-prefix-map
5fece105
AB
1027 :prefix "s-o"
1028 ("TAB" . outline-toggle-children)
1029 ("a" . outline-hide-body)
1030 ("H" . outline-hide-body)
1031 ("S" . outline-show-all)
1032 ("h" . outline-hide-subtree)
1033 ("s" . outline-show-subtree)))
1034#+end_src
1035
1036* Borg's =layer/essentials=
673d5faa
AB
1037:PROPERTIES:
1038:CUSTOM_ID: borg-essentials
1039:END:
5fece105 1040
5fece105
AB
1041TODO: break this giant source block down into individual org sections.
1042
1043#+begin_src emacs-lisp
1044(use-package dash
1045 :config (dash-enable-font-lock))
1046
1047(use-package diff-hl
1048 :config
1049 (setq diff-hl-draw-borders nil)
1050 (global-diff-hl-mode)
1051 (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh t))
1052
1053(use-package dired
1054 :defer t
1055 :config (setq dired-listing-switches "-alh"))
1056
1057(use-package eldoc
1058 :when (version< "25" emacs-version)
1059 :config (global-eldoc-mode))
1060
1061(use-package help
1062 :defer t
1063 :config
1064 (temp-buffer-resize-mode)
1065 (setq help-window-select t))
1066
1067(progn ; `isearch'
1068 (setq isearch-allow-scroll t))
1069
1070(use-package lisp-mode
1071 :config
1072 (add-hook 'emacs-lisp-mode-hook 'outline-minor-mode)
1073 (add-hook 'emacs-lisp-mode-hook 'reveal-mode)
1074 (defun indent-spaces-mode ()
1075 (setq indent-tabs-mode nil))
1076 (add-hook 'lisp-interaction-mode-hook #'indent-spaces-mode))
1077
1078(use-package man
1079 :defer t
1080 :config (setq Man-width 80))
1081
1082(use-package paren
1083 :config (show-paren-mode))
1084
1085(use-package prog-mode
1086 :config (global-prettify-symbols-mode)
1087 (defun indicate-buffer-boundaries-left ()
1088 (setq indicate-buffer-boundaries 'left))
1089 (add-hook 'prog-mode-hook #'indicate-buffer-boundaries-left))
1090
1091(use-package recentf
1092 :defer 0.5
1093 :config
1094 (add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?:")
1095 (setq recentf-max-saved-items 40))
1096
1097(use-package savehist
1098 :config (savehist-mode))
1099
1100(use-package saveplace
1101 :when (version< "25" emacs-version)
1102 :config (save-place-mode))
1103
1104(use-package simple
1105 :config (column-number-mode))
1106
1107(progn ; `text-mode'
1108 (add-hook 'text-mode-hook #'indicate-buffer-boundaries-left)
1109 (add-hook 'text-mode-hook #'abbrev-mode))
1110
1111(use-package tramp
1112 :defer t
1113 :config
1114 (add-to-list 'tramp-default-proxies-alist '(nil "\\`root\\'" "/ssh:%h:"))
1115 (add-to-list 'tramp-default-proxies-alist '("localhost" nil nil))
1116 (add-to-list 'tramp-default-proxies-alist
1117 (list (regexp-quote (system-name)) nil nil)))
1118
5fece105
AB
1119#+end_src
1120
1121* Editing
673d5faa
AB
1122:PROPERTIES:
1123:CUSTOM_ID: editing
1124:END:
5fece105 1125
5fece105
AB
1126** Company
1127
1128#+begin_src emacs-lisp
1129(use-package company
1130 :defer 1
1131 :bind
1132 (:map company-active-map
1133 ([tab] . company-complete-common-or-cycle)
1134 ([escape] . company-abort))
1135 :custom
1136 (company-minimum-prefix-length 1)
1137 (company-selection-wrap-around t)
1138 (company-dabbrev-char-regexp "\\sw\\|\\s_\\|[-_]")
1139 (company-dabbrev-downcase nil)
1140 (company-dabbrev-ignore-case nil)
1141 :config
1142 (global-company-mode t))
1143#+end_src
1144
1145* Syntax and spell checking
673d5faa
AB
1146:PROPERTIES:
1147:CUSTOM_ID: syntax-spell-checking
1148:END:
5fece105 1149
5fece105
AB
1150#+begin_src emacs-lisp
1151(use-package flycheck
1152 :defer 3
1153 :hook (prog-mode . flycheck-mode)
1154 :bind
1155 (:map flycheck-mode-map
1156 ("M-P" . flycheck-previous-error)
1157 ("M-N" . flycheck-next-error))
1158 :config
1159 ;; Use the load-path from running Emacs when checking elisp files
1160 (setq flycheck-emacs-lisp-load-path 'inherit)
1161
1162 ;; Only flycheck when I actually save the buffer
1163 (setq flycheck-check-syntax-automatically '(mode-enabled save)))
1164
1165;; http://endlessparentheses.com/ispell-and-apostrophes.html
1166(use-package ispell
1167 :defer 3
1168 :config
1169 ;; ’ can be part of a word
1170 (setq ispell-local-dictionary-alist
1171 `((nil "[[:alpha:]]" "[^[:alpha:]]"
1172 "['\x2019]" nil ("-B") nil utf-8)))
1173 ;; don't send ’ to the subprocess
1174 (defun endless/replace-apostrophe (args)
1175 (cons (replace-regexp-in-string
1176 "’" "'" (car args))
1177 (cdr args)))
1178 (advice-add #'ispell-send-string :filter-args
1179 #'endless/replace-apostrophe)
1180
1181 ;; convert ' back to ’ from the subprocess
1182 (defun endless/replace-quote (args)
1183 (if (not (derived-mode-p 'org-mode))
1184 args
1185 (cons (replace-regexp-in-string
1186 "'" "’" (car args))
1187 (cdr args))))
1188 (advice-add #'ispell-parse-output :filter-args
1189 #'endless/replace-quote))
1190#+end_src
9678e6da 1191
5fece105 1192* Programming modes
673d5faa
AB
1193:PROPERTIES:
1194:CUSTOM_ID: programming-modes
1195:END:
5fece105 1196
5fece105
AB
1197** [[http://alloytools.org][Alloy]] (with [[https://github.com/dwwmmn/alloy-mode][alloy-mode]])
1198
1199#+begin_src emacs-lisp
1200(use-package alloy-mode
1201 :defer t
1202 :config (setq alloy-basic-offset 2))
1203#+end_src
1204
1205** [[https://coq.inria.fr][Coq]] (with [[https://github.com/ProofGeneral/PG][Proof General]])
1206
1207#+begin_src emacs-lisp
1208(use-package proof-site ; Proof General
1209 :defer t
1210 :load-path "lib/proof-site/generic/")
1211#+end_src
1212
1213** [[https://leanprover.github.io][Lean]] (with [[https://github.com/leanprover/lean-mode][lean-mode]])
1214
1215#+begin_src emacs-lisp
1216(eval-when-compile (defvar lean-mode-map))
1217(use-package lean-mode
1218 :defer 1
1219 :bind (:map lean-mode-map
1220 ("S-SPC" . company-complete))
1221 :config
1222 (require 'lean-input)
1223 (setq default-input-method "Lean"
1224 lean-input-tweak-all '(lean-input-compose
1225 (lean-input-prepend "/")
1226 (lean-input-nonempty))
1227 lean-input-user-translations '(("/" "/")))
1228 (lean-input-setup))
1229 #+end_src
1230
1231** Haskell
1232
1233*** [[https://github.com/haskell/haskell-mode][haskell-mode]]
1234
1235#+begin_src emacs-lisp
1236(use-package haskell-mode
1237 :defer t
1238 :config
1239 (setq haskell-indentation-layout-offset 4
1240 haskell-indentation-left-offset 4
1241 flycheck-checker 'haskell-hlint
1242 flycheck-disabled-checkers '(haskell-stack-ghc haskell-ghc)))
1243#+end_src
1244
1245*** [[https://github.com/jyp/dante][dante]]
1246
1247#+begin_src emacs-lisp
1248(use-package dante
1249 :after haskell-mode
1250 :commands dante-mode
1251 :hook (haskell-mode . dante-mode))
1252#+end_src
1253
1254*** [[https://github.com/mpickering/hlint-refactor-mode][hlint-refactor]]
1255
1256Emacs bindings for [[https://github.com/ndmitchell/hlint][hlint]]'s refactor option. This requires the refact
1257executable from [[https://github.com/mpickering/apply-refact][apply-refact]].
1258
1259#+begin_src emacs-lisp
1260(use-package hlint-refactor
1261 :after haskell-mode
1262 :bind (:map hlint-refactor-mode-map
1263 ("C-c l b" . hlint-refactor-refactor-buffer)
1264 ("C-c l r" . hlint-refactor-refactor-at-point))
1265 :hook (haskell-mode . hlint-refactor-mode))
1266#+end_src
1267
1268*** [[https://github.com/flycheck/flycheck-haskell][flycheck-haskell]]
1269
1270#+begin_src emacs-lisp
1271(use-package flycheck-haskell
1272 :after haskell-mode)
1273#+end_src
1274
1275*** [[https://github.com/ndmitchell/hlint/blob/20e116a043f2073c57b17b24ae6364b5e433ba7e/data/hs-lint.el][hs-lint.el]]
1276:PROPERTIES:
1277:header-args+: :tangle lisp/hs-lint.el :mkdirp yes
1278:END:
1279
1280Currently using =flycheck-haskell= with the =haskell-hlint= checker
1281instead.
1282
1283#+begin_src emacs-lisp :tangle no
1284;;; hs-lint.el --- minor mode for HLint code checking
1285
1286;; Copyright 2009 (C) Alex Ott
1287;;
1288;; Author: Alex Ott <alexott@gmail.com>
1289;; Keywords: haskell, lint, HLint
1290;; Requirements:
1291;; Status: distributed under terms of GPL2 or above
1292
1293;; Typical message from HLint looks like:
1294;;
1295;; /Users/ott/projects/lang-exp/haskell/test.hs:52:1: Eta reduce
1296;; Found:
1297;; count1 p l = length (filter p l)
1298;; Why not:
1299;; count1 p = length . filter p
1300
1301
1302(require 'compile)
1303
1304(defgroup hs-lint nil
1305 "Run HLint as inferior of Emacs, parse error messages."
1306 :group 'tools
1307 :group 'haskell)
1308
1309(defcustom hs-lint-command "hlint"
1310 "The default hs-lint command for \\[hlint]."
1311 :type 'string
1312 :group 'hs-lint)
1313
1314(defcustom hs-lint-save-files t
1315 "Save modified files when run HLint or no (ask user)"
1316 :type 'boolean
1317 :group 'hs-lint)
1318
1319(defcustom hs-lint-replace-with-suggestions nil
1320 "Replace user's code with suggested replacements"
1321 :type 'boolean
1322 :group 'hs-lint)
1323
1324(defcustom hs-lint-replace-without-ask nil
1325 "Replace user's code with suggested replacements automatically"
1326 :type 'boolean
1327 :group 'hs-lint)
1328
1329(defun hs-lint-process-setup ()
1330 "Setup compilation variables and buffer for `hlint'."
1331 (run-hooks 'hs-lint-setup-hook))
1332
1333;; regex for replace suggestions
1334;;
1335;; ^\(.*?\):\([0-9]+\):\([0-9]+\): .*
1336;; Found:
1337;; \s +\(.*\)
1338;; Why not:
1339;; \s +\(.*\)
1340
1341(defvar hs-lint-regex
1342 "^\\(.*?\\):\\([0-9]+\\):\\([0-9]+\\): .*[\n\C-m]Found:[\n\C-m]\\s +\\(.*\\)[\n\C-m]Why not:[\n\C-m]\\s +\\(.*\\)[\n\C-m]"
1343 "Regex for HLint messages")
1344
1345(defun make-short-string (str maxlen)
1346 (if (< (length str) maxlen)
1347 str
1348 (concat (substring str 0 (- maxlen 3)) "...")))
1349
1350(defun hs-lint-replace-suggestions ()
1351 "Perform actual replacement of suggestions"
1352 (goto-char (point-min))
1353 (while (re-search-forward hs-lint-regex nil t)
1354 (let* ((fname (match-string 1))
1355 (fline (string-to-number (match-string 2)))
1356 (old-code (match-string 4))
1357 (new-code (match-string 5))
1358 (msg (concat "Replace '" (make-short-string old-code 30)
1359 "' with '" (make-short-string new-code 30) "'"))
1360 (bline 0)
1361 (eline 0)
1362 (spos 0)
1363 (new-old-code ""))
1364 (save-excursion
1365 (switch-to-buffer (get-file-buffer fname))
1366 (goto-char (point-min))
1367 (forward-line (1- fline))
1368 (beginning-of-line)
1369 (setf bline (point))
1370 (when (or hs-lint-replace-without-ask
1371 (yes-or-no-p msg))
1372 (end-of-line)
1373 (setf eline (point))
1374 (beginning-of-line)
1375 (setf old-code (regexp-quote old-code))
1376 (while (string-match "\\\\ " old-code spos)
1377 (setf new-old-code (concat new-old-code
1378 (substring old-code spos (match-beginning 0))
1379 "\\ *"))
1380 (setf spos (match-end 0)))
1381 (setf new-old-code (concat new-old-code (substring old-code spos)))
1382 (remove-text-properties bline eline '(composition nil))
1383 (when (re-search-forward new-old-code eline t)
1384 (replace-match new-code nil t)))))))
1385
1386(defun hs-lint-finish-hook (buf msg)
1387 "Function, that is executed at the end of HLint execution"
1388 (if hs-lint-replace-with-suggestions
1389 (hs-lint-replace-suggestions)
1390 (next-error 1 t)))
1391
1392(define-compilation-mode hs-lint-mode "HLint"
1393 "Mode for check Haskell source code."
1394 (set (make-local-variable 'compilation-process-setup-function)
1395 'hs-lint-process-setup)
1396 (set (make-local-variable 'compilation-disable-input) t)
1397 (set (make-local-variable 'compilation-scroll-output) nil)
1398 (set (make-local-variable 'compilation-finish-functions)
1399 (list 'hs-lint-finish-hook))
1400 )
1401
1402(defun hs-lint ()
1403 "Run HLint for current buffer with haskell source"
1404 (interactive)
1405 (save-some-buffers hs-lint-save-files)
1406 (compilation-start (concat hs-lint-command " \"" buffer-file-name "\"")
1407 'hs-lint-mode))
1408
1409(provide 'hs-lint)
1410;;; hs-lint.el ends here
1411#+end_src
1412
1413#+begin_src emacs-lisp :tangle no
1414(use-package hs-lint
1415 :load-path "lisp/"
1416 :bind (:map haskell-mode-map
1417 ("C-c l l" . hs-lint)))
1418#+end_src
1419
1420** Web dev
1421
1422*** SGML and HTML
1423
1424#+begin_src emacs-lisp
1425(use-package sgml-mode
1426 :defer t
1427 :config
1428 (setq sgml-basic-offset 2))
1429#+end_src
1430
1431*** CSS and SCSS
1432
1433#+begin_src emacs-lisp
1434(use-package css-mode
1435 :defer t
1436 :config
1437 (setq css-indent-offset 2))
1438#+end_src
1439
1440*** Web mode
1441
1442#+begin_src emacs-lisp
1443(use-package web-mode
1444 :defer t
1445 :mode "\\.html\\'"
1446 :config
c5d8bb25 1447 (a/setq-every 2
5fece105
AB
1448 web-mode-code-indent-offset
1449 web-mode-css-indent-offset
1450 web-mode-markup-indent-offset))
1451#+end_src
1452
1453*** Emmet mode
1454
1455#+begin_src emacs-lisp
1456(use-package emmet-mode
1457 :after (:any web-mode css-mode sgml-mode)
1458 :bind* (("C-)" . emmet-next-edit-point)
1459 ("C-(" . emmet-prev-edit-point))
1460 :config
1461 (unbind-key "C-j" emmet-mode-keymap)
1462 (setq emmet-move-cursor-between-quotes t)
1463 :hook (web-mode css-mode html-mode sgml-mode))
1464#+end_src
1465
9cebbd53 1466** COMMENT Java
5fece105
AB
1467
1468*** meghanada
1469
9cebbd53 1470#+begin_src emacs-lisp
5fece105
AB
1471(use-package meghanada
1472 :bind
1473 (:map meghanada-mode-map
1474 (("C-M-o" . meghanada-optimize-import)
1475 ("C-M-t" . meghanada-import-all)))
1476 :hook (java-mode . meghanada-mode))
1477#+end_src
1478
1479*** lsp-java
1480
1481#+begin_comment
1482dependencies:
1483
1484ace-window
1485avy
1486bui
1487company-lsp
1488dap-mode
1489lsp-java
1490lsp-mode
1491lsp-ui
1492pfuture
1493tree-mode
1494treemacs
1495#+end_comment
1496
9cebbd53 1497#+begin_src emacs-lisp
5fece105
AB
1498(use-package treemacs
1499 :config (setq treemacs-never-persist t))
1500
1501(use-package yasnippet
1502 :config
1503 ;; (yas-global-mode)
1504 )
1505
1506(use-package lsp-mode
1507 :init (setq lsp-eldoc-render-all nil
1508 lsp-highlight-symbol-at-point nil)
1509 )
1510
1511(use-package hydra)
1512
1513(use-package company-lsp
1514 :after company
1515 :config
1516 (setq company-lsp-cache-candidates t
1517 company-lsp-async t))
1518
1519(use-package lsp-ui
1520 :config
1521 (setq lsp-ui-sideline-update-mode 'point))
1522
1523(use-package lsp-java
1524 :config
1525 (add-hook 'java-mode-hook
1526 (lambda ()
1527 (setq-local company-backends (list 'company-lsp))))
1528
1529 (add-hook 'java-mode-hook 'lsp-java-enable)
1530 (add-hook 'java-mode-hook 'flycheck-mode)
1531 (add-hook 'java-mode-hook 'company-mode)
1532 (add-hook 'java-mode-hook 'lsp-ui-mode))
1533
1534(use-package dap-mode
1535 :after lsp-mode
1536 :config
1537 (dap-mode t)
1538 (dap-ui-mode t))
1539
1540(use-package dap-java
1541 :after (lsp-java))
1542
1543(use-package lsp-java-treemacs
1544 :after (treemacs))
1545#+end_src
1546
5492a3dc
AB
1547** geiser
1548
1549#+begin_src emacs-lisp
1550(use-package geiser)
1551
1552(use-package geiser-guile
1553 :config
1554 (setq geiser-guile-load-path "~/src/git/guix"))
1555#+end_src
1556
1557** guix
1558
1559#+begin_src emacs-lisp
1560(use-package guix
1561 :load-path "lib/guix/elisp")
1562#+end_src
1563
673d5faa
AB
1564* Emacs enhancements
1565:PROPERTIES:
1566:CUSTOM_ID: emacs-enhancements
1567:END:
5fece105 1568
5fece105
AB
1569** [[https://github.com/justbur/emacs-which-key][which-key]]
1570
1571#+begin_quote
1572Emacs package that displays available keybindings in popup
1573#+end_quote
1574
1575#+begin_src emacs-lisp
1576(use-package which-key
1577 :defer 1
1578 :config (which-key-mode))
1579#+end_src
1580
1581** theme
1582
1583#+begin_src emacs-lisp
1584(add-to-list 'custom-theme-load-path "~/.emacs.d/lisp")
1585(load-theme 'tangomod t)
1586#+end_src
1587
21ad71fa 1588** smart-mode-line
5fece105
AB
1589
1590#+begin_src emacs-lisp
21ad71fa
AB
1591(use-package smart-mode-line
1592 :config
1593 (sml/setup))
5fece105
AB
1594#+end_src
1595
1596** doom-themes
1597
1598#+begin_src emacs-lisp
1599(use-package doom-themes)
1600#+end_src
1601
1602** theme helper functions
1603
1604#+begin_src emacs-lisp
c5d8bb25 1605(defun a/lights-on ()
5fece105
AB
1606 "Enable my favourite light theme."
1607 (interactive)
21ad71fa
AB
1608 (mapc #'disable-theme custom-enabled-themes)
1609 (load-theme 'tangomod t)
1610 (sml/apply-theme 'automatic))
5fece105 1611
c5d8bb25 1612(defun a/lights-off ()
5fece105
AB
1613 "Go dark."
1614 (interactive)
21ad71fa
AB
1615 (mapc #'disable-theme custom-enabled-themes)
1616 (load-theme 'doom-tomorrow-night t)
1617 (sml/apply-theme 'automatic))
5fece105
AB
1618
1619(bind-keys
c5d8bb25
AB
1620 ("s-t d" . a/lights-off)
1621 ("s-t l" . a/lights-on))
5fece105
AB
1622#+end_src
1623
1624** [[https://github.com/bbatsov/crux][crux]]
1625
1626#+begin_src emacs-lisp
1627(use-package crux
1628 :defer 1
1629 :bind (("C-c b k" . crux-kill-other-buffers)
1630 ("C-c d" . crux-duplicate-current-line-or-region)
1631 ("C-c D" . crux-duplicate-and-comment-current-line-or-region)
1632 ("C-c f c" . crux-copy-file-preserve-attributes)
1633 ("C-c f d" . crux-delete-file-and-buffer)
1634 ("C-c f r" . crux-rename-file-and-buffer)
1635 ("C-c j" . crux-top-join-line)
1636 ("C-S-j" . crux-top-join-line)))
1637#+end_src
1638
1639** [[https://github.com/alezost/mwim.el][mwim]]
1640
1641#+begin_src emacs-lisp
1642(use-package mwim
1643 :bind (("C-a" . mwim-beginning-of-code-or-line)
1644 ("C-e" . mwim-end-of-code-or-line)
1645 ("<home>" . mwim-beginning-of-line-or-code)
1646 ("<end>" . mwim-end-of-line-or-code)))
1647#+end_src
1648
1649** projectile
1650
1651#+begin_src emacs-lisp
1652(use-package projectile
1653 :defer t
1654 :bind-keymap ("C-c p" . projectile-command-map)
1655 :config
1656 (projectile-mode)
1657
1658 (defun my-projectile-invalidate-cache (&rest _args)
1659 ;; ignore the args to `magit-checkout'
1660 (projectile-invalidate-cache nil))
1661
1662 (eval-after-load 'magit-branch
1663 '(progn
1664 (advice-add 'magit-checkout
1665 :after #'my-projectile-invalidate-cache)
1666 (advice-add 'magit-branch-and-checkout
c371adda
AB
1667 :after #'my-projectile-invalidate-cache)))
1668 :custom (projectile-completion-system 'ivy))
5fece105
AB
1669#+end_src
1670
1671** [[https://github.com/Wilfred/helpful][helpful]]
1672
1673#+begin_src emacs-lisp
1674(use-package helpful
1675 :defer 1
1676 :bind
1677 (("C-S-h c" . helpful-command)
1678 ("C-S-h f" . helpful-callable) ; helpful-function
1679 ("C-S-h v" . helpful-variable)
1680 ("C-S-h k" . helpful-key)
1681 ("C-S-h p" . helpful-at-point)))
1682#+end_src
1683
5fece105
AB
1684** [[https://github.com/EricCrosson/unkillable-scratch][unkillable-scratch]]
1685
1686Make =*scratch*= and =*Messages*= unkillable.
1687
1688#+begin_src emacs-lisp
1689(use-package unkillable-scratch
1690 :defer 3
1691 :config
1692 (unkillable-scratch 1)
1693 :custom
1694 (unkillable-scratch-behavior 'do-nothing)
1695 (unkillable-buffers '("^\\*scratch\\*$" "^\\*Messages\\*$")))
1696#+end_src
1697
1698** [[https://github.com/davep/boxquote.el][boxquote.el]]
1699
1700#+begin_example
1701,----
1702| make pretty boxed quotes like this
1703`----
1704#+end_example
1705
1706#+begin_src emacs-lisp
1707(use-package boxquote
1708 :defer 3
1709 :bind
c5d8bb25 1710 (:prefix-map a/boxquote-prefix-map
5fece105
AB
1711 :prefix "C-c q"
1712 ("b" . boxquote-buffer)
1713 ("B" . boxquote-insert-buffer)
1714 ("d" . boxquote-defun)
1715 ("F" . boxquote-insert-file)
1716 ("hf" . boxquote-describe-function)
1717 ("hk" . boxquote-describe-key)
1718 ("hv" . boxquote-describe-variable)
1719 ("hw" . boxquote-where-is)
1720 ("k" . boxquote-kill)
1721 ("p" . boxquote-paragraph)
1722 ("q" . boxquote-boxquote)
1723 ("r" . boxquote-region)
1724 ("s" . boxquote-shell-command)
1725 ("t" . boxquote-text)
1726 ("T" . boxquote-title)
1727 ("u" . boxquote-unbox)
1728 ("U" . boxquote-unbox-region)
1729 ("y" . boxquote-yank)
1730 ("M-q" . boxquote-fill-paragraph)
1731 ("M-w" . boxquote-kill-ring-save)))
1732#+end_src
1733
1734Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
1735
5fece105
AB
1736** typo.el
1737
1738#+begin_src emacs-lisp
1739(use-package typo
1740 :defer 2
1741 :config
1742 (typo-global-mode 1)
1743 :hook (text-mode . typo-mode))
1744#+end_src
1745
1746** hl-todo
1747
1748#+begin_src emacs-lisp
1749(use-package hl-todo
1750 :defer 4
1751 :config
1752 (global-hl-todo-mode))
1753#+end_src
1754
1755** shrink-path
1756
1757#+begin_src emacs-lisp
1758(use-package shrink-path
1759 :after eshell
1760 :config
1761 (setq eshell-prompt-regexp "\\(.*\n\\)*λ "
1762 eshell-prompt-function #'+eshell/prompt)
1763
1764 (defun +eshell/prompt ()
1765 (let ((base/dir (shrink-path-prompt default-directory)))
1766 (concat (propertize (car base/dir)
1767 'face 'font-lock-comment-face)
1768 (propertize (cdr base/dir)
1769 'face 'font-lock-constant-face)
1770 (propertize (+eshell--current-git-branch)
1771 'face 'font-lock-function-name-face)
1772 "\n"
1773 (propertize "λ" 'face 'eshell-prompt-face)
1774 ;; needed for the input text to not have prompt face
1775 (propertize " " 'face 'default))))
1776
1777 (defun +eshell--current-git-branch ()
1778 (let ((branch (car (loop for match in (split-string (shell-command-to-string "git branch") "\n")
1779 when (string-match "^\*" match)
1780 collect match))))
1781 (if (not (eq branch nil))
1782 (concat " " (substring branch 2))
1783 ""))))
1784#+end_src
1785
5fece105
AB
1786** [[https://github.com/peterwvj/eshell-up][eshell-up]]
1787
1788#+begin_src emacs-lisp
1789(use-package eshell-up
1790 :after eshell)
1791#+end_src
1792
1793** multi-term
1794
1795#+begin_src emacs-lisp
1796(use-package multi-term
1797 :defer 1
a219024e
AB
1798 :bind (("C-c a s m m" . multi-term)
1799 ("C-c a s m p" . multi-term-dedicated-toggle)
1800 :map term-mode-map
1801 ("C-c C-j" . term-char-mode)
1802 :map term-raw-map
1803 ("C-c C-j" . term-line-mode))
5fece105
AB
1804 :config
1805 (setq multi-term-program "/bin/screen"
1806 ;; TODO: add separate bindings for connecting to existing
1807 ;; session vs. always creating a new one
1808 multi-term-dedicated-select-after-open-p t
1809 multi-term-dedicated-window-height 20
1810 multi-term-dedicated-max-window-height 30
1811 term-bind-key-alist
1812 '(("C-c C-c" . term-interrupt-subjob)
1813 ("C-c C-e" . term-send-esc)
1814 ("C-k" . kill-line)
1815 ("C-y" . term-paste)
1816 ("M-f" . term-send-forward-word)
1817 ("M-b" . term-send-backward-word)
1818 ("M-p" . term-send-up)
1819 ("M-n" . term-send-down)
1820 ("<C-backspace>" . term-send-backward-kill-word)
1821 ("<M-DEL>" . term-send-backward-kill-word)
1822 ("M-d" . term-send-delete-word)
1823 ("M-," . term-send-raw)
1824 ("M-." . comint-dynamic-complete))
1825 term-unbind-key-alist
1826 '("C-z" "C-x" "C-c" "C-h" "C-y" "<ESC>")))
1827#+end_src
1828
1829** page-break-lines
1830
1831#+begin_src emacs-lisp
1832(use-package page-break-lines
1833 :config
1834 (global-page-break-lines-mode))
1835#+end_src
1836
f2a57944
AB
1837** expand-region
1838
1839#+begin_src emacs-lisp
1840(use-package expand-region
1841 :bind ("C-=" . er/expand-region))
1842#+end_src
1843
5fece105 1844* Email
673d5faa
AB
1845:PROPERTIES:
1846:CUSTOM_ID: email
1847:END:
5fece105 1848
5fece105 1849#+begin_src emacs-lisp
c5d8bb25 1850(defvar a/maildir (expand-file-name "~/mail/"))
ab6781dd 1851(with-eval-after-load 'recentf
c5d8bb25 1852 (add-to-list 'recentf-exclude a/maildir))
5fece105
AB
1853#+end_src
1854
1855** Gnus
1856
1857#+begin_src emacs-lisp
1858(setq
c5d8bb25
AB
1859 a/gnus-init-file (no-littering-expand-etc-file-name "gnus")
1860 mail-user-agent 'gnus-user-agent
1861 read-mail-command 'gnus)
5fece105
AB
1862
1863(use-package gnus
a0801748
AB
1864 :bind (("C-c m" . gnus)
1865 ("C-c M" . gnus-unplugged)
1866 ("s-m" . gnus)
1867 ("s-M" . gnus-unplugged))
5fece105
AB
1868 :init
1869 (setq
1870 gnus-select-method '(nnnil "")
1871 gnus-secondary-select-methods
1872 '((nnimap "amin"
1873 (nnimap-stream plain)
1874 (nnimap-address "127.0.0.1")
1875 (nnimap-server-port 143)
1876 (nnimap-authenticator plain)
1877 (nnimap-user "amin@aminb.org"))
1878 (nnimap "uwaterloo"
1879 (nnimap-stream plain)
1880 (nnimap-address "127.0.0.1")
1881 (nnimap-server-port 143)
1882 (nnimap-authenticator plain)
1883 (nnimap-user "abandali@uwaterloo.ca")))
1884 gnus-message-archive-group "nnimap+amin:Sent"
1885 gnus-parameters
1886 '(("gnu.*"
1887 (gcc-self . t)))
1888 gnus-large-newsgroup 50
1889 gnus-home-directory (no-littering-expand-var-file-name "gnus/")
1890 gnus-directory (concat gnus-home-directory "news/")
1891 message-directory (concat gnus-home-directory "mail/")
1892 nndraft-directory (concat gnus-home-directory "drafts/")
1893 gnus-save-newsrc-file nil
1894 gnus-read-newsrc-file nil
1895 gnus-interactive-exit nil
1896 gnus-gcc-mark-as-read t))
1897
1898(use-package gnus-art
1899 :config
1900 (setq
1901 gnus-visible-headers
1902 (concat gnus-visible-headers "\\|^List-Id:\\|^X-RT-Originator:\\|^User-Agent:")
1903 gnus-sorted-header-list
1904 '("^From:" "^Subject:" "^Summary:" "^Keywords:"
1905 "^Followup-To:" "^To:" "^Cc:" "X-RT-Originator"
1906 "^Newsgroups:" "List-Id:" "^Organization:"
1907 "^User-Agent:" "^Date:")
1908 ;; local-lapsed article dates
1909 ;; from https://www.emacswiki.org/emacs/GnusFormatting#toc11
1910 gnus-article-date-headers '(user-defined)
1911 gnus-article-time-format
1912 (lambda (time)
1913 (let* ((date (format-time-string "%a, %d %b %Y %T %z" time))
1914 (local (article-make-date-line date 'local))
1915 (combined-lapsed (article-make-date-line date
1916 'combined-lapsed))
1917 (lapsed (progn
1918 (string-match " (.+" combined-lapsed)
1919 (match-string 0 combined-lapsed))))
1920 (concat local lapsed))))
1921 (bind-keys
1922 :map gnus-article-mode-map
1923 ("r" . gnus-article-reply-with-original)
1924 ("R" . gnus-article-wide-reply-with-original)
1925 ("M-L" . org-store-link)))
1926
1927(use-package gnus-sum
1928 :bind (:map gnus-summary-mode-map
c5d8bb25 1929 :prefix-map a/gnus-summary-prefix-map
5fece105
AB
1930 :prefix "v"
1931 ("r" . gnus-summary-reply)
1932 ("w" . gnus-summary-wide-reply)
1933 ("v" . gnus-summary-show-raw-article))
1934 :config
1935 (bind-keys
1936 :map gnus-summary-mode-map
1937 ("r" . gnus-summary-reply-with-original)
1938 ("R" . gnus-summary-wide-reply-with-original)
1939 ("M-L" . org-store-link))
c5d8bb25 1940 :hook (gnus-summary-mode . a/no-mouse-autoselect-window))
5fece105
AB
1941
1942(use-package gnus-msg
1943 :config
1944 (setq gnus-posting-styles
1945 '((".*"
1946 (address "amin@aminb.org")
1947 (body "\nBest,\namin\n")
c5d8bb25 1948 (eval (setq a/message-cite-say-hi t)))
5fece105
AB
1949 ("gnu.*"
1950 (address "bandali@gnu.org"))
1951 ((header "subject" "ThankCRM")
1952 (to "webmasters-comment@gnu.org")
1953 (body "\nAdded to 2018supporters.html.\n\nMoving to campaigns.\n\n-amin\n")
c5d8bb25 1954 (eval (setq a/message-cite-say-hi nil)))
5fece105
AB
1955 ("nnimap\\+uwaterloo:.*"
1956 (address "abandali@uwaterloo.ca")
1957 (gcc "\"nnimap+uwaterloo:Sent Items\"")))))
1958
1959(use-package gnus-topic
1960 :hook (gnus-group-mode . gnus-topic-mode))
1961
1962(use-package gnus-agent
1963 :config
1964 (setq gnus-agent-synchronize-flags 'ask)
1965 :hook (gnus-group-mode . gnus-agent-mode))
1966
1967(use-package gnus-group
1968 :config
1969 (setq gnus-permanently-visible-groups "\\((INBOX\\|gnu$\\)"))
1970
1971(use-package mm-decode
1972 :config
1973 (setq mm-discouraged-alternatives '("text/html" "text/richtext")))
1974#+end_src
1975
1976** sendmail
1977
1978#+begin_src emacs-lisp
1979(use-package sendmail
1980 :config
1981 (setq sendmail-program "/usr/bin/msmtp"
1982 ;; message-sendmail-extra-arguments '("-v" "-d")
1983 mail-specify-envelope-from t
1984 mail-envelope-from 'header))
1985#+end_src
1986
1987** message
1988
1989#+begin_src emacs-lisp
1990(use-package message
1991 :config
c5d8bb25 1992 (defconst a/message-cite-style-format "On %Y-%m-%d %l:%M %p, %N wrote:")
5fece105
AB
1993 (defconst message-cite-style-bandali
1994 '((message-cite-function 'message-cite-original)
1995 (message-citation-line-function 'message-insert-formatted-citation-line)
1996 (message-cite-reply-position 'traditional)
1997 (message-yank-prefix "> ")
1998 (message-yank-cited-prefix ">")
1999 (message-yank-empty-prefix ">")
2000 (message-citation-line-format
c5d8bb25
AB
2001 (if a/message-cite-say-hi
2002 (concat "Hi %F,\n\n" a/message-cite-style-format)
2003 a/message-cite-style-format)))
5fece105
AB
2004 "Citation style based on Mozilla Thunderbird's. Use with message-cite-style.")
2005 (setq message-cite-style 'message-cite-style-bandali
2006 message-kill-buffer-on-exit t
2007 message-send-mail-function 'message-send-mail-with-sendmail
2008 message-sendmail-envelope-from 'header
2009 message-dont-reply-to-names
2010 "\\(\\(.*@aminb\\.org\\)\\|\\(amin@bandali\\.me\\)\\|\\(\\(aminb?\\|mab\\|bandali\\)@gnu\\.org\\)\\|\\(\\(m\\|a\\(min\\.\\)?\\)bandali@uwaterloo\\.ca\\)\\)"
2011 message-user-fqdn "aminb.org")
2012 :hook (;; (message-setup . mml-secure-message-sign-pgpmime)
2013 (message-mode . flyspell-mode)
2014 (message-mode . (lambda ()
2015 ;; (setq fill-column 65
2016 ;; message-fill-column 65)
2017 (make-local-variable 'company-idle-delay)
2018 (setq company-idle-delay 0.2))))
2019 ;; :custom-face
2020 ;; (message-header-subject ((t (:foreground "#111" :weight semi-bold))))
2021 ;; (message-header-to ((t (:foreground "#111" :weight normal))))
2022 ;; (message-header-cc ((t (:foreground "#333" :weight normal))))
2023 )
2024
ab6781dd 2025(with-eval-after-load 'mml-sec
5fece105
AB
2026 (setq mml-secure-openpgp-encrypt-to-self t
2027 mml-secure-openpgp-sign-with-sender t))
2028#+end_src
2029
2030** footnote
2031
2032Convenient footnotes in =message-mode=.
2033
2034#+begin_src emacs-lisp
2035(use-package footnote
2036 :after message
2037 :bind
2038 (:map message-mode-map
c5d8bb25 2039 :prefix-map a/footnote-prefix-map
5fece105
AB
2040 :prefix "C-c f"
2041 ("a" . footnote-add-footnote)
2042 ("b" . footnote-back-to-message)
2043 ("c" . footnote-cycle-style)
2044 ("d" . footnote-delete-footnote)
2045 ("g" . footnote-goto-footnote)
2046 ("r" . footnote-renumber-footnotes)
2047 ("s" . footnote-set-style))
2048 :config
2049 (setq footnote-start-tag ""
2050 footnote-end-tag ""
2051 footnote-style 'unicode))
2052#+end_src
2053
490554d3
AB
2054** ebdb
2055
2056#+begin_src emacs-lisp
2057(use-package ebdb
2058 :defer 1
2059 :bind (:map gnus-group-mode-map ("e" . ebdb))
2060 :config
2061 (setq ebdb-sources (no-littering-expand-var-file-name "ebdb"))
ab6781dd 2062 (with-eval-after-load 'swiper
490554d3
AB
2063 (add-to-list 'swiper-font-lock-exclude 'ebdb-mode t)))
2064
2065(use-package ebdb-com
2066 :after ebdb)
2067
2068;; (use-package ebdb-complete
2069;; :after ebdb
2070;; :config
2071;; (ebdb-complete-enable))
2072
2073(use-package company-ebdb
2074 :after (:all company message)
2075 :config
2076 (defun company-ebdb--post-complete (_) nil)
2077 :hook
2078 (message-mode . (lambda ()
2079 (add-to-list (make-local-variable 'company-backends)
2080 'company-ebdb))))
2081
2082(use-package ebdb-gnus
2083 :after ebdb
2084 :custom
2085 (ebdb-gnus-window-configuration
2086 '(article
2087 (vertical 1.0
2088 (summary 0.25 point)
2089 (horizontal 1.0
2090 (article 1.0)
2091 (ebdb-gnus 0.3))))))
2092
2093(use-package ebdb-mua
2094 :after ebdb
2095 ;; :custom (ebdb-mua-pop-up nil)
2096 )
2097
2098;; (use-package ebdb-message
2099;; :after ebdb)
2100
2101
2102;; (use-package ebdb-vcard
2103;; :after ebdb)
2104#+end_src
2105
9cebbd53 2106** COMMENT message-x
5fece105
AB
2107
2108#+begin_src emacs-lisp
2109(use-package message-x
5fece105
AB
2110 :custom
2111 (message-x-completion-alist
2112 (quote
2113 (("\\([rR]esent-\\|[rR]eply-\\)?[tT]o:\\|[bB]?[cC][cC]:" . gnus-harvest-find-address)
2114 ((if
2115 (boundp
2116 (quote message-newgroups-header-regexp))
2117 message-newgroups-header-regexp message-newsgroups-header-regexp)
2118 . message-expand-group)))))
2119#+end_src
2120
9cebbd53 2121** COMMENT gnus-harvest
5fece105
AB
2122
2123#+begin_src emacs-lisp
2124(use-package gnus-harvest
5fece105
AB
2125 :commands gnus-harvest-install
2126 :demand t
2127 :config
2128 (if (featurep 'message-x)
2129 (gnus-harvest-install 'message-x)
2130 (gnus-harvest-install)))
2131#+end_src
2132
2133* Blogging
673d5faa
AB
2134:PROPERTIES:
2135:CUSTOM_ID: blogging
2136:END:
5fece105 2137
5fece105
AB
2138** [[https://ox-hugo.scripter.co][ox-hugo]]
2139
2140#+begin_src emacs-lisp
2141(use-package ox-hugo
2142 :after ox)
2143
2144(use-package ox-hugo-auto-export
2145 :load-path "lib/ox-hugo")
2146#+end_src
2147
2148* Post initialization
2149:PROPERTIES:
2150:CUSTOM_ID: post-initialization
2151:END:
2152
5fece105
AB
2153Display how long it took to load the init file.
2154
2155#+begin_src emacs-lisp
2156(message "Loading %s...done (%.3fs)" user-init-file
2157 (float-time (time-subtract (current-time)
c5d8bb25 2158 a/before-user-init-time)))
5fece105
AB
2159#+end_src
2160
2161* Footer
2162:PROPERTIES:
2163:CUSTOM_ID: footer
2164:END:
2165
2166#+begin_src emacs-lisp :comments none
2167;;; init.el ends here
2168#+end_src
2169
2170* COMMENT Local Variables :ARCHIVE:
2171# Local Variables:
c5d8bb25 2172# eval: (add-hook 'after-save-hook #'a/async-babel-tangle 'append 'local)
6b569be8 2173# eval: (typo-mode -1)
5fece105 2174# End: