Open
Conversation
Contributor
orjson migration moved to a separate branch (feature/orjson-migration) and PR #58 to keep concerns isolated.
932e823 to
355f67a
Compare
juftin
commented
Apr 2, 2026
juftin
commented
Apr 2, 2026
juftin
commented
Apr 2, 2026
juftin
commented
Apr 2, 2026
juftin
commented
Apr 2, 2026
juftin
commented
Apr 2, 2026
juftin
commented
Apr 2, 2026
juftin
commented
Apr 2, 2026
juftin
commented
Apr 2, 2026
There was a problem hiding this comment.
Pull request overview
Integrates Textual’s TextArea as the primary interactive code/text viewer and adds a ?-triggered keyboard shortcuts overlay, along with supporting theme/language config and updated tests/snapshots.
Changes:
- Replace the read-only
Syntax-based code viewer with a read-onlyTextArea-basedTextWindowand updateWindowSwitcherrouting/theme/lineno propagation. - Add a reusable overlay/popup base plus a new shortcuts overlay that discovers active bindings and displays them in a
DataTable. - Update docs, CLI help text, dependencies, and expand test/snapshot coverage to match the new UI behavior.
Reviewed changes
Copilot reviewed 24 out of 26 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
browsr/widgets/windows.py |
Adds TextWindow, mixins, new WindowSwitcher routing, and theme/lineno synchronization logic. |
browsr/config.py |
Introduces TextArea theme mapping and language/filename detection maps. |
browsr/widgets/base.py |
Adds BasePopUp / BaseOverlay primitives for consistent overlay behavior. |
browsr/widgets/shortcuts.py |
Implements shortcuts popup/window with active binding discovery and filtering. |
browsr/widgets/confirmation.py |
Refactors confirmation UI to use the new popup/overlay base. |
browsr/widgets/code_browser.py |
Adjusts key binding registration and confirmation workflow display restoration. |
browsr/screens/code_browser.py |
Adds ? and w actions, overlay layer support, and shortcuts overlay wiring. |
browsr/browsr.py |
Adds action_copy_text delegating to TextWindow selection-copy behavior. |
browsr/browsr.css |
Styles shortcuts/confirmation as true overlays with semi-transparent backgrounds. |
browsr/utils.py |
Adjusts image scaling math used for rendering images in-terminal. |
browsr/cli.py |
Updates documented key bindings to match the new bindings and features. |
pyproject.toml |
Enables textual[syntax] extra for Tree-sitter highlighting in TextArea. |
README.md |
Updates marketing copy to mention TextArea-based syntax highlighting. |
docs/index.md |
Mirrors README copy update for the documentation homepage. |
docs/superpowers/summaries/2026-03-30-keyboard-shortcuts-implementation.md |
Adds implementation summary document for the feature. |
docs/superpowers/specs/2026-03-30-keyboard-shortcuts-widget-design.md |
Adds design spec document for the shortcuts overlay. |
docs/superpowers/plans/2026-03-30-keyboard-shortcuts-widget.md |
Adds implementation plan document for the shortcuts overlay. |
tests/test_windows.py |
Adds unit/integration-style tests for TextWindow and WindowSwitcher behavior. |
tests/test_shortcuts.py |
Adds a basic mount/render test for shortcut discovery. |
tests/test_screenshots.py |
Updates screenshot test to open the shortcuts overlay during snapshot. |
tests/cassettes/test_shortcuts_screenshot.yaml |
Adds VCR cassette data used by the new screenshot test. |
tests/__snapshots__/test_screenshots/test_shortcuts_screenshot.raw |
Adds new snapshot output for the shortcuts overlay screenshot. |
tests/__snapshots__/test_screenshots/test_github_screenshot.raw |
Removes an obsolete snapshot tied to the renamed screenshot test. |
Comments suppressed due to low confidence (1)
browsr/widgets/confirmation.py:90
ConfirmationWindow.compose()currently returns immediately and contains an unreachableyieldstatement. This makes the method misleading and can result in an empty overlay ifConfirmationWindowis ever instantiated without children passed to the constructor. Either remove this override entirely (letContainerhandle children) or implementcompose()to yield the expectedConfirmationPopUpcontent.
def compose(self) -> ComposeResult:
"""
Compose the Confirmation Window
"""
return
yield
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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
Integrates Textual's native
TextAreawidget as the primary code viewer inbrowsr, replacing the staticSyntax-based view for text and JSON files, and adds a new interactive Keyboard Shortcuts overlay accessible via?.Context
Two major features land in this PR:
TextArea Integration — The static
Syntaxwidget (via Rich) was read-only and non-interactive. Replacing it withTextAreaunlocks native syntax highlighting, vim-style cursor navigation, text selection, clipboard copy, and soft-wrap toggling — all within the existingbrowsrUI architecture.Keyboard Shortcuts Widget — A new
?-triggered overlay that dynamically lists all active bindings, filtered to a trusted action list, and sorted alphabetically. Built on a reusableBasePopUp/BaseOverlaypattern that also benefits the existingConfirmationWindow.Changes
Code Changes
browsr/widgets/windows.pyTextWindow(TextArea, BaseCodeWindow)widget with read-only mode, vim key bindings (hjkl), smart language detection, theme mapping, and clipboard copy support viapyperclip.FileToStringResultNamedTuple carrying both the decoded text and anerror_occurredflag, enabling graceful fallback toStaticWindowon load failure.ThemeVisibleMixinandLinenosVisibleMixinto share reactive state cleanly betweenStaticWindow,TextWindow, andWindowSwitcher.WindowSwitcherto compose and route files toTextWindow(code/JSON) orStaticWindow(images/markdown/errors), with unifiedlinenos,theme, and dark-mode reactive watchers._update_subtitleto keep the app subtitle consistent (with theme annotation) across all window types.next_themeinto_next_textarea_theme/_next_rich_themehelpers to cycle TextArea themes (fromtextarea_theme_map) and Rich themes (forStaticWindow) independently.watch_darktoWindowSwitcherto propagate dark-mode changes toTextWindow.apply_smart_theme.browsr/config.pytextarea_default_theme(defaults tovscode_dark).textarea_theme_map(OrderedDictmapping Rich theme names to equivalent TextArea theme names for coordinated cycling).language_map(file extension → TextArea language string).filename_map(special-case filenames likeDockerfile,uv.lock,Makefile→ language).browsr/widgets/base.py(new file)BasePopUp(Container): focusable popup base withescapebinding and aTogglemessage for communicating display state to a parent overlay.BaseOverlay(Container): overlay container that listens forBasePopUp.Toggle, managesdisplay, auto-focuses on show, and hides on mount.browsr/widgets/shortcuts.py(new file)ShortcutsPopUp(BasePopUp): dynamically readsapp.active_bindings, filters toTRUSTED_ACTIONSand ignoresIGNORED_KEYS(e.g.ctrl+q), and presents a sortedDataTableof key → description.ShortcutsWindow(BaseOverlay): overlay container wrappingShortcutsPopUp.browsr/widgets/confirmation.pyConfirmationPopUpandConfirmationWindowto inherit fromBasePopUp/BaseOverlay, removing duplicated display-toggle and escape-handling logic.browsr/screens/code_browser.py?binding foraction_toggle_shortcuts— opens/closesShortcutsWindowand refreshes the DataTable.wbinding foraction_toggle_wrap— togglesTextWindow.soft_wrap.LAYERS = ["default", "overlay"]to support true overlay rendering forShortcutsWindowandConfirmationWindow.BINDING_WEIGHTSto accommodate neww,C, and?entries.action_linenosto setlinenosonWindowSwitcherrather than directly onStaticWindow.browsr/widgets/code_browser.pyC(Shift+C) tocopy_textaction withkey_display="shift+c"for footer display.browsr/browsr.pyaction_copy_textto delegate clipboard copy totext_window.copy_selected_text().browsr/browsr.cssShortcutsWindowandConfirmationWindowas true overlay layers with semi-transparent backgrounds.pyproject.toml/uv.locktextual[syntax]extra (enables Tree-sitter syntax highlighting inTextArea).pyperclipfor clipboard copy support.tests/test_windows.py(new file)TextWindow: initialization, language detection, theme application, linenos sync, copy behavior, andWindowSwitcherrouting logic.tests/test_shortcuts.py(new file)ShortcutsWindowmount and rendering.tests/__snapshots__/TextArea-based rendering and new shortcuts overlay.Test Plan
w) verified.StaticWindowon file load error verified.ShortcutsWindowrenders active bindings filtered to trusted actions.ShortcutsWindowandConfirmationWindow.uv run pytest tests/).mypypasses with no errors.rufflinting and formatting pass..py,.json,.md,.csv, image) and verify correct window routing and theme cycling.?to open shortcuts overlay, verify it shows the correct bindings and closes withescapeor the Close button.Behavior Diagram
graph TD subgraph WindowSwitcher A[file_path] --> B{extension?} B -->|datatable| C[DataTableWindow] B -->|image| D[StaticWindow - image] B -->|markdown| E[StaticWindow - markdown] B -->|json| F[TextWindow - json] B -->|text / error| G{load error?} G -->|yes| H[StaticWindow - error art] G -->|no| I[TextWindow - code] end subgraph Overlays J["? key"] --> K[ShortcutsWindow] K --> L[ShortcutsPopUp DataTable] M[download action] --> N[ConfirmationWindow] N --> O[ConfirmationPopUp] end