docs(extensions): documented composer shape renderer and styling contract
- Document the `registerComposerShape` API method for adding input-editor layouts. - Detail the `ComposerStyle` layout metadata properties and rendering methods. - Provide a full implementation example demonstrating custom composer styling and registration.
This commit is contained in:
@@ -115,6 +115,7 @@ Core methods:
|
||||
- `on(event, handler)`
|
||||
- `registerTool`, `registerCommand`, `registerShortcut`, `registerFlag`
|
||||
- `registerMessageRenderer`, `registerAssistantThinkingRenderer`
|
||||
- `registerComposerShape`
|
||||
- `setLabel`, `getFlag`
|
||||
- `sendMessage`, `sendUserMessage`, `appendEntry`, `exec`
|
||||
- `getActiveTools`, `getAllTools`, `setActiveTools`
|
||||
@@ -576,6 +577,81 @@ pi.on("session_start", async (_event, ctx) => {
|
||||
|
||||
## Rendering extension points
|
||||
|
||||
## Composer shape renderer
|
||||
|
||||
`registerComposerShape` adds an extension-owned input-editor layout to **Appearance → Composer Shape**. Register it from the extension factory; the renderer is used by the live editor and its settings preview.
|
||||
|
||||
```ts
|
||||
import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
|
||||
import type { ComposerStyle } from "@oh-my-pi/pi-tui";
|
||||
|
||||
const dockStyle: ComposerStyle = {
|
||||
id: "acme-dock",
|
||||
sideBorders: false,
|
||||
verticalChrome: 1,
|
||||
statusAttachment: "none",
|
||||
bottomBar: "full",
|
||||
bottomBarGap: true,
|
||||
defaultPromptGutter: "❯ ",
|
||||
|
||||
defaultPaddingX: () => 0,
|
||||
sideChromeWidth: () => 0,
|
||||
renderTop: ({ box, width, borderColor }) =>
|
||||
borderColor(box.horizontal.repeat(width)),
|
||||
renderRow: ({ gutter, text, pad }) => [gutter + text + pad],
|
||||
renderBottom: () => undefined,
|
||||
};
|
||||
|
||||
export default function (pi: ExtensionAPI) {
|
||||
pi.registerComposerShape({
|
||||
label: "Acme Dock",
|
||||
description: "Prompt below a single rule",
|
||||
style: dockStyle,
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
`ComposerShapeDefinition` contains:
|
||||
|
||||
- `label`: required selector label.
|
||||
- `description`: optional selector detail.
|
||||
- `style`: the complete `ComposerStyle` rendering contract. `style.id` is also the persisted `composer.shape` value.
|
||||
|
||||
Use a package-qualified, non-empty, trimmed `style.id`. Built-in ids (`box`, `claude`, `pi`, `borderless`, `rule`, `field`, and `rail`) cannot be replaced. If the extension is unavailable while its id remains configured, the editor falls back to `box`.
|
||||
|
||||
### `ComposerStyle` layout metadata
|
||||
|
||||
- `sideBorders`: whether content rows own side chrome. This controls cursor reserve, IME layout, and scrollbar behavior; it is not merely descriptive.
|
||||
- `verticalChrome`: exact number of fixed top/bottom chrome rows (`0`, `1`, or `2`) used for editor height budgeting.
|
||||
- `statusAttachment`: `"top-border"` receives the embedded status gauge, `"top-rule-chip"` receives the right status group for docking on a rule, and `"none"` detaches status from the editor chrome.
|
||||
- `bottomBar`: standalone status content below the editor: `"none"`, `"left"`, or `"full"`.
|
||||
- `bottomBarGap`: whether a blank row separates the editor from a standalone bottom status bar.
|
||||
- `defaultPromptGutter`: prompt text used when the host supplies no override.
|
||||
- `defaultPaddingX(themePaddingX)`: horizontal padding selected for this style.
|
||||
- `sideChromeWidth(paddingX)`: visible cells consumed on **each** side of a content row, including padding and border/rail glyphs.
|
||||
|
||||
`renderTop` and `renderBottom` return one styled terminal row or `undefined`. `renderRow` returns one or more styled rows. Every normal rendered row must occupy exactly `ctx.width` visible cells; ANSI escape sequences have zero width. Preserve the supplied `gutter`, `text`, and `pad` instead of reflowing or truncating them.
|
||||
|
||||
### Renderer context
|
||||
|
||||
All render methods receive `width`, `paddingX`, the theme's `box` glyphs, and three styling functions:
|
||||
|
||||
- `borderColor(text)`: ordinary frame/rule color.
|
||||
- `accentColor(text)`: stable accent for shape-defining rails or caps.
|
||||
- `surfaceColor(text)`: composer background fill that survives nested SGR resets in decorated input.
|
||||
|
||||
`topBorder`, when present, is already-styled status content with its visible `width`. A top renderer owns its placement and must leave the final line at `ctx.width`.
|
||||
|
||||
`renderRow` additionally receives:
|
||||
|
||||
- `gutter`, `text`, and `pad`: pre-rendered content pieces.
|
||||
- `isLastRow`: last visible input row.
|
||||
- `cursorOverflow`: cells consumed from the right chrome by an end-of-line cursor.
|
||||
- `imeSafeCursorTail`: omit right-side cells after the cursor so terminal-local IME preedit cannot shift the chrome.
|
||||
- `scrollbarThumb`: this row intersects the editor scrollbar thumb.
|
||||
|
||||
The built-in implementations in `packages/tui/src/components/composer/` are the reference for framed, rule, filled-surface, and IME-safe layouts.
|
||||
|
||||
## Custom message renderer
|
||||
|
||||
```ts
|
||||
|
||||
Reference in New Issue
Block a user