byte-compiled the packages. Something along these lines should work:
#+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
* Contents :toc_1:noexport:
- [[#header][Header]]
- [[#initial-setup][Initial setup]]
- [[#core][Core]]
+- [[#borg-essentials][Borg's =layer/essentials=]]
+- [[#editing][Editing]]
+- [[#syntax-spell-checking][Syntax and spell checking]]
+- [[#programming-modes][Programming modes]]
+- [[#emacs-enhancements][Emacs enhancements]]
+- [[#email][Email]]
+- [[#blogging][Blogging]]
- [[#post-initialization][Post initialization]]
- [[#footer][Footer]]
#+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
=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*=
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)
+;; Solid rocket booster ignition...
(borg-initialize)
+;; We have lift off!
;; (require 'borg-nix-shell)
;; (setq borg-build-shell-command 'borg-nix-shell-build-command)
debug-on-error t)
(setq use-package-verbose nil
use-package-expand-minimally t))
+
+(setq use-package-always-defer t)
#+end_src
*** Epkg
#+begin_src emacs-lisp
(use-package epkg
- :defer t
:bind
(("C-c b d" . epkg-describe-package)
("C-c b p" . epkg-list-packages)
- ("C-c b u" . epkg-update)))
+ ("C-c b u" . epkg-update))
+ :config
+ (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=
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
** Useful utilities
-#+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)))
-
-; 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)))))
-#+end_src
-
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
*** Don’t display =*compilation*= on success
-From https://stackoverflow.com/a/17788551.
+Based on https://stackoverflow.com/a/17788551, with changes to use
+=cl-letf= instead of the now obsolete =flet=.
#+begin_src emacs-lisp
-(defun amin--compilation-finish-function (buffer outstr)
- (unless (string-match "finished" outstr)
- (switch-to-buffer-other-window buffer))
- t)
+(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)
+ (require 'cl-macs)
-(defadvice compilation-start
- (around inhibit-display
- (command &optional mode name-function highlight-regexp))
- (if (not (string-match "^\\(find\\|grep\\)" command))
- (flet ((display-buffer)
- (set-window-point)
- (goto-char))
- (fset 'display-buffer 'ignore)
- (fset 'goto-char 'ignore)
- (fset 'set-window-point 'ignore)
- (save-window-excursion
- ad-do-it))
- ad-do-it))
-
-(ad-activate 'compilation-start)
+ (defadvice compilation-start
+ (around inhibit-display
+ (command &optional mode name-function highlight-regexp))
+ (if (not (string-match "^\\(find\\|grep\\)" command))
+ (cl-letf (((symbol-function 'display-buffer) #'ignore))
+ (save-window-excursion ad-do-it))
+ ad-do-it))
+ (ad-activate 'compilation-start))
#+end_src
*** Search for non-ASCII characters
;; (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
#+begin_src emacs-lisp
'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
#+begin_src emacs-lisp
(use-package org
- :defer 1
+ :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)
(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 "make ti"
"If non-nil, pass to `compile' after successful tangle.")
- (defun amin/async-babel-tangle ()
+ (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"))
+ ;; (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-package 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.5
:bind
(:map ivy-minibuffer-map
([escape] . keyboard-escape-quit)
#+begin_src emacs-lisp
(use-package swiper
- :bind (("C-s" . swiper)
- ("C-r" . swiper)))
+ :after ivy
+ :bind (("C-s" . swiper)
+ ("C-r" . swiper)
+ ("C-S-s" . isearch-forward)))
#+end_src
**** Counsel
#+begin_src emacs-lisp
(use-package counsel
- :defer 1
+ :defer 0.6
+ :after ivy
:bind (([remap execute-extended-command] . counsel-M-x)
([remap find-file] . counsel-find-file)
("s-r" . counsel-recentf)
#+begin_src emacs-lisp
(use-package eshell
- :defer 1
+ :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)
(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))
#+begin_src emacs-lisp
(use-package ibuffer
- :defer t
:bind
(("C-x C-b" . ibuffer-other-window)
:map ibuffer-mode-map
'(("default"
("dired" (mode . dired-mode))
("org" (mode . org-mode))
+ ("gnus"
+ (or
+ (mode . gnus-group-mode)
+ (mode . gnus-summary-mode)
+ (mode . gnus-article-mode)
+ ;; not really, but...
+ (mode . message-mode)))
("web"
(or
(mode . web-mode)
("shell"
(or
(mode . eshell-mode)
- (mode . shell-mode)))
- ("notmuch" (name . "\*notmuch\*"))
+ (mode . shell-mode)
+ (mode . term-mode)))
("programming"
(or
(mode . python-mode)
+ (mode . c-mode)
(mode . c++-mode)
- (mode . emacs-lisp-mode)))
+ (mode . emacs-lisp-mode)
+ (mode . scheme-mode)
+ (mode . haskell-mode)
+ (mode . lean-mode)))
("emacs"
(or
(name . "^\\*scratch\\*$")
- (name . "^\\*Messages\\*$")))
- ("slack"
- (or
- (name . "^\\*Slack*"))))))
+ (name . "^\\*Messages\\*$"))))))
(ibuffer-formats
'((mark modified read-only locked " "
(name 18 18 :left :elide)
#+begin_src emacs-lisp
(use-package outline
- :defer t
: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=
+*** Dired
-TODO: break this giant source block down into individual org sections.
+#+begin_src emacs-lisp
+(use-package ls-lisp
+ :custom (ls-lisp-dirs-first t))
+
+(use-package 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-package help
+ :config
+ (temp-buffer-resize-mode)
+ (setq help-window-select t))
+#+end_src
+
+*** Tramp
+
+#+begin_src emacs-lisp
+(use-package 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
+
+Display Lisp objects at point in the echo area.
+#+begin_src emacs-lisp
(use-package 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))
-
-(progn ; `isearch'
- (setq isearch-allow-scroll t))
+** paren
-(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))
-
-(use-package man
- :defer t
- :config (setq Man-width 80))
+Highlight matching parens.
+#+begin_src emacs-lisp
(use-package paren
+ :demand
:config (show-paren-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))
+** simple (for column numbers)
-(use-package recentf
- :defer 0.5
- :config
- (add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?:")
- (setq recentf-max-saved-items 40))
+#+begin_src emacs-lisp
+(use-package simple
+ :config (column-number-mode))
+#+end_src
+
+** =savehist=
+Save minibuffer history.
+
+#+begin_src emacs-lisp
(use-package savehist
:config (savehist-mode))
+#+end_src
+
+** =saveplace=
+Automatically save place in each file.
+
+#+begin_src emacs-lisp
(use-package 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-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))
+#+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-package text-mode
+ :hook ((text-mode . indicate-buffer-boundaries-left)
+ (text-mode . abbrev-mode)))
#+end_src
-* Editing
-
** 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
+** Flycheck
#+begin_src emacs-lisp
(use-package flycheck
(advice-add #'ispell-parse-output :filter-args
#'endless/replace-quote))
#+end_src
+
* Programming modes
+:PROPERTIES:
+:CUSTOM_ID: programming-modes
+:END:
+
+** Lisp
+
+#+begin_src emacs-lisp
+(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))
+#+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
: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/")
#+end_src
#+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
-** Nix
-
-#+begin_src emacs-lisp
-(use-package nix-mode
- :defer t
- :mode "\\.nix\\'")
-#+end_src
-
-** Java
+** COMMENT Java
*** meghanada
-#+begin_src emacs-lisp :tangle no
+#+begin_src emacs-lisp
(use-package meghanada
:bind
(:map meghanada-mode-map
treemacs
#+end_comment
-#+begin_src emacs-lisp :tangle no
+#+begin_src emacs-lisp
(use-package treemacs
:config (setq treemacs-never-persist t))
:after (treemacs))
#+end_src
-* Emacs Enhancements
+** geiser
+
+#+begin_src emacs-lisp
+(use-package geiser)
+
+(use-package 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")
+#+end_src
+
+* Emacs enhancements
+:PROPERTIES:
+:CUSTOM_ID: emacs-enhancements
+:END:
+
+** man
+
+#+begin_src emacs-lisp
+(use-package man
+ :config (setq Man-width 80))
+#+end_src
** [[https://github.com/justbur/emacs-which-key][which-key]]
#+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 s" "shells"
+ "C-c b" "borg"
+ "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))
#+end_src
** theme
#+begin_src emacs-lisp
(use-package smart-mode-line
+ :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 projectile
- :defer t
:bind-keymap ("C-c p" . projectile-command-map)
:config
(projectile-mode)
(advice-add 'magit-checkout
:after #'my-projectile-invalidate-cache)
(advice-add 'magit-branch-and-checkout
- :after #'my-projectile-invalidate-cache))))
+ :after #'my-projectile-invalidate-cache)))
+ :custom (projectile-completion-system 'ivy))
#+end_src
** [[https://github.com/Wilfred/helpful][helpful]]
#+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
("C-S-h p" . helpful-at-point)))
#+end_src
-** [[https://github.com/knu/shell-toggle.el][shell-toggle]]
-
-#+begin_src emacs-lisp
-(use-package shell-toggle
- :after eshell
- :bind ("C-c a s e" . amin/shell-toggle)
- :config
- (defun amin/shell-toggle (make-cd)
- "Toggle between the shell buffer and whatever buffer you are editing.
-With a prefix argument MAKE-CD also insert a \"cd DIR\" command
-into the shell, where DIR is the directory of the current buffer.
-
-When called in the shell buffer returns you to the buffer you were editing
-before calling this the first time.
-
-Options: `shell-toggle-goto-eob'"
- (interactive "P")
- ;; Try to decide on one of three possibilities:
- ;; If not in shell-buffer, switch to it.
- ;; If in shell-buffer, return to state before going to the shell-buffer
- (if (eq (current-buffer) shell-toggle-shell-buffer)
- (shell-toggle-buffer-return-from-shell)
- (progn
- (shell-toggle-buffer-goto-shell make-cd)
- (if shell-toggle-full-screen-window-only (delete-other-windows)))))
-
- ;; override to split horizontally instead
- (defun shell-toggle-buffer-switch-to-other-window ()
- "Switch to other window.
-If the current window is the only window in the current frame,
-create a new window and switch to it.
-
-\(This is less intrusive to the current window configuration than
-`switch-buffer-other-window')"
- (let ((this-window (selected-window)))
- (other-window 1)
- ;; If we did not switch window then we only have one window and need to
- ;; create a new one.
- (if (eq this-window (selected-window))
- (progn
- (split-window-horizontally)
- (other-window 1)))))
-
- :custom
- (shell-toggle-launch-shell 'shell-toggle-eshell))
-#+end_src
-
** [[https://github.com/EricCrosson/unkillable-scratch][unkillable-scratch]]
Make =*scratch*= and =*Messages*= unkillable.
(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]].
-** [[https://github.com/DarthFennec/highlight-indent-guides][highlight-indent-guides]]
+** orgalist
#+begin_src emacs-lisp
-(use-package highlight-indent-guides
- :disabled t
- :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
-#+end_src
-
-** pdf-tools
-
-#+begin_src emacs-lisp
-(use-package pdf-tools
- :defer t
- :magic ("%PDF" . pdf-view-mode)
- :config
- (setq pdf-view-resize-factor 1.05)
- (pdf-tools-install)
- :bind
- (:map pdf-view-mode-map
- ("C-s" . isearch-forward)
- ("C-r" . isearch-backward)
- ("j" . pdf-view-next-line-or-next-page)
- ("k" . pdf-view-previous-line-or-previous-page)
- ("h" . image-backward-hscroll)
- ("l" . image-forward-hscroll)))
-#+end_src
-
-** anzu
-
-#+begin_src emacs-lisp
-(use-package anzu)
+(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)
collect match))))
(if (not (eq branch nil))
(concat " " (substring branch 2))
- ""))))
-#+end_src
-
-** slack
-
-Hopefully temporary.
-
-#+begin_src emacs-lisp
-(use-package slack
- :disabled t
- :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 C-j" . term-line-mode)
- ("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
+ ("C-c C-j" . term-line-mode))
:config
(setq multi-term-program "/bin/screen"
;; TODO: add separate bindings for connecting to existing
(global-page-break-lines-mode))
#+end_src
+** expand-region
+
+#+begin_src emacs-lisp
+(use-package expand-region
+ :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
+
* 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)
+ a/gnus-init-file (no-littering-expand-etc-file-name "gnus")
+ mail-user-agent 'gnus-user-agent
+ read-mail-command 'gnus)
(use-package gnus
- :bind (("s-m" . gnus)
- ("s-M" . gnus-unplugged))
+ :bind (("s-m" . gnus)
+ ("s-M" . gnus-unplugged))
:init
(setq
gnus-select-method '(nnnil "")
(use-package 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
:config
'((".*"
(address "amin@aminb.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"))
((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)))
+ (eval (setq a/message-cite-say-hi nil)))
("nnimap\\+uwaterloo:.*"
(address "abandali@uwaterloo.ca")
(gcc "\"nnimap+uwaterloo:Sent Items\"")))))
#+begin_src emacs-lisp
(use-package message
:config
- (defconst amin--message-cite-style-format "On %Y-%m-%d %l:%M %p, %N wrote:")
+ (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-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
:after message
: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)
footnote-style 'unicode))
#+end_src
-** bbdb
+** ebdb
+
+#+begin_src emacs-lisp
+(use-package ebdb
+ :defer 2
+ :after gnus
+ :bind (:map gnus-group-mode-map ("e" . ebdb))
+ :config
+ (setq ebdb-sources (no-littering-expand-var-file-name "ebdb"))
+ (with-eval-after-load 'swiper
+ (add-to-list 'swiper-font-lock-exclude 'ebdb-mode t)))
-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.
+(use-package ebdb-com
+ :after ebdb)
-#+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
+;; (use-package ebdb-complete
+;; :after ebdb
+;; :config
+;; (ebdb-complete-enable))
-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.
+(use-package company-ebdb
+ :defer 2
+ :config
+ (defun company-ebdb--post-complete (_) nil))
-#+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 ebdb-gnus
+ :defer 3
+ :after ebdb
+ :custom
+ (ebdb-gnus-window-configuration
+ '(article
+ (vertical 1.0
+ (summary 0.25 point)
+ (horizontal 1.0
+ (article 1.0)
+ (ebdb-gnus 0.3))))))
+
+(use-package ebdb-mua
+ :defer 3
+ :after ebdb
+ ;; :custom (ebdb-mua-pop-up nil)
+ )
+
+;; (use-package ebdb-message
+;; :after ebdb)
+
+
+;; (use-package ebdb-vcard
+;; :after ebdb)
#+end_src
-** message-x
+** COMMENT message-x
#+begin_src emacs-lisp
(use-package message-x
- :disabled t
:custom
(message-x-completion-alist
(quote
. message-expand-group)))))
#+end_src
-** gnus-harvest
+** COMMENT gnus-harvest
#+begin_src emacs-lisp
(use-package gnus-harvest
- :disabled t
:commands gnus-harvest-install
:demand t
:config
#+end_src
* Blogging
+:PROPERTIES:
+:CUSTOM_ID: blogging
+:END:
** [[https://ox-hugo.scripter.co][ox-hugo]]
#+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: (add-hook 'after-save-hook #'a/async-babel-tangle 'append 'local)
+# eval: (when (featurep 'typo (typo-mode -1)))
# End: