179 lines
5.9 KiB
EmacsLisp
179 lines
5.9 KiB
EmacsLisp
;;; acdw.el -*- lexical-binding: t; coding: utf-8-unix -*-
|
|
;; Author: Case Duckworth <acdw@acdw.net>
|
|
;; 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:
|
|
|
|
;;; Utilities
|
|
|
|
;;;; Determine the system I'm on
|
|
(defconst acdw/system (pcase system-type
|
|
('gnu/linux :home)
|
|
((or 'msdos 'windows-nt) :work)
|
|
(_ :other))
|
|
"Which system is currently being used.")
|
|
|
|
;;;; Run commands only when unfocused
|
|
(defun acdw/when-unfocused (func &rest args)
|
|
"Call FUNC, with ARGS, iff all Emacs frames are out of focus.
|
|
|
|
Ready for use with `after-focus-change-function'."
|
|
(when (seq-every-p #'null (mapcar #'frame-focus-state (frame-list)))
|
|
(apply func args)))
|
|
|
|
;;;; Run commands at sunrise and sunset
|
|
(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)))
|
|
|
|
;;;; Define a function and add it to hooks
|
|
(defun defun-with-hooks (hooks function-def)
|
|
"Add FUNCTION-DEF to HOOKS.
|
|
|
|
FUNCTION-DEF should be a `defun' form. This function is just to
|
|
put functions that only exist for hooks closer to the hooks
|
|
they bind to."
|
|
(let ((func function-def))
|
|
(dolist (hook hooks)
|
|
(add-hook hook func))))
|
|
;;; Garbage collection hacks
|
|
|
|
(defconst acdw/gc-cons-threshold-basis (* 800 1024)
|
|
"Basis value for `gc-cons-threshold' to return to after jumping.
|
|
800 KB is Emacs's default.")
|
|
|
|
(defconst acdw/gc-cons-percentage-basis 0.1
|
|
"Basis value for `gc-cons-percentage' to return to after jumping.
|
|
0.1 is Emacs's default.")
|
|
|
|
(defun acdw/gc-disable ()
|
|
"Disable garbage collection by setting relevant variables to their maxima."
|
|
(setq gc-cons-threshold most-positive-fixnum
|
|
gc-cons-percentage 0.8))
|
|
|
|
(defun acdw/gc-enable ()
|
|
"Re-enable garbage collection by setting relevant variables back to bases."
|
|
(setq gc-cons-threshold acdw/gc-cons-threshold-basis
|
|
gc-cons-percentage acdw/gc-cons-percentage-basis))
|
|
|
|
;;; Directories (think `no-littering')
|
|
|
|
(defvar acdw/dir (expand-file-name
|
|
(convert-standard-filename "var/")
|
|
user-emacs-directory)
|
|
"A directory to hold extra configuration and emacs data.")
|
|
|
|
(defun acdw/in-dir (file &optional make-directory)
|
|
"Expand FILE relative to `acdw/dir', optionally creating its
|
|
directory."
|
|
(let ((f (expand-file-name (convert-standard-filename file)
|
|
acdw/dir)))
|
|
(when make-directory
|
|
(make-directory (file-name-directory f) 'parents))
|
|
f))
|
|
|
|
;;; Reading mode
|
|
|
|
(define-minor-mode acdw/reading-mode
|
|
"A mode for reading."
|
|
:init-value t
|
|
:lighter " Read"
|
|
(if acdw/reading-mode
|
|
(progn ;; turn on
|
|
;; settings
|
|
(setq-local mode-line-format
|
|
'(:eval
|
|
(let* ((fmt " Reading %b (%m) ")
|
|
(len (length (format-mode-line fmt))))
|
|
(concat
|
|
(propertize " "
|
|
'display `((space :align-to (- right
|
|
,len)))
|
|
'face '(:inherit italic))
|
|
fmt))))
|
|
;; modes to disable
|
|
(dolist (mode '(display-fill-column-indicator-mode
|
|
simple-modeline-mode))
|
|
(when (fboundp mode)
|
|
(funcall mode -1)))
|
|
;; modes to enable
|
|
(dolist (mode '(iscroll-mode
|
|
olivetti-mode))
|
|
(when (fboundp mode)
|
|
(funcall mode +1))))
|
|
;; turn off
|
|
;; settings
|
|
(kill-local-variable 'mode-line-format)
|
|
;; modes to re-enable
|
|
(dolist (mode '(display-fill-column-indicator-mode
|
|
simple-modeline-mode))
|
|
(when (fboundp mode)
|
|
(funcall mode +1)))
|
|
;; modes to re-disable
|
|
(dolist (mode '(olivetti-mode
|
|
iscroll-mode))
|
|
(when (fboundp mode)
|
|
(funcall mode -1)))
|
|
(force-mode-line-update)))
|
|
|
|
;;; Keymap & Mode
|
|
|
|
(defvar acdw/map (make-sparse-keymap)
|
|
"A keymap for my custom bindings.")
|
|
|
|
(define-minor-mode acdw/mode
|
|
"A mode for `acdw/map'."
|
|
:init-value t
|
|
:lighter " acdw"
|
|
:keymap acdw/map)
|
|
(define-globalized-minor-mode acdw/global-mode acdw/mode acdw/mode)
|
|
|
|
;; Disable `acdw/mode' in the minibuffer
|
|
(defun acdw/mode--disable ()
|
|
"Disable `acdw/mode'."
|
|
(acdw/mode -1))
|
|
(add-hook 'minibuffer-setup-hook #'acdw/mode--disable)
|
|
|
|
;; Set up a leader key for `acdw/mode'
|
|
(defvar acdw/leader
|
|
(let ((map (make-sparse-keymap))
|
|
(c-z (global-key-binding "\C-z")))
|
|
(define-key acdw/map "\C-z" map)
|
|
(define-key map "\C-z" c-z)
|
|
map))
|
|
|
|
(provide 'acdw)
|
|
;;; acdw.el ends here
|