diff options
Diffstat (limited to '')
| -rw-r--r-- | .emacs.d/init.el | 435 | 
1 files changed, 383 insertions, 52 deletions
diff --git a/.emacs.d/init.el b/.emacs.d/init.el index c7eac7e..8c1ff78 100644 --- a/.emacs.d/init.el +++ b/.emacs.d/init.el @@ -18,18 +18,34 @@  ;;; Commentary:  ;; Emacs configuration of Amin Bandali, computer scientist, functional -;; programmer, and free software advocate. - -;; THIS FILE IS AUTO-GENERATED FROM `init.org'. +;; programmer, and free software advocate.  Uses straight.el for +;; purely functional and fully reproducible package management. + +;; Over the years, I've taken inspiration from configurations of many +;; great people.  Some that I can remember off the top of my head are: +;; +;; - https://github.com/dieggsy/dotfiles +;; - https://github.com/dakra/dmacs +;; - http://pages.sachachua.com/.emacs.d/Sacha.html +;; - https://github.com/dakrone/eos +;; - http://doc.rix.si/cce/cce.html +;; - https://github.com/jwiegley/dot-emacs +;; - https://github.com/wasamasa/dotemacs +;; - https://github.com/hlissner/doom-emacs  ;;; Code: +;;; Emacs initialization +  (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 a/before-user-init-time                                      before-init-time))) +;; temporarily increase `gc-cons-threshhold' and `gc-cons-percentage' +;; during startup to reduce garbage collection frequency.  clearing +;; `file-name-handler-alist' seems to help reduce startup time too.  (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) @@ -39,6 +55,7 @@        ;; sidesteps a bug when profiling with esup        esup-child-profile-require-level 0) +;; set them back to their defaults once we're done initializing  (add-hook   'after-init-hook   (lambda () @@ -46,14 +63,46 @@           gc-cons-percentage a/gc-cons-percentage           file-name-handler-alist a/file-name-handler-alist))) +;; increase number of lines kept in *Messages* log  (setq message-log-max 20000) +;; optionally, uncomment to supress some byte-compiler warnings +;;   (see C-h v byte-compile-warnings RET for more info)  ;; (setq byte-compile-warnings  ;;       '(not free-vars unresolved noruntime lexical make-local)) + +;;; whoami +  (setq user-full-name "Amin Bandali"        user-mail-address "amin@bndl.org") + +;;; comment macro + +;; useful for commenting out multiple sexps at a time +(defmacro comment (&rest _) +  "Comment out one or more s-expressions." +  (declare (indent defun)) +  nil) + + +;;; Package management + +;; No package.el  (for emacs 26 and before, uncomment the following) +;; Not necessary when using straight.el +;;   (C-h v straight-package-neutering-mode RET) + +(comment +  (setq package-enable-at-startup nil) +  ;; (package-initialize) +  ) + +;; for emacs 27 and later, we use early-init.el.  see +;; https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=24acb31c04b4048b85311d794e600ecd7ce60d3b + +;; straight.el +  ;; Main engine start...  (setq straight-repository-branch "develop" @@ -99,6 +148,7 @@      (straight-mark-transaction-as-init)      (load user-init-file))) +;; use-package  (straight-use-package 'use-package)  (if nil                             ; set to t when need to debug init      (progn @@ -113,12 +163,24 @@  (setq use-package-always-defer t)  (require 'bind-key) -;; comment macro, useful for commenting out multiple sexps at a time -(defmacro comment (&rest _) -  "Comment out one or more s-expressions." -  (declare (indent defun)) -  nil) - +;; for browsing the Emacsmirror package database +(comment +  (use-package epkg +    :commands (epkg-list-packages epkg-describe-package) +    :bind +    (("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)))) + + +;;; Initial setup + +;; keep ~/.emacs.d clean  (use-package no-littering    :demand t    :config @@ -128,17 +190,21 @@    (setq auto-save-file-name-transforms          `((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))) +;; separate custom file (don't want it mixing with init.el)  (use-feature custom    :no-require t    :config    (setq custom-file (no-littering-expand-etc-file-name "custom.el"))    (when (file-exists-p custom-file)      (load custom-file)) +  ;; while at it, treat themes as safe    (setf custom-safe-themes t)) +;; load the secrets file if it exists, otherwise show a warning  (with-demoted-errors      (load (no-littering-expand-etc-file-name "secrets"))) +;; better $PATH (and other environment variable) handling  (use-package exec-path-from-shell    :defer 0.4    :init @@ -150,18 +216,65 @@    (exec-path-from-shell-copy-env "SSH_AGENT_PID")    (exec-path-from-shell-copy-env "SSH_AUTH_SOCK")) + +;; only one custom theme at a time +(comment +  (defadvice load-theme (before clear-previous-themes activate) +    "Clear existing theme settings instead of layering them" +    (mapc #'disable-theme custom-enabled-themes))) + +;; start up emacs server.  see +;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.html#Emacs-Server  (use-feature server    :defer 0.4    :config (or (server-running-p) (server-mode))) +;; unicode support +(comment +  (dolist (ft (fontset-list)) +    (set-fontset-font +     ft +     'unicode +     (font-spec :name "Source Code Pro" :size 14)) +    (set-fontset-font +     ft +     'unicode +     (font-spec :name "DejaVu Sans Mono") +     nil +     'append) +    ;; (set-fontset-font +    ;;  ft +    ;;  'unicode +    ;;  (font-spec +    ;;   :name "Symbola monospacified for DejaVu Sans Mono") +    ;;  nil +    ;;  'append) +    ;; (set-fontset-font +    ;;  ft +    ;;  #x2115  ; ℕ +    ;;  (font-spec :name "DejaVu Sans Mono") +    ;;  nil +    ;;  'append) +    (set-fontset-font +     ft +     (cons ?Α ?ω) +     (font-spec :name "DejaVu Sans Mono" :size 14) +     nil +     'prepend))) + +;; gentler font resizing  (setq text-scale-mode-step 1.05) +;; focus follows mouse  (setq mouse-autoselect-window t)  (defun a/no-mouse-autoselect-window () +  "Conveniently disable `focus-follows-mouse'. +For disabling the behaviour for certain buffers and/or modes."    (make-local-variable 'mouse-autoselect-window)    (setq mouse-autoselect-window nil)) +;; better scrolling  (setq ;; scroll-margin 1        ;; scroll-conservatively 10000        scroll-step 1 @@ -179,11 +292,16 @@    :defer 0.4    :config (pixel-scroll-mode 1)) +;; ask for GPG passphrase in minibuffer  (setq epg-pinentry-mode 'loopback) +;; useful libraries  (require 'cl-lib)  (require 'subr-x) + +;;; Useful utilities +  (defmacro a/setq-every (value &rest vars)    "Set all the variables from VARS to value VALUE."    (declare (indent defun) (debug t)) @@ -205,51 +323,93 @@           program           (remove nil (list args (dired-get-file-for-visit))))) +(defun a/add-elisp-section () +  (interactive) +  (insert "\n") +  (previous-line) +  (insert "\n\n;;; ")) + + +;;; Defaults + +;; time and battery in mode-line +(comment +  (use-package time +    :init +    (setq display-time-default-load-average nil) +    :config +    (display-time-mode)) + +  (use-package battery +    :config +    (display-battery-mode))) + +;; smaller fringe  ;; (fringe-mode '(3 . 1))  (fringe-mode nil) +;; disable disabled commands  (setq disabled-command-function nil) +;; Save what I copy into clipboard from other applications into Emacs' +;; kill-ring, which would allow me to still be able to easily access +;; it in case I kill (cut or copy) something else inside Emacs before +;; yanking (pasting) what I'd originally intended to.  (setq save-interprogram-paste-before-kill t) +;; minibuffer  (setq enable-recursive-minibuffers t        resize-mini-windows t) +;; lazy-person-friendly yes/no prompts  (defalias 'yes-or-no-p #'y-or-n-p) +;; i want *scratch* as my startup buffer  (setq initial-buffer-choice t) +;; i don't need the default hint  (setq initial-scratch-message nil) +;; use customizable text-mode as major mode for *scratch*  (setq initial-major-mode 'text-mode) +;; inhibit buffer list when more than 2 files are loaded  (setq inhibit-startup-buffer-menu t) +;; don't need to see the startup screen or the echo area message  (advice-add #'display-startup-echo-area-message :override #'ignore)  (setq inhibit-startup-screen t        inhibit-startup-echo-area-message user-login-name) +;; more useful frame titles  (setq frame-title-format        '("" invocation-name " - "          (:eval (if (buffer-file-name)                     (abbreviate-file-name (buffer-file-name))                   "%b")))) +;; backups (C-h v make-backup-files RET)  (setq backup-by-copying t        version-control t        delete-old-versions t) +;; enable automatic reloading of changed buffers and files  (global-auto-revert-mode 1)  (setq auto-revert-verbose nil        global-auto-revert-non-file-buffers nil) +;; always use space for indentation  (setq-default   indent-tabs-mode nil   require-final-newline t   tab-width 4) +;; enable winner-mode (C-h f winner-mode RET)  (winner-mode 1) +;; don't display *compilation* buffer on success.  based on +;; https://stackoverflow.com/a/17788551, with changes to use `cl-letf' +;; instead of the now obsolete `flet'.  (with-eval-after-load 'compile    (defun a/compilation-finish-function (buffer outstr)      (unless (string-match "finished" outstr) @@ -269,15 +429,23 @@        ad-do-it))    (ad-activate 'compilation-start)) +;; search for non-ASCII characters: i’d like non-ASCII characters such +;; as ‘’“”«»‹›áⓐ𝒶 to be selected when i search for their ASCII +;; counterpart.  shoutout to +;; http://endlessparentheses.com/new-in-emacs-25-1-easily-search-non-ascii-characters.html  (setq search-default-mode #'char-fold-to-regexp) -  ;; uncomment to extend this behaviour to query-replace  ;; (setq replace-char-fold t) +;; cursor shape  (setq-default cursor-type 'bar) +;; allow scrolling in Isearch  (setq isearch-allow-scroll t) + +;;; General bindings +  (bind-keys   ("C-c a i" . ielm) @@ -300,7 +468,10 @@   ("C-x K"   . kill-buffer)   ("s-p"     . beginning-of-buffer) - ("s-n"     . end-of-buffer)) + ("s-n"     . end-of-buffer) + + :map emacs-lisp-mode-map + ("<C-return>" . a/add-elisp-section))  (when (display-graphic-p)    (unbind-key "C-z" global-map)) @@ -331,6 +502,9 @@   ("p P" . straight-push-package)   ("p r" . straight-rebuild-package)) + +;;; Essential packages +  (use-package auto-compile    :demand t    :config @@ -344,6 +518,7 @@    (add-hook 'auto-compile-inhibit-compile-hook              'auto-compile-inhibit-compile-detached-git-head)) +;; use the org-plus-contrib package to get the whole deal  (straight-use-package 'org-plus-contrib)  (use-feature org @@ -397,6 +572,9 @@    :config    (ox-extras-activate '(latex-header-blocks ignore-headlines))) +;; asynchronous tangle, using emacs-async to asynchronously tangle an +;; org file.  closely inspired by +;; https://github.com/dieggsy/dotfiles/tree/cc10edf7701958eff1cd94d4081da544d882a28c/emacs.d#dotfiles  (with-eval-after-load 'org    (defvar a/show-async-tangle-results nil      "Keep *emacs* async buffers around for later inspection.") @@ -432,6 +610,7 @@   'safe-local-variable-values   '(eval add-hook 'after-save-hook #'a/async-babel-tangle 'append 'local)) +;; *the* right way to do git  (use-package magit    :defer 0.5    :bind (("C-x g" . magit-status) @@ -449,12 +628,14 @@             ([unpushed status] . show)))    :custom-face (magit-diff-file-heading ((t (:weight normal))))) +;; recently opened files  (use-feature recentf    :defer 0.2    :config    (add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?:")    (setq recentf-max-saved-items 40)) +;; smart M-x enhancement (needed by counsel for history)  (use-package smex)  (use-package ivy @@ -497,6 +678,23 @@    (counsel-mode 1)    (defalias 'locate #'counsel-locate)) +(comment +  (use-package helm +    :commands (helm-M-x helm-mini helm-resume) +    :bind (("M-x"     . helm-M-x) +           ("M-y"     . helm-show-kill-ring) +           ("C-x b"   . helm-mini) +           ("C-x C-b" . helm-buffers-list) +           ("C-x C-f" . helm-find-files) +           ("C-h r"   . helm-info-emacs) +           ("s-r"     . helm-recentf) +           ("C-s-r"   . helm-resume) +           :map helm-map +           ("<tab>" . helm-execute-persistent-action) +           ("C-i"   . helm-execute-persistent-action) ; Make TAB work in terminals +           ("C-z"   . helm-select-action))            ; List actions +    :config (helm-mode 1))) +  (use-feature eshell    :defer 0.5    :commands eshell @@ -680,16 +878,22 @@    :bind (:map doc-view-mode-map                ("M-RET" . image-previous-line))) + +;;; Editing + +;; highlight uncommitted changes in the left fringe  (use-package diff-hl    :config    (setq diff-hl-draw-borders nil)    (global-diff-hl-mode)    :hook (magit-post-refresh . diff-hl-magit-post-refresh)) +;; display Lisp objects at point in the echo area  (use-feature eldoc    :when (version< "25" emacs-version)    :config (global-eldoc-mode)) +;; highlight matching parens  (use-feature paren    :demand    :config (show-paren-mode)) @@ -697,9 +901,11 @@  (use-feature simple    :config (column-number-mode)) +;; save minibuffer history  (use-feature savehist    :config (savehist-mode)) +;; automatically save place in files  (use-feature saveplace    :when (version< "25" emacs-version)    :config (save-place-mode)) @@ -769,6 +975,9 @@    (advice-add #'ispell-parse-output :filter-args                #'endless/replace-quote)) + +;;; Programming modes +  (use-feature lisp-mode    :config    (add-hook 'emacs-lisp-mode-hook 'outline-minor-mode) @@ -782,7 +991,7 @@    :mode "\\.als\\'"    :config (setq alloy-basic-offset 2)) -(use-package proof-site  ; Proof General +(use-package proof-site                 ; for Coq    :straight proof-general)  (eval-when-compile (defvar lean-mode-map)) @@ -820,6 +1029,7 @@  (use-package flycheck-haskell    :after haskell-mode) +;; alternative: hs-lint https://github.com/ndmitchell/hlint/blob/20e116a043f2073c57b17b24ae6364b5e433ba7e/data/hs-lint.el  (use-package sgml-mode    :config @@ -846,6 +1056,78 @@    (setq emmet-move-cursor-between-quotes t)    :hook (web-mode css-mode html-mode sgml-mode)) +(comment +  (use-package meghanada +    :bind +    (:map meghanada-mode-map +          (("C-M-o" . meghanada-optimize-import) +           ("C-M-t" . meghanada-import-all))) +    :hook (java-mode . meghanada-mode))) + +(comment +  (use-package treemacs +    :config (setq treemacs-never-persist t)) + +  (use-package yasnippet +    :config +    ;; (yas-global-mode) +    ) + +  (use-package lsp-mode +    :init (setq lsp-eldoc-render-all nil +                lsp-highlight-symbol-at-point nil) +    ) + +  (use-package hydra) + +  (use-package company-lsp +    :after company +    :config +    (setq company-lsp-cache-candidates t +          company-lsp-async t)) + +  (use-package lsp-ui +    :config +    (setq lsp-ui-sideline-update-mode 'point)) + +  (use-package lsp-java +    :config +    (add-hook 'java-mode-hook +	          (lambda () +	            (setq-local company-backends (list 'company-lsp)))) + +    (add-hook 'java-mode-hook 'lsp-java-enable) +    (add-hook 'java-mode-hook 'flycheck-mode) +    (add-hook 'java-mode-hook 'company-mode) +    (add-hook 'java-mode-hook 'lsp-ui-mode)) + +  (use-package dap-mode +    :after lsp-mode +    :config +    (dap-mode t) +    (dap-ui-mode t)) + +  (use-package dap-java +    :after (lsp-java)) + +  (use-package lsp-java-treemacs +    :after (treemacs))) + +(comment +  (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")))) +  (use-package geiser)  (use-feature geiser-guile @@ -854,6 +1136,56 @@  (use-package guix) +(comment +  (use-package auctex +    :custom +    (font-latex-fontify-sectioning 'color))) + + +;;; Theme + +(add-to-list 'custom-theme-load-path "~/.emacs.d/lisp") +(load-theme 'tangomod t) + +(use-package smart-mode-line +  :commands (sml/apply-theme) +  :demand +  :config +  (sml/setup)) + +(use-package doom-themes) + +(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) +  (font-lock-remove-keywords +   'org-mode a/org-mode-font-lock-keywords)) + +(defun a/lights-off () +  "Go dark." +  (interactive) +  (mapc #'disable-theme custom-enabled-themes) +  (load-theme 'doom-tomorrow-night t) +  (sml/apply-theme 'automatic) +  (font-lock-add-keywords +   'org-mode a/org-mode-font-lock-keywords t)) + +(bind-keys + ("s-t d" . a/lights-off) + ("s-t l" . a/lights-on)) + + +;;; Emacs enhancements & auxiliary packages +  (use-feature man    :config (setq Man-width 80)) @@ -914,46 +1246,7 @@    (which-key-add-column-padding 5)    (which-key-max-description-length 32)) -(add-to-list 'custom-theme-load-path "~/.emacs.d/lisp") -(load-theme 'tangomod t) - -(use-package smart-mode-line -  :commands (sml/apply-theme) -  :demand -  :config -  (sml/setup)) - -(use-package doom-themes) - -(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) -  (font-lock-remove-keywords -   'org-mode a/org-mode-font-lock-keywords)) - -(defun a/lights-off () -  "Go dark." -  (interactive) -  (mapc #'disable-theme custom-enabled-themes) -  (load-theme 'doom-tomorrow-night t) -  (sml/apply-theme 'automatic) -  (font-lock-add-keywords -   'org-mode a/org-mode-font-lock-keywords t)) - -(bind-keys - ("s-t d" . a/lights-off) - ("s-t l" . a/lights-on)) - -(use-package crux                       ; results in Waiting for git... [2 times] +(use-package crux            ; results in Waiting for git... [2 times]    :defer 0.4    :bind (("C-c b k" . crux-kill-other-buffers)           ("C-c d"   . crux-duplicate-current-line-or-region) @@ -1003,6 +1296,9 @@    :custom    (unkillable-buffers '("^\\*scratch\\*$" "^\\*Messages\\*$"))) +;; ,---- +;; | make pretty boxed quotes like this +;; `----  (use-package boxquote    :defer 0.6    :bind @@ -1030,16 +1326,19 @@     ("M-w" . boxquote-kill-ring-save)))  (use-package orgalist +  ;; http://lists.gnu.org/archive/html/emacs-orgmode/2019-04/msg00007.html    :disabled t    :after message    :hook (message-mode . orgalist-mode)) +;; easily type pretty quotes & other typography, like ‘’“”-–—«»‹›  (use-package typo    :defer 0.5    :config    (typo-global-mode 1)    :hook (text-mode . typo-mode)) +;; highlight TODOs in buffers  (use-package hl-todo    :defer 0.5    :config @@ -1097,6 +1396,7 @@          '("C-z" "C-x" "C-c" "C-h" "C-y" "<ESC>")))  (use-package page-break-lines +  :defer 0.5    :config    (global-page-break-lines-mode)) @@ -1143,6 +1443,7 @@     org-ref-bibliography-notes "~/usr/org/notes.org"     org-ref-pdf-directory "~/usr/org/bibtex-pdfs/")) +;; ugh, temporary (still better than using the proprietary web app)  (use-package slack    :commands (slack-start)    :init @@ -1192,6 +1493,9 @@    :init    (setq alert-default-style 'notifier)) + +;;; Email (with Gnus) +  (defvar a/maildir (expand-file-name "~/mail/"))  (with-eval-after-load 'recentf    (add-to-list 'recentf-exclude a/maildir)) @@ -1518,6 +1822,30 @@  (use-package message-x) +(comment +  (use-package message-x +    :custom +    (message-x-completion-alist +     (quote +      (("\\([rR]esent-\\|[rR]eply-\\)?[tT]o:\\|[bB]?[cC][cC]:" . gnus-harvest-find-address) +       ((if +            (boundp +             (quote message-newgroups-header-regexp)) +            message-newgroups-header-regexp message-newsgroups-header-regexp) +        . message-expand-group)))))) + +(comment +  (use-package gnus-harvest +    :commands gnus-harvest-install +    :demand t +    :config +    (if (featurep 'message-x) +        (gnus-harvest-install 'message-x) +      (gnus-harvest-install)))) + + +;;; IRC +  (use-package znc    :straight (:host nil :repo "https://git.bndl.org/amin/znc.el")    :bind (("C-c a e e" . znc-erc) @@ -1533,6 +1861,9 @@              ("znc.bndl.org" 1337 t               ((moznet "amin/moznet" ,pwd))))))) + +;;; Post initialization +  (message "Loading %s...done (%.3fs)" user-init-file           (float-time (time-subtract (current-time)                                      a/before-user-init-time)))  | 
