Skip to content

targets: an area follows the selection unless you pin it - #120

Open
zmaril wants to merge 1 commit into
mainfrom
targets/linked
Open

targets: an area follows the selection unless you pin it#120
zmaril wants to merge 1 commit into
mainfrom
targets/linked

Conversation

@zmaril

@zmaril zmaril commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Stacked on #117.

You were right that #109 was hard to tell apart from nothing. Here's why: the file browser could not open anything.

TreeView { children_of }     // ← no on_pick

on_pick was wired in exactly one place — the target-picker modal. So clicking a file selected the row inside that one editor and no other area heard. The only way to point a code viewer at a file was the chip and the modal. Which made #109 nearly untestable too: it marks the row an area is already open on, and almost nothing ever opened one.

The model

Blender's, because it's the right one: an editor follows the active thing, and a pin freezes it. Pin is opt-out.

select { kind: "file", value: "src/main.rs" }

Writes the target on every unpinned area whose editor points at that kind. Not resolved at draw time — written into the layout, so the document still says exactly what each area shows and every reader of it (the target chip, get_state, a saved workspace) needs no new concept. set_pinned { id, pinned } is the freeze.

Both are bus commands, so both got MCP tools — the parity test asked for them by name.

target_kind is not target_noun

The noun is the word shown to a person. The kind is what an area points at.

editor kind
code, diff file
files folder
run run
chart chart

code and diff share one, so picking a file drives both — that's the Code and Changes arrangements finally working. The browser deliberately does not share it: its target is the folder it's rooted at, and re-rooting it onto the file you just clicked would collapse the tree you clicked it in. There's a test asserting the browser stays put.

Details worth knowing

  • The pin is composed into every targeting header, not declared fourteen times — it belongs to the act of looking at something, not to any one editor. Uses the header-item slot from editors: the area header carries the editor's own controls #114.
  • The half you split off keeps what it was showing. Splitting is how you get a second view of this thing; a fresh half that followed the next selection away would be the opposite of the gesture.
  • select is navigational, so a click in a list doesn't bury the splits and joins on the undo stack.
  • Selecting a kind nothing shows is not an error — picking a file with no viewer open is a reasonable thing to do. A malformed call still is.
  • pinned is serde(default), so every layout saved before it reads as unpinned, which is what those layouts did. The test uses a real pre-pin document, because a default coming out the other way would silently freeze every existing workbench.

Trying it

Open the Code workspace and click a file. Then Changes — same click, both panes. Pin the code viewer, click another file, watch only the diff move.

161 tests pass (5 new); fmt clean, clippy clean under -D warnings, docs/reference.md regenerated with the two new commands and tools.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XjCx5QszLXroGYh1YBxybw

@github-actions

Copy link
Copy Markdown

powderman preview

https://powderman-pr-120.fly.dev

The workbench, live: split/join/swap areas, the F3 palette, the widgets, themes, tooltips, the status bar.
The fleet and run execution are inert here (a Fly machine has no herdr) — this is for driving the interface.

On branches with the MCP server, point an agent at it:

claude mcp add --transport http powderman-preview "https://powderman-pr-120.fly.dev/mcp"

Updated on every push. Destroyed when this PR closes.

The file browser could not open anything. It mounted the tree with no
on_pick, so clicking a file selected the row inside that one editor and no
other area heard — the only way to point a code viewer at a file was the
chip and the modal picker. Which also made #109 nearly untestable: it marks
the row an area is already open on, and almost nothing ever opened one.

Blender's model, because it is the right one: an editor follows the active
thing, and a pin freezes it. Pin is opt-out.

`select { kind, value }` writes the target on every unpinned area whose
editor points at that kind. Not resolved when an area is drawn — written
into the layout — so the document still says exactly what each area shows
and every reader of it, the target chip and get_state and a saved
workspace, needs no new concept. `set_pinned { id, pinned }` is the
freeze. Both are bus commands, so both got MCP tools, which the parity test
asked for by name.

`target_kind` is deliberately not `target_noun`. The noun is the word shown
to a person; the kind is what an area points *at*. The code viewer and the
diff viewer share one, so picking a file drives both — the Code and Changes
arrangements, working. The file browser does not share it: its target is
the folder it is rooted at, and re-rooting it onto the file you just
clicked would collapse the tree you clicked it in.

The pin is composed into every targeting editor's header rather than
declared fourteen times, since it belongs to the act of looking at
something rather than to any one editor. The half you split off keeps what
it was showing — splitting is how you get a second view of *this* thing,
and a fresh half that followed the next selection away would be the
opposite of the gesture.

`pinned` is serde(default), so every layout saved before it reads as
unpinned, which is the behaviour those layouts had. There is a test with a
real pre-pin document in it, because a default that came out the other way
would silently freeze every existing workbench.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XjCx5QszLXroGYh1YBxybw
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