X-Git-Url: https://git.shemshak.org/gitweb.cgi/~bandali/configs/blobdiff_plain/f1516d514c999d36839ff7f6e70f63a7d4c43390..197330785f9a001d49ad6afb33e2e69761fa3169:/init.org?ds=inline diff --git a/init.org b/init.org index 3a170a3..9acbd33 100644 --- a/init.org +++ b/init.org @@ -104,28 +104,12 @@ file. #+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 @@ -138,10 +122,10 @@ let's see how long Emacs takes to start up, before even loading =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 @@ -151,9 +135,9 @@ frequency. Clearing the ~file-name-handler-alist~ seems to help reduce 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 @@ -168,9 +152,9 @@ done initializing. (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*= @@ -200,9 +184,9 @@ but for now I've decided to keep them enabled. See documentation for *** 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) @@ -213,12 +197,56 @@ right now), and even when released it'll be long before most distros 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 +Next-generation, purely functional package manager for the Emacs +hacker. +#+end_quote + +=straight.el= allows me to have a fully reproducible Emacs setup. + +#+begin_src emacs-lisp +(setq straight-repository-branch "develop") + +(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)) + +(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 + +*** COMMENT Borg #+begin_quote Assimilate Emacs packages as Git submodules @@ -260,7 +288,7 @@ packages (in our case especially the latter) in a neatly organized way and without compromising on performance. #+begin_src emacs-lisp -(require 'use-package) +(straight-use-package 'use-package) (if nil ; set to t when need to debug init (setq use-package-verbose t use-package-expand-minimally nil @@ -268,9 +296,11 @@ and without compromising on performance. debug-on-error t) (setq use-package-verbose nil use-package-expand-minimally t)) + +(setq use-package-always-defer t) #+end_src -*** Epkg +*** COMMENT Epkg #+begin_quote Browse the Emacsmirror package database @@ -286,7 +316,12 @@ database, low-level functions for querying the database, and a :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= @@ -317,7 +352,7 @@ definitely don't want it mixing with =init.el=. So, here; let's give 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")) @@ -371,7 +406,7 @@ login; so starting the server from inside Emacs is good enough for me. 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 @@ -433,7 +468,7 @@ Let’s define a function to conveniently disable this for certain 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 @@ -447,48 +482,35 @@ buffers and/or modes. ** 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 @@ -660,12 +682,12 @@ Based on https://stackoverflow.com/a/17788551, with changes to use #+begin_src emacs-lisp (with-eval-after-load 'compile - (defun amin--compilation-finish-function (buffer outstr) + (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) @@ -698,9 +720,16 @@ for this. (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 +(require 'bind-key) (bind-keys ("C-c a i" . ielm) @@ -748,7 +777,7 @@ customizing it. '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 @@ -758,9 +787,52 @@ system. In short, my favourite way of life. +First, we have to resort to a [[https://github.com/raxod502/straight.el#installing-org-with-straightel][hack]] to be able to use the correct +latest version of Org from upstream. + #+begin_src emacs-lisp -(use-package org - :defer 1 + (use-package git) + + (defun org-git-version () + "The Git version of org-mode. + Inserted by installing org-mode or when a release is made." + (require 'git) + (let ((git-repo (expand-file-name + "straight/repos/org/" user-emacs-directory))) + (string-trim + (git-run "describe" + "--match=release\*" + "--abbrev=6" + "HEAD")))) + + (defun org-release () + "The release version of org-mode. + Inserted by installing org-mode or when a release is made." + (require 'git) + (let ((git-repo (expand-file-name + "straight/repos/org/" user-emacs-directory))) + (string-trim + (string-remove-prefix + "release_" + (git-run "describe" + "--match=release\*" + "--abbrev=0" + "HEAD"))))) + +(provide 'org-version) +#+end_src + +We will use the =org-plus-contrib= package to get the whole deal: + +#+begin_src emacs-lisp +(straight-use-package 'org-plus-contrib) +#+end_src + +And here's where my actual Org configurations begin: + +#+begin_src emacs-lisp +(use-feature org + :defer 0.5 :config (setq org-src-tab-acts-natively t org-src-preserve-indentation nil @@ -790,7 +862,7 @@ In short, my favourite way of life. '(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 @@ -807,32 +879,28 @@ In short, my favourite way of life. ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) t)) -(use-package ox-beamer +(use-feature ox-beamer :after ox) - -(use-package orgalist - :after message - :hook (message-mode . orgalist-mode)) #+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 () + (defun a/async-babel-tangle () "Tangle org file asynchronously." (interactive) (let* ((file-tangle-start-time (current-time)) @@ -844,24 +912,24 @@ file. `(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 (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))) (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]] @@ -892,6 +960,30 @@ Not just how I do git, but /the/ way to do git. :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 @@ -905,7 +997,7 @@ There's no way I could top that, so I won't attempt to. #+begin_src emacs-lisp (use-package ivy - :defer 1 + :defer 0.6 :bind (:map ivy-minibuffer-map ([escape] . keyboard-escape-quit) @@ -926,6 +1018,7 @@ There's no way I could top that, so I won't attempt to. #+begin_src emacs-lisp (use-package swiper + :after ivy :bind (("C-s" . swiper) ("C-r" . swiper) ("C-S-s" . isearch-forward))) @@ -935,7 +1028,7 @@ There's no way I could top that, so I won't attempt to. #+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) @@ -951,34 +1044,35 @@ There's no way I could top that, so I won't attempt to. *** eshell #+begin_src emacs-lisp -(use-package eshell +(use-feature eshell :defer 1 :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)) @@ -987,8 +1081,7 @@ There's no way I could top that, so I won't attempt to. *** 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 @@ -1058,8 +1151,7 @@ There's no way I could top that, so I won't attempt to. *** Outline #+begin_src emacs-lisp -(use-package outline - :defer t +(use-feature outline :hook (prog-mode . outline-minor-mode) :bind (:map @@ -1067,7 +1159,7 @@ There's no way I could top that, so I won't attempt to. ("" . 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) @@ -1077,96 +1169,151 @@ There's no way I could top that, so I won't attempt to. ("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)) - -(progn ; `isearch' - (setq isearch-allow-scroll t)) - -(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)) +** paren -(use-package man - :defer t - :config (setq Man-width 80)) +Highlight matching parens. -(use-package paren +#+begin_src emacs-lisp +(use-feature paren :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)) +** =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 @@ -1186,10 +1333,7 @@ TODO: break this giant source block down into individual org sections. (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 @@ -1238,20 +1382,30 @@ TODO: break this giant source block down into individual org sections. :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 ** [[https://coq.inria.fr][Coq]] (with [[https://github.com/ProofGeneral/PG][Proof General]]) #+begin_src emacs-lisp -(use-package proof-site ; Proof General - :defer t - :load-path "lib/proof-site/generic/") +(use-package proof-general) #+end_src ** [[https://leanprover.github.io][Lean]] (with [[https://github.com/leanprover/lean-mode][lean-mode]]) @@ -1278,7 +1432,6 @@ TODO: break this giant source block down into individual org sections. #+begin_src emacs-lisp (use-package haskell-mode - :defer t :config (setq haskell-indentation-layout-offset 4 haskell-indentation-left-offset 4 @@ -1461,13 +1614,12 @@ instead. ("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 @@ -1476,7 +1628,6 @@ instead. #+begin_src emacs-lisp (use-package css-mode - :defer t :config (setq css-indent-offset 2)) #+end_src @@ -1485,10 +1636,9 @@ instead. #+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)) @@ -1588,21 +1738,20 @@ treemacs :after (treemacs)) #+end_src -** geiser +** COMMENT 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 +** COMMENT guix #+begin_src emacs-lisp -(use-package guix - :load-path "lib/guix/elisp") +(use-package guix) #+end_src * Emacs enhancements @@ -1610,6 +1759,13 @@ treemacs :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 @@ -1619,7 +1775,51 @@ Emacs package that displays available keybindings in popup #+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 @@ -1646,14 +1846,14 @@ Emacs package that displays available keybindings in popup ** theme helper functions #+begin_src emacs-lisp -(defun amin/lights-on () +(defun a/lights-on () "Enable my favourite light theme." (interactive) (mapc #'disable-theme custom-enabled-themes) (load-theme 'tangomod t) (sml/apply-theme 'automatic)) -(defun amin/lights-off () +(defun a/lights-off () "Go dark." (interactive) (mapc #'disable-theme custom-enabled-themes) @@ -1661,14 +1861,14 @@ Emacs package that displays available keybindings in popup (sml/apply-theme 'automatic)) (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) @@ -1694,7 +1894,6 @@ Emacs package that displays available keybindings in popup #+begin_src emacs-lisp (use-package projectile - :defer t :bind-keymap ("C-c p" . projectile-command-map) :config (projectile-mode) @@ -1751,7 +1950,7 @@ 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) @@ -1777,6 +1976,14 @@ Make =*scratch*= and =*Messages*= unkillable. Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. +** orgalist + +#+begin_src emacs-lisp +(use-package orgalist + :after message + :hook (message-mode . orgalist-mode)) +#+end_src + ** typo.el #+begin_src emacs-lisp @@ -1839,8 +2046,7 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. #+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) + :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 @@ -1885,29 +2091,41 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. :bind ("C-=" . er/expand-region)) #+end_src +** multiple-cursors + +#+begin_src emacs-lisp +(use-package multiple-cursors + :bind + (("C-S-" . 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) - -(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 @@ -1939,7 +2157,7 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. gnus-interactive-exit nil gnus-gcc-mark-as-read t)) -(use-package gnus-art +(use-feature gnus-art :config (setq gnus-visible-headers @@ -1968,9 +2186,9 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. ("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) @@ -1981,38 +2199,38 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. ("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") (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\""))))) -(use-package gnus-topic +(use-feature gnus-topic :hook (gnus-group-mode . gnus-topic-mode)) -(use-package gnus-agent +(use-feature gnus-agent :config (setq gnus-agent-synchronize-flags 'ask) :hook (gnus-group-mode . gnus-agent-mode)) -(use-package gnus-group +(use-feature gnus-group :config (setq gnus-permanently-visible-groups "\\((INBOX\\|gnu$\\)")) -(use-package mm-decode +(use-feature mm-decode :config (setq mm-discouraged-alternatives '("text/html" "text/richtext"))) #+end_src @@ -2020,7 +2238,7 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. ** sendmail #+begin_src emacs-lisp -(use-package sendmail +(use-feature sendmail :config (setq sendmail-program "/usr/bin/msmtp" ;; message-sendmail-extra-arguments '("-v" "-d") @@ -2031,9 +2249,9 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. ** 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:") + (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) @@ -2042,9 +2260,9 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. (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 @@ -2066,7 +2284,7 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. ;; (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 @@ -2076,11 +2294,11 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]]. Convenient footnotes in =message-mode=. #+begin_src emacs-lisp -(use-package footnote +(use-feature footnote :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) @@ -2099,14 +2317,14 @@ Convenient footnotes in =message-mode=. #+begin_src emacs-lisp (use-package ebdb - :defer 1 + :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 @@ -2123,7 +2341,7 @@ Convenient footnotes in =message-mode=. (add-to-list (make-local-variable 'company-backends) 'company-ebdb)))) -(use-package ebdb-gnus +(use-feature ebdb-gnus :after ebdb :custom (ebdb-gnus-window-configuration @@ -2134,7 +2352,7 @@ Convenient footnotes in =message-mode=. (article 1.0) (ebdb-gnus 0.3)))))) -(use-package ebdb-mua +(use-feature ebdb-mua :after ebdb ;; :custom (ebdb-mua-pop-up nil) ) @@ -2185,8 +2403,8 @@ Convenient footnotes in =message-mode=. (use-package ox-hugo :after ox) -(use-package ox-hugo-auto-export - :load-path "lib/ox-hugo") +(use-feature ox-hugo-auto-export + :after ox-hugo) #+end_src * Post initialization @@ -2199,7 +2417,7 @@ Display how long it took to load the init file. #+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 @@ -2213,6 +2431,6 @@ Display how long it took to load the init file. * 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: (typo-mode -1) # End: