:END:
This org file is my literate configuration for GNU Emacs, and is
- tangled to [[./init.el][init.el]]. Packages are installed and managed using
- [[https://github.com/emacscollective/borg][Borg]]. Over the years, I've taken inspiration from configurations of
- many different people. Some of the configurations that I can remember
- off the top of my head are:
+ tangled to [[./init.el][init.el]]. Packages are installed and managed using
+ [[https://github.com/raxod502/straight.el][straight.el]]. Over the years, I've taken inspiration from
+ configurations of many different people. Some of the configurations
+ that I can remember off the top of my head are:
- [[https://github.com/dieggsy/dotfiles][dieggsy/dotfiles]]: literate Emacs and dotfiles configuration, uses
straight.el for managing packages
I'd like to have a fully reproducible Emacs setup (part of the reason
why I store my configuration in this repository) but unfortunately out
of the box, that's not achievable with =package.el=, not currently
- anyway. So, I've opted to use Borg. For what it's worth, I briefly
- experimented with [[https://github.com/raxod502/straight.el][straight.el]], but found that it added about 2 seconds
- to my init time; which is unacceptable for me: I use Emacs as my
- window manager (via EXWM) and coming from bspwm, I'm too used to
- having fast startup times.
-
- ** Installation
-
- To use this config for your Emacs, first you need to clone this repo,
- then bootstrap Borg, tell Borg to retrieve package submodules, and
- byte-compiled the packages. Something along these lines should work:
-
- #+begin_src sh :tangle no
- git clone https://git.sr.ht/~bandali/dotfiles ~/.emacs.d
- cd ~/.emacs.d
- make bootstrap-borg
- make bootstrap
- #+end_src
+ anyway. So, I've opted to use =straight.el=. I also used Borg for a
+ few months, but decided to try =straight.el= which allows direct use
+ of the various package archives.
* Contents :toc_1:noexport:
*** No =package.el=
- I can do all my package management things with Borg, and don't need
- Emacs' built-in =package.el=. Emacs 27 lets us disable =package.el= in
- the =early-init-file= (see [[https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=24acb31c04b4048b85311d794e600ecd7ce60d3b][here]]).
+ I can do all my package management things with =straight.el=, and
+ don't need Emacs' built-in =package.el=. Emacs 27 lets us disable
+ =package.el= in the =early-init-file= (see [[https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=24acb31c04b4048b85311d794e600ecd7ce60d3b][here]]).
#+begin_src emacs-lisp :tangle early-init.el
(setq package-enable-at-startup nil)
ship in their repos, I'll still put the old workaround with the
commented call to ~package-initialize~ here anyway.
- #+begin_src emacs-lisp
+ #+begin_src emacs-lisp :tangle no
(setq package-enable-at-startup nil)
;; (package-initialize)
#+end_src
- *** Borg
+ Update: the above is not necessary, since =straight.el= automatically
+ does that (and more). See =straight-package-neutering-mode=.
+
+ *** =straight.el=
#+begin_quote
- Assimilate Emacs packages as Git submodules
+ Next-generation, purely functional package manager for the Emacs
+ hacker.
#+end_quote
- [[https://github.com/emacscollective/borg][Borg]] is at the heart of package management of my Emacs setup. In
- short, it creates a git submodule in =lib/= for each package, which
- can then be managed with the help of Magit or other tools.
+ =straight.el= allows me to have a fully reproducible Emacs setup.
#+begin_src emacs-lisp
- (setq user-init-file (or load-file-name buffer-file-name)
- user-emacs-directory (file-name-directory user-init-file))
- (add-to-list 'load-path
- (expand-file-name "lib/borg" user-emacs-directory))
;; Main engine start...
- (require 'borg)
+
+ (setq straight-repository-branch "develop"
+ straight-check-for-modifications '(check-on-save find-when-checking))
+
+ (defun a/bootstrap-straight ()
+ (defvar bootstrap-version)
+ (let ((bootstrap-file
+ (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
+ (bootstrap-version 5))
+ (unless (file-exists-p bootstrap-file)
+ (with-current-buffer
+ (url-retrieve-synchronously
+ "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
+ 'silent 'inhibit-cookies)
+ (goto-char (point-max))
+ (eval-print-last-sexp)))
+ (load bootstrap-file nil 'nomessage)))
+
;; Solid rocket booster ignition...
- (borg-initialize)
+
+ (defun a/build-init ()
+ (a/bootstrap-straight)
+ (byte-compile-file "init.el"))
+
+ (a/bootstrap-straight)
+
;; We have lift off!
- ;; (require 'borg-nix-shell)
- ;; (setq borg-build-shell-command 'borg-nix-shell-build-command)
+ (setq straight-use-package-by-default t)
+ #+end_src
+
+ Since we enable =straight.el='s =straight-use-package-by-default=
+ integration, we will define a =use-feature= for plain ole
+ =use-package= without any of the =straight.el= stuff.
- (with-eval-after-load 'bind-key
- (bind-keys
- :package borg
- ("C-c b A" . borg-activate)
- ("C-c b a" . borg-assimilate)
- ("C-c b b" . borg-build)
- ("C-c b c" . borg-clone)
- ("C-c b r" . borg-remove)))
+ #+begin_src emacs-lisp
+ (defmacro use-feature (name &rest args)
+ "Like `use-package', but with `straight-use-package-by-default' disabled."
+ (declare (indent defun))
+ `(use-package ,name
+ :straight nil
+ ,@args))
#+end_src
*** =use-package=
and without compromising on performance.
#+begin_src emacs-lisp
- (require 'use-package)
+ (straight-use-package 'use-package)
(if nil ; set to t when need to debug init
(setq use-package-verbose t
use-package-expand-minimally nil
=package.el=-like user interface for browsing the available packages.
#+begin_src emacs-lisp
+ (require 'bind-key)
(use-package epkg
+ :commands (epkg-list-packages epkg-describe-package)
:bind
- (("C-c b d" . epkg-describe-package)
- ("C-c b p" . epkg-list-packages)
- ("C-c b u" . epkg-update))
+ (("C-c P e d" . epkg-describe-package)
+ ("C-c P e p" . epkg-list-packages))
:config
+ (setq epkg-repository "~/.emacs.d/straight/repos/epkgs/")
(eval-when-compile (defvar ivy-initial-inputs-alist))
(with-eval-after-load 'ivy
(add-to-list
it it's own file. While at it, treat themes as safe.
#+begin_src emacs-lisp
- (use-package custom
+ (use-feature custom
:no-require t
:config
(setq custom-file (no-littering-expand-etc-file-name "custom.el"))
See [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html#Emacs-Server][Using Emacs as a Server]].
#+begin_src emacs-lisp
- (use-package server
+ (use-feature server
:defer 1
:config (or (server-running-p) (server-mode)))
#+end_src
In short, my favourite way of life.
+ First, we have to resort to a [[https://github.com/raxod502/straight.el#installing-org-with-straightel][hack]] to be able to use the correct
+ latest version of Org from upstream.
+
#+begin_src emacs-lisp
- (use-package org
+ (use-package git)
+
+ (defun org-git-version ()
+ "The Git version of org-mode.
+ Inserted by installing org-mode or when a release is made."
+ (require 'git)
+ (let ((git-repo (expand-file-name
+ "straight/repos/org/" user-emacs-directory)))
+ (string-trim
+ (git-run "describe"
+ "--match=release\*"
+ "--abbrev=6"
+ "HEAD"))))
+
+ (defun org-release ()
+ "The release version of org-mode.
+ Inserted by installing org-mode or when a release is made."
+ (require 'git)
+ (let ((git-repo (expand-file-name
+ "straight/repos/org/" user-emacs-directory)))
+ (string-trim
+ (string-remove-prefix
+ "release_"
+ (git-run "describe"
+ "--match=release\*"
+ "--abbrev=0"
+ "HEAD")))))
+
+ (provide 'org-version)
+ #+end_src
+
+ We will use the =org-plus-contrib= package to get the whole deal:
+
+ #+begin_src emacs-lisp
+ (straight-use-package 'org-plus-contrib)
+ #+end_src
+
+ And here's where my actual Org configurations begin:
+
+ #+begin_src emacs-lisp
+ (use-feature org
- :defer 0.5
+ :defer 2
:config
(setq org-src-tab-acts-natively t
org-src-preserve-indentation nil
org-catch-invisible-edits 'show-and-error
org-log-done 'time)
(add-to-list 'org-structure-template-alist '("L" . "src emacs-lisp") t)
- (font-lock-add-keywords
- 'org-mode
- '(("[ \t]*\\(#\\+\\(BEGIN\\|END\\|begin\\|end\\)_\\(\\S-+\\)\\)[ \t]*\\([^\n:]*\\)"
- (1 '(:foreground "#5a5b5a" :background "#292b2b") t) ; directive
- (3 '(:foreground "#81a2be" :background "#292b2b") t) ; kind
- (4 '(:foreground "#c5c8c6") t))) ; title
- t)
:bind (:map org-mode-map ("M-L" . org-insert-last-stored-link))
:hook ((org-mode . org-indent-mode)
(org-mode . auto-fill-mode)
'(org-block ((t (:background "#1d1f21"))))
'(org-latex-and-related ((t (:foreground "#b294bb")))))
- (use-package ox-latex
+ (use-feature ox-latex
:after ox
:config
(setq org-latex-listings 'listings
;; org-latex-prefer-user-labels t
)
- (add-to-list 'org-latex-packages-alist '("" "listings"))
- (add-to-list 'org-latex-packages-alist '("" "color"))
(add-to-list 'org-latex-classes
'("IEEEtran" "\\documentclass[11pt]{IEEEtran}"
- ("\\section{%s}" . "\\section*{%s}")
- ("\\subsection{%s}" . "\\subsection*{%s}")
+ ("\\section{%s}" . "\\section*{%s}")
+ ("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
- ("\\paragraph{%s}" . "\\paragraph*{%s}")
- ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
- t))
-
-(use-feature ox-beamer
- :demand
- :after ox)
+ ("\\paragraph{%s}" . "\\paragraph*{%s}")
+ ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
+ t)
+ (require 'ox-beamer))
#+end_src
**** asynchronous tangle
(defvar a/show-async-tangle-time nil
"Show the time spent tangling the file.")
- (defvar a/async-tangle-post-compile "make ti"
+ (defvar a/async-tangle-post-compile "make bi"
"If non-nil, pass to `compile' after successful tangle.")
(defvar a/async-tangle-byte-recompile nil
`(lambda (result)
(if result
(progn
- (setq byte-compile-warnings '(not noruntime unresolved))
+ ;; (setq byte-compile-warnings '(not noruntime unresolved))
(message "Tangled %s%s"
,file-nodir
(if a/show-async-tangle-time
#+begin_src emacs-lisp
(use-package magit
- :defer 1
+ :defer 2
:bind (("C-x g" . magit-status)
("s-g s" . magit-status)
("s-g l" . magit-log-buffer-file))
Recently opened files.
#+begin_src emacs-lisp
- (use-package recentf
+ (use-feature recentf
:defer 0.5
:config
(add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?:")
#+begin_src emacs-lisp
(use-package ivy
- :defer 0.5
+ :defer 0.6
:bind
(:map ivy-minibuffer-map
([escape] . keyboard-escape-quit)
#+begin_src emacs-lisp
(use-package counsel
+ :defer 0.6
:after ivy
:bind (([remap execute-extended-command] . counsel-M-x)
([remap find-file] . counsel-find-file)
*** eshell
#+begin_src emacs-lisp
- (use-package eshell
+ (use-feature eshell
- :defer 1
+ :defer 2
:commands eshell
:bind ("C-c a s e" . eshell)
:config
*** Ibuffer
#+begin_src emacs-lisp
- (use-package ibuffer
+ (use-feature ibuffer
:bind
(("C-x C-b" . ibuffer-other-window)
:map ibuffer-mode-map
*** Outline
#+begin_src emacs-lisp
- (use-package outline
+ (use-feature outline
:hook (prog-mode . outline-minor-mode)
:bind
(:map
*** Dired
#+begin_src emacs-lisp
- (use-package ls-lisp
+ (use-feature ls-lisp
:custom (ls-lisp-dirs-first t))
- (use-package dired
+ (use-feature dired
:config
(setq dired-listing-switches "-alh"
ls-lisp-use-insert-directory-program nil)
*** Help
#+begin_src emacs-lisp
- (use-package help
+ (use-feature help
:config
(temp-buffer-resize-mode)
(setq help-window-select t))
*** Tramp
#+begin_src emacs-lisp
- (use-package tramp
+ (use-feature tramp
:config
(add-to-list 'tramp-default-proxies-alist '(nil "\\`root\\'" "/ssh:%h:"))
(add-to-list 'tramp-default-proxies-alist '("localhost" nil nil))
Display Lisp objects at point in the echo area.
#+begin_src emacs-lisp
- (use-package eldoc
+ (use-feature eldoc
:when (version< "25" emacs-version)
:config (global-eldoc-mode))
#+end_src
Highlight matching parens.
#+begin_src emacs-lisp
- (use-package paren
- :demand
+ (use-feature paren
:config (show-paren-mode))
#+end_src
** simple (for column numbers)
#+begin_src emacs-lisp
- (use-package simple
+ (use-feature simple
:config (column-number-mode))
#+end_src
Save minibuffer history.
#+begin_src emacs-lisp
- (use-package savehist
+ (use-feature savehist
:config (savehist-mode))
#+end_src
Automatically save place in each file.
#+begin_src emacs-lisp
- (use-package saveplace
+ (use-feature saveplace
:when (version< "25" emacs-version)
:config (save-place-mode))
#+end_src
** =prog-mode=
#+begin_src emacs-lisp
- (use-package prog-mode
+ (use-feature prog-mode
:config (global-prettify-symbols-mode)
(defun indicate-buffer-boundaries-left ()
(setq indicate-buffer-boundaries 'left))
** =text-mode=
#+begin_src emacs-lisp
- (use-package text-mode
+ (use-feature text-mode
:hook ((text-mode . indicate-buffer-boundaries-left)
(text-mode . abbrev-mode)))
#+end_src
#+begin_src emacs-lisp
(use-package company
- :defer 1
+ :defer 3
:bind
(:map company-active-map
([tab] . company-complete-common-or-cycle)
** Lisp
#+begin_src emacs-lisp
- (use-package lisp-mode
+ (use-feature lisp-mode
:config
(add-hook 'emacs-lisp-mode-hook 'outline-minor-mode)
(add-hook 'emacs-lisp-mode-hook 'reveal-mode)
#+begin_src emacs-lisp
(use-package alloy-mode
+ :straight (:host github :repo "dwwmmn/alloy-mode")
:config (setq alloy-basic-offset 2))
#+end_src
** [[https://coq.inria.fr][Coq]] (with [[https://github.com/ProofGeneral/PG][Proof General]])
#+begin_src emacs-lisp
-(use-package proof-site
+(use-package proof-site ; Proof General
- :load-path "lib/proof-site/generic/")
+ :straight proof-general)
#+end_src
** [[https://leanprover.github.io][Lean]] (with [[https://github.com/leanprover/lean-mode][lean-mode]])
#+begin_src emacs-lisp
(use-package geiser)
- (use-package geiser-guile
+ (use-feature geiser-guile
:config
(setq geiser-guile-load-path "~/src/git/guix"))
#+end_src
** guix
#+begin_src emacs-lisp
- (use-package guix
- :load-path "lib/guix/elisp")
+ (use-package guix)
#+end_src
* Emacs enhancements
** man
#+begin_src emacs-lisp
- (use-package man
+ (use-feature man
:config (setq Man-width 80))
#+end_src
;; prefixes for my personal bindings
"C-c a" "applications"
"C-c a s" "shells"
- "C-c b" "borg"
+ "C-c P" "package-management"
+ "C-c P e" "package-management/epkg"
+ "C-c P s" "package-management/straight.el"
"C-c c" "compile-and-comments"
"C-c e" "eval"
"C-c f" "files"
#+begin_src emacs-lisp
(use-package smart-mode-line
+ :commands (sml/apply-theme)
:demand
:config
(sml/setup))
** theme helper functions
#+begin_src emacs-lisp
+(defvar a/org-mode-font-lock-keywords
+ '(("[ \t]*\\(#\\+\\(BEGIN\\|END\\|begin\\|end\\)_\\(\\S-+\\)\\)[ \t]*\\([^\n:]*\\)"
+ (1 '(:foreground "#5a5b5a" :background "#292b2b") t) ; directive
+ (3 '(:foreground "#81a2be" :background "#292b2b") t) ; kind
+ (4 '(:foreground "#c5c8c6") t)))) ; title
+
(defun a/lights-on ()
"Enable my favourite light theme."
(interactive)
(mapc #'disable-theme custom-enabled-themes)
(load-theme 'tangomod t)
- (sml/apply-theme 'automatic))
+ (sml/apply-theme 'automatic)
+ (font-lock-remove-keywords
+ 'org-mode a/org-mode-font-lock-keywords))
(defun a/lights-off ()
"Go dark."
(interactive)
(mapc #'disable-theme custom-enabled-themes)
(load-theme 'doom-tomorrow-night t)
- (sml/apply-theme 'automatic))
+ (sml/apply-theme 'automatic)
+ (font-lock-add-keywords
+ 'org-mode a/org-mode-font-lock-keywords t))
(bind-keys
("s-t d" . a/lights-off)
** [[https://github.com/bbatsov/crux][crux]]
#+begin_src emacs-lisp
- (use-package crux
+ (use-package crux ; results in Waiting for git... [2 times]
:defer 1
:bind (("C-c b k" . crux-kill-other-buffers)
("C-c d" . crux-duplicate-current-line-or-region)
#+begin_src emacs-lisp
(use-package helpful
- :defer 1
+ :defer 3
:bind
(("C-S-h c" . helpful-command)
("C-S-h f" . helpful-callable) ; helpful-function
:config
(unkillable-scratch 1)
:custom
- (unkillable-scratch-behavior 'do-nothing)
(unkillable-buffers '("^\\*scratch\\*$" "^\\*Messages\\*$")))
#+end_src
#+begin_src emacs-lisp
(use-package shrink-path
:defer 2
+ :after eshell
:config
- (setq eshell-prompt-regexp "\\(.*\n\\)*λ "
- eshell-prompt-function #'+eshell/prompt)
-
(defun +eshell/prompt ()
(let ((base/dir (shrink-path-prompt default-directory)))
(concat (propertize (car base/dir)
collect match))))
(if (not (eq branch nil))
(concat " " (substring branch 2))
- ""))))
+ "")))
+ (setq eshell-prompt-regexp "\\(.*\n\\)*λ "
+ eshell-prompt-function #'+eshell/prompt))
#+end_src
** [[https://github.com/peterwvj/eshell-up][eshell-up]]
#+begin_src emacs-lisp
(use-package eshell-up
- :commands eshell-up
- :after eshell)
+ :after eshell
+ :commands eshell-up)
#+end_src
** multi-term
#+begin_src emacs-lisp
(use-package multi-term
- :defer 1
+ :defer 3
:bind (("C-c a s m" . multi-term-dedicated-toggle)
:map term-mode-map
("C-c C-j" . term-char-mode)
mail-user-agent 'gnus-user-agent
read-mail-command 'gnus)
- (use-package gnus
+ (use-feature gnus
:bind (("s-m" . gnus)
("s-M" . gnus-unplugged))
:init
gnus-interactive-exit nil
gnus-gcc-mark-as-read t))
- (use-package gnus-art
+ (use-feature gnus-art
:config
(setq
gnus-visible-headers
("R" . gnus-article-wide-reply-with-original)
("M-L" . org-store-link)))
- (use-package gnus-sum
+ (use-feature gnus-sum
:bind (:map gnus-summary-mode-map
:prefix-map a/gnus-summary-prefix-map
:prefix "v"
("M-L" . org-store-link))
:hook (gnus-summary-mode . a/no-mouse-autoselect-window))
- (use-package gnus-msg
+ (use-feature gnus-msg
:config
(setq gnus-posting-styles
'((".*"
(address "abandali@uwaterloo.ca")
(gcc "\"nnimap+uwaterloo:Sent Items\"")))))
- (use-package gnus-topic
+ (use-feature gnus-topic
:hook (gnus-group-mode . gnus-topic-mode))
- (use-package gnus-agent
+ (use-feature gnus-agent
:config
(setq gnus-agent-synchronize-flags 'ask)
:hook (gnus-group-mode . gnus-agent-mode))
- (use-package gnus-group
+ (use-feature gnus-group
:config
(setq gnus-permanently-visible-groups "\\((INBOX\\|gnu$\\)"))
- (use-package mm-decode
+ (use-feature mm-decode
:config
(setq mm-discouraged-alternatives '("text/html" "text/richtext")))
#+end_src
** sendmail
#+begin_src emacs-lisp
- (use-package sendmail
+ (use-feature sendmail
:config
(setq sendmail-program "/usr/bin/msmtp"
;; message-sendmail-extra-arguments '("-v" "-d")
** message
#+begin_src emacs-lisp
- (use-package message
+ (use-feature message
:config
(defconst a/message-cite-style-format "On %Y-%m-%d %l:%M %p, %N wrote:")
(defconst message-cite-style-bandali
Convenient footnotes in =message-mode=.
#+begin_src emacs-lisp
- (use-package footnote
+ (use-feature footnote
:after message
:bind
(:map message-mode-map
#+begin_src emacs-lisp
(use-package ebdb
+ :straight (:host github :repo "girzel/ebdb")
+ :defer 2
:after gnus
:bind (:map gnus-group-mode-map ("e" . ebdb))
:config
(with-eval-after-load 'swiper
(add-to-list 'swiper-font-lock-exclude 'ebdb-mode t)))
- (use-package ebdb-com
+ (use-feature ebdb-com
:after ebdb)
;; (use-package ebdb-complete
;; (ebdb-complete-enable))
(use-package company-ebdb
- :after (:all company message)
+ :defer 2
:config
- (defun company-ebdb--post-complete (_) nil)
- :hook
- (message-mode . (lambda ()
- (add-to-list (make-local-variable 'company-backends)
- 'company-ebdb))))
+ (defun company-ebdb--post-complete (_) nil))
- (use-package ebdb-gnus
+ (use-feature ebdb-gnus
+ :defer 3
:after ebdb
+ :demand
:custom
(ebdb-gnus-window-configuration
'(article
(article 1.0)
(ebdb-gnus 0.3))))))
- (use-package ebdb-mua
+ (use-feature ebdb-mua
+ :defer 3
:after ebdb
+ :demand
;; :custom (ebdb-mua-pop-up nil)
)
(use-package ox-hugo
:after ox)
- (use-package ox-hugo-auto-export
- :load-path "lib/ox-hugo")
+ (use-feature ox-hugo-auto-export
+ :after ox-hugo)
#+end_src
* Post initialization