Repository navigation
P952: show actual editor mode in native footer and hint captions - #209
Merged
Merged
Conversation
trissim
marked this pull request as ready for review
October 29, 2026 21:09
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
3 implementation commits; 6 native Textual files, +212/-34. Final source head:
bc4f72dde5332eda49c9918a44b10136f1f9b4b4. Latest mount correction: 2 files, +100/-3; production-only delta +4/-2.FooterProjection.mode_label: main 0 declarations → candidate 1. No new mode state, type roster, timer, Toad wrapper or engine interpretation.P952 makes existing editor-owned mode labels available to native Footer and left/right hint captions independently of Toad's Prompt InfoBar. Source delivery only: draft and unarmed for root review and copied-history/private-XDG frontend qualification. P917/P939 remap/application obligations and P928 Neovim remain separate; this change does not prove those workflows.
Ownership and class structure
Before:
DOMNode.key_modesupplies the ordinary/profile scope;TextArea.editing_modeis the actual reactive editor state.Screen.active_binding_modereads focused binding identity, but no display-label projection exists.HintClick.captionand takes focus away from the originating editor.4c3c4f3a03cd86b54453d83862d66df106c90fbadeclaresStandard.label = "STANDARD"; its Prompt InfoBar is the only existing mode-text consumer in the requested UI.After:
The existing
EditingMode/profile subclasses keep all mode meanings, transitions and bindings. A parameterizedAwaitKey/pending state is never reconstructed to ask its label. Existing DOMNode, Screen and TextArea method bodies are AST-identical after excluding the new read-only properties.Footer mechanism
Adds one native
FooterLabelwith-modeclass, before the command-palette key. Empty native labels hide that child; nonempty labels contribute one column. The existing immutableFooterProjectionequality includes the label.Keeps the single existing bindings-updated subscription, mount refresh, recompose/batch lock, revision rescheduling, group handling and palette behavior. When only mode text changes,
_apply_binding_projectionupdates the label in place and skips_reconcile_keys; unchanged binding children are neither removed nor mounted.Hint lifecycle and geometry
The original editor remains the label owner while it is attached to the same active screen.
_current_original_focusowns that validity decision for the label and focus restoration. Publication reconciliation retires a lost original reference once and invalidates the caption and bindings, including when the fallback label has the same cell width. Losing that resource uses the current native profile scope, not a retained mode string. Escape, click activation, paste, target availability and asynchronous retirement keep their existing paths; detached focus cannot remain a label source.The caption is one
Contentvalue containing the mode plus the existing left/right description and Escape cancellation. Width and reserved cells use its cell length, not the shorter old click caption. Initial label placement now occurs on mount, after the session has its native screen; later width/bottom-offset changes reconcile placement through the existing publication lifecycle.HintSession previously had no bindings subscription. It now owns one transient subscription/unsubscribe pair for caption invalidation. The order's no-second-subscription restriction is applied to Footer, whose count stays one; HintSession's first subscription is needed to invalidate an actual mode change without a writable mode cache or per-frame repaint loop. Publication reconciliation checks current geometry, but reruns target placement only when the caption width or bottom offset changes.
Deleted/replaced work
34 old lines removed cumulatively, mostly relocation of existing geometry/reconciliation logic, not 34 independently removed slop obligations. The three uses of the shorter click-only caption for initial width/reservation/render are replaced by the complete-caption owner. No old engine path, historical PR, compatibility alias or application preference was changed.
AST source evidence and checks
ModuleSyntaxIndex, not another parser/consumer resolver.79a8a6d69eed1d3300b54b12c490bc7d3753ee9c; Toadorigin/mainat4c3c4f3a03cd86b54453d83862d66df106c90fba(read Git blobs, not its older checked-out working source)._hints.py, not another whole scan.p952-final-source-proof.jsonretains the five production-file hashes and hint declarations/consumers at197849b89. The current mount-correction proof below supersedes only its hints hash; the other four hashes remain identical. The initial 584 count describes the first checkpoint, not a new claimed final count.compile(source, path, 'exec')passed for all five changed modules, with no generated pycache.Widget | None.FooterProjection.mode_labelmain 0, candidate 1.git diff --checkpassed./home/ts/.cache/agent-scratch/awareness-schema/p952-source-before.json,p952-source-after.json,p952-final-source-proof.json,p952-source-check.log,p952-focus-publish.log.31cd48838583c253d544465ff993d5f9d601b7805341c2527a3ce46c2dbc4916. Invocation: shared Core Pythonp952-source-map.py p952-source-before.json, then the same collector against the initial applied source intop952-source-after.json; final correction reproved only its changed module withModuleSyntaxIndex.build.No pytest, mypy, ratchet, GUI/controller attachment, provider input, environment/package changes, live preference mutation, installation or service operations were run by the author, as ordered.
Open-PR overlap
Read the live native PR file list before editing. Only Textual #208cd4d860 overlapped
dom.py/_text_area.py; Footer, hints and Screen had no open overlaps. Root message 39086 confirms the two exact display-only hooks were relayed to vim-neovim. P952 owns those hooks and Footer/HintSession/Screen; vim-neovim retains all engine semantics. No Toad PR or wrapper is part of this delivery.Initial-width mount correction (root40691)
The actual private Toad run failed in
HintSession.on_mount -> _bindings_changed -> _reconcile_caption_geometry:styles.widthwas stillNone, so the oldstyles.width.valuecomparison raisedAttributeError. Twelve published targets did not imply a retained hint session. This was my source defect, not evidence of focus loss. Retained trace:codex-greentext/p952-private-hints-20261029-144110/state/toad/logs/AttributeError_2026-10-29T14_41_18_733171.txt.The existing geometry owner now converts the desired cell width once with
Scalar.from_number, compares the completeScalarwithstyles.width, and assigns that same value. This handles initial unset width by normal value equality and distinguishes equal numeric values with different units. No fallback branch, cached width, blur workaround or new lifecycle owner. Offset, reserved-cell placement, focus rules and subscriptions are unchanged. The other four production-file hashes, including Footer, are identical to197849b89.Authored two controls, each parameterized over declared left/right click intents; UNRUN in
tests/test_hints.py:test_hint_caption_initial_unset_width_mount: actual published targets, explicit unset-width precondition, real App mount, retained session/focus/caption width and Escape restoration.test_hint_caption_same_width_mode_change: NORMAL -> INSERT through the original editor's mode owner, cached rendered-line content changes while caption width, position, session identity and target-label positions remain unchanged. A shared label-only EditingMode fixture avoids depending on the separately evolving engine classes.Bounded source evidence: NRA
ModuleSyntaxIndexreproof of hints, Scalar, ScalarProperty and the test module; all four parse and compile, zero omissions. Hash-checked all 256 native production modules from the retained 565-module paired map: only_hints.pychanged from the final197849b89hashes. This is not a new complete scan or behavioral proof.git diff --checkpasses. Artifacts:awareness-schema/p952-mount-{before,after}-proof.jsonand corresponding logs. One-shot source collector retired after both completed runs; SHA2562ce723f9dbd5d185fd4dbcd4f1c92e5b900590d9579287fbc5cd0ca3d641afc2.Fresh live native open-PR readback found only #209; no additional hints/test overlap. Queue-toad-fix subsequently received the exact unmerged Footer head and blob in40742 and owns its separate in-place group reconciliation; this correction does not touch Footer.
Required root run / Assumed
Root39504 already reports actual hidden/scrolled STANDARD, NORMAL/INSERT/VISUAL/AwaitKey Footer and Input/noneditor mode controls passed at
197849b89. Those are retained root results, not author executions. The mounting crash prevented hint qualification. Root40691 retains those successful controls and reruns the failed left/right actual-app cases on this correction. No whole-head approval, merge, installation or hint acceptance is claimed.Root owns exact-head review, recording/linking, installation and the real copied-history/private-XDG frontend run. All these runtime cases remain unrun by the author:
Native ordinary
EditingMode.labelis intentionally empty; Toad Standard supplies STANDARD through its existing declaration. Future Neovim noneditor profile fallback must not manufacture NORMAL before acknowledgement. This change does not interpret Neovim codes; its actual acknowledgedediting_mode.labelremains the separate engine owner's contract and needs paired qualification after that work lands.