-#+title: =aminb='s Literate Emacs Configuration
+#+title: Literate Emacs Configuration of Amin Bandali
#+author: Amin Bandali
#+babel: :cache yes
#+property: header-args :tangle yes
: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
+:PROPERTIES:
+:CUSTOM_ID: installation
+:END:
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 [[#byte-compiled-init][a/byte-compiled-init]] variable accordingly.
+
+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]]
** License
#+begin_src emacs-lisp :comments none
-;; Copyright (C) 2018 Amin Bandali <bandali@gnu.org>
+;; Copyright (C) 2018-2019 Amin Bandali <bandali@gnu.org>
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
#+begin_src emacs-lisp :comments none
;;; Commentary:
-;; Emacs configuration of Amin Bandali, computer scientist and functional
-;; programmer.
+;; Emacs configuration of Amin Bandali, computer scientist, functional
+;; programmer, and free software advocate.
;; THIS FILE IS AUTO-GENERATED FROM `init.org'.
#+end_src
-** Naming conventions
-
-The conventions below were inspired by [[https://github.com/hlissner/doom-emacs][Doom]]'s, found [[https://github.com/hlissner/doom-emacs/blob/5dacbb7cb1c6ac246a9ccd15e6c4290def67757c/core/core.el#L3-L17][here]].
-
-#+begin_src emacs-lisp :comments none
-;; Naming conventions:
-;;
-;; amin-... public variables or non-interactive functions
-;; amin--... private anything (non-interactive), not safe for direct use
-;; amin/... an interactive function; safe for M-x or keybinding
-;; amin|... a hook function
-;; amin*... an advising function
-;; amin@... a hydra command
-;; ...! a macro
-#+end_src
-
* Initial setup
:PROPERTIES:
:CUSTOM_ID: initial-setup
:END:
+** Byte-compiled init preference
+:PROPERTIES:
+:CUSTOM_ID: byte-compiled-init
+:END:
+
+If you would like a byte-compiled init file, set the following
+variable to ~t~, otherwise set it to ~nil~.
+
+#+begin_src emacs-lisp
+(defvar a/byte-compiled-init t
+ "If non-nil, byte-(re)compile init.el on successful tangles.")
+#+end_src
+
+You can click on [[#installation][Installation]] to jump back up there if you like :)
+
** Emacs initialization
I'd like to do a couple of measurements of Emacs' startup time. First,
=init.el=, i.e. =user-init-file=:
#+begin_src emacs-lisp
-(defvar amin--before-user-init-time (current-time)
+(defvar a/before-user-init-time (current-time)
"Value of `current-time' when Emacs begins loading `user-init-file'.")
(message "Loading Emacs...done (%.3fs)"
- (float-time (time-subtract amin--before-user-init-time
+ (float-time (time-subtract a/before-user-init-time
before-init-time)))
#+end_src
startup time as well.
#+begin_src emacs-lisp
-(defvar amin--gc-cons-threshold gc-cons-threshold)
-(defvar amin--gc-cons-percentage gc-cons-percentage)
-(defvar amin--file-name-handler-alist file-name-handler-alist)
+(defvar a/gc-cons-threshold gc-cons-threshold)
+(defvar a/gc-cons-percentage gc-cons-percentage)
+(defvar a/file-name-handler-alist file-name-handler-alist)
(setq gc-cons-threshold (* 400 1024 1024) ; 400 MiB
gc-cons-percentage 0.6
file-name-handler-alist nil
(add-hook
'after-init-hook
(lambda ()
- (setq gc-cons-threshold amin--gc-cons-threshold
- gc-cons-percentage amin--gc-cons-percentage
- file-name-handler-alist amin--file-name-handler-alist)))
+ (setq gc-cons-threshold a/gc-cons-threshold
+ gc-cons-percentage a/gc-cons-percentage
+ file-name-handler-alist a/file-name-handler-alist)))
#+end_src
Increase the number of lines kept in message logs (the =*Messages*=
#+begin_src emacs-lisp
(setq user-full-name "Amin Bandali"
- user-mail-address "amin@aminb.org")
+ user-mail-address "amin@bndl.org")
#+end_src
** Package management
*** 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))
-(require 'borg)
-(borg-initialize)
+;; Main engine start...
-;; (require 'borg-nix-shell)
-;; (setq borg-build-shell-command 'borg-nix-shell-build-command)
+(setq straight-repository-branch "develop"
+ straight-check-for-modifications '(check-on-save find-when-checking))
-(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)))
+(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"))
+
+(a/bootstrap-straight)
+
+;; We have lift off!
+
+(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.
+
+#+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)
-(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)
+(straight-use-package 'use-package)
+(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)
+(require 'bind-key)
#+end_src
-*** Epkg
+*** COMMENT Epkg
#+begin_quote
Browse the Emacsmirror package database
#+begin_src emacs-lisp
(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
+ 'ivy-initial-inputs-alist '(epkg-describe-package . "^") t)))
#+end_src
** No littering in =~/.emacs.d=
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"))
(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
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
buffers and/or modes.
#+begin_src emacs-lisp
-(defun amin--no-mouse-autoselect-window ()
+(defun a/no-mouse-autoselect-window ()
(make-local-variable 'mouse-autoselect-window)
(setq mouse-autoselect-window nil))
#+end_src
-** Libraries
+** Better scrolling (arguably)
#+begin_src emacs-lisp
-(require 'cl-lib)
-(require 'subr-x)
+(setq ;; scroll-margin 1
+ ;; scroll-conservatively 10000
+ scroll-step 1
+ scroll-conservatively 10
+ scroll-preserve-screen-position 1)
+
+(use-feature mwheel
+ :defer 1
+ :config
+ (setq mouse-wheel-scroll-amount '(1 ((shift) . 1)) ; one line at a time
+ mouse-wheel-progressive-speed nil ; don't accelerate scrolling
+ mouse-wheel-follow-mouse t)) ; scroll window under mouse
+
+(use-feature pixel-scroll
+ :defer 1
+ :config (pixel-scroll-mode 1))
#+end_src
-** Useful utilities
+** Ask for GPG passphrase in minibuffer
#+begin_src emacs-lisp
-(defun amin-enlist (exp)
- "Return EXP wrapped in a list, or as-is if already a list."
-(if (listp exp) exp (list exp)))
+(setq epg-pinentry-mode 'loopback)
+#+end_src
-; from https://github.com/hlissner/doom-emacs/commit/589108fdb270f24a98ba6209f6955fe41530b3ef
-(defmacro after! (features &rest body)
- "A smart wrapper around `with-eval-after-load'. Supresses warnings during
-compilation."
- (declare (indent defun) (debug t))
- (list (if (or (not (bound-and-true-p byte-compile-current-file))
- (dolist (next (amin-enlist features))
- (if (symbolp next)
- (require next nil :no-error)
- (load next :no-message :no-error))))
- #'progn
- #'with-no-warnings)
- (cond ((symbolp features)
- `(eval-after-load ',features '(progn ,@body)))
- ((and (consp features)
- (memq (car features) '(:or :any)))
- `(progn
- ,@(cl-loop for next in (cdr features)
- collect `(after! ,next ,@body))))
- ((and (consp features)
- (memq (car features) '(:and :all)))
- (dolist (next (cdr features))
- (setq body `(after! ,next ,@body)))
- body)
- ((listp features)
- `(after! (:all ,@features) ,@body)))))
+** Libraries
+
+#+begin_src emacs-lisp
+(require 'cl-lib)
+(require 'subr-x)
#+end_src
+** Useful utilities
+
Convenience macro for =setq='ing multiple variables to the same value:
#+begin_src emacs-lisp
-(defmacro setq-every! (value &rest vars)
+(defmacro a/setq-every (value &rest vars)
"Set all the variables from VARS to value VALUE."
(declare (indent defun) (debug t))
`(progn ,@(mapcar (lambda (x) (list 'setq x value)) vars)))
#+end_src
+The following process-related stuff from [[https://github.com/alezost/emacs-config][alezost's emacs-config]].
+
+#+begin_src emacs-lisp
+(defun a/start-process (program &rest args)
+ "Same as `start-process', but doesn't bother about name and buffer."
+ (let ((process-name (concat program "_process"))
+ (buffer-name (generate-new-buffer-name
+ (concat program "_output"))))
+ (apply #'start-process
+ process-name buffer-name program args)))
+
+(defun a/dired-start-process (program &optional args)
+ "Open current file with a PROGRAM."
+ ;; Shell command looks like this: "program [ARGS]... FILE" (ARGS can
+ ;; be nil, so remove it).
+ (apply #'a/start-process
+ program
+ (remove nil (list args (dired-get-file-for-visit)))))
+#+end_src
+
* Core
:PROPERTIES:
:CUSTOM_ID: core
=cl-letf= instead of the now obsolete =flet=.
#+begin_src emacs-lisp
-(use-package compile
- :config
- (defun amin--compilation-finish-function (buffer outstr)
+(with-eval-after-load 'compile
+ (defun a/compilation-finish-function (buffer outstr)
(unless (string-match "finished" outstr)
(switch-to-buffer-other-window buffer))
t)
- (setq compilation-finish-functions #'amin--compilation-finish-function)
+ (setq compilation-finish-functions #'a/compilation-finish-function)
(require 'cl-macs)
;; (setq replace-char-fold t)
#+end_src
+*** Cursor shape
+
+#+begin_src emacs-lisp
+(setq-default cursor-type 'bar)
+#+end_src
+
+*** Allow scrolling in Isearch
+
+#+begin_src emacs-lisp
+(setq isearch-allow-scroll t)
+#+end_src
+
** Bindings
+Some bindings for functions from built-in GNU Emacs packages:
+
#+begin_src emacs-lisp
(bind-keys
("C-c a i" . ielm)
("C-c e b" . eval-buffer)
("C-c e r" . eval-region)
+ ("C-c e i" . emacs-init-time)
+ ("C-c e u" . emacs-uptime)
+
("C-c F m" . make-frame-command)
("C-c F d" . delete-frame)
("C-c F D" . delete-other-frames)
("C-c o" . other-window)
- ("C-c Q" . save-buffers-kill-terminal)
-
("C-S-h C" . describe-char)
("C-S-h F" . describe-face)
- ("C-x K" . kill-this-buffer)
+ ("C-x k" . kill-this-buffer)
+ ("C-x K" . kill-buffer)
("s-p" . beginning-of-buffer)
("s-n" . end-of-buffer))
+
+(when (display-graphic-p)
+ (unbind-key "C-z" global-map))
+#+end_src
+
+While at it, let's bind a few for some =straight-*= functions too:
+
+#+begin_src emacs-lisp
+(bind-keys
+ :prefix-map a/straight-prefix-map
+ :prefix "C-c p s"
+ ("u" . straight-use-package)
+ ("f" . straight-freeze-versions)
+ ("t" . straight-thaw-versions)
+ ("P" . straight-prune-build)
+ ("r" . straight-get-recipe)
+ ;; M-x ^straight-.*-all$
+ ("a c" . straight-check-all)
+ ("a f" . straight-fetch-all)
+ ("a m" . straight-merge-all)
+ ("a n" . straight-normalize-all)
+ ("a F" . straight-pull-all)
+ ("a P" . straight-push-all)
+ ("a r" . straight-rebuild-all)
+ ;; M-x ^straight-.*-package$
+ ("p c" . straight-check-package)
+ ("p f" . straight-fetch-package)
+ ("p m" . straight-merge-package)
+ ("p n" . straight-normalize-package)
+ ("p F" . straight-pull-package)
+ ("p P" . straight-push-package)
+ ("p r" . straight-rebuild-package))
#+end_src
** Packages
'auto-compile-inhibit-compile-detached-git-head))
#+end_src
-*** [[https://orgmode.org/][Org mode]]
+*** [[https://orgmode.org/][Org]]
#+begin_quote
Org mode is for keeping notes, maintaining TODO lists, planning
In short, my favourite way of life.
+We will use the =org-plus-contrib= package to get the whole deal:
+
#+begin_src emacs-lisp
-(use-package org
- :defer 1
+(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 2
:config
(setq org-src-tab-acts-natively t
org-src-preserve-indentation nil
org-edit-src-content-indentation 0
org-email-link-description-format "Email %c: %s" ; %.30s
org-highlight-latex-and-related '(entities)
+ org-use-speed-commands t
+ org-startup-folded 'content
+ 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-package ox-beamer
- :after ox)
-
-(use-package orgalist
- :after message
- :hook (message-mode . orgalist-mode))
+ ("\\paragraph{%s}" . "\\paragraph*{%s}")
+ ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
+ t)
+ (require 'ox-beamer))
#+end_src
**** asynchronous tangle
-=amin/async-babel-tangle= is a function closely inspired by [[https://github.com/dieggsy/dotfiles/tree/cc10edf7701958eff1cd94d4081da544d882a28c/emacs.d#dotfiles][dieggsy's
+=a/async-babel-tangle= is a function closely inspired by [[https://github.com/dieggsy/dotfiles/tree/cc10edf7701958eff1cd94d4081da544d882a28c/emacs.d#dotfiles][dieggsy's
d/async-babel-tangle]] which uses [[https://github.com/jwiegley/emacs-async][async]] to asynchronously tangle an org
file.
#+begin_src emacs-lisp
-(after! org
- (defvar amin-show-async-tangle-results nil
+(with-eval-after-load 'org
+ (defvar a/show-async-tangle-results nil
"Keep *emacs* async buffers around for later inspection.")
- (defvar amin-show-async-tangle-time nil
+ (defvar a/show-async-tangle-time nil
"Show the time spent tangling the file.")
- (defvar amin-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.")
- (defun amin/async-babel-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)
(let* ((file-tangle-start-time (current-time))
(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)
(org-babel-tangle-file ,file))
- (unless amin-show-async-tangle-results
+ (unless a/show-async-tangle-results
`(lambda (result)
(if result
(progn
+ ;; (setq byte-compile-warnings '(not noruntime unresolved))
(message "Tangled %s%s"
,file-nodir
- (if amin-show-async-tangle-time
+ (if a/show-async-tangle-time
(format " (%.3fs)"
(float-time (time-subtract (current-time)
',file-tangle-start-time)))
""))
- (when amin-async-tangle-post-compile
- (compile amin-async-tangle-post-compile)))
+ (when 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
'safe-local-variable-values
- '(eval add-hook 'after-save-hook #'amin/async-babel-tangle 'append 'local))
+ '(eval add-hook 'after-save-hook #'a/async-babel-tangle 'append 'local))
#+end_src
*** [[https://magit.vc/][Magit]]
#+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))
:custom-face (magit-diff-file-heading ((t (:weight normal)))))
#+end_src
+*** recentf
+
+Recently opened files.
+
+#+begin_src emacs-lisp
+(use-feature recentf
+ :defer 0.5
+ :config
+ (add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?:")
+ (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-package ivy
- :defer 1
+ :defer 0.6
:bind
(:map ivy-minibuffer-map
([escape] . keyboard-escape-quit)
#+begin_src emacs-lisp
(use-package swiper
+ :after ivy
:bind (("C-s" . swiper)
("C-r" . swiper)
("C-S-s" . isearch-forward)))
#+begin_src emacs-lisp
(use-package counsel
- :defer 1
+ :after ivy
:bind (([remap execute-extended-command] . counsel-M-x)
([remap find-file] . counsel-find-file)
("s-r" . counsel-recentf)
*** eshell
#+begin_src emacs-lisp
-(use-package eshell
- :defer 1
+(use-feature eshell
+ :defer 2
:commands eshell
:bind ("C-c a s e" . eshell)
:config
(eval-when-compile (defvar eshell-prompt-regexp))
- (defun amin/eshell-quit-or-delete-char (arg)
+ (defun a/eshell-quit-or-delete-char (arg)
(interactive "p")
(if (and (eolp) (looking-back eshell-prompt-regexp nil))
(eshell-life-is-too-much)
(delete-char arg)))
- (defun amin/eshell-clear ()
+ (defun a/eshell-clear ()
(interactive)
(let ((inhibit-read-only t))
(erase-buffer))
(eshell-send-input))
- (defun amin|eshell-setup ()
+ (defun a/eshell-setup ()
(make-local-variable 'company-idle-delay)
- (defvar company-idle-delay nil)
+ (defvar company-idle-delay)
+ (setq company-idle-delay nil)
(bind-keys :map eshell-mode-map
- ("C-d" . amin/eshell-quit-or-delete-char)
- ("C-S-l" . amin/eshell-clear)
+ ("C-d" . a/eshell-quit-or-delete-char)
+ ("C-S-l" . a/eshell-clear)
("M-r" . counsel-esh-history)
([tab] . company-complete)))
- :hook (eshell-mode . amin|eshell-setup)
+ :hook (eshell-mode . a/eshell-setup)
:custom
(eshell-hist-ignoredups t)
(eshell-input-filter 'eshell-input-filter-initial-space))
*** Ibuffer
#+begin_src emacs-lisp
-(use-package ibuffer
- :defer t
+(use-feature ibuffer
:bind
(("C-x C-b" . ibuffer-other-window)
:map ibuffer-mode-map
(mode . python-mode)
(mode . c-mode)
(mode . c++-mode)
+ (mode . java-mode)
(mode . emacs-lisp-mode)
(mode . scheme-mode)
(mode . haskell-mode)
("emacs"
(or
(name . "^\\*scratch\\*$")
- (name . "^\\*Messages\\*$"))))))
+ (name . "^\\*Messages\\*$")))
+ ("erc" (mode . erc-mode)))))
(ibuffer-formats
'((mark modified read-only locked " "
(name 18 18 :left :elide)
*** Outline
#+begin_src emacs-lisp
-(use-package outline
- :defer t
+(use-feature outline
:hook (prog-mode . outline-minor-mode)
:bind
(:map
("<s-tab>" . outline-toggle-children)
("M-p" . outline-previous-visible-heading)
("M-n" . outline-next-visible-heading)
- :prefix-map amin--outline-prefix-map
+ :prefix-map a/outline-prefix-map
:prefix "s-o"
("TAB" . outline-toggle-children)
("a" . outline-hide-body)
("s" . outline-show-subtree)))
#+end_src
-* Borg's =layer/essentials=
-:PROPERTIES:
-:CUSTOM_ID: borg-essentials
-:END:
+*** Dired
-TODO: break this giant source block down into individual org sections.
+#+begin_src emacs-lisp
+(use-feature ls-lisp
+ :custom (ls-lisp-dirs-first t))
+
+(use-feature dired
+ :config
+ (setq dired-listing-switches "-alh"
+ ls-lisp-use-insert-directory-program nil)
+
+ ;; easily diff 2 marked files
+ ;; 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)))
+ (if (<= (length files) 2)
+ (let ((file1 (car files))
+ (file2 (if (cdr files)
+ (cadr files)
+ (read-file-name
+ "file: "
+ (dired-dwim-target-directory)))))
+ (if (file-newer-than-file-p file1 file2)
+ (ediff-files file2 file1)
+ (ediff-files file1 file2))
+ (add-hook 'ediff-after-quit-hook-internal
+ (lambda ()
+ (setq ediff-after-quit-hook-internal nil)
+ (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)
+ ("z" . (lambda ()
+ (interactive)
+ (a/dired-start-process "zathura"))))
+ :hook (dired-mode . dired-hide-details-mode))
+#+end_src
+
+*** Help
+
+#+begin_src emacs-lisp
+(use-feature help
+ :config
+ (temp-buffer-resize-mode)
+ (setq help-window-select t))
+#+end_src
+
+*** Tramp
+
+#+begin_src emacs-lisp
+(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))
+ (add-to-list 'tramp-default-proxies-alist
+ (list (regexp-quote (system-name)) nil nil)))
+#+end_src
+
+*** Dash
#+begin_src emacs-lisp
(use-package dash
:config (dash-enable-font-lock))
+#+end_src
+* Editing
+:PROPERTIES:
+:CUSTOM_ID: editing
+:END:
+
+** =diff-hl=
+
+Highlight uncommitted changes in the left fringe.
+
+#+begin_src emacs-lisp
(use-package diff-hl
:config
(setq diff-hl-draw-borders nil)
(global-diff-hl-mode)
- (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh t))
+ :hook (magit-post-refresh . diff-hl-magit-post-refresh))
+#+end_src
-(use-package dired
- :defer t
- :config (setq dired-listing-switches "-alh"))
+** ElDoc
-(use-package eldoc
+Display Lisp objects at point in the echo area.
+
+#+begin_src emacs-lisp
+(use-feature eldoc
:when (version< "25" emacs-version)
:config (global-eldoc-mode))
+#+end_src
-(use-package help
- :defer t
- :config
- (temp-buffer-resize-mode)
- (setq help-window-select t))
+** paren
-(progn ; `isearch'
- (setq isearch-allow-scroll t))
+Highlight matching parens.
-(use-package lisp-mode
- :config
- (add-hook 'emacs-lisp-mode-hook 'outline-minor-mode)
- (add-hook 'emacs-lisp-mode-hook 'reveal-mode)
- (defun indent-spaces-mode ()
- (setq indent-tabs-mode nil))
- (add-hook 'lisp-interaction-mode-hook #'indent-spaces-mode))
+#+begin_src emacs-lisp
+(use-feature paren
+ :demand
+ :config (show-paren-mode))
+#+end_src
-(use-package man
- :defer t
- :config (setq Man-width 80))
+** simple (for column numbers)
-(use-package paren
- :config (show-paren-mode))
+#+begin_src emacs-lisp
+(use-feature simple
+ :config (column-number-mode))
+#+end_src
-(use-package prog-mode
- :config (global-prettify-symbols-mode)
- (defun indicate-buffer-boundaries-left ()
- (setq indicate-buffer-boundaries 'left))
- (add-hook 'prog-mode-hook #'indicate-buffer-boundaries-left))
+** =savehist=
-(use-package recentf
- :defer 0.5
- :config
- (add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?:")
- (setq recentf-max-saved-items 40))
+Save minibuffer history.
-(use-package savehist
+#+begin_src emacs-lisp
+(use-feature savehist
:config (savehist-mode))
+#+end_src
+
+** =saveplace=
+
+Automatically save place in each file.
-(use-package saveplace
+#+begin_src emacs-lisp
+(use-feature saveplace
:when (version< "25" emacs-version)
:config (save-place-mode))
+#+end_src
-(use-package simple
- :config (column-number-mode))
+** =prog-mode=
-(progn ; `text-mode'
- (add-hook 'text-mode-hook #'indicate-buffer-boundaries-left)
- (add-hook 'text-mode-hook #'abbrev-mode))
+#+begin_src emacs-lisp
+(use-feature prog-mode
+ :config (global-prettify-symbols-mode)
+ (defun indicate-buffer-boundaries-left ()
+ (setq indicate-buffer-boundaries 'left))
+ (add-hook 'prog-mode-hook #'indicate-buffer-boundaries-left))
+#+end_src
-(use-package 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))
- (add-to-list 'tramp-default-proxies-alist
- (list (regexp-quote (system-name)) nil nil)))
+** =text-mode=
+#+begin_src emacs-lisp
+(use-feature text-mode
+ :hook ((text-mode . indicate-buffer-boundaries-left)
+ (text-mode . abbrev-mode)))
#+end_src
-* Editing
-:PROPERTIES:
-:CUSTOM_ID: editing
-:END:
-
** Company
#+begin_src emacs-lisp
(use-package company
- :defer 1
+ :defer 3
:bind
(:map company-active-map
([tab] . company-complete-common-or-cycle)
(global-company-mode t))
#+end_src
-* Syntax and spell checking
-:PROPERTIES:
-:CUSTOM_ID: syntax-spell-checking
-:END:
+** Flycheck
#+begin_src emacs-lisp
(use-package flycheck
:CUSTOM_ID: programming-modes
:END:
+** Lisp
+
+#+begin_src emacs-lisp
+(use-feature lisp-mode
+ :config
+ (add-hook 'emacs-lisp-mode-hook 'outline-minor-mode)
+ (add-hook 'emacs-lisp-mode-hook 'reveal-mode)
+ (defun indent-spaces-mode ()
+ (setq indent-tabs-mode nil))
+ (add-hook 'lisp-interaction-mode-hook #'indent-spaces-mode))
+#+end_src
+
** [[http://alloytools.org][Alloy]] (with [[https://github.com/dwwmmn/alloy-mode][alloy-mode]])
#+begin_src emacs-lisp
(use-package alloy-mode
- :defer t
+ :straight (:host github :repo "dwwmmn/alloy-mode")
:config (setq alloy-basic-offset 2))
#+end_src
#+begin_src emacs-lisp
(use-package proof-site ; Proof General
- :defer t
- :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 haskell-mode
- :defer t
:config
(setq haskell-indentation-layout-offset 4
haskell-indentation-left-offset 4
("C-c l l" . hs-lint)))
#+end_src
-** Web dev
+** Web
*** SGML and HTML
#+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
- (setq-every! 2
+ (a/setq-every 2
web-mode-code-indent-offset
web-mode-css-indent-offset
web-mode-markup-indent-offset))
:hook (web-mode css-mode html-mode sgml-mode))
#+end_src
-** COMMENT Java
+** Java
-*** meghanada
+*** COMMENT meghanada
#+begin_src emacs-lisp
(use-package meghanada
:hook (java-mode . meghanada-mode))
#+end_src
-*** lsp-java
+*** COMMENT lsp-java
#+begin_comment
dependencies:
:after (treemacs))
#+end_src
+*** COMMENT eclim
+
+#+begin_src emacs-lisp
+(use-package eclim
+ :bind (:map eclim-mode-map ("S-SPC" . company-complete))
+ :hook ((java-mode . eclim-mode)
+ (eclim-mode . (lambda ()
+ (make-local-variable 'company-idle-delay)
+ (defvar company-idle-delay)
+ ;; (setq company-idle-delay 0.7)
+ (setq company-idle-delay nil))))
+ :custom
+ (eclim-auto-save nil)
+ ;; (eclimd-default-workspace "~/src/eclipse-workspace-exp")
+ (eclim-executable "~/.p2/pool/plugins/org.eclim_2.8.0/bin/eclim")
+ (eclim-eclipse-dirs '("~/usr/eclipse/dsl-2018-09/eclipse")))
+#+end_src
+
** geiser
#+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
:CUSTOM_ID: emacs-enhancements
:END:
+** man
+
+#+begin_src emacs-lisp
+(use-feature man
+ :config (setq Man-width 80))
+#+end_src
+
** [[https://github.com/justbur/emacs-which-key][which-key]]
#+begin_quote
#+begin_src emacs-lisp
(use-package which-key
:defer 1
- :config (which-key-mode))
+ :config
+ (which-key-add-key-based-replacements
+ ;; prefixes for global prefixes and minor modes
+ "C-c @" "outline"
+ "C-c !" "flycheck"
+ "C-c 8" "typo"
+ "C-c 8 -" "typo/dashes"
+ "C-c 8 <" "typo/left-brackets"
+ "C-c 8 >" "typo/right-brackets"
+ "C-x 8" "unicode"
+ "C-x a" "abbrev/expand"
+ "C-x r" "rectangle/register/bookmark"
+ "C-x v" "version control"
+ ;; prefixes for my personal bindings
+ "C-c a" "applications"
+ "C-c a e" "erc"
+ "C-c a s" "shells"
+ "C-c p" "package-management"
+ ;; "C-c p e" "package-management/epkg"
+ "C-c p s" "straight.el"
+ "C-c psa" "all"
+ "C-c psp" "package"
+ "C-c c" "compile-and-comments"
+ "C-c e" "eval"
+ "C-c f" "files"
+ "C-c F" "frames"
+ "C-S-h" "help(ful)"
+ "C-c m" "multiple-cursors"
+ "C-c P" "projectile"
+ "C-c P s" "projectile/search"
+ "C-c P x" "projectile/execute"
+ "C-c P 4" "projectile/other-window"
+ "C-c q" "boxquote"
+ "s-g" "magit"
+ "s-o" "outline"
+ "s-t" "themes")
+
+ ;; prefixes for major modes
+ (which-key-add-major-mode-key-based-replacements 'message-mode
+ "C-c f" "footnote")
+ (which-key-add-major-mode-key-based-replacements 'org-mode
+ "C-c C-v" "org-babel")
+ (which-key-add-major-mode-key-based-replacements 'web-mode
+ "C-c C-a" "web/attributes"
+ "C-c C-b" "web/blocks"
+ "C-c C-d" "web/dom"
+ "C-c C-e" "web/element"
+ "C-c C-t" "web/tags")
+
+ (which-key-mode)
+ :custom
+ (which-key-add-column-padding 5)
+ (which-key-max-description-length 32))
#+end_src
** theme
#+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
-(defun amin/lights-on ()
+(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 amin/lights-off ()
+(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" . amin/lights-off)
- ("s-t l" . amin/lights-on))
+ ("s-t d" . a/lights-off)
+ ("s-t l" . a/lights-on))
#+end_src
** [[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 projectile
- :defer t
- :bind-keymap ("C-c p" . projectile-command-map)
+ :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
(use-package boxquote
:defer 3
:bind
- (:prefix-map amin--boxquote-prefix-map
+ (:prefix-map a/boxquote-prefix-map
:prefix "C-c q"
("b" . boxquote-buffer)
("B" . boxquote-insert-buffer)
Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
-** COMMENT [[https://github.com/DarthFennec/highlight-indent-guides][highlight-indent-guides]]
+** orgalist
#+begin_src emacs-lisp
-(use-package highlight-indent-guides
- :defer 3
- :hook ((prog-mode . highlight-indent-guides-mode)
- ;; (org-mode . highlight-indent-guides-mode)
- )
- :config
- (setq highlight-indent-guides-character ?\|)
- (setq highlight-indent-guides-auto-enabled nil)
- (setq highlight-indent-guides-method 'character)
- (setq highlight-indent-guides-responsive 'top)
- (set-face-foreground 'highlight-indent-guides-character-face "gainsboro")
- (set-face-foreground 'highlight-indent-guides-top-character-face "grey40")) ; grey13 is nice too
+(use-package orgalist
+ :after message
+ :hook (message-mode . orgalist-mode))
#+end_src
** typo.el
#+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)
(propertize (+eshell--current-git-branch)
'face 'font-lock-function-name-face)
"\n"
- (propertize "λ" 'face 'eshell-prompt-face)
+ ;; "λ"
+ ;; (propertize "λ" 'face 'eshell-prompt)
;; needed for the input text to not have prompt face
- (propertize " " 'face 'default))))
+ (propertize "λ " 'face 'default))))
(defun +eshell--current-git-branch ()
(let ((branch (car (loop for match in (split-string (shell-command-to-string "git branch") "\n")
collect match))))
(if (not (eq branch nil))
(concat " " (substring branch 2))
- ""))))
-#+end_src
-
-** COMMENT slack
-
-Hopefully temporary.
-
-#+begin_src emacs-lisp
-(use-package slack
- :commands (slack-start)
- :init
- (eval-when-compile ; silence the byte-compiler
- (defvar url-http-data nil)
- (defvar url-http-extra-headers nil)
- (defvar url-http-method nil)
- (defvar url-callback-function nil)
- (defvar url-callback-arguments nil)
- (defvar oauth--token-data nil))
- (setq slack-buffer-emojify t
- slack-prefer-current-team t)
- :config
- (slack-register-team
- :name "uw-apv"
- :default t
- :client-id uw-apv-client-id
- :client-secret uw-apv-client-secret
- :token uw-apv-token
- :subscribed-channels '(general)
- :full-and-display-names t)
- (slack-register-team
- :name "watform"
- :default nil
- :client-id watform-client-id
- :client-secret watform-client-secret
- :token watform-token
- :subscribed-channels '(general)
- :full-and-display-names t)
- (add-to-list 'swiper-font-lock-exclude 'slack-message-buffer-mode t)
- (setq lui-time-stamp-format "[%Y-%m-%d %H:%M:%S]"
- lui-time-stamp-only-when-changed-p t
- lui-time-stamp-position 'right)
- :bind
- (("C-c s s" . slack-start)
- ("C-c s u" . slack-select-unread-rooms)
- ("C-c s b" . slack-select-rooms)
- ("C-c s t" . slack-change-current-team)
- ("C-c s c" . slack-ws-close)
- :map slack-mode-map
- ("M-p" . slack-buffer-goto-prev-message)
- ("M-n" . slack-buffer-goto-next-message)
- ("C-c e" . slack-message-edit)
- ("C-c k" . slack-message-delete)
- ("C-c C-k" . slack-channel-leave)
- ("C-c r a" . slack-message-add-reaction)
- ("C-c r r" . slack-message-remove-reaction)
- ("C-c r s" . slack-message-show-reaction-users)
- ("C-c p l" . slack-room-pins-list)
- ("C-c p a" . slack-message-pins-add)
- ("C-c p r" . slack-message-pins-remove)
- ("@" . slack-message-embed-mention)
- ("#" . slack-message-embed-channel)))
-
-(use-package alert
- :commands (alert)
- :init
- (setq alert-default-style 'notifier))
+ "")))
+ (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
- :bind (("C-c a s m m" . multi-term)
- ("C-c a s m p" . multi-term-dedicated-toggle)
+ :defer 3
+ :bind (("C-c a s m" . multi-term-dedicated-toggle)
:map term-mode-map
("C-c C-j" . term-char-mode)
:map term-raw-map
:bind ("C-=" . er/expand-region))
#+end_src
+** multiple-cursors
+
+#+begin_src emacs-lisp
+(use-package multiple-cursors
+ :bind
+ (("C-S-<mouse-1>" . mc/add-cursor-on-click)
+ (:prefix-map a/mc-prefix-map
+ :prefix "C-c m"
+ ("c" . mc/edit-lines)
+ ("n" . mc/mark-next-like-this)
+ ("p" . mc/mark-previous-like-this)
+ ("a" . mc/mark-all-like-this))))
+#+end_src
+
+** forge
+
+#+begin_src emacs-lisp
+(use-package forge
+ :after magit
+ :demand)
+#+end_src
+
+** yasnippet
+
+#+begin_src emacs-lisp
+(use-package yasnippet
+ :defer 3
+ :config
+ (defconst yas-verbosity-cur yas-verbosity)
+ (setq yas-verbosity 2)
+ (add-to-list 'yas-snippet-dirs "~/src/git/guix/etc/snippets")
+ (yas-reload-all)
+ (setq yas-verbosity yas-verbosity-cur)
+ :hook
+ (text-mode . yas-minor-mode))
+#+end_src
+
* Email
:PROPERTIES:
:CUSTOM_ID: email
:END:
#+begin_src emacs-lisp
-(defvar amin-maildir (expand-file-name "~/mail/"))
-(after! recentf
- (add-to-list 'recentf-exclude amin-maildir))
+(defvar a/maildir (expand-file-name "~/mail/"))
+(with-eval-after-load 'recentf
+ (add-to-list 'recentf-exclude a/maildir))
#+end_src
** Gnus
#+begin_src emacs-lisp
(setq
- amin-gnus-init-file (no-littering-expand-etc-file-name "gnus")
- mail-user-agent 'gnus-user-agent
- read-mail-command 'gnus)
-
-(use-package gnus
- :bind (("C-c m" . gnus)
- ("C-c M" . gnus-unplugged)
- ("s-m" . gnus)
+ a/gnus-init-file (no-littering-expand-etc-file-name "gnus")
+ mail-user-agent 'gnus-user-agent
+ read-mail-command 'gnus)
+
+(use-feature gnus
+ :bind (("s-m" . gnus)
("s-M" . gnus-unplugged))
:init
(setq
(nnimap-address "127.0.0.1")
(nnimap-server-port 143)
(nnimap-authenticator plain)
- (nnimap-user "amin@aminb.org"))
+ (nnimap-user "amin@bndl.org"))
(nnimap "uwaterloo"
(nnimap-stream plain)
(nnimap-address "127.0.0.1")
(nnimap-server-port 143)
(nnimap-authenticator plain)
- (nnimap-user "abandali@uwaterloo.ca")))
+ (nnimap-user "abandali@uwaterloo.ca"))
+ (nnimap "csclub"
+ (nnimap-stream plain)
+ (nnimap-address "127.0.0.1")
+ (nnimap-server-port 143)
+ (nnimap-authenticator plain)
+ (nnimap-user "abandali@csclub.uw")))
gnus-message-archive-group "nnimap+amin:Sent"
gnus-parameters
'(("gnu.*"
gnus-save-newsrc-file nil
gnus-read-newsrc-file nil
gnus-interactive-exit nil
- gnus-gcc-mark-as-read t))
+ gnus-gcc-mark-as-read t)
+ :config
+ (require 'ebdb)
+ (require 'ebdb-mua)
+ (require 'ebdb-gnus))
-(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 amin--gnus-summary-prefix-map
+ :prefix-map a/gnus-summary-prefix-map
:prefix "v"
("r" . gnus-summary-reply)
("w" . gnus-summary-wide-reply)
("r" . gnus-summary-reply-with-original)
("R" . gnus-summary-wide-reply-with-original)
("M-L" . org-store-link))
- :hook (gnus-summary-mode . amin--no-mouse-autoselect-window))
+ :hook (gnus-summary-mode . a/no-mouse-autoselect-window))
-(use-package gnus-msg
+(use-feature gnus-msg
:config
(setq gnus-posting-styles
'((".*"
- (address "amin@aminb.org")
+ (address "amin@bndl.org")
(body "\nBest,\namin\n")
- (eval (setq amin--message-cite-say-hi t)))
+ (eval (setq a/message-cite-say-hi t)))
("gnu.*"
- (address "bandali@gnu.org"))
+ (address "bandali@gnu.org")
+ (eval (set (make-local-variable 'message-user-fqdn) "fencepost.gnu.org")))
((header "subject" "ThankCRM")
(to "webmasters-comment@gnu.org")
- (body "\nAdded to 2018supporters.html.\n\nMoving to campaigns.\n\n-amin\n")
- (eval (setq amin--message-cite-say-hi nil)))
+ (body "\nAdded to 2019supporters.html.\n\nMoving to campaigns.\n\n-amin\n")
+ (eval (setq a/message-cite-say-hi nil)))
("nnimap\\+uwaterloo:.*"
(address "abandali@uwaterloo.ca")
- (gcc "\"nnimap+uwaterloo:Sent Items\"")))))
+ (gcc "\"nnimap+uwaterloo:Sent Items\""))
+ ("nnimap\\+csclub:.*"
+ (address "abandali@csclub.uwaterloo.ca")
+ (gcc "nnimap+csclub:Sent")))))
-(use-package gnus-topic
- :hook (gnus-group-mode . gnus-topic-mode))
+(use-feature gnus-topic
+ :hook (gnus-group-mode . gnus-topic-mode)
+ :config (setq gnus-topic-line-format "%i[ %A: %(%{%n%}%) ]%v\n"))
-(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$\\)"))
+ (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 amin--message-cite-style-format "On %Y-%m-%d %l:%M %p, %N wrote:")
+ ;; redefine for a simplified In-Reply-To header
+ ;; (see https://todo.sr.ht/~sircmpwn/lists.sr.ht/67)
+ (defun message-make-in-reply-to ()
+ "Return the In-Reply-To header for this message."
+ (when message-reply-headers
+ (let ((from (mail-header-from message-reply-headers))
+ (msg-id (mail-header-id message-reply-headers)))
+ (when from
+ msg-id))))
+
+ (defconst a/message-cite-style-format "On %Y-%m-%d %l:%M %p, %N wrote:")
(defconst message-cite-style-bandali
'((message-cite-function 'message-cite-original)
(message-citation-line-function 'message-insert-formatted-citation-line)
(message-yank-cited-prefix ">")
(message-yank-empty-prefix ">")
(message-citation-line-format
- (if amin--message-cite-say-hi
- (concat "Hi %F,\n\n" amin--message-cite-style-format)
- amin--message-cite-style-format)))
+ (if a/message-cite-say-hi
+ (concat "Hi %F,\n\n" a/message-cite-style-format)
+ a/message-cite-style-format)))
"Citation style based on Mozilla Thunderbird's. Use with message-cite-style.")
(setq message-cite-style 'message-cite-style-bandali
message-kill-buffer-on-exit t
message-send-mail-function 'message-send-mail-with-sendmail
message-sendmail-envelope-from 'header
message-dont-reply-to-names
- "\\(\\(.*@aminb\\.org\\)\\|\\(amin@bandali\\.me\\)\\|\\(\\(aminb?\\|mab\\|bandali\\)@gnu\\.org\\)\\|\\(\\(m\\|a\\(min\\.\\)?\\)bandali@uwaterloo\\.ca\\)\\)"
- message-user-fqdn "aminb.org")
+ "\\(\\(amin@bndl\\.org\\)\\|\\(.*@\\(aminb\\|amin\\.bndl\\)\\.org\\)\\|\\(\\(bandali\\|aminb?\\|mab\\)@gnu\\.org\\)\\|\\(a\\(min\\.\\)?bandali@uwaterloo\\.ca\\)\\|\\(abandali@csclub\\.uwaterloo\\.ca\\)\\)")
+ (require 'company-ebdb)
:hook (;; (message-setup . mml-secure-message-sign-pgpmime)
(message-mode . flyspell-mode)
(message-mode . (lambda ()
;; (message-header-cc ((t (:foreground "#333" :weight normal))))
)
-(after! mml-sec
+(with-eval-after-load 'mml-sec
(setq mml-secure-openpgp-encrypt-to-self t
mml-secure-openpgp-sign-with-sender t))
#+end_src
Convenient footnotes in =message-mode=.
#+begin_src emacs-lisp
-(use-package footnote
+(use-feature footnote
:after message
+ ;; :config
+ ;; (setq footnote-start-tag ""
+ ;; footnote-end-tag ""
+ ;; footnote-style 'unicode)
:bind
(:map message-mode-map
- :prefix-map amin--footnote-prefix-map
+ :prefix-map a/footnote-prefix-map
:prefix "C-c f"
("a" . footnote-add-footnote)
("b" . footnote-back-to-message)
("d" . footnote-delete-footnote)
("g" . footnote-goto-footnote)
("r" . footnote-renumber-footnotes)
- ("s" . footnote-set-style))
- :config
- (setq footnote-start-tag ""
- footnote-end-tag ""
- footnote-style 'unicode))
+ ("s" . footnote-set-style)))
#+end_src
** ebdb
#+begin_src emacs-lisp
(use-package ebdb
- :defer 1
+ :straight (:host github :repo "girzel/ebdb")
+ :after gnus
:bind (:map gnus-group-mode-map ("e" . ebdb))
:config
(setq ebdb-sources (no-littering-expand-var-file-name "ebdb"))
- (after! swiper
+ (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)
: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
:after ebdb
:custom
(ebdb-gnus-window-configuration
(article 1.0)
(ebdb-gnus 0.3))))))
-(use-package ebdb-mua
+(use-feature ebdb-mua
:after ebdb
;; :custom (ebdb-mua-pop-up nil)
)
;; :after ebdb)
#+end_src
-** COMMENT bbdb
-
-Manually install bbdb (=lisp/bbdb= copied from an ELPA-based setup),
-because installing it from source on Emacs 27 using the following
-submodule configuration for some reason doesn’t work and results in
-very strange errors when using any of the functions.
-
-#+begin_src conf :tangle no
-[submodule "bbdb"]
- path = lib/bbdb
- url = https://git.savannah.nongnu.org/git/bbdb.git
- load-path = lisp
- info-path = doc
- build-step = ./autogen.sh
- build-step = ./configure
- build-step = make
- build-step = make install
-#+end_src
-
-I tried using =borg-elpa= instead of doing it like this, but it added
-2 seconds to my startup time, which is unacceptable to me.
+** message-x
#+begin_src emacs-lisp
-(use-package bbdb
- :load-path "lisp/bbdb"
- :init
- (load (expand-file-name "lisp/bbdb/bbdb-autoloads.el" user-emacs-directory))
- ;; (bbdb-mua-auto-update-init 'message)
- (setq bbdb-mua-auto-update-p 'query
- bbdb-complete-mail nil)
- (bbdb-initialize 'gnus 'message))
+(use-package message-x)
#+end_src
-** COMMENT message-x
-
-#+begin_src emacs-lisp
+#+begin_src emacs-lisp :tangle no
(use-package message-x
:custom
(message-x-completion-alist
(gnus-harvest-install)))
#+end_src
+* IRC
+:PROPERTIES:
+:CUSTOM_ID: irc
+:END:
+
+Now with ERC!
+
+#+begin_src emacs-lisp
+(use-package znc
+ :straight (:host nil :repo "https://git.bndl.org/amin/znc.el")
+ :bind (("C-c a e e" . znc-erc)
+ ("C-c a e a" . znc-all))
+ :config
+ (let ((pwd (let ((auth (auth-source-search :host "znca")))
+ (cond
+ ((null auth) (error "Couldn't find znca's authinfo"))
+ (t (funcall (plist-get (car auth) :secret)))))))
+ (setq znc-servers
+ `(("znc.bndl.org" 1337 t
+ ((freenode "amin/freenode" ,pwd)))
+ ("znc.bndl.org" 1337 t
+ ((moznet "amin/moznet" ,pwd)))))))
+#+end_src
+
* Blogging
:PROPERTIES:
:CUSTOM_ID: blogging
#+begin_src emacs-lisp
(use-package ox-hugo
- :after ox)
-
-(use-package ox-hugo-auto-export
- :load-path "lib/ox-hugo")
+ :after ox
+ :demand)
#+end_src
* Post initialization
#+begin_src emacs-lisp
(message "Loading %s...done (%.3fs)" user-init-file
(float-time (time-subtract (current-time)
- amin--before-user-init-time)))
+ a/before-user-init-time)))
#+end_src
* Footer
* COMMENT Local Variables :ARCHIVE:
# Local Variables:
-# eval: (add-hook 'after-save-hook #'amin/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: