├── README.org ├── hell.el ├── init.el └── manifest.scm /README.org: -------------------------------------------------------------------------------- 1 | #+title: 🔥 EMACS FROM HELL 🔥 2 | 3 | > /I warned you about Emacs bro! I told you, dawg!/ 4 | 5 | This is an Emacs configuration you should definitely not try. 6 | 7 | However, since you insist: 8 | 9 | - *STEP 1*: Delete your existing Emacs configuration 10 | - *STEP 2*: =git clone https://github.com/daviwil/emacs-from-hell ~/.emacs.d= 11 | - *STEP 3*: PAIN 12 | 13 | * Contributing 14 | 15 | Yes, you can send a PR to add more pain and suffering to this configuration. No, I will not fix your broken computer. 16 | 17 | At some point in the future, I will subject myself to the community-conjured demons in this configuration live on stream. 18 | 19 | * Streams 20 | 21 | - [[https://systemcrafters.net/live-streams/january-14-2022/][System Crafters Live! - Creating the World's WORST Emacs Configuration]]: [[https://youtu.be/L4NaIUqx8fw][Part 1]] / [[https://youtu.be/IDFm4y6KLks][Part 2]] 22 | 23 | * License 24 | 25 | My team of lawyers have advised me that I must post a warranty disclaimer for the inevitable scenario when this configuration ruins your life: 26 | 27 | #+begin_src sh 28 | 29 | Copyright © 2022 Satan Himself 30 | 31 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 32 | 33 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 34 | 35 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 36 | 37 | #+end_src 38 | -------------------------------------------------------------------------------- /hell.el: -------------------------------------------------------------------------------- 1 | ;;; hell.el --- Emacs from Hell -*- lexical-binding: t; -*- 2 | 3 | ;;; Commentary: 4 | 5 | ;; Inspired by the System Crafter live stream 2022-01-14, titled "Creating the 6 | ;; World's WORST Emacs Configuration:" https://youtu.be/L4NaIUqx8fw 7 | ;; https://youtu.be/IDFm4y6KLks 8 | 9 | ;; This package implements `hell-mode', which will turn your (or a victim's) 10 | ;; Emacs into the Emacs from Hell. There are a variety of changes, from the 11 | ;; purely aesthetic to the downright destructive. Read the source code for 12 | ;; more. 13 | 14 | ;;; Code: 15 | 16 | ;;; Customization options 17 | 18 | (defgroup hell nil 19 | "Tweaks to making Emacs Hell." 20 | :group 'emacs 21 | :prefix "hell-") 22 | 23 | (defcustom hell-text-height-minimum 100 24 | "The minimum height for text." 25 | :type 'integer) 26 | 27 | (defcustom hell-text-height-maximum 600 28 | "The maximum height for text." 29 | :type 'integer) 30 | 31 | (defcustom hell-ignore-safe-commands '(kill-emacs 32 | hell-mode 33 | hell-exit-hell) 34 | "Commands that are safe from `hell-ignore-commands'." 35 | :type '(repeat function)) 36 | 37 | (defcustom hell-ignore-command-probability 6000 38 | "Inverse of the probability to ignore a command. 39 | Every `hell-ignore-command-probability' commands will, on 40 | average, be ignored.") 41 | 42 | (defcustom hell-ignore-function-probability 8000 43 | "Inverse of the probability to ignore a function. 44 | Every `hell-ignore-functionf-probability' functions will, on 45 | average, be ignored.") 46 | 47 | (defcustom hell-ignore-safe-functions '(hell-message 48 | hell-random-color 49 | hell-random-text-height 50 | hell-random-buffer 51 | hell--filter-atoms 52 | hell--random-hit-p 53 | hell-ignore-commands 54 | hell-ignore-functions 55 | hell-no-or-yes-p 56 | hell-exit-hell 57 | hell-run-timer 58 | hell-ignore 59 | random 60 | hell-random-number) 61 | "Functions that are safe from `hell-ignore-functions'." 62 | :type '(repeat function)) 63 | 64 | (defcustom hell-idle-functions '(zone) 65 | "Functions to randomly call idly." 66 | :type '(repeat function)) 67 | 68 | (defcustom hell-typing-functions '(hell-morse-buffer 69 | hell-rot13-buffer) 70 | "Functions to randomly fire when typing." 71 | :type '(repeat function)) 72 | 73 | ;;; Internal variables 74 | 75 | (defvar hell--saved nil 76 | "Alist of things to return to normal when exiting hell.") 77 | 78 | (defvar hell--timers nil 79 | "Alist of timers set by hell.") 80 | 81 | (defvar hell--hooks nil 82 | "Alist of hooks set by hell.") 83 | 84 | ;;; Helper functions 85 | 86 | (defun hell-random-number (&optional max min) 87 | "Return a random number between MIN and MAX. 88 | The order of MIN and MAX doesn't matter." 89 | (cond ((and (null min) (null max)) (random t)) 90 | ((null min) (random max)) 91 | (t (+ (min max min) (random (- (max min max) (min max min))))))) 92 | 93 | (defun hell-message (format &rest args) 94 | "Display a message, Hell-style. 95 | FORMAT and ARGS are passed to `message'." 96 | (message "😈 %s" (apply #'format format args))) 97 | 98 | (defun hell-random-color () 99 | "Return a random color in HTML format." 100 | (let ((red (random 256)) 101 | (blue (random 256)) 102 | (green (random 256))) 103 | (format "#%02x%02x%02x" red blue green))) 104 | 105 | (defun hell-random-text-height () 106 | "Return a random height acceptable for text." 107 | (+ hell-text-height-minimum (random (- hell-text-height-maximum 108 | hell-text-height-minimum)))) 109 | 110 | (defun hell-theme () 111 | "Theme Emacs randomlly." 112 | (set-face-attribute 'mode-line nil 113 | :foreground (hell-random-color) 114 | :background (hell-random-color) 115 | :height (hell-random-text-height)) 116 | (set-face-attribute 'font-lock-builtin-face nil 117 | :foreground (random-color)) 118 | (set-face-attribute 'font-lock-function-name-face nil 119 | :background (random-color)) 120 | (set-face-attribute 'font-lock-keyword-face nil 121 | :foreground (random-color))) 122 | 123 | (defun hell-morse-buffer () 124 | "Morse-code the buffer." 125 | (interactive) 126 | (morse-region (point-min) (point-max))) 127 | 128 | (defun hell-rot13-buffer () 129 | "Rot-13 the buffer." 130 | (interactive) 131 | (rot13-region (point-min) (point-max))) 132 | 133 | (defun hell-random-buffer (&optional frame) 134 | "Return a random buffer from FRAME." 135 | (let ((bl (seq-remove #'minibufferp (buffer-list frame)))) 136 | (nth (random (length bl)) bl))) 137 | 138 | (defun hell--filter-atoms (pred &optional obarr) 139 | "Return all atoms in obarray OBARR that match PRED. 140 | PRED should be a function that takes one atom and returns nil or 141 | non-nil." 142 | (let (ret) 143 | (mapatoms (lambda (a) (when (funcall pred a) (push a ret))) obarr) 144 | ret)) 145 | 146 | (defun hell--random-hit-p (probability) 147 | "Return t 1/PROBABILITY of the time, else nil." 148 | (zerop (mod (random t) probability))) 149 | 150 | (defun hell-ignore-commands () 151 | "Alias random commands to `ignore'. 152 | Don't ignore those commands in `hell-ignore-safe-commands'." 153 | (dolist (a (hell--filter-atoms #'commandp)) 154 | (when (hell--random-hit-p hell-ignore-command-probability) 155 | (hell-message "Say goodbye to %s!" a) 156 | ))) 157 | 158 | (defun hell-ignore-functions () 159 | "Alias random functions to `ignore'. 160 | Don't ignore those functions in `hell-ignore-safe-functions'." 161 | (dolist (a (hell--filter-atoms #'functionp)) 162 | (when (and (not (commandp a)) 163 | (hell--random-hit-p hell-ignore-function-probability)) 164 | (hell-message "Say goodbye to %s!" a) 165 | (defalias a 'ignore)))) 166 | 167 | (defun hell-no-or-yes-p (prompt &optional prob) 168 | "PROMPT the user for a yes-or-no answer, but flip the answer. 169 | If optional PROB is passed, only flip the answer 1/PROB times." 170 | (funcall (if (and prob (hell--random-hit-p prob)) #'not #'identity) 171 | (yes-or-no-p prompt))) 172 | 173 | (defun hell-exit-hell () 174 | "Exit `hell-mode'." 175 | (interactive) 176 | (when (and (hell-no-or-yes-p "Are you sure you want to exit Hell? " 4) 177 | ;; other tests here ... 178 | ) 179 | (hell-mode -1))) 180 | 181 | (defun hell-run-timer (idle time repeat function &rest args) 182 | "Perform an action at time TIME. 183 | TIME, REPEAT, FUNCTION, and ARGS are all passed to `run-at-time', 184 | or `run-with-idle-timer' if IDLE is non-nil. The timer object is 185 | saved in `hell--timers' for easy cancellation." 186 | (push (apply (if idle #'run-with-idle-timer #'run-at-time) 187 | time repeat function args) 188 | hell--timers)) 189 | 190 | (defun hell-ignore (fn &optional actually) 191 | "Alias FN to ignore. 192 | This actually advises FN with :override ignore, for easier 193 | undoing, unless ACTUALLY is non-nil. Then it's really aliased to 194 | ignore." 195 | (if actually 196 | (defalias fn #'ignore) 197 | (push fn hell--saved) 198 | (advice-add fn :override #'ignore))) 199 | 200 | (defun hell-add-hook (fn &rest hooks) 201 | "Add FN to HOOKS." 202 | (dolist (hook hooks) 203 | (push (list hook fn) hell--hooks) 204 | (add-hook hook fn -90))) 205 | 206 | ;;; Minor mode 207 | 208 | (define-minor-mode hell-mode 209 | "A mode of Hell." 210 | :lighter " 😈" 211 | :global t 212 | :keymap (let ((map (make-sparse-keymap))) 213 | (define-key map "heaven" #'hell-exit-hell) 214 | map) 215 | (if hell-mode 216 | (progn 217 | (add-hook 'post-self-insert-hook 'hell-theme) 218 | (dolist (fn hell-idle-functions) 219 | (hell-run-timer t (hell-random-number 10 60) t fn))) 220 | (progn 221 | (dolist (hookfn hell--hooks) 222 | (apply #'remove-hook hookfn)) 223 | (dolist (timer hell--timers) 224 | (cancel-timer timer)) 225 | (dolist (fn hell--saved) 226 | (advice-remove fn #'ignore))))) 227 | 228 | (provide 'hell) 229 | ;;; hell.el ends here 230 | -------------------------------------------------------------------------------- /init.el: -------------------------------------------------------------------------------- 1 | ;; Terror awaits... 2 | 3 | (require 'cl-lib) 4 | 5 | (message "Enabling Emacs hard-mode...") 6 | (mapatoms (lambda (a) 7 | (when (and (fboundp a) 8 | (= (random (+ 100 (random 6000))) 90)) 9 | (message "I hope you liked %s!" a) 10 | (defalias a 'ignore)))) 11 | 12 | (set-face-attribute 'default nil :font "Liberation Serif" :weight 'light :height 300 :foreground "white" :background "red3") 13 | (set-face-attribute 'mode-line nil :weight 'light :height 500 :foreground "purple" :background "yellow") 14 | (set-face-attribute 'region nil :weight 'light :height 300 :foreground nil :background "red3") 15 | 16 | (defun random-color () 17 | (let ((red (random 256)) 18 | (blue (random 256)) 19 | (green (random 256))) 20 | (format "#%02x%02x%02x" red blue green))) 21 | 22 | (defun random-color-face (&optional face frame) 23 | (set-face-attribute 'mode-line frame :foreground (random-color) :background (random-color)) 24 | (set-face-attribute 'font-lock-builtin-face frame :foreground (random-color)) 25 | (set-face-attribute 'font-lock-function-name-face frame :foreground (random-color)) 26 | (set-face-attribute 'font-lock-keyword-face frame :foreground (random-color))) 27 | 28 | (add-hook 'post-command-hook 'random-color-face) 29 | 30 | (defun morse-my-buffer () 31 | (interactive) 32 | (morse-region 33 | (point-min) 34 | (point-max))) 35 | 36 | (defun rot13-my-buffer () 37 | (interactive) 38 | (rot13-region 39 | (point-min) 40 | (point-max))) 41 | 42 | (setq functions-of-typing-hell 43 | '[morse-my-buffer 44 | rot13-my-buffer]) 45 | 46 | (defun resize-mode-line () 47 | (set-face-attribute 'mode-line nil :height (+ 100 (random 600)))) 48 | 49 | (defun ransom-text () 50 | (cl-loop for x from 1 to (buffer-size) do 51 | (put-text-property x (+ x 1) 'font-lock-face `(:height ,(+ 200 (random 200)))))) 52 | 53 | (setq functions-of-idle-hell 54 | '[resize-mode-line 55 | zone 56 | ransom-text]) 57 | 58 | (defun engine-of-hell (frequency funcs) 59 | (let* ((idx (random frequency)) 60 | (func-to-call (when (< idx (length funcs)) (aref funcs idx)))) 61 | (when func-to-call (funcall func-to-call)))) 62 | 63 | (defun haunt-me-plenty () 64 | (interactive) 65 | (engine-of-hell 50 functions-of-typing-hell)) 66 | 67 | (defun haunt-me-randomly () 68 | (interactive) 69 | (engine-of-hell 10 functions-of-idle-hell)) 70 | 71 | (defun haunt-every-command ()) 72 | 73 | ;; Things to run on idle 74 | (setq random-hell-timer (run-at-time 5 t #'haunt-me-randomly)) 75 | (setq random-idle-timer (run-with-idle-timer 1 t #'haunt-me-randomly)) 76 | 77 | ;; Things to run every time a key is pressed 78 | (add-hook 'post-self-insert-hook #'haunt-me-plenty) 79 | 80 | -------------------------------------------------------------------------------- /manifest.scm: -------------------------------------------------------------------------------- 1 | (specifications->manifest 2 | '("coreutils" 3 | "alsa-utils" 4 | "font-jetbrains-mono" 5 | "font-liberation" 6 | "font-bitstream-vera" 7 | "emacs-native-comp")) 8 | --------------------------------------------------------------------------------