;;; acdw.el -*- lexical-binding: t; coding: utf-8-unix -*- ;; Author: Case Duckworth ;; Created: Sometime during Covid-19, 2020 ;; Keywords: configuration ;; URL: https://tildegit.org/acdw/emacs ;; This file is NOT part of GNU Emacs. ;;; License: ;; Everyone is permitted to do whatever with this software, without ;; limitation. This software comes without any warranty whatsoever, ;; but with two pieces of advice: ;; - Don't hurt yourself. ;; - Make good choices. ;;; Commentary: ;; `acdw.el' contains `acdw/map', its mode, and assorted ease-of-life ;; functions for me, acdw. ;;; Code: ;; Utility constants (defconst acdw/system (pcase system-type ('gnu/linux :home) ((or 'msdos 'windows-nt) :work) (_ :other)) "Which computer system is currently being used.") ;; Utility functions (defmacro when-unfocused (name &rest forms) "Define a function NAME, executing FORMS, that fires when Emacs is unfocused." (declare (indent 1)) (let ((func-name (intern (concat "when-unfocused-" (symbol-name name))))) `(progn (defun ,func-name () "Defined by `when-unfocused'." (when (seq-every-p #'null (mapcar #'frame-focus-state (frame-list))) ,@forms)) (add-function :after after-focus-change-function #',func-name)))) (defmacro hook-defun (name hooks &rest forms) "Define a function NAME that executes FORMS, and add it to each hook in HOOKS." (declare (indent 2)) (let ((func-name (intern (concat "hook-defun-" (symbol-name name)))) (hook-list (if (consp hooks) hooks (list hooks))) (hook-defun-add-hook-list)) `(progn (defun ,func-name () "Defined by `hook-defun'." ,@forms) ,@(dolist (hook hook-list hook-defun-add-hook-list) (push `(add-hook ',hook #',func-name) hook-defun-add-hook-list))))) (defun refresh-emacs () "Reload Emacs's configuration files." (interactive) (dolist (file (list (locate-user-emacs-file "early-init.el") (locate-user-emacs-file "init.el" ".emacs"))) (when (file-exists-p file) (load-file file)))) (defun expand-file-name-exists-p (&rest expand-file-name-args) "Call `expand-file-name' on EXPAND-FILE-NAME-ARGS, returning its name if it exists, or NIL otherwise." (let ((file (apply #'expand-file-name expand-file-name-args))) (if (file-exists-p file) file nil))) (defun acdw/dir (&optional file make-directory) "Place Emacs files in one place. If called without parameters, `acdw/dir' expands to ~/.emacs.d/var or similar. If called with FILE, `acdw/dir' expands FILE to ~/.emacs.d/var, optionally making its directory if MAKE-DIRECTORY is non-nil." (let ((dir (expand-file-name (convert-standard-filename "var/") user-emacs-directory))) (if file (let ((file-name (expand-file-name (convert-standard-filename file) dir))) (when make-directory (make-directory (file-name-directory file-name) 'parents)) file-name) dir))) (defun acdw/gc-enable () "Enable the Garbage collector." (setq gc-cons-threshold (* 800 1024 1024) gc-cons-percentage 0.1)) (defun acdw/gc-disable () "Functionally disable the Garbage collector." (setq gc-cons-threshold most-positive-fixnum gc-cons-percentage 0.8)) (defun acdw/sunrise-sunset (sunrise-command sunset-command) "Run commands at sunrise and sunset." (let* ((times-regex (rx (* nonl) (: (any ?s ?S) "unrise") " " (group (repeat 1 2 digit) ":" (repeat 1 2 digit) (: (any ?a ?A ?p ?P) (any ?m ?M))) (* nonl) (: (any ?s ?S) "unset") " " (group (repeat 1 2 digit) ":" (repeat 1 2 digit) (: (any ?a ?A ?p ?P) (any ?m ?M))) (* nonl))) (ss (sunrise-sunset)) (_m (string-match times-regex ss)) (sunrise-time (match-string 1 ss)) (sunset-time (match-string 2 ss))) (run-at-time sunrise-time (* 60 60 24) sunrise-command) (run-at-time sunset-time (* 60 60 24) sunset-command) (run-at-time "12:00am" (* 60 60 24) sunset-command))) (defun acdw/find-emacs-dotfiles () "Finds lisp files in `user-emacs-directory' and passes them to `completing-read'." (interactive) (find-file (completing-read ".emacs: " (directory-files-recursively user-emacs-directory "\.el$")))) ;; Make `C-z' more useful (defvar acdw/leader (let ((map (make-sparse-keymap)) (c-z (global-key-binding "\C-z"))) (global-set-key "\C-z" map) (define-key map "\C-z" c-z) map)) ;; `acdw/reading-mode' (define-minor-mode acdw/reading-mode "A mode for reading." :init-value nil :lighter " Read" (if acdw/reading-mode (progn ;; turn on ;; settings (setq-local mode-line-format '(:eval (let* ((fmt " Reading %b") (len (length (format-mode-line fmt)))) (concat (propertize " " 'display `((space :align-to (- right ,len))) 'face '(:inherit italic)) fmt))) orig-indicate-empty-lines indicate-empty-lines indicate-empty-lines nil orig-indicate-buffer-boundaries indicate-buffer-boundaries indicate-buffer-boundaries nil) ;; disable modes (dolist (mode '(display-fill-column-indicator-mode)) (when (fboundp mode) (funcall mode -1))) ;; enable modes (dolist (mode '(iscroll-mode olivetti-mode)) (when (fboundp mode) (funcall mode +1)))) ;; turn off ;; settings (setq-local indicate-empty-lines orig-indicate-empty-lines indicate-buffer-boundaries orig-indicate-buffer-boundaries) (kill-local-variable 'mode-line-format) ;; enable modes (dolist (mode '(display-fill-column-indicator-mode)) (when (fboundp mode) (funcall mode +1))) ;; disable modes (dolist (mode '(olivetti-mode iscroll-mode)) (when (fboundp mode) (funcall mode -1))))) (provide 'acdw) ;;; acdw.el ends here