From 03d8b587b1f49073d94bd0c4114fe09e832183f8 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 21 Jun 2026 01:57:44 -0400 Subject: refactor: defer games-config behind autoloads (load-graph Phase 4) init.el eagerly required games-config at startup just to configure two on-demand game packages. package.el already autoloads malyon and 2048-game, so the eager require bought nothing but the one setting the module adds (malyon-stories-directory). init.el now autoloads malyon and 2048-game to games-config instead of requiring it. The first game command loads the module, which configures then loads the package. Startup no longer touches games-config, and both the commands and the stories-directory setting still work. This is the first module of the Phase 4 low-risk batch. --- docs/design/module-inventory.org | 2 +- init.el | 5 ++++- modules/games-config.el | 16 +++++++++++----- tests/test-init-defer-games.el | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 tests/test-init-defer-games.el diff --git a/docs/design/module-inventory.org b/docs/design/module-inventory.org index eeb824b57..3903d0ba9 100644 --- a/docs/design/module-inventory.org +++ b/docs/design/module-inventory.org @@ -205,7 +205,7 @@ flyspell-and-abbrev is the one Core-UX member (text-mode hooks). | =eshell-config= | 3 | D/P | eager | command | system-utils | add-hook, advice-add, package config | yes | | =eww-config= | 3 | D/P | eager | command | cl-lib | package config | yes | | =flyspell-and-abbrev= | 2 | C/P | eager | hook | cl-lib | mode-hook package config | yes | -| =games-config= | 4 | O | eager | command | none | package config | yes | +| =games-config= | 4 | O | command | command | none | package config | yes | | =gloss-config= | 4 | O/D/P | eager | command | none | package config | yes | | =httpd-config= | 4 | O/D/P | eager | command | none | package config | yes | | =jumper= | 4 | O/L | eager | command | cl-lib | jumper keymap | yes | diff --git a/init.el b/init.el index cf6b75bd4..eab444d00 100644 --- a/init.el +++ b/init.el @@ -153,7 +153,10 @@ ;; ------------------------------- Entertainment ------------------------------- (require 'music-config) -(require 'games-config) +;; games-config: deferred (load-graph Phase 4). malyon / 2048-game autoload the +;; module, so it loads on first use instead of at startup. +(autoload 'malyon "games-config" "Play interactive fiction; loads games-config." t) +(autoload '2048-game "games-config" "Play 2048; loads games-config." t) ;; ------------------------------- Misc Modules -------------------------------- diff --git a/modules/games-config.el b/modules/games-config.el index 9aa598168..1e5ba5b87 100644 --- a/modules/games-config.el +++ b/modules/games-config.el @@ -5,9 +5,9 @@ ;; ;; Layer: 4 (Optional). ;; Category: O. -;; Load shape: eager. -;; Eager reason: none; optional games, a command-loaded deferral candidate. -;; Top-level side effects: package configuration via use-package. +;; Load shape: command (deferred). +;; Eager reason: none; loaded on first use of `malyon' or `2048-game'. +;; Top-level side effects: package configuration via use-package (deferred). ;; Runtime requires: none. ;; Direct test load: yes. ;; @@ -17,20 +17,26 @@ ;; (stories directory: ~/sync/org/text.games/) ;; - 2048 number-tile puzzle game ;; +;; init.el autoloads `malyon' and `2048-game' to this module instead of +;; requiring it eagerly, so the first invocation of either command loads +;; games-config, which configures and then loads the package. +;; ;;; Code: ;; ----------------------------------- Malyon ---------------------------------- ;; text based adventure player (use-package malyon - :defer 1 + :defer t + :commands (malyon) :config (setq malyon-stories-directory (concat org-dir "text.games/"))) ;; ------------------------------------ 2048 ----------------------------------- ;; combine numbered tiles to create the elusive number 2048. (use-package 2048-game - :defer 1) + :defer t + :commands (2048-game)) (provide 'games-config) ;;; games-config.el ends here. diff --git a/tests/test-init-defer-games.el b/tests/test-init-defer-games.el new file mode 100644 index 000000000..0b85a1ea7 --- /dev/null +++ b/tests/test-init-defer-games.el @@ -0,0 +1,38 @@ +;;; test-init-defer-games.el --- games-config Phase 4 deferral -*- lexical-binding: t; -*- + +;;; Commentary: +;; games-config is deferred (load-graph Phase 4): init.el autoloads `malyon' +;; and `2048-game' instead of requiring the module eagerly. These tests guard +;; that the game commands stay reachable with the module unloaded, and that +;; loading the module still applies the one setting it owns. + +;;; Code: + +(require 'ert) +(require 'package) + +(ert-deftest test-init-defer-games-commands-autoload-without-module () + "Normal: the game commands resolve with games-config unloaded. +This is the safety net for the deferral -- dropping the eager require keeps +malyon and 2048-game reachable only because the packages autoload their own +commands, so assert that holds." + (package-initialize) + (should-not (featurep 'games-config)) + (should (commandp 'malyon)) + (should (commandp '2048-game))) + +(ert-deftest test-init-defer-games-config-applies-malyon-stories-dir () + "Normal: loading games-config still applies malyon's stories directory. +The module is the config owner; deferring it must not drop the one setting it +adds (`malyon-stories-directory'), which use-package applies when malyon loads." + (package-initialize) + (add-to-list 'load-path (expand-file-name "modules" default-directory)) + (require 'user-constants) + (let ((org-dir "/tmp/games-defer-test/")) + (load "games-config" nil t) + (unless (require 'malyon nil t) + (ert-skip "malyon package not available")) + (should (equal malyon-stories-directory "/tmp/games-defer-test/text.games/")))) + +(provide 'test-init-defer-games) +;;; test-init-defer-games.el ends here -- cgit v1.2.3