blob: 0791c3b2f8295fa8be3a86d7557f60b8070208d8 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
#+TITLE: No empty input as meaningful
#+SLUG: no-empty-input-as-meaningful
#+PRINCIPLE: If "no value" is a meaningful choice, it belongs in the candidate list, not behind an empty-input convention.
#+PROBLEM: An empty-RET-means-none idiom is an affordance the user has to know but can't see; the only hint lives in the prompt label, not where the eye is looking.
#+TAGS: completing-read prompts affordances sentinel
#+SOURCE: pearl commit 1288c2a (ad-hoc filter builder), handoff note 2026-05-28
#+EXAMPLES: pearl ad-hoc filter builder
* Problem
A prompt lets the user pick a value or pick "no value." The common shortcut is to let empty input mean "none," so RET on an untouched prompt does something silently. The user has to remember the convention, and the only on-screen hint is a parenthetical in the prompt label, which sits away from the candidate list where the eye actually is.
* Do
Make the "no value" choice a candidate the user sees and picks. Prepend a sentinel like =[ None. ]= as the first candidate, picked by default RET, with =require-match= on so the user chooses from the list rather than free-typing.
Before:
#+begin_example
Team (empty for any): _
#+end_example
After:
#+begin_example
Team: [ None. ] <- first candidate, default RET
Engineering
Design
...
#+end_example
The cost is one predicate plus one list-prepender and a defconst for the sentinel string. The predicate also treats nil and empty as the opt-out, so any caller still producing empty input is handled. The win: users stop having to know a rule that isn't on screen. The underlying rule is no hidden affordances: if it's a choice, it's in the list.
* Anti-pattern
"Empty input means none/any/skip." Any behavior triggered by the absence of input is invisible. A label hint is not a substitute for the choice being a visible candidate.
* Applicability
Every prompt across every project where "none" is a meaningful answer is a candidate. This is the base case the next three patterns sharpen.
* Related
The root of patterns 4-6. Pair it with [[file:label-matches-behavior.org][label-matches-behavior]]: a visible sentinel whose label is wrong is no better than a hidden idiom.
|