refactor: restructure lib.rs into theme + router modules (#89)#107
Conversation
Move rgb() and palette_from_style() — the lone boundary touching both zellij's color types and the dependency-free color module — out of lib.rs into a focused theme adapter (rule #8). The ModeUpdate arm now calls theme::palette_from_style(); the palette_slots_come_from_multiplayer_user_colors test moves alongside its subject. No public API change (pub(crate) mod). Part of #89.
…er.rs Move pane_at / clicked_new_tab_button / clicked_close_button — the three zellij-type-free decisions a left-click resolves against the recorded frame — out of impl State into free functions in a new router module (rule #8), carrying TabPaneGeom (now pub(crate)) and the predicates' tests alongside. update() and focus_or_switch_at now call router::; the host effects stay in lib.rs, dispatched past these predicates. No public API change. Part of #89.
…e sole host-effect dispatcher Add ClickIntent + route_click to the router: one pure function resolves a left click against the recorded frame, in the bar's paint priority (+ button > close × > minimap pane > tab block > nothing), returning the single intent it triggers. update()'s LeftClick arm now matches that intent and fires the one matching host effect, so every host call (new_tab, close_tab_with_index, focus_terminal_pane, switch_tab_to) lives in exactly one place. Deletes the now-redundant focus_or_switch_at / switch_to_tab_at methods; the focus/no-op dispatch is covered by driving update() directly, and route_click's five arms by a dedicated router test. load() and the permission flow are untouched. The only off-wasm-uncovered line stays the new_tab dispatch arm (new_tab reads stdin, so it cannot run natively) — its routing decision is covered in router. Part of #89.
|
Warning Review limit reached
More reviews will be available in 35 minutes and 17 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughTwo new crate-internal modules are introduced: ChangesRouter and Theme Extraction
Sequence Diagram(s)sequenceDiagram
participant Plugin as ZellijPlugin::update()
participant Theme as theme::palette_from_style
participant Router as router::route_click
participant Host as Zellij Host
Plugin->>Theme: palette_from_style(&mode_info.style)
Theme-->>Plugin: color::Palette
Plugin->>Router: route_click(button_layout, close_layout, tab_layout, tab_panes, row, col)
Router-->>Plugin: ClickIntent
alt ClickIntent::NewTab
Plugin->>Host: new_tab()
else ClickIntent::CloseTab(idx)
Plugin->>Host: close_tab_with_index(idx)
Plugin->>Plugin: clear close_layout
else ClickIntent::FocusPane(id)
Plugin->>Host: focus_pane(id)
else ClickIntent::SwitchTab(n)
Plugin->>Host: switch_tab_to(n)
else ClickIntent::NoOp
Plugin->>Plugin: no action taken
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
This PR refactors the crate’s src/lib.rs by extracting two focused, unit-testable modules—theme (zellij theme → renderer palette adapter) and router (pure click intent routing)—so zellij-host effects are dispatched in one place while pure decisions remain dependency-free.
Changes:
- Added
src/theme.rsto isolate theme-to-color::Paletteconversion (and its tests) fromlib.rs. - Added
src/router.rsto consolidate click hit-testing into a pureroute_clickfunction returning a singleClickIntent. - Updated
src/lib.rsto usetheme::palette_from_styleand to dispatch mouse left-click host effects viarouter::route_click.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/theme.rs | New adapter module converting Style → color::Palette plus migrated test coverage. |
| src/router.rs | New pure click-routing module (ClickIntent + route_click) with focused unit tests. |
| src/lib.rs | Wires in the new modules; centralizes left-click host-effect dispatch via the router. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Restructures
src/lib.rsby extracting two focused modules, so the plugin'szellij-facing glue, its pure click routing, and its theme adapter no longer
share one file. Pure mechanical-equivalence refactor — no behavior change,
no public API change, no new permission. Done as three independently
green commits, never a big-bang (the issue's core ask).
Closes #89.
What moved, and why
src/theme.rs(new)rgb+palette_from_stylecolormodule — isolated as an adapter (rule #8)src/router.rs(new)pane_at/clicked_new_tab_button/clicked_close_button(now free functions) +TabPaneGeomsrc/router.rsClickIntentenum +route_clickupdate()becomes the sole host-effect dispatcherAfter commit 3, every host effect (
new_tab,close_tab_with_index,focus_terminal_pane,switch_tab_to) lives in exactly one place — theupdate()LeftClickmatch arm — dispatched off the pureroute_clickdecision. The now-redundant
focus_or_switch_at/switch_to_tab_atmethodsare deleted.
Click routing priority (unchanged)
route_clickcomposes the affordances in the order the bar paints them:Verification
All three commits build (
wasm32-wasip1) and passcargo test --libgreen;final state 243 tests pass, clippy adds no new warnings over baseline.
Four independent adversarial reviews (behavior-equivalence, #54 host-count
contract, rule-#8 boundary, coverage parity) all came back clean:
Review verdicts
EQUIVALENT— priority order,falsereturn on every path, host-effect args, theclose_layout.clear()-before-close ordering, and theSwitchTab(u32)type all identical pre/post; no divergent-input counterexample found.PRESERVED— the native-test stub trio is byte-identical,loadstill emits exactly 2 host commands and eachPermissionRequestResultexactly 1, and the permission set staysReadApplicationState+ChangeApplicationState(no third permission → no feat(title): pane-title summarization module (icon table + width-aware truncation) #15 freeze).CLEAN—router.rsreferences zero zellij types;theme.rsis the only new module touchingzellij_tile::preludeand leaks nothing past itscolor::Palettereturn; visibility stayspub(crate)(public API unchanged); content is English.NO REGRESSION— TOTAL 99.52% vs 99.53% baseline (−0.01%, within the 1% project gate);router.rsandtheme.rsboth 100% line-covered; all moved tests keep their assertions; the deletedfocus_or_switch_atsmoke test is replaced by a strongerupdate()-driven focus/no-op test; a newroute_clicktest covers all fiveClickIntentarms.Coverage note
The single off-wasm-uncovered line stays the
new_tabdispatch arm —new_tabreads a return value from stdin and panics under the native test host, so it is
inherently wasm-only (this was already uncovered at baseline). Its routing
decision (
route_click→ClickIntent::NewTab) is fully covered inrouter.rs; only the host call itself can't run off-wasm.Deferred
The
RenderGeometrybundle (folding the per-render geometry args into onestruct, the design's Step 4) is intentionally out of scope here and left to
a follow-up PR, to keep this change a clean extraction with no signature churn.
Summary by CodeRabbit
Refactor
Tests