: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.
+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.
** 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:
+then tangle =init.org= into =init.el=, and optionally byte-compile
+=init.el=.
+
+First, clone the repository and =cd= into it:
#+begin_src sh :tangle no
-git clone https://github.com/aminb/dotfiles ~/.emacs.d
+git clone https://git.sr.ht/~bandali/dotfiles ~/.emacs.d
cd ~/.emacs.d
-make bootstrap-borg
-make bootstrap
-make build
#+end_src
+Then, decide if you would like to use a byte-compiled init file, and
+set the following variable accordingly:
+
+#+begin_src emacs-lisp
+(defvar a/byte-compiled-init t
+ "If non-nil, byte-(re)compile init.el on successful tangles.")
+#+end_src
+
+Now, first tangle =init.org=, and only if you chose to have a
+byte-compiled init, build init as well:
+
+#+begin_src sh :tangle no
+make tangle-init
+make build-init
+#+end_src
+
+If you'd like to use a byte-compiled init, it's important that it be
+recompiled whenever =init.el= is generated from an updated =init.org=.
+Not only does my setup automatically and asynchronously tangle
+=init.org= to =init.el= every time you edit and save =init.org= in GNU
+Emacs, it will also invoke =make build-init= if you set
+=a/byte-compiled-init= to =t= above, so you wouldn't have to worry
+about manually tangling and compiling your init file whenever you
+change it. The output of the last byte-compilation in the current
+session is kept in a =*compilation*= buffer, which will automatically
+be displayed if compilation fails.
+
* Contents :toc_1:noexport:
- [[#about][About]]
=straight.el= allows me to have a fully reproducible Emacs setup.
#+begin_src emacs-lisp
-(setq straight-repository-branch "develop")
+;; Main engine start...
+
+(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...
+
+(defun a/build-init ()
+ (a/bootstrap-straight)
+ (byte-compile-file "init.el"))
-(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))
+(a/bootstrap-straight)
+
+;; We have lift off!
(setq straight-use-package-by-default t)
#+end_src
(declare (indent defun))
`(use-package ,name
:straight nil
-,@args))
-#+end_src
-
-*** COMMENT Borg
-
-#+begin_quote
-Assimilate Emacs packages as Git submodules
-#+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.
-
-#+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))
-(require 'borg)
-(borg-initialize)
-
-;; (require 'borg-nix-shell)
-;; (setq borg-build-shell-command 'borg-nix-shell-build-command)
-
-(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)))
+ ,@args))
#+end_src
*** =use-package=
#+begin_src emacs-lisp
(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
- use-package-compute-statistics t
- debug-on-error t)
+(if nil ; set to t when need to debug init
+ (progn
+ (setq use-package-verbose t
+ use-package-expand-minimally nil
+ use-package-compute-statistics t
+ debug-on-error t)
+ (require 'use-package))
(setq use-package-verbose nil
use-package-expand-minimally t))
+
+(setq use-package-always-defer t)
#+end_src
-*** COMMENT Epkg
+*** Epkg
#+begin_quote
Browse the Emacsmirror package database
=package.el=-like user interface for browsing the available packages.
#+begin_src emacs-lisp
+(require 'bind-key)
(use-package epkg
- :defer t
+ :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
(use-package exec-path-from-shell
:defer 1
:init
- (setq exec-path-from-shell-check-startup-files nil)
+ (setq exec-path-from-shell-arguments nil
+ exec-path-from-shell-check-startup-files nil)
:config
(exec-path-from-shell-initialize)
;; while we're at it, let's fix access to our running ssh-agent
#+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)
(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
- :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
+ (when a/byte-compiled-init "make build-init")
"If non-nil, pass to `compile' after successful tangle.")
+ ;; TODO: look into why directly byte-compiling init.el causes a
+ ;; number of problems, including magit-status not loading (busy
+ ;; waiting).
+ (defvar a/async-tangle-byte-recompile nil
+ "If non-nil, byte-recompile the file on successful tangle.")
+
(defun a/async-babel-tangle ()
"Tangle org file asynchronously."
(interactive)
(file (buffer-file-name))
(file-nodir (file-name-nondirectory file))
;; (async-quiet-switch "-q")
- )
+ (file-noext (file-name-sans-extension file)))
(async-start
`(lambda ()
(require 'org)
`(lambda (result)
(if result
(progn
+ ;; (setq byte-compile-warnings '(not noruntime unresolved))
(message "Tangled %s%s"
,file-nodir
(if a/show-async-tangle-time
',file-tangle-start-time)))
""))
(when a/async-tangle-post-compile
- (compile a/async-tangle-post-compile)))
+ (compile a/async-tangle-post-compile))
+ (when a/async-tangle-byte-recompile
+ (byte-recompile-file (concat ,file-noext ".el"))))
(message "Tangling %s failed" ,file-nodir))))))))
(add-to-list
#+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))
(setq recentf-max-saved-items 40))
#+end_src
+*** smex
+
+#+begin_quote
+A smart M-x enhancement for Emacs.
+#+end_quote
+
+Mostly because =counsel= needs it to remember history.
+
+#+begin_src emacs-lisp
+(use-package smex)
+#+end_src
+
*** [[https://github.com/abo-abo/swiper][Ivy]] (and friends)
#+begin_quote
#+begin_src emacs-lisp
(use-feature eshell
- :defer 1
+ :defer 2
:commands eshell
:bind ("C-c a s e" . eshell)
:config
#+begin_src emacs-lisp
(use-feature ibuffer
- :defer t
:bind
(("C-x C-b" . ibuffer-other-window)
:map ibuffer-mode-map
#+begin_src emacs-lisp
(use-feature outline
- :defer t
:hook (prog-mode . outline-minor-mode)
:bind
(:map
:custom (ls-lisp-dirs-first t))
(use-feature dired
- :defer t
:config
(setq dired-listing-switches "-alh"
ls-lisp-use-insert-directory-program nil)
;; https://oremacs.com/2017/03/18/dired-ediff/
(defun dired-ediff-files ()
(interactive)
+ (require 'dired-aux)
(defvar ediff-after-quit-hook-internal)
(let ((files (dired-get-marked-files))
(wnd (current-window-configuration)))
(set-window-configuration wnd))))
(error "no more than 2 files should be marked"))))
:bind (:map dired-mode-map
+ ("b" . dired-up-directory)
("e" . dired-ediff-files)
("E" . dired-toggle-read-only)
("\\" . dired-hide-details-mode)
#+begin_src emacs-lisp
(use-feature help
- :defer t
:config
(temp-buffer-resize-mode)
(setq help-window-select t))
#+begin_src emacs-lisp
(use-feature tramp
- :defer t
:config
(add-to-list 'tramp-default-proxies-alist '(nil "\\`root\\'" "/ssh:%h:"))
(add-to-list 'tramp-default-proxies-alist '("localhost" nil nil))
#+begin_src emacs-lisp
(use-package dash
- :defer t
:config (dash-enable-font-lock))
#+end_src
#+begin_src emacs-lisp
(use-feature paren
+ :demand
:config (show-paren-mode))
#+end_src
+** simple (for column numbers)
+
+#+begin_src emacs-lisp
+(use-feature simple
+ :config (column-number-mode))
+#+end_src
+
** =savehist=
Save minibuffer history.
#+begin_src emacs-lisp
(use-package company
- :defer 1
+ :defer 3
:bind
(:map company-active-map
([tab] . company-complete-common-or-cycle)
#+begin_src emacs-lisp
(use-package alloy-mode
:straight (:host github :repo "dwwmmn/alloy-mode")
- :defer t
: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-general
- :defer t)
+(use-package proof-site ; Proof General
+ :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 haskell-mode
- :defer t
:config
(setq haskell-indentation-layout-offset 4
haskell-indentation-left-offset 4
#+begin_src emacs-lisp
(use-package sgml-mode
- :defer t
:config
(setq sgml-basic-offset 2))
#+end_src
#+begin_src emacs-lisp
(use-package css-mode
- :defer t
:config
(setq css-indent-offset 2))
#+end_src
#+begin_src emacs-lisp
(use-package web-mode
- :defer t
:mode "\\.html\\'"
:config
(a/setq-every 2
:after (treemacs))
#+end_src
-** COMMENT geiser
+** geiser
#+begin_src emacs-lisp
(use-package geiser)
(setq geiser-guile-load-path "~/src/git/guix"))
#+end_src
-** COMMENT guix
+** guix
#+begin_src emacs-lisp
(use-package guix)
#+begin_src emacs-lisp
(use-feature man
- :defer t
: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))
#+end_src
** 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)
#+begin_src emacs-lisp
(use-package projectile
- :defer t
:bind-keymap ("C-c p" . projectile-command-map)
:config
(projectile-mode)
#+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
- :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)
#+begin_src emacs-lisp
(use-package ebdb
- :defer 1
+ :straight (:host github :repo "girzel/ebdb")
+ :defer 2
+ :after gnus
:bind (:map gnus-group-mode-map ("e" . ebdb))
:config
(setq ebdb-sources (no-littering-expand-var-file-name "ebdb"))
;; (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-feature ebdb-gnus
+ :defer 3
:after ebdb
+ :demand
:custom
(ebdb-gnus-window-configuration
'(article
(ebdb-gnus 0.3))))))
(use-feature ebdb-mua
+ :defer 3
:after ebdb
+ :demand
;; :custom (ebdb-mua-pop-up nil)
)
(gnus-harvest-install)))
#+end_src
-* COMMENT Blogging
+* Blogging
:PROPERTIES:
:CUSTOM_ID: blogging
:END:
(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
* COMMENT Local Variables :ARCHIVE:
# Local Variables:
-# eval: ;; (add-hook 'after-save-hook #'a/async-babel-tangle 'append 'local)
-# eval: (typo-mode -1)
+# eval: (add-hook 'after-save-hook #'a/async-babel-tangle 'append 'local)
+# eval: (when (featurep 'typo (typo-mode -1)))
# End: