diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-05 12:20:29 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-05 12:20:29 -0500 |
| commit | 68877f04c2ceb569ae5cd74b8303b84b36ced1c5 (patch) | |
| tree | 6ca0e67785c759bae0687728798e8c7c4b164841 /chime.el | |
| parent | 44831f8587947212f2df8c38e81a3c1b6fa588fc (diff) | |
| download | chime-68877f04c2ceb569ae5cd74b8303b84b36ced1c5.tar.gz chime-68877f04c2ceb569ae5cd74b8303b84b36ced1c5.zip | |
fix: validate numeric defcustoms at customize-time
Six numeric settings are declared as integers but were read straight into
arithmetic and timer math. A bad value (string, negative number, nil where
nil isn't supported) used to slip past the defcustom and surface as a
timer error or `arith-error' deep in a callback, instead of as a
configuration problem at the moment the user set it.
I added `chime--validate-integer-setting' as a small shared helper and
wired a `:set' on each of the affected defcustoms:
- `chime-modeline-lookahead-minutes' — integer >= 0 (0 disables)
- `chime-tooltip-lookahead-hours' — integer >= 1
- `chime-modeline-tooltip-max-events' — integer >= 1 or nil (show all)
- `chime-day-wide-advance-notice' — integer >= 0 or nil (same-day only)
- `chime-max-consecutive-failures' — integer >= 0 (0 disables warnings)
- `chime-validation-max-retries' — integer >= 0 (0 = fail immediately)
The constraints follow each docstring's stated intent. The helper signals
`user-error', so `customize-set-variable' surfaces it as a config problem
rather than a generic error trace.
Tests: 22 cases in `tests/test-chime-numeric-defcustom-setters.el' —
five direct on the helper plus each defcustom's accept/reject paths
through `customize-set-variable'.
Diffstat (limited to 'chime.el')
| -rw-r--r-- | chime.el | 48 |
1 files changed, 42 insertions, 6 deletions
@@ -78,6 +78,24 @@ "Chime customization options." :group 'org) +(defun chime--validate-integer-setting (symbol value min allow-nil) + "Reject bad integer values for SYMBOL at customize time. +VALUE is what the user is trying to set. MIN is the inclusive floor. +When ALLOW-NIL is non-nil, nil is accepted; otherwise nil fails like any +other non-integer. Returns VALUE on success so the caller can chain into +`set-default'. The error is a `user-error' so `customize-set-variable' +surfaces it as a configuration problem rather than a generic error." + (cond + ((and allow-nil (null value)) value) + ((not (integerp value)) + (user-error "%s must be %s, got: %S" + symbol + (if allow-nil "nil or an integer" "an integer") + value)) + ((< value min) + (user-error "%s must be >= %d, got: %d" symbol min value)) + (t value))) + (defcustom chime-alert-intervals '((10 . medium) (0 . high)) "Alert intervals with severity levels for upcoming events. Each element is a cons cell (MINUTES . SEVERITY) where: @@ -311,7 +329,10 @@ Example: With value 1 and alert times \\='(\"08:00\"), you'll get: :package-version '(chime . "0.6.0") :group 'chime :type '(choice (const :tag "Same day only" nil) - (integer :tag "Days in advance"))) + (integer :tag "Days in advance")) + :set (lambda (symbol value) + (chime--validate-integer-setting symbol value 0 t) + (set-default symbol value))) (defcustom chime-tooltip-show-all-day-events t "Whether to show all-day events in the tooltip. @@ -350,7 +371,10 @@ Set to 0 to disable modeline display. This setting only takes effect when `chime-enable-modeline' is non-nil." :package-version '(chime . "0.6.0") :group 'chime - :type '(integer :tag "Minutes")) + :type '(integer :tag "Minutes") + :set (lambda (symbol value) + (chime--validate-integer-setting symbol value 0 nil) + (set-default symbol value))) (defcustom chime-modeline-format " ⏰ %s" "Format string for modeline display. @@ -388,7 +412,10 @@ Note: larger values increase the `org-agenda-list' span in the async subprocess, which may slow event checks for large org collections." :package-version '(chime . "0.6.0") :group 'chime - :type '(integer :tag "Hours")) + :type '(integer :tag "Hours") + :set (lambda (symbol value) + (chime--validate-integer-setting symbol value 1 nil) + (set-default symbol value))) (defcustom chime-modeline-tooltip-max-events 5 "Maximum number of events to show in modeline tooltip. @@ -396,7 +423,10 @@ Set to nil to show all events within tooltip lookahead window." :package-version '(chime . "0.6.0") :group 'chime :type '(choice (integer :tag "Maximum events") - (const :tag "Show all" nil))) + (const :tag "Show all" nil)) + :set (lambda (symbol value) + (chime--validate-integer-setting symbol value 1 t) + (set-default symbol value))) (defcustom chime-modeline-no-events-text " ⏰" "Text to display in modeline when no events are within lookahead window. @@ -536,7 +566,10 @@ via `display-warning'. The counter resets on any successful check. Set to 0 to disable failure warnings." :package-version '(chime . "0.6.0") :group 'chime - :type 'integer) + :type 'integer + :set (lambda (symbol value) + (chime--validate-integer-setting symbol value 0 nil) + (set-default symbol value))) (defcustom chime-debug nil "Enable debug functions for troubleshooting chime behavior. @@ -616,7 +649,10 @@ Set to 0 to show errors immediately without retrying. Default is 3 retries (with 30-60s check intervals, this gives ~1.5-3 minutes for org-agenda-files to be populated)." :type 'integer - :group 'chime) + :group 'chime + :set (lambda (symbol value) + (chime--validate-integer-setting symbol value 0 nil) + (set-default symbol value))) (defvar chime-modeline-string nil "Modeline string showing next upcoming event.") |
