Skip to content

Commit 4e2a514

Browse files
Visualize actions on the documentation page (#3330)
1 parent 4bdaf08 commit 4e2a514

109 files changed

Lines changed: 2621 additions & 13 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## 2026
44

5+
- 2026-09-02: Visualize actions on the documentation page. ([#3330](https://github.com/cursorless-dev/cursorless/pull/3330))
56
- 2026-09-01: Visualize modifiers on the documentation page. ([#3328](https://github.com/cursorless-dev/cursorless/pull/3328); [#3329](https://github.com/cursorless-dev/cursorless/pull/3329))
67
- 2026-08-30: Overhauled the user documentation with generated and grouped action, modifier, and scope reference pages, richer descriptions and examples, dedicated paired-delimiter and target guides, and a streamlined landing page. ([#3303](https://github.com/cursorless-dev/cursorless/pull/3303); [#3304](https://github.com/cursorless-dev/cursorless/pull/3304); [#3305](https://github.com/cursorless-dev/cursorless/pull/3305); [#3306](https://github.com/cursorless-dev/cursorless/pull/3306); [#3307](https://github.com/cursorless-dev/cursorless/pull/3307); [#3308](https://github.com/cursorless-dev/cursorless/pull/3308); [#3309](https://github.com/cursorless-dev/cursorless/pull/3309); [#3310](https://github.com/cursorless-dev/cursorless/pull/3310); [#3311](https://github.com/cursorless-dev/cursorless/pull/3311); [#3312](https://github.com/cursorless-dev/cursorless/pull/3312); [#3313](https://github.com/cursorless-dev/cursorless/pull/3313); [#3314](https://github.com/cursorless-dev/cursorless/pull/3314); [#3315](https://github.com/cursorless-dev/cursorless/pull/3315); [#3316](https://github.com/cursorless-dev/cursorless/pull/3316))
78
- 2026-05-03: Add support for if and for statements in Talon-script. [`#3274`](https://github.com/cursorless-dev/cursorless/pull/3274)

‎packages/app-web-docs/src/docs/components/RecordedTestVisualizer.tsx‎

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -141,19 +141,27 @@ function CodeState({
141141
const decorations = useMemo(
142142
() => [
143143
...state.selections.map(toDecoration),
144-
...toMarkDecorations(state.marks),
144+
...toMarkDecorations(state.marks, state.documentContents),
145145
],
146-
[state.selections, state.marks],
146+
[state.selections, state.marks, state.documentContents],
147147
);
148148
return (
149-
<Code
150-
link={link}
151-
languageId={languageId}
152-
renderWhitespace={renderWhitespace}
153-
decorations={decorations}
154-
>
155-
{state.documentContents}
156-
</Code>
149+
<>
150+
<Code
151+
link={link}
152+
languageId={languageId}
153+
renderWhitespace={renderWhitespace}
154+
decorations={decorations}
155+
>
156+
{state.documentContents}
157+
</Code>
158+
{state.clipboard != null && (
159+
<div className="mt-2">
160+
<strong>Clipboard:</strong>
161+
&nbsp;<i>&quot;{state.clipboard}&quot;</i>
162+
</div>
163+
)}
164+
</>
157165
);
158166
}
159167

@@ -178,19 +186,46 @@ function toDecoration(plainSelection: SelectionPlainObject): DecorationItem {
178186
};
179187
}
180188

189+
/**
190+
* Converts serialized token marks to Shiki decorations around the first
191+
* occurrence of each mark's decorated character within its token.
192+
*/
181193
function toMarkDecorations(
182194
marks: SerializedMarks | undefined,
195+
documentContents: string,
183196
): DecorationItem[] {
184197
if (marks == null) {
185198
return [];
186199
}
187200

201+
const lines = documentContents.split(/\r?\n/u);
202+
188203
return Object.entries(marks).map(([key, range]) => {
189-
const { hatStyle } = splitKey(key);
204+
if (range.start.line !== range.end.line) {
205+
throw new Error(`Mark ${key} spans multiple lines`);
206+
}
207+
208+
const line = lines[range.start.line];
209+
210+
if (line == null) {
211+
throw new Error(`Mark ${key} is outside the document`);
212+
}
213+
214+
const { hatStyle, character } = splitKey(key);
215+
const tokenText = line.slice(range.start.character, range.end.character);
216+
const characterOffset = tokenText.indexOf(character);
217+
const characterStart = range.start.character + characterOffset;
218+
219+
if (characterOffset === -1) {
220+
throw new Error(`Mark ${key} does not occur in its token`);
221+
}
190222

191223
return {
192-
start: range.start,
193-
end: range.end,
224+
start: { line: range.start.line, character: characterStart },
225+
end: {
226+
line: range.start.line,
227+
character: characterStart + character.length,
228+
},
194229
alwaysWrap: true,
195230
properties: {
196231
className: ["code-hat", `code-hat-${hatStyle}`],

‎packages/app-web-docs/src/docs/user/actions/addSelection.mdx‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
sidebar_label: Append
33
---
44

5+
import { RecordedTestVisualizer, RecordedTestVisualizerOptions, RecordedTestVisualizerProvider } from "@site/src/docs/components/RecordedTestVisualizer";
6+
57
# Append (Add selection)
68

79
Cursorless ID: `addSelection`
@@ -17,3 +19,15 @@ Default: `append`
1719
## Examples
1820

1921
- `"append blue air"` - Adds the token containing letter `a` with a blue hat to the current selections.
22+
23+
## Visualization
24+
25+
<RecordedTestVisualizerProvider>
26+
27+
<RecordedTestVisualizerOptions />
28+
29+
### `"append air"`
30+
31+
<RecordedTestVisualizer fixtureName="docs/actions/addSelection" />
32+
33+
</RecordedTestVisualizerProvider>

‎packages/app-web-docs/src/docs/user/actions/addSelectionAfter.mdx‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
sidebar_label: Append post
33
---
44

5+
import { RecordedTestVisualizer, RecordedTestVisualizerOptions, RecordedTestVisualizerProvider } from "@site/src/docs/components/RecordedTestVisualizer";
6+
57
# Append post (Add selection after)
68

79
Cursorless ID: `addSelectionAfter`
@@ -17,3 +19,15 @@ Default: `append post`
1719
## Examples
1820

1921
- `"append post blue air"` - Adds an empty selection after the token containing letter `a` with a blue hat.
22+
23+
## Visualization
24+
25+
<RecordedTestVisualizerProvider>
26+
27+
<RecordedTestVisualizerOptions />
28+
29+
### `"append post air"`
30+
31+
<RecordedTestVisualizer fixtureName="docs/actions/addSelectionAfter" />
32+
33+
</RecordedTestVisualizerProvider>

‎packages/app-web-docs/src/docs/user/actions/addSelectionBefore.mdx‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
sidebar_label: Append pre
33
---
44

5+
import { RecordedTestVisualizer, RecordedTestVisualizerOptions, RecordedTestVisualizerProvider } from "@site/src/docs/components/RecordedTestVisualizer";
6+
57
# Append pre (Add selection before)
68

79
Cursorless ID: `addSelectionBefore`
@@ -17,3 +19,15 @@ Default: `append pre`
1719
## Examples
1820

1921
- `"append pre blue air"` - Adds an empty selection before the token containing letter `a` with a blue hat.
22+
23+
## Visualization
24+
25+
<RecordedTestVisualizerProvider>
26+
27+
<RecordedTestVisualizerOptions />
28+
29+
### `"append pre air"`
30+
31+
<RecordedTestVisualizer fixtureName="docs/actions/addSelectionBefore" />
32+
33+
</RecordedTestVisualizerProvider>

‎packages/app-web-docs/src/docs/user/actions/applyFormatter.mdx‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
sidebar_label: Format
33
---
44

5+
import { RecordedTestVisualizer, RecordedTestVisualizerOptions, RecordedTestVisualizerProvider } from "@site/src/docs/components/RecordedTestVisualizer";
6+
57
# Format (Apply formatter)
68

79
Cursorless ID: `applyFormatter`
@@ -17,3 +19,23 @@ Default: `format`
1719
## Examples
1820

1921
- `"format camel at blue air"` - Reformats the token containing letter `a` with a blue hat as camel case.
22+
23+
## Visualization
24+
25+
<RecordedTestVisualizerProvider>
26+
27+
<RecordedTestVisualizerOptions />
28+
29+
### `"format camel at bat"`
30+
31+
<RecordedTestVisualizer fixtureName="docs/actions/applyFormatter" />
32+
33+
### `"format snake at bat"`
34+
35+
<RecordedTestVisualizer fixtureName="docs/actions/applyFormatter2" />
36+
37+
### `"format camel at line"`
38+
39+
<RecordedTestVisualizer fixtureName="docs/actions/applyFormatter3" />
40+
41+
</RecordedTestVisualizerProvider>

‎packages/app-web-docs/src/docs/user/actions/breakLine.mdx‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
sidebar_label: Break
33
---
44

5+
import { RecordedTestVisualizer, RecordedTestVisualizerOptions, RecordedTestVisualizerProvider } from "@site/src/docs/components/RecordedTestVisualizer";
6+
57
# Break (Break line)
68

79
Cursorless ID: `breakLine`
@@ -17,3 +19,15 @@ Default: `break`
1719
## Examples
1820

1921
- `"break blue air"` - Breaks the line before the token containing letter `a` with a blue hat.
22+
23+
## Visualization
24+
25+
<RecordedTestVisualizerProvider>
26+
27+
<RecordedTestVisualizerOptions />
28+
29+
### `"break air"`
30+
31+
<RecordedTestVisualizer fixtureName="docs/actions/breakLine" />
32+
33+
</RecordedTestVisualizerProvider>

‎packages/app-web-docs/src/docs/user/actions/callAsFunction.mdx‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
sidebar_label: Call
33
---
44

5+
import { RecordedTestVisualizer, RecordedTestVisualizerOptions, RecordedTestVisualizerProvider } from "@site/src/docs/components/RecordedTestVisualizer";
6+
57
# Call (Call as function)
68

79
Cursorless ID: `callAsFunction`
@@ -19,3 +21,23 @@ Default: `call`
1921

2022
- `"call blue air"` - Inserts a call to the token containing letter `a` with a blue hat at the current selection.
2123
- `"call blue air on green bat"` - Inserts a call to the token containing letter `a` with a blue hat on the token containing letter `b` with a green hat.
24+
25+
## Visualization
26+
27+
<RecordedTestVisualizerProvider>
28+
29+
<RecordedTestVisualizerOptions />
30+
31+
### `"call air"`
32+
33+
<RecordedTestVisualizer fixtureName="docs/actions/callAsFunction" />
34+
35+
### `"call air"`
36+
37+
<RecordedTestVisualizer fixtureName="docs/actions/callAsFunction2" />
38+
39+
### `"call air on bat"`
40+
41+
<RecordedTestVisualizer fixtureName="docs/actions/callAsFunction3" />
42+
43+
</RecordedTestVisualizerProvider>

‎packages/app-web-docs/src/docs/user/actions/clearAndSetSelection.mdx‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
sidebar_label: Change
33
---
44

5+
import { RecordedTestVisualizer, RecordedTestVisualizerOptions, RecordedTestVisualizerProvider } from "@site/src/docs/components/RecordedTestVisualizer";
6+
57
# Change
68

79
Cursorless ID: `clearAndSetSelection`
@@ -18,3 +20,15 @@ Legacy: `clear`
1820
## Examples
1921

2022
- `"change blue air"` - Changes the token containing letter `a` with a blue hat by clearing it and leaving the cursor in its place.
23+
24+
## Visualization
25+
26+
<RecordedTestVisualizerProvider>
27+
28+
<RecordedTestVisualizerOptions />
29+
30+
### `"change air"`
31+
32+
<RecordedTestVisualizer fixtureName="docs/actions/clearAndSetSelection" />
33+
34+
</RecordedTestVisualizerProvider>

‎packages/app-web-docs/src/docs/user/actions/copyToClipboard.mdx‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
sidebar_label: Copy
33
---
44

5+
import { RecordedTestVisualizer, RecordedTestVisualizerOptions, RecordedTestVisualizerProvider } from "@site/src/docs/components/RecordedTestVisualizer";
6+
57
# Copy (Copy to clipboard)
68

79
Cursorless ID: `copyToClipboard`
@@ -17,3 +19,15 @@ Default: `copy`
1719
## Examples
1820

1921
- `"copy blue air"` - Copies the token containing letter `a` with a blue hat to the clipboard.
22+
23+
## Visualization
24+
25+
<RecordedTestVisualizerProvider>
26+
27+
<RecordedTestVisualizerOptions />
28+
29+
### `"copy line"`
30+
31+
<RecordedTestVisualizer fixtureName="docs/actions/copyToClipboard" />
32+
33+
</RecordedTestVisualizerProvider>

0 commit comments

Comments
 (0)