|
1 | 1 | import { describe, expect, test } from "bun:test" |
2 | | -import type { TextareaRenderable } from "@opentui/core" |
3 | | -import { createSignal } from "solid-js" |
| 2 | +import type { ScrollBoxRenderable, TextareaRenderable } from "@opentui/core" |
| 3 | +import type { Part } from "@opencode-ai/sdk/v2" |
| 4 | +import { createRoot, createSignal } from "solid-js" |
| 5 | +import { createCopyMode } from "../../../src/cli/cmd/tui/routes/session/copy-mode" |
4 | 6 | import { createVimHandler } from "../../../src/cli/cmd/tui/component/vim/vim-handler" |
5 | 7 | import { createVimState } from "../../../src/cli/cmd/tui/component/vim/vim-state" |
6 | 8 | import type { VimScroll } from "../../../src/cli/cmd/tui/component/vim/vim-scroll" |
@@ -4634,6 +4636,44 @@ describe("copy mode", () => { |
4634 | 4636 | expect(ctx.copyVisualCalls).not.toContain("char") |
4635 | 4637 | }) |
4636 | 4638 |
|
| 4639 | + test("V after characterwise visual preserves copy anchor", () => { |
| 4640 | + createRoot((dispose) => { |
| 4641 | + const children = [ |
| 4642 | + { id: "text-part", y: 0, height: 1 }, |
| 4643 | + { id: "text-part", y: 1, height: 1 }, |
| 4644 | + { id: "text-part", y: 2, height: 1 }, |
| 4645 | + ] |
| 4646 | + const scroll = { |
| 4647 | + y: 0, |
| 4648 | + height: 3, |
| 4649 | + width: 80, |
| 4650 | + getChildren: () => children, |
| 4651 | + scrollBy(delta: number) { |
| 4652 | + scroll.y += delta |
| 4653 | + }, |
| 4654 | + } as unknown as ScrollBoxRenderable |
| 4655 | + const cm = createCopyMode({ |
| 4656 | + scroll: () => scroll, |
| 4657 | + messages: () => [{ id: "msg", role: "assistant" }], |
| 4658 | + parts: () => [{ type: "text", id: "part" } as Part], |
| 4659 | + thinking: () => false, |
| 4660 | + details: () => false, |
| 4661 | + session: () => "session", |
| 4662 | + toBottom() {}, |
| 4663 | + }) |
| 4664 | + |
| 4665 | + cm.prompt.enter() |
| 4666 | + cm.prompt.visual("char") |
| 4667 | + cm.prompt.move("up") |
| 4668 | + cm.prompt.visual("line") |
| 4669 | + |
| 4670 | + expect(cm.state().visual).toBe("line") |
| 4671 | + expect(cm.state().anchor).toEqual({ idx: 2, col: 3 }) |
| 4672 | + expect(cm.state().idx).toBe(1) |
| 4673 | + dispose() |
| 4674 | + }) |
| 4675 | + }) |
| 4676 | + |
4637 | 4677 | test("y yanks copy selection and exits copy mode", () => { |
4638 | 4678 | const ctx = createHandler("abc", { mode: "copy", copy: { text: "picked text", isVisual: true } }) |
4639 | 4679 |
|
|
0 commit comments