Skip to content

Add C APIs for keyboard copy-mode selection control#4

Open
lawrencecchen wants to merge 1 commit intomainfrom
issue-788-terminal-vi-copy-mode
Open

Add C APIs for keyboard copy-mode selection control#4
lawrencecchen wants to merge 1 commit intomainfrom
issue-788-terminal-vi-copy-mode

Conversation

@lawrencecchen
Copy link

@lawrencecchen lawrencecchen commented Mar 3, 2026

Summary

  • expose ghostty_surface_select_cursor_cell and ghostty_surface_clear_selection from embedded C API
  • add Surface.selectCursorCell()/Surface.clearSelection() helpers for selection lifecycle
  • anchor cursor-cell selection to viewport origin when the live cursor is off-screen, so keyboard copy mode starts on visible content

Related: manaflow-ai/cmux#788


Summary by cubic

Add embedded C APIs to start and clear keyboard copy-mode selections, and make copy mode start on visible content. Supports terminal vi copy mode work (cmux#788).

  • New Features

    • Export ghostty_surface_select_cursor_cell and ghostty_surface_clear_selection.
    • Add Surface.selectCursorCell() and Surface.clearSelection() helpers that update selection and trigger render.
  • Bug Fixes

    • When the live cursor is off-screen, start selection at the viewport origin so keyboard copy mode anchors to visible text.

Written for commit 7dd5898. Summary will update on new commits.

Summary by CodeRabbit

Release Notes

  • New Features
    • Select text starting from the cell at your cursor position
    • Clear your current selection with a dedicated command

@coderabbitai
Copy link

coderabbitai bot commented Mar 3, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 80d3fa0 and 7dd5898.

📒 Files selected for processing (2)
  • src/Surface.zig
  • src/apprt/embedded.zig

📝 Walkthrough

Walkthrough

Two new public methods are added to the Surface API: selectCursorCell to initiate a selection at the cursor position and clearSelection to remove the active selection. Corresponding C API exports wrap these methods with error handling for embedded use.

Changes

Cohort / File(s) Summary
Core Surface API
src/Surface.zig
Added two public methods: selectCursorCell() to create a selection anchored at the active cursor, and clearSelection() to remove active selections. Both manage renderer locking and trigger selection dirty state updates.
C API Wrappers
src/apprt/embedded.zig
Added two exported C functions: ghostty_surface_select_cursor_cell() and ghostty_surface_clear_selection() that wrap the core Surface methods with error handling and logging.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 With whisker-twitched precision, I declare,
The cursor's cell now yielding to selection's care,
And clear commands banish unwanted states—
A rabbit's joy when interfaces are straight! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding C API functions for keyboard copy-mode selection control, which aligns with the new exported functions ghostty_surface_select_cursor_cell and ghostty_surface_clear_selection.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch issue-788-terminal-vi-copy-mode

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7dd589824d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

/// Start a selection at the active cursor cell.
export fn ghostty_surface_select_cursor_cell(surface: *Surface) bool {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Declare new selection APIs in the public C header

These two new exports are not declared in include/ghostty.h, so embedders using the shipped header cannot call them directly; in C99+ this typically surfaces as an implicit-declaration build error (often fatal under -Werror) even though the symbols exist at link time. I checked the header section around the existing selection APIs (ghostty_surface_has_selection/ghostty_surface_read_selection) and there are no prototypes for ghostty_surface_select_cursor_cell or ghostty_surface_clear_selection.

Useful? React with 👍 / 👎.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

@greptile-apps
Copy link

greptile-apps bot commented Mar 3, 2026

Greptile Summary

Adds C API functions to control terminal selection lifecycle for keyboard copy mode, with smart viewport-aware cursor anchoring.

  • Implemented Surface.selectCursorCell() that intelligently anchors selection to cursor position if visible, or viewport origin if scrolled away
  • Implemented Surface.clearSelection() for explicit selection cleanup
  • Exposed both functions through C API as ghostty_surface_select_cursor_cell() and ghostty_surface_clear_selection()
  • Properly handles viewport edge cases where cursor may be off-screen during scrollback
  • Avoids clobbering clipboard contents when entering keyboard copy mode by bypassing setSelection() clipboard logic
  • Consistent error handling and mutex protection throughout

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • Clean implementation that follows existing codebase patterns - proper mutex locking, consistent error handling, thoughtful edge case handling for viewport visibility, and well-commented logic. No breaking changes or security concerns.
  • No files require special attention

Important Files Changed

Filename Overview
src/Surface.zig Added selectCursorCell() and clearSelection() helpers with proper viewport visibility checks and mutex protection
src/apprt/embedded.zig Exposed C API exports for selection control with consistent error handling

Sequence Diagram

sequenceDiagram
    participant App as C Application
    participant API as Embedded C API
    participant Surface as Surface.zig
    participant Screen as Terminal Screen

    Note over App,Screen: Select Cursor Cell Flow
    App->>API: ghostty_surface_select_cursor_cell()
    API->>Surface: selectCursorCell()
    Surface->>Surface: Lock renderer mutex
    Surface->>Screen: Check cursor visibility
    alt Cursor visible in viewport
        Surface->>Screen: Use cursor page_pin
    else Cursor off-screen
        Surface->>Screen: Use viewport origin pin
    end
    Surface->>Screen: select(Selection.init(pin, pin, false))
    Surface->>Screen: Mark selection dirty
    Surface->>Surface: Queue render
    Surface->>Surface: Unlock mutex
    Surface-->>API: Return true
    API-->>App: Return true

    Note over App,Screen: Clear Selection Flow
    App->>API: ghostty_surface_clear_selection()
    API->>Surface: clearSelection()
    Surface->>Surface: Lock renderer mutex
    alt No selection exists
        Surface-->>API: Return false
    else Selection exists
        Surface->>Surface: setSelection(null)
        Surface->>Screen: Mark selection dirty
        Surface->>Surface: Queue render
        Surface-->>API: Return true
    end
    Surface->>Surface: Unlock mutex
    API-->>App: Return result
Loading

Last reviewed commit: 7dd5898

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