(defvar b/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 b/before-user-init-time
- before-init-time)))
+(defvar b/emacs-initialized nil
+ "Whether Emacs has been initialized.")
+
+(when (not (bound-and-true-p b/emacs-initialized))
+ (message "Loading Emacs...done (%.3fs)"
+ (float-time (time-subtract b/before-user-init-time
+ before-init-time))))
;; temporarily increase `gc-cons-threshhold' and `gc-cons-percentage'
;; during startup to reduce garbage collection frequency. clearing
;; set them back to their defaults once we're done initializing
(defun b/post-init ()
- (setq gc-cons-threshold b/gc-cons-threshold
- gc-cons-percentage b/gc-cons-percentage
+ "My post-initialize function, run after loading `user-init-file'."
+ (setq b/emacs-initialized t
+ gc-cons-threshold b/gc-cons-threshold
+ gc-cons-percentage b/gc-cons-percentage
file-name-handler-alist b/file-name-handler-alist))
(add-hook 'after-init-hook #'b/post-init)
:straight nil
,@args))
+(with-eval-after-load 'use-package-core
+ (let ((upflk (car use-package-font-lock-keywords)))
+ (font-lock-add-keywords
+ 'emacs-lisp-mode
+ `((,(replace-regexp-in-string
+ "use-package" "use-feature"
+ (car upflk))
+ ,@(cdr upflk))))))
+
(with-eval-after-load 'recentf
(add-to-list 'recentf-exclude
(expand-file-name "~/.emacs.d/straight/build/")))
(defun b/reload-init ()
- "Reload init.el."
+ "Reload `user-init-file'."
(interactive)
- (setq b/file-name-handler-alist file-name-handler-alist)
+ (setq b/before-user-init-time (current-time)
+ b/file-name-handler-alist file-name-handler-alist)
(load user-init-file nil 'nomessage)
(b/post-init))
(setq use-package-always-defer t)
(require 'bind-key)
-(use-package delight)
-
\f
;;; Initial setup
;; keep ~/.emacs.d clean
-(defvar b/etc-dir
- (expand-file-name
- (convert-standard-filename "etc/") user-emacs-directory)
- "The directory where packages place their configuration files.")
-
-(defvar b/var-dir
- (expand-file-name
- (convert-standard-filename "var/") user-emacs-directory)
- "The directory where packages place their persistent data files.")
-
-(defun b/etc (file)
- "Expand filename FILE relative to `b/etc-dir'."
- (expand-file-name (convert-standard-filename file) b/etc-dir))
-
-(defun b/var (file)
- "Expand filename FILE relative to `b/var-dir'."
- (expand-file-name (convert-standard-filename file) b/var-dir))
-
-(setq
- auto-save-list-file-prefix (b/var "auto-save/sessions/")
- nsm-settings-file (b/var "nsm-settings.el"))
+(use-package no-littering
+ :demand
+ :config
+ (defalias 'b/etc 'no-littering-expand-etc-file-name)
+ (defalias 'b/var 'no-littering-expand-var-file-name))
;; separate custom file (don't want it mixing with init.el)
(use-feature custom
- :no-require t
+ :no-require
:config
(setq custom-file (b/etc "custom.el"))
(when (file-exists-p custom-file)
(load custom-file))
;; while at it, treat themes as safe
- (setf custom-safe-themes t))
+ (setf custom-safe-themes t)
+ ;; 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))))
;; load the secrets file if it exists, otherwise show a warning
(comment
(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)))
+\f
+;;; Useful utilities
+
+;; useful libraries
+(require 'cl-lib)
+(require 'subr-x)
+
+(defmacro b/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)))
+
+(defun b/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 b/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 #'b/start-process
+ program
+ (remove nil (list args (dired-get-file-for-visit)))))
+
+(defun b/add-elisp-section ()
+ (interactive)
+ (insert "\n")
+ (previous-line)
+ (insert "\n\f\n;;; "))
+
+(defun b/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))
+
+\f
+;;; Defaults
+
+;;;; C-level customizations
+
+(setq
+ ;; minibuffer
+ enable-recursive-minibuffers t
+ resize-mini-windows t
+ ;; more useful frame titles
+ frame-title-format '("" invocation-name " - "
+ (:eval
+ (if (buffer-file-name)
+ (abbreviate-file-name (buffer-file-name))
+ "%b")))
+ ;; i don't feel like jumping out of my chair every now and again; so
+ ;; don't BEEP! at me, emacs
+ ring-bell-function 'ignore
+ ;; better scrolling
+ ;; scroll-margin 1
+ ;; scroll-conservatively 10000
+ scroll-step 1
+ scroll-conservatively 10
+ scroll-preserve-screen-position 1
+ ;; focus follows mouse
+ mouse-autoselect-window t)
+
+(setq-default
+ ;; always use space for indentation
+ indent-tabs-mode nil
+ tab-width 4
+ ;; cursor shape
+ cursor-type 'bar)
+
;; unicode support
(comment
(dolist (ft (fontset-list))
nil
'prepend)))
-;; gentler font resizing
-(setq text-scale-mode-step 1.05)
-
-;; focus follows mouse
-(setq mouse-autoselect-window t)
+;;;; Elisp-level customizations
-(defun b/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
- scroll-conservatively 10
- scroll-preserve-screen-position 1)
-
-(use-feature mwheel
- :defer 0.4
+(use-feature startup
+ :no-require
+ :demand
:config
- (setq mouse-wheel-scroll-amount '(1 ((shift) . 1)) ; one line at a time
- mouse-wheel-progressive-speed nil ; don't accelerate scrolling
- mouse-wheel-follow-mouse t)) ; scroll window under mouse
-
-(use-feature pixel-scroll
- :defer 0.4
- :config (pixel-scroll-mode 1))
-
-;; ask for GPG passphrase in minibuffer
-(use-feature epa
- :custom
- ; this will fail if gpg>=2.1 is not available
- (epa-pinentry-mode 'loopback))
-
-(use-feature epg-config
- :defer 0.4
+ ;; don't need to see the startup echo area message
+ (advice-add #'display-startup-echo-area-message :override #'ignore)
:custom
- ((epg-gpg-program (executable-find "gpg"))
- (epg-pinentry-mode 'loopback)))
-
-(use-feature epg
- :after epg-config)
-
-(use-package pinentry
+ ;; i want *scratch* as my startup buffer
+ (initial-buffer-choice t)
+ ;; i don't need the default hint
+ (initial-scratch-message nil)
+ ;; use customizable text-mode as major mode for *scratch*
+ ;; (initial-major-mode 'text-mode)
+ ;; inhibit buffer list when more than 2 files are loaded
+ (inhibit-startup-buffer-menu t)
+ ;; don't need to see the startup screen or echo area message
+ (inhibit-startup-screen t)
+ (inhibit-startup-echo-area-message user-login-name))
+
+(use-feature files
+ :no-require
:demand
- :after (epa epg server)
- :config
- (setq pinentry--socket-dir server-socket-dir)
- (pinentry-start))
-
-;; useful libraries
-(require 'cl-lib)
-(require 'subr-x)
-
-\f
-;;; Useful utilities
-
-(defmacro b/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)))
-
-(defun b/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 b/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 #'b/start-process
- program
- (remove nil (list args (dired-get-file-for-visit)))))
-
-(defun b/add-elisp-section ()
- (interactive)
- (insert "\n")
- (previous-line)
- (insert "\n\f\n;;; "))
-
-\f
-;;; Defaults
+ :custom
+ ;; backups (C-h v make-backup-files RET)
+ (backup-by-copying t)
+ (version-control t)
+ (delete-old-versions t)
-;; time and battery in mode-line
-(comment
- (use-package time
- :init
- (setq display-time-default-load-average nil)
- :config
- (display-time-mode))
+ ;; auto-save
+ (auto-save-file-name-transforms
+ `((".*" ,(b/var "auto-save/") t)))
- (use-package battery
- :config
- (display-battery-mode)))
+ ;; insert newline at the end of files
+ (require-final-newline t)
-;; smaller fringe
-;; (fringe-mode '(3 . 1))
-(fringe-mode nil)
+ ;; open read-only file buffers in view-mode
+ ;; (enables niceties like `q' for quit)
+ (view-read-only t))
;; 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"))))
+;; enable automatic reloading of changed buffers and files
+(use-feature autorevert
+ :demand
+ :config
+ (global-auto-revert-mode 1)
+ :custom
+ (auto-revert-verbose nil)
+ (global-auto-revert-non-file-buffers nil))
-;; backups (C-h v make-backup-files RET)
-(setq backup-by-copying t
- backup-directory-alist (list (cons "." (b/var "backup/")))
- version-control t
- delete-old-versions t)
+;; time and battery in mode-line
+(use-feature time
+ :demand
+ :config
+ (display-time-mode)
+ :custom
+ (display-time-default-load-average nil)
+ (display-time-format "%a %b %-e, %-l:%M%P"))
-;; 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)
+(use-feature battery
+ :demand
+ :config
+ (display-battery-mode)
+ :custom
+ (battery-mode-line-format " %p%% %t"))
-;; always use space for indentation
-(setq-default
- indent-tabs-mode nil
- require-final-newline t
- tab-width 4)
+(use-feature fringe
+ :demand
+ :config
+ ;; smaller fringe
+ ;; (fringe-mode '(3 . 1))
+ (fringe-mode nil))
-;; enable winner-mode (C-h f winner-mode RET)
-(winner-mode 1)
+(use-feature winner
+ :demand
+ :config
+ ;; 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
+(use-feature compile
+ :config
+ ;; 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'.
(defun b/compilation-finish-function (buffer outstr)
(unless (string-match "finished" outstr)
(switch-to-buffer-other-window buffer))
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)
-
-;; open read-only file buffers in view-mode
-;; (enables niceties like `q' for quit)
-(setq view-read-only t)
+(use-feature isearch
+ :custom
+ ;; allow scrolling in Isearch
+ (isearch-allow-scroll t)
+ ;; 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
+ (search-default-mode #'char-fold-to-regexp))
+
+;; uncomment to extend the above behaviour to query-replace
+(comment
+ (use-feature replace
+ :custom
+ (replace-char-fold t)))
(use-feature vc
:bind ("C-x v C-=" . vc-ediff))
:custom ((ediff-window-setup-function 'ediff-setup-windows-plain)
(ediff-split-window-function 'split-window-horizontally)))
-;; i don't feel like jumping out of my chair every now and again; so
-;; don't BEEP! at me, emacs
-(setq ring-bell-function 'ignore)
+(use-feature face-remap
+ :custom
+ ;; gentler font resizing
+ (text-scale-mode-step 1.05))
+
+(use-feature mwheel
+ :defer 0.4
+ :config
+ (setq mouse-wheel-scroll-amount '(1 ((shift) . 1)) ; one line at a time
+ mouse-wheel-progressive-speed nil ; don't accelerate scrolling
+ mouse-wheel-follow-mouse t)) ; scroll window under mouse
+
+(use-feature pixel-scroll
+ :defer 0.4
+ :config (pixel-scroll-mode 1))
+
+(use-feature epg-config
+ :custom
+ ((epg-gpg-program (executable-find "gpg"))))
\f
;;; General bindings
(bind-keys
;; for back and forward mouse keys
+ ("<XF86Back>" . previous-buffer)
("<mouse-8>" . previous-buffer)
("<drag-mouse-8>" . previous-buffer)
+ ("<XF86Forward>" . next-buffer)
("<mouse-9>" . next-buffer)
("<drag-mouse-9>" . next-buffer)
("<drag-mouse-2>" . kill-this-buffer)
("<drag-mouse-3>" . ivy-switch-buffer))
(bind-keys
- :prefix-map mab/straight-prefix-map
+ :prefix-map b/straight-prefix-map
:prefix "C-c p s"
("u" . straight-use-package)
("f" . straight-freeze-versions)
("t" . straight-thaw-versions)
("P" . straight-prune-build)
("g" . straight-get-recipe)
- ("r" . mab/reload-init)
+ ("r" . b/reload-init)
;; M-x ^straight-.*-all$
("a c" . straight-check-all)
("a f" . straight-fetch-all)
\f
;;; Essential packages
+(use-package exwm
+ :demand
+ :config
+ ;; make class name the buffer name, truncating beyond 60 characters
+ (defun b/exwm-rename-buffer ()
+ (interactive)
+ (exwm-workspace-rename-buffer
+ (concat exwm-class-name ":"
+ (if (<= (length exwm-title) 60) exwm-title
+ (concat (substring exwm-title 0 59) "...")))))
+ ;; Enable EXWM
+ (exwm-enable)
+ :hook ((exwm-update-class . b/exwm-rename-buffer)
+ (exwm-update-title . b/exwm-rename-buffer)))
+
+(use-feature exwm-config
+ :demand
+ :after exwm
+ :hook (exwm-init . exwm-config--fix/ido-buffer-window-other-frame))
+
+(use-feature exwm-input
+ :demand
+ :after exwm-workspace
+ :config
+ (defun b/exwm-ws-prev-index ()
+ "Return the index for the previous EXWM workspace, wrapping
+around if needed."
+ (if (= exwm-workspace-current-index 0)
+ (1- exwm-workspace-number)
+ (1- exwm-workspace-current-index)))
+
+ (defun b/exwm-ws-next-index ()
+ "Return the index for the next EXWM workspace, wrapping
+around if needed."
+ (if (= exwm-workspace-current-index
+ (1- exwm-workspace-number))
+ 0
+ (1+ exwm-workspace-current-index)))
+
+ ;; shorten 'C-c C-q' to 'C-q'
+ (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key)
+
+ (setq exwm-input-global-keys
+ `(([?\s-R] . exwm-reset)
+ ([?\s-\\] . exwm-workspace-switch)
+ ([?\s-\s] . (lambda (command)
+ (interactive
+ (list (read-shell-command "➜ ")))
+ (start-process-shell-command
+ command nil command)))
+ ([s-return] . (lambda ()
+ (interactive)
+ (start-process "" nil "urxvt")))
+ ([?\C-\s-\s] . counsel-linux-app)
+ ([?\M-\s-\s] . (lambda ()
+ (interactive)
+ (start-process-shell-command
+ "rofi-pass" nil "rofi-pass")))
+ ([?\s-h] . windmove-left)
+ ([?\s-j] . windmove-down)
+ ([?\s-k] . windmove-up)
+ ([?\s-l] . windmove-right)
+ ([?\s-H] . windmove-swap-states-left)
+ ([?\s-J] . windmove-swap-states-down)
+ ([?\s-K] . windmove-swap-states-up)
+ ([?\s-L] . windmove-swap-states-right)
+ ([?\M-\s-h] . shrink-window-horizontally)
+ ([?\M-\s-l] . enlarge-window-horizontally)
+ ([?\M-\s-k] . shrink-window)
+ ([?\M-\s-j] . enlarge-window)
+ ([?\s-\[] . (lambda ()
+ (interactive)
+ (exwm-workspace-switch-create
+ (b/exwm-ws-prev-index))))
+ ([?\s-\]] . (lambda ()
+ (interactive)
+ (exwm-workspace-switch-create
+ (b/exwm-ws-next-index))))
+ ([?\s-{] . (lambda ()
+ (interactive)
+ (exwm-workspace-move-window
+ (b/exwm-ws-prev-index))))
+ ([?\s-}] . (lambda ()
+ (interactive)
+ (exwm-workspace-move-window
+ (b/exwm-ws-next-index))))
+ ,@(mapcar (lambda (i)
+ `(,(kbd (format "s-%d" i)) .
+ (lambda ()
+ (interactive)
+ (exwm-workspace-switch-create ,i))))
+ (number-sequence 0 (1- exwm-workspace-number)))
+ ([?\s-t] . exwm-floating-toggle-floating)
+ ([?\s-f] . exwm-layout-toggle-fullscreen)
+ ([?\s-w] . (lambda ()
+ (interactive)
+ (kill-buffer (current-buffer))))
+ ([?\s-q] . (lambda ()
+ (interactive)
+ (exwm-manage--kill-client)))
+ ([?\s-\'] . (lambda ()
+ (interactive)
+ (start-process-shell-command
+ "rofi-light" nil "rofi-light")))
+ ([XF86AudioMute] .
+ (lambda ()
+ (interactive)
+ (start-process "" nil "pamixer" "--toggle-mute")))
+ ([XF86AudioLowerVolume] .
+ (lambda ()
+ (interactive)
+ (start-process
+ "" nil "pamixer" "--allow-boost" "--decrease" "5")))
+ ([XF86AudioRaiseVolume] .
+ (lambda ()
+ (interactive)
+ (start-process
+ "" nil "pamixer" "--allow-boost" "--increase" "5")))
+ ([XF86AudioPlay] .
+ (lambda ()
+ (interactive)
+ (start-process "" nil "mpc" "toggle")))
+ ([XF86AudioPrev] .
+ (lambda ()
+ (interactive)
+ (start-process "" nil "mpc" "prev")))
+ ([XF86AudioNext] .
+ (lambda ()
+ (interactive)
+ (start-process "" nil "mpc" "next")))
+ ([XF86ScreenSaver] .
+ (lambda ()
+ (interactive)
+ (start-process "" nil "dm-tool" "lock")))))
+
+ ;; Line-editing shortcuts
+ (setq exwm-input-simulation-keys
+ '(;; movement
+ ([?\C-b] . [left])
+ ([?\M-b] . [C-left])
+ ([?\C-f] . [right])
+ ([?\M-f] . [C-right])
+ ([?\C-p] . [up])
+ ([?\C-n] . [down])
+ ([?\C-a] . [home])
+ ([?\C-e] . [end])
+ ([?\M-v] . [prior])
+ ([?\C-v] . [next])
+ ([?\C-d] . [delete])
+ ([?\C-k] . [S-end ?\C-x])
+ ([?\M-<] . C-home)
+ ([?\M->] . C-end)
+ ;; cut/copy/paste
+ ([?\C-w] . [?\C-x])
+ ([?\M-w] . [?\C-c])
+ ([?\C-y] . [?\C-v])
+ ([?\M-d] . [C-S-right ?\C-x])
+ ([?\M-\d] . [C-S-left ?\C-x])
+ ;; search
+ ([?\C-s] . [?\C-f])
+ ;; escape
+ ([?\C-g] . [escape]))))
+
+(use-feature exwm-manage
+ :demand
+ :after exwm
+ :hook
+ (exwm-manage-finish . (lambda ()
+ (when exwm-class-name
+ (cond
+ ((string= exwm-class-name "Abrowser")
+ (exwm-input-set-local-simulation-keys
+ `(,@exwm-input-simulation-keys
+ ([?\C-\S-d] . [?\C-d])
+ ([?\C-q] . [?\C-w])
+ ([?\s-q] . [?\C-q]))))
+ ((string= exwm-class-name "URxvt")
+ (exwm-input-set-local-simulation-keys
+ '(([?\C-c ?\C-c] . [?\C-c])
+ ([?\C-c ?\C-u] . [?\C-u]))))
+ ((string= exwm-class-name "Zathura")
+ (exwm-input-set-local-simulation-keys
+ '(([?\C-p] . [C-up])
+ ([?\C-n] . [C-down])))))))))
+
+(use-feature exwm-randr
+ :demand
+ :after exwm
+ :config
+ (exwm-randr-enable))
+
+(use-feature exwm-systemtray
+ :demand
+ :after exwm
+ :config
+ (exwm-systemtray-enable))
+
+(use-feature exwm-workspace
+ :demand
+ :after exwm
+ :custom
+ (exwm-workspace-number 4))
+
+(use-package exwm-edit
+ :demand
+ :after exwm)
+
;; use the org-plus-contrib package to get the whole deal
(use-package org-plus-contrib)
(nconc magit-section-initial-visibility-alist
'(([unpulled status] . show)
([unpushed status] . show)))
- (setq transient-history-file (b/var "transient/history.el")
- transient-levels-file (b/etc "transient/levels.el")
- transient-values-file (b/etc "transient/values.el"))
- :custom (magit-display-buffer-function #'magit-display-buffer-fullframe-status-v1)
+ :custom
+ (magit-diff-refine-hunk t)
+ (magit-display-buffer-function #'magit-display-buffer-fullframe-status-v1)
:custom-face (magit-diff-file-heading ((t (:weight normal)))))
;; recently opened files
;; :config
;; (add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?:")
:custom
- (recentf-max-saved-items 2000)
- (recentf-save-file (b/var "recentf-save.el")))
+ (recentf-max-saved-items 2000))
;; smart M-x enhancement (needed by counsel for history)
-(use-package smex
- :config
- (setq smex-save-file (b/var "smex-save.el")))
+(use-package smex)
(use-package ivy
:defer 0.3
- :delight ;; " 🙒"
:bind
(:map ivy-minibuffer-map
([escape] . keyboard-escape-quit)
(use-package counsel
:after ivy
- :delight
:bind (([remap execute-extended-command] . counsel-M-x)
([remap find-file] . counsel-find-file)
("C-c b b" . ivy-switch-buffer)
:hook (eshell-mode . b/eshell-setup)
:custom
- (eshell-directory-name (b/var "eshell/"))
(eshell-hist-ignoredups t)
(eshell-input-filter 'eshell-input-filter-initial-space))
(or
(name . "^\\*scratch\\*$")
(name . "^\\*Messages\\*$")))
+ ("exwm" (mode . exwm-mode))
("erc" (mode . erc-mode)))))
(ibuffer-formats
'((mark modified read-only locked " "
- (name 18 18 :left :elide)
+ (name 72 72 :left :elide)
" "
(size-h 9 -1 :right)
" "
(use-feature outline
:disabled
:hook (prog-mode . outline-minor-mode)
- :delight (outline-minor-mode " outl")
:bind
(:map
outline-minor-mode-map
;; display Lisp objects at point in the echo area
(use-feature eldoc
:when (version< "25" emacs-version)
- :delight " eldoc"
:config (global-eldoc-mode))
;; highlight matching parens
:config (electric-pair-mode))
(use-feature simple
- :delight (auto-fill-function " fill")
- :config (column-number-mode))
+ :config (column-number-mode)
+ :custom
+ ;; 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.
+ (save-interprogram-paste-before-kill t))
;; save minibuffer history
(use-feature savehist
+ :demand
:config
(savehist-mode)
- :custom
- (savehist-file (b/var "savehist.el")))
+ (add-to-list 'savehist-additional-variables 'kill-ring))
;; automatically save place in files
(use-feature saveplace
:when (version< "25" emacs-version)
- :config (save-place-mode)
- :custom
- (save-place-file (b/var "save-place.el")))
+ :config (save-place-mode))
(use-feature prog-mode
:config (global-prettify-symbols-mode)
(use-package company
:defer 0.6
- :delight " comp"
:bind
(:map company-active-map
([tab] . company-complete-common-or-cycle)
(setq flycheck-check-syntax-automatically '(mode-enabled save))
:custom (flycheck-mode-line-prefix "flyc"))
-(use-feature flyspell
- :delight " flysp")
+(use-feature flyspell)
;; http://endlessparentheses.com/ispell-and-apostrophes.html
(use-feature ispell
#'endless/replace-quote))
(use-feature abbrev
- :delight " abbr"
- :hook (text-mode . abbrev-mode)
- :custom
- (abbrev-file-name (b/var "abbrev.el")))
+ :hook (text-mode . abbrev-mode))
\f
;;; Programming modes
(add-hook 'lisp-interaction-mode-hook #'indent-spaces-mode))
(use-feature reveal
- :delight (reveal-mode " reveal")
:hook (emacs-lisp-mode . reveal-mode))
-(use-feature elisp-mode
- :delight (emacs-lisp-mode "Elisp" :major))
-
+(use-feature elisp-mode)
(use-package alloy-mode
:straight (:host github :repo "dwwmmn/alloy-mode")
(use-package lsp-java
:config
(add-hook 'java-mode-hook
- (lambda ()
- (setq-local company-backends (list 'company-lsp))))
+ (lambda ()
+ (setq-local company-backends (list 'company-lsp))))
(add-hook 'java-mode-hook 'lsp-java-enable)
(add-hook 'java-mode-hook 'flycheck-mode)
(eclim-executable "~/.p2/pool/plugins/org.eclim_2.8.0/bin/eclim")
(eclim-eclipse-dirs '("~/usr/eclipse/dsl-2018-09/eclipse"))))
-(use-package geiser
- :config
- (make-directory (b/var "geiser/") t)
- (setq geiser-repl-history-filename (b/var "geiser/repl-history")))
+(use-package geiser)
(use-feature geiser-guile
:config
(lambda (p) (string-match "^---?" (car p)))
tex--prettify-symbols-alist)
:hook ((tex-mode . auto-fill-mode)
- (tex-mode . flyspell-mode)
- (tex-mode . (lambda () (electric-indent-local-mode -1)))))
+ (tex-mode . flyspell-mode)))
\f
;;; Theme
(load-theme 'tangomod t)
(use-package smart-mode-line
+ :disabled
:commands (sml/apply-theme)
:demand
:config
(sml/setup)
(smart-mode-line-enable))
-(use-package doom-themes)
+(use-package doom-modeline
+ :disabled
+ :demand
+ :hook (after-init . doom-modeline-init)
+ :custom
+ (doom-modeline-buffer-file-name-style 'relative-to-project))
+
+(use-package doom-themes
+ :disabled)
+
+(use-package solarized-theme
+ :demand
+ :config
+ (load-theme 'solarized-light t)
+ (let ((line (face-attribute 'mode-line :underline)))
+ (set-face-attribute 'mode-line nil :overline line)
+ (set-face-attribute 'mode-line-inactive nil :overline line)
+ (set-face-attribute 'mode-line-inactive nil :underline line)
+ (set-face-attribute 'mode-line nil :box nil)
+ (set-face-attribute 'mode-line-inactive nil :box nil)
+ (set-face-attribute 'mode-line-inactive nil :background "#f9f2d9")))
+
+(use-package moody
+ :demand
+ :config
+ (setq x-underline-at-descent-line t)
+ (moody-replace-mode-line-buffer-identification)
+ (moody-replace-vc-mode))
(defvar b/org-mode-font-lock-keywords
+ "For use with the `doom-tomorrow-night' theme."
'(("[ \t]*\\(#\\+\\(BEGIN\\|END\\|begin\\|end\\)_\\(\\S-+\\)\\)[ \t]*\\([^\n:]*\\)"
(1 '(:foreground "#5a5b5a" :background "#292b2b") t) ; directive
(3 '(:foreground "#81a2be" :background "#292b2b") t) ; kind
"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 b/org-mode-font-lock-keywords))
+ (load-theme 'solarized-light t)
+ ;; (sml/apply-theme 'automatic)
+ ;; (font-lock-remove-keywords
+ ;; 'org-mode b/org-mode-font-lock-keywords)
+ (run-with-timer 0.01 nil 'exwm-systemtray--refresh))
(defun b/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 b/org-mode-font-lock-keywords t))
+ (load-theme 'solarized-dark t)
+ ;; (sml/apply-theme 'automatic)
+ ;; (font-lock-add-keywords
+ ;; 'org-mode b/org-mode-font-lock-keywords t)
+ (run-with-timer 0.01 nil 'exwm-systemtray--refresh))
(bind-keys
("C-c t d" . b/lights-off)
(use-package which-key
:defer 0.4
- :delight
:config
(which-key-add-key-based-replacements
;; prefixes for global prefixes and minor modes
;; prefixes for major modes
(which-key-add-major-mode-key-based-replacements 'message-mode
- "C-c f" "footnote")
+ "C-c f n" "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
:defer 0.4
:bind (("C-c d" . crux-duplicate-current-line-or-region)
("C-c D" . crux-duplicate-and-comment-current-line-or-region)
- ("C-c f c" . crux-copy-file-preserve-attributes)
- ("C-c f d" . crux-delete-file-and-buffer)
- ("C-c f r" . crux-rename-file-and-buffer)
+ ("C-c f C" . crux-copy-file-preserve-attributes)
+ ("C-c f D" . crux-delete-file-and-buffer)
+ ("C-c f R" . crux-rename-file-and-buffer)
("C-c j" . crux-top-join-line)
("C-S-j" . crux-top-join-line)))
:defer 0.5
:bind-keymap ("C-c P" . projectile-command-map)
:config
- (make-directory (b/var "projectile/") t)
(projectile-mode)
(defun b/projectile-mode-line-fun ()
(advice-add 'magit-branch-and-checkout
:after #'my-projectile-invalidate-cache)))
:custom
- (projectile-cache-file (b/var "projectile/cache.el"))
(projectile-completion-system 'ivy)
- (projectile-known-projects-file (b/var "projectile/known-projects.el"))
(projectile-mode-line-prefix " proj"))
(use-package helpful
;; easily type pretty quotes & other typography, like ‘’“”-–—«»‹›
(use-package typo
:defer 0.5
- :delight " typo"
:config
(typo-global-mode 1)
:hook (((text-mode erc-mode) . typo-mode)
:commands eshell-up)
(use-package multi-term
+ :disabled
:defer 0.6
:bind (("C-c a s m m" . multi-term)
("C-c a s m d" . multi-term-dedicated-toggle)
(use-package page-break-lines
:defer 0.5
- :delight " pgln"
:custom
(page-break-lines-max-width fill-column)
:config
("c" . mc/edit-lines)
("n" . mc/mark-next-like-this)
("p" . mc/mark-previous-like-this)
- ("a" . mc/mark-all-like-this)))
- :config
- (setq mc/list-file (b/var "mc-list.el")))
+ ("a" . mc/mark-all-like-this))))
-(comment
- ;; TODO
- (use-package forge
- :after magit
- :demand))
+(use-package forge
+ :demand
+ :after magit)
(use-package yasnippet
:defer 0.6
:config
(defconst yas-verbosity-cur yas-verbosity)
(setq yas-verbosity 2)
- (setq yas-snippet-dirs (list (b/etc "yasnippet/snippets/")))
(add-to-list 'yas-snippet-dirs "~/src/git/guix/etc/snippets" t)
(yas-reload-all)
(setq yas-verbosity yas-verbosity-cur)
;; (use-package fill-column-indicator)
(use-package emojify
- :config
- (make-directory (b/var "emojify/") t)
- (setq emojify-emojis-dir (b/var "emojify/"))
:hook (erc-mode . emojify-mode))
(use-feature window
(use-package pdf-tools
:defer 0.5
:bind (:map pdf-view-mode-map
- ("<XF86Back>" . pdf-history-backward)
- ("<XF86Forward>" . pdf-history-forward)
- ("M-RET" . image-previous-line))
+ ("<C-XF86Back>" . pdf-history-backward)
+ ("<mouse-8>" . pdf-history-backward)
+ ("<drag-mouse-8>" . pdf-history-backward)
+ ("<C-XF86Forward>" . pdf-history-forward)
+ ("<mouse-9>" . pdf-history-forward)
+ ("<drag-mouse-9>" . pdf-history-forward)
+ ("M-RET" . image-previous-line))
:config (pdf-tools-install nil t)
:custom (pdf-view-resize-factor 1.05))
(goto-char (cdr macro)))
(reftex-this-word)))))
+(use-package minions
+ :demand
+ :config (minions-mode))
+
+(use-package dmenu
+ :disabled
+ :custom
+ (dmenu-history-size 0)
+ (dmenu-prompt-string "run: ")
+ (dmenu-save-file (b/var "dmenu-items")))
+
+(use-package eosd
+ ;; TODO: fix build by properly building the eosd-pixbuf.c module
+ ;; e.g. see https://github.com/raxod502/straight.el/issues/386
+ :disabled
+ :straight (:host github :repo "clarete/eosd")
+ :demand
+ :after exwm
+ :config
+ (eosd-start))
+
\f
;;; Email (with Gnus)
gnus-interactive-exit nil
gnus-gcc-mark-as-read t)
:config
- (require 'ebdb)
- (require 'ebdb-mua)
- (require 'ebdb-gnus)
-
(when (version< emacs-version "27")
(add-to-list
'nnmail-split-abbrev-alist
(bind-keys
:map gnus-summary-mode-map
("M-L" . org-store-link))
- :hook (gnus-summary-mode . b/no-mouse-autoselect-window))
+ :hook (gnus-summary-mode . b/no-mouse-autoselect-window)
+ :custom
+ (gnus-thread-sort-functions '(gnus-thread-sort-by-number
+ gnus-thread-sort-by-subject
+ gnus-thread-sort-by-date)))
(use-feature gnus-msg
:config
mm-decrypt-option 'known
mm-verify-option 'known))
+(use-feature mm-uu
+ :custom
+ (mm-uu-diff-groups-regexp
+ "\\(gmane\\|gnu\\|l\\)\\..*\\(diff\\|commit\\|cvs\\|bug\\|dev\\)"))
+
(use-feature sendmail
:config
(setq sendmail-program (executable-find "msmtp")
"Return the In-Reply-To header for this message."
(when message-reply-headers
(let ((from (mail-header-from message-reply-headers))
- (msg-id (mail-header-id message-reply-headers)))
+ (msg-id (mail-header-id message-reply-headers)))
(when from
msg-id))))
;; (message-header-subject ((t (:foreground "#111" :weight semi-bold))))
;; (message-header-to ((t (:foreground "#111" :weight normal))))
;; (message-header-cc ((t (:foreground "#333" :weight normal))))
- )
+ :custom
+ (message-elide-ellipsis "[...]\n"))
-(use-feature mml
- :delight " mml")
+(use-feature mml)
(use-feature mml-sec
:custom
:bind
(:map message-mode-map
:prefix-map b/footnote-prefix-map
- :prefix "C-c f"
+ :prefix "C-c f n"
("a" . footnote-add-footnote)
("b" . footnote-back-to-message)
("c" . footnote-cycle-style)
("s" . footnote-set-style)))
(use-package ebdb
+ :demand
:after gnus
:bind (:map gnus-group-mode-map ("e" . ebdb))
:config
(defun company-ebdb--post-complete (_) nil))
(use-feature ebdb-gnus
+ :demand
: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))))))
+ (ebdb-gnus-window-size 0.3))
(use-feature ebdb-mua
+ :demand
:after ebdb
- ;; :custom (ebdb-mua-pop-up nil)
- )
+ :custom (ebdb-mua-pop-up nil))
;; (use-package ebdb-message
;; :after ebdb)
(gnus-harvest-install 'message-x)
(gnus-harvest-install))))
+(use-feature gnus-article-treat-patch
+ :disabled
+ :demand
+ :load-path "lisp/"
+ :config
+ ;; note: be sure to customize faces with `:foreground "white"' when
+ ;; using a theme with a white/light background :)
+ (setq ft/gnus-article-patch-conditions
+ '("^@@ -[0-9]+,[0-9]+ \\+[0-9]+,[0-9]+ @@")))
+
\f
;;; IRC (with ERC and ZNC)
(add-to-list 'erc-modules 'notifications)
(add-to-list 'erc-modules 'spelling)
(add-to-list 'erc-modules 'scrolltoplace)
- (erc-update-modules)
-
- (when (and (version<= "24.4" emacs-version)
- (version< emacs-version "27"))
- ;; fix erc-lurker bug
- ;; patch submitted: https://bugs.gnu.org/36843#10
- ;; TODO: remove when patch is merged and emacs 27 is released
- (defvar erc-message-parsed)
- (defun erc-display-message (parsed type buffer msg &rest args)
- "Display MSG in BUFFER.
-
-ARGS, PARSED, and TYPE are used to format MSG sensibly.
-
-See also `erc-format-message' and `erc-display-line'."
- (let ((string (if (symbolp msg)
- (apply #'erc-format-message msg args)
- msg))
- (erc-message-parsed parsed))
- (setq string
- (cond
- ((null type)
- string)
- ((listp type)
- (mapc (lambda (type)
- (setq string
- (erc-display-message-highlight type string)))
- type)
- string)
- ((symbolp type)
- (erc-display-message-highlight type string))))
-
- (if (not (erc-response-p parsed))
- (erc-display-line string buffer)
- (unless (erc-hide-current-message-p parsed)
- (erc-put-text-property 0 (length string) 'erc-parsed parsed string)
- (erc-put-text-property 0 (length string) 'rear-sticky t string)
- (when (erc-response.tags parsed)
- (erc-put-text-property 0 (length string) 'tags (erc-response.tags parsed)
- string))
- (erc-display-line string buffer)))))
-
- (defun erc-lurker-update-status (_message)
- "Update `erc-lurker-state' if necessary.
-
-This function is called from `erc-insert-pre-hook'. If the
-current message is a PRIVMSG, update `erc-lurker-state' to
-reflect the fact that its sender has issued a PRIVMSG at the
-current time. Otherwise, take no action.
-
-This function depends on the fact that `erc-display-message'
-lexically binds `erc-message-parsed', which is used to check if
-the current message is a PRIVMSG and to determine its sender.
-See also `erc-lurker-trim-nicks' and `erc-lurker-ignore-chars'.
-
-In order to limit memory consumption, this function also calls
-`erc-lurker-cleanup' once every `erc-lurker-cleanup-interval'
-updates of `erc-lurker-state'."
- (when (and (boundp 'erc-message-parsed)
- (erc-response-p erc-message-parsed))
- (let* ((command (erc-response.command erc-message-parsed))
- (sender
- (erc-lurker-maybe-trim
- (car (erc-parse-user (erc-response.sender erc-message-parsed)))))
- (server
- (erc-canonicalize-server-name erc-server-announced-name)))
- (when (equal command "PRIVMSG")
- (when (>= (cl-incf erc-lurker-cleanup-count)
- erc-lurker-cleanup-interval)
- (setq erc-lurker-cleanup-count 0)
- (erc-lurker-cleanup))
- (unless (gethash server erc-lurker-state)
- (puthash server (make-hash-table :test 'equal) erc-lurker-state))
- (puthash sender (current-time)
- (gethash server erc-lurker-state))))))))
+ (erc-update-modules))
(use-feature erc-fill
:after erc
(erc-track-enable-keybindings nil)
(erc-track-exclude-types '("JOIN" "MODE" "NICK" "PART" "QUIT"
"324" "329" "332" "333" "353" "477"))
+ (erc-track-position-in-mode-line t)
(erc-track-priority-faces-only 'all)
(erc-track-shorten-function nil))