Skip to content

Make the Emacs client easier to pick up#140

Merged
bbatsov merged 7 commits into
masterfrom
better-ux
Jul 17, 2026
Merged

Make the Emacs client easier to pick up#140
bbatsov merged 7 commits into
masterfrom
better-ux

Conversation

@bbatsov

@bbatsov bbatsov commented Jul 17, 2026

Copy link
Copy Markdown
Member

A UX pass over the Emacs client, aimed at people new to Sayid. C-c s now opens a transient menu that groups the commands along the core loop (trace something, run your code, explore the recording) and shows live state about what's traced and recorded. Empty views explain how to get data instead of erroring, the trace commands describe their outcome in plain language, there's a plain sayid-trace-fn for people who haven't met the inner/outer distinction yet, and the workspace tree now covers everything the legacy text view could do (def/pprint/reproduction expressions, form queries), so it's where all default bindings land.

All the classic key sequences keep working - the menu uses the same keys, and sayid-use-menu set to nil restores the plain prefix map. The op changes are backward compatible with older middleware (details in doc/nrepl-api.md).

bbatsov added 7 commits July 17, 2026 12:08
An empty workspace tree and an empty traced view used to signal a bare
user-error - the most common first-run experience was a dead end. Render
the buffer anyway with a short hint on how to trace something and get
calls recorded. Also drops the stale "or Sayid isn't loaded" clause:
middleware presence is checked upfront on every request these days.
Trace commands used to echo the raw server reply (a bare qualified
symbol) and pop up the traced view on every action. Now they say what
happened in user terms and point at the next step, refreshing the traced
view only when it's already visible. The middleware reply carries the
resolved symbol plus whether the fn was traced, so enable/disable/remove
on an untraced function reports the real problem instead of silently
no-oping.

Also: g refreshes the tree and traced buffers (each re-runs the fetch
that produced it), and sayid-reset-workspace asks before irreversibly
dropping traces and the recording.
A newcomer just wants "trace this function" without first learning the
inner/outer distinction - sayid-trace-fn (C-c s t t) is that: an outer
trace of the fn at point. The per-function commands also get consistent
names (sayid-trace-fn-outer/-inner/-remove); the old flipped-prefix
names live on as obsolete aliases.
The tree and the old text buffer each had capabilities the other lacked,
so no single view could carry a debugging session. The tree now covers
the rest: c d defs a captured value to $s/*, c p pretty-prints one, and
c r copies an expression reproducing the call at point (all sharing the
inspect command's value picker). sayid-query-form-at-point renders in
the tree too, via a new sayid-query-form-at-point-data op, making the
tree where every default binding lands.
Sayid's core loop (trace -> run -> explore) was invisible: the entry
point was a flat prefix map of 20+ memorized bindings. C-c s now pops
up a transient menu that groups the commands along that loop and shows
live state - how much is traced and how many calls are recorded (via a
new sayid-get-log-count op) - or what's missing (REPL, middleware) when
disconnected. The menu uses the same key sequences as the classic
prefix map, so existing muscle memory keeps working, and setting
sayid-use-menu to nil restores the raw keymap.
The review of this branch caught three compatibility breaks. The
sayid-trace-fn-at-point reply keeps its old string value and carries the
new sym/was-traced fields as extra response slots, so either side can be
older without crashing; remove applies unconditionally again, preserving
the reconciliation path for traces that fell out of sync with the
workspace. sayid--menu-key now understands both transient layout
encodings (suffix plist as the cdr or as an element). And
sayid-query-form-at-point falls back to the legacy text view when the
middleware predates the data op, instead of misreporting recorded calls
as absent. A middleware error is also surfaced as such now, not as "no
function at point".
Refreshing a query whose calls disappeared (log cleared, workspace
reset) now renders the emptied view with a hint instead of erroring
over stale content. The auto-refresh of a visible traced view keeps its
namespace filter. The tree's pretty-print no longer resets point in the
tree buffer. The empty-state hints look their key sequences up live
instead of hardcoding C-c s, so custom prefixes show correctly. Also
merges the accidentally duplicated Changes heading in the changelog.
@bbatsov
bbatsov merged commit ec0ba20 into master Jul 17, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant