@edv4h/usketch-plugin-tool-vim 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +101 -0
- package/dist/__tests__/test-helpers.d.ts +15 -0
- package/dist/__tests__/test-helpers.d.ts.map +1 -0
- package/dist/__tests__/test-helpers.js +96 -0
- package/dist/__tests__/test-helpers.js.map +1 -0
- package/dist/candidates.d.ts +13 -0
- package/dist/candidates.d.ts.map +1 -0
- package/dist/candidates.js +47 -0
- package/dist/candidates.js.map +1 -0
- package/dist/commands.d.ts +18 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +58 -0
- package/dist/commands.js.map +1 -0
- package/dist/config/default-config.d.ts +14 -0
- package/dist/config/default-config.d.ts.map +1 -0
- package/dist/config/default-config.js +35 -0
- package/dist/config/default-config.js.map +1 -0
- package/dist/config/schema.d.ts +51 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +65 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/constants.d.ts +6 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +6 -0
- package/dist/constants.js.map +1 -0
- package/dist/cursor.d.ts +18 -0
- package/dist/cursor.d.ts.map +1 -0
- package/dist/cursor.js +97 -0
- package/dist/cursor.js.map +1 -0
- package/dist/extensions.d.ts +44 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +2 -0
- package/dist/extensions.js.map +1 -0
- package/dist/hop.d.ts +13 -0
- package/dist/hop.d.ts.map +1 -0
- package/dist/hop.js +53 -0
- package/dist/hop.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/keymap.d.ts +17 -0
- package/dist/keymap.d.ts.map +1 -0
- package/dist/keymap.js +223 -0
- package/dist/keymap.js.map +1 -0
- package/dist/machine/actions.d.ts +23 -0
- package/dist/machine/actions.d.ts.map +1 -0
- package/dist/machine/actions.js +97 -0
- package/dist/machine/actions.js.map +1 -0
- package/dist/machine/types.d.ts +159 -0
- package/dist/machine/types.d.ts.map +1 -0
- package/dist/machine/types.js +2 -0
- package/dist/machine/types.js.map +1 -0
- package/dist/machine/vim-machine.d.ts +200 -0
- package/dist/machine/vim-machine.d.ts.map +1 -0
- package/dist/machine/vim-machine.js +425 -0
- package/dist/machine/vim-machine.js.map +1 -0
- package/dist/plugin.d.ts +5 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +180 -0
- package/dist/plugin.js.map +1 -0
- package/dist/ui/help-overlay.d.ts +6 -0
- package/dist/ui/help-overlay.d.ts.map +1 -0
- package/dist/ui/help-overlay.js +104 -0
- package/dist/ui/help-overlay.js.map +1 -0
- package/dist/ui/overlay.d.ts +14 -0
- package/dist/ui/overlay.d.ts.map +1 -0
- package/dist/ui/overlay.js +97 -0
- package/dist/ui/overlay.js.map +1 -0
- package/dist/ui/status-line.d.ts +6 -0
- package/dist/ui/status-line.d.ts.map +1 -0
- package/dist/ui/status-line.js +44 -0
- package/dist/ui/status-line.js.map +1 -0
- package/dist/ui/vim-ui-store.d.ts +46 -0
- package/dist/ui/vim-ui-store.d.ts.map +1 -0
- package/dist/ui/vim-ui-store.js +36 -0
- package/dist/ui/vim-ui-store.js.map +1 -0
- package/dist/ui/which-key.d.ts +6 -0
- package/dist/ui/which-key.d.ts.map +1 -0
- package/dist/ui/which-key.js +71 -0
- package/dist/ui/which-key.js.map +1 -0
- package/dist/viewport-utils.d.ts +11 -0
- package/dist/viewport-utils.d.ts.map +1 -0
- package/dist/viewport-utils.js +26 -0
- package/dist/viewport-utils.js.map +1 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 EdV4H
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# @edv4h/usketch-plugin-tool-vim
|
|
2
|
+
|
|
3
|
+
uSketch にVim ライクなキーボード操作を追加するツールプラグイン。XState 5 のステートマシンで
|
|
4
|
+
`normal` / `insert` / `visual` / `command` モードを管理する。ステータスライン・カーソル・候補表示・
|
|
5
|
+
which-key ヘルプはすべてプラグインが**自前のレイヤーとして描画**するため、ホストアプリは UI を追加
|
|
6
|
+
する必要がない。
|
|
7
|
+
|
|
8
|
+
## 使い方
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { createVimToolPlugin } from "@edv4h/usketch-plugin-tool-vim";
|
|
12
|
+
|
|
13
|
+
const plugins = [
|
|
14
|
+
// ...他のプラグイン
|
|
15
|
+
createVimToolPlugin({
|
|
16
|
+
cursorStep: 20,
|
|
17
|
+
shapeMap: {
|
|
18
|
+
rect: { type: "rectangle", width: 120, height: 80 },
|
|
19
|
+
note: { type: "sticky", meta: { stickyColor: "#fef08a" } },
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
];
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
ツール ID は `vim`。`store.setActiveToolId("vim")` でアクティブにすると、capture フェーズの
|
|
26
|
+
keydown リスナがキー入力を奪い、ステートマシンへ送る。
|
|
27
|
+
|
|
28
|
+
## モードと操作
|
|
29
|
+
|
|
30
|
+
### normal
|
|
31
|
+
| キー | 動作 |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `h j k l` | 論理カーソル移動(`5j` のように回数指定可) |
|
|
34
|
+
| `H J K L` | 画角を移動(pan) |
|
|
35
|
+
| `i` | insert モードへ |
|
|
36
|
+
| `v` / `V` | visual / 複数選択 |
|
|
37
|
+
| `:` | command モードへ |
|
|
38
|
+
| `x` / `d` | 削除(選択 or カーソル最近傍) |
|
|
39
|
+
| `y` / `p` | ヤンク / 貼り付け |
|
|
40
|
+
| `u` / `Ctrl+r` | undo / redo |
|
|
41
|
+
| `+` / `-` | ズーム、`zz` ビューをカーソルへ寄せる |
|
|
42
|
+
| `M` | カーソルを画面中央へ(`:center` でも可) |
|
|
43
|
+
| `f` | hop: shape にラベルを表示し、入力でジャンプ |
|
|
44
|
+
| `gg` / `G` | 最初 / 最後の shape へ |
|
|
45
|
+
| `m{a-z}` / `` `{a-z} `` | マーク設定 / ジャンプ |
|
|
46
|
+
| `?` | which-key ヘルプ表示切替 |
|
|
47
|
+
|
|
48
|
+
### hop(ラベルジャンプ)
|
|
49
|
+
`f` で全 shape にラベル(`hopKeys` の文字)が表示される。ラベルを入力するとカーソルがその shape
|
|
50
|
+
中心へ一気にジャンプする。shape 数が多いと自動で2文字ラベルになり、2打で確定。`Esc` で取消。
|
|
51
|
+
|
|
52
|
+
### insert
|
|
53
|
+
文字列を入力すると `shapeMap`(明示)と shape レジストリ(自動補完)から候補が絞り込まれ、
|
|
54
|
+
カーソル位置にゴーストが表示される。`Tab` で候補切替、`Enter` で確定、`Esc` で normal へ。
|
|
55
|
+
|
|
56
|
+
### visual
|
|
57
|
+
入った瞬間カーソル最近傍の shape が選択される。`hjkl` で方向最近傍へ選択を移動。`V` で複数選択
|
|
58
|
+
(`hjkl` で選択を追加)。`d`/`x` 削除、`y` ヤンク、`Esc` で解除。
|
|
59
|
+
|
|
60
|
+
### command
|
|
61
|
+
`:q`(Vim 終了)、`:tool <id>`、`:set bg=dots|grid|none`、`:zoom <n>`、`:export <fmt>`、`:help`。
|
|
62
|
+
|
|
63
|
+
## 設定
|
|
64
|
+
|
|
65
|
+
`createVimToolPlugin(config)` の第1引数は Zod で検証される(`VimConfigSchema`)。`shapeMap` と
|
|
66
|
+
`keymap` は既定値とマージされ、それ以外のスカラ値は上書きされる。
|
|
67
|
+
|
|
68
|
+
## 拡張(独自コマンド / キーバインド)
|
|
69
|
+
|
|
70
|
+
関数は JSON 化できないため、`config`(JSON可)とは分離した**第2引数 `extensions`** で渡す。
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import { createVimToolPlugin, type VimExtensions } from "@edv4h/usketch-plugin-tool-vim";
|
|
74
|
+
|
|
75
|
+
const extensions: VimExtensions = {
|
|
76
|
+
// 独自 ex コマンド(:deploy)。組み込みより優先。戻り値はステータスラインに表示。
|
|
77
|
+
commands: {
|
|
78
|
+
deploy: (args, api) => {
|
|
79
|
+
api.store.addShape(/* ... */);
|
|
80
|
+
return `deployed ${args[0] ?? ""}`;
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
// キー → 独自関数(モード別)。組み込みキーマップより優先(全モードで最優先)。
|
|
84
|
+
bindings: {
|
|
85
|
+
normal: {
|
|
86
|
+
D: (api) => api.commands.execute(/* ... */),
|
|
87
|
+
o: (api) => api.setMode("insert"),
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
createVimToolPlugin({ cursorStep: 20 }, extensions);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
ハンドラに渡る `api`(`VimApi`)でできること:
|
|
96
|
+
|
|
97
|
+
- `store` / `shapes` / `commands` / `events` — 実サービスへの直接アクセス
|
|
98
|
+
- `getCursor()` / `setCursor(p)` — 論理カーソルの取得・移動
|
|
99
|
+
- `getMode()` / `setMode(mode)` — モードの取得・切替
|
|
100
|
+
- `getSelection()` — 選択中 shape ID
|
|
101
|
+
- `message(msg)` — ステータスラインへのメッセージ表示
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EventBus, ToolContext } from "@edv4h/usketch-shared";
|
|
2
|
+
export interface StubEvents extends EventBus {
|
|
3
|
+
emitted: {
|
|
4
|
+
event: string;
|
|
5
|
+
data: unknown;
|
|
6
|
+
}[];
|
|
7
|
+
}
|
|
8
|
+
export interface TestDeps extends ToolContext {
|
|
9
|
+
events: StubEvents;
|
|
10
|
+
}
|
|
11
|
+
/** テスト用の deps(実 store + スタブ registry/commands/events)。 */
|
|
12
|
+
export declare function makeDeps(shapeTypes?: string[]): TestDeps;
|
|
13
|
+
/** store に矩形を1つ追加してその id を返す。 */
|
|
14
|
+
export declare function addRect(deps: ToolContext, x: number, y: number, w?: number, h?: number): string;
|
|
15
|
+
//# sourceMappingURL=test-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../../src/__tests__/test-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEX,QAAQ,EAIR,WAAW,EACX,MAAM,uBAAuB,CAAC;AA8D/B,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC3C,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CAC5C;AAgBD,MAAM,WAAW,QAAS,SAAQ,WAAW;IAC5C,MAAM,EAAE,UAAU,CAAC;CACnB;AAED,0DAA0D;AAC1D,wBAAgB,QAAQ,CAAC,UAAU,GAAE,MAAM,EAA4B,GAAG,QAAQ,CAOjF;AAED,iCAAiC;AACjC,wBAAgB,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,SAAM,EAAE,CAAC,SAAK,GAAG,MAAM,CAaxF"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { createBoardStore } from "@edv4h/usketch-store";
|
|
2
|
+
/** テスト用の最小 ShapeDefinition(bounds は素直に x/y/w/h を返す)。 */
|
|
3
|
+
function stubDef(type) {
|
|
4
|
+
return {
|
|
5
|
+
render: () => null,
|
|
6
|
+
getBounds: (s) => ({ x: s.x, y: s.y, width: s.width, height: s.height }),
|
|
7
|
+
hitTest: () => false,
|
|
8
|
+
resize: (s) => s,
|
|
9
|
+
createDefault: ({ id, x, y }) => ({
|
|
10
|
+
id,
|
|
11
|
+
type,
|
|
12
|
+
x,
|
|
13
|
+
y,
|
|
14
|
+
width: 100,
|
|
15
|
+
height: 80,
|
|
16
|
+
style: { fill: "#fff", stroke: "#000", strokeWidth: 2, opacity: 1 },
|
|
17
|
+
}),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function stubShapes(types) {
|
|
21
|
+
const map = new Map();
|
|
22
|
+
for (const t of types)
|
|
23
|
+
map.set(t, stubDef(t));
|
|
24
|
+
return {
|
|
25
|
+
register: (t, d) => map.set(t, d),
|
|
26
|
+
get: (t) => map.get(t),
|
|
27
|
+
getAll: () => map,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function stubCommands() {
|
|
31
|
+
const undos = [];
|
|
32
|
+
let redos = [];
|
|
33
|
+
return {
|
|
34
|
+
execute(cmd) {
|
|
35
|
+
cmd.execute();
|
|
36
|
+
undos.push(cmd);
|
|
37
|
+
redos = [];
|
|
38
|
+
},
|
|
39
|
+
undo() {
|
|
40
|
+
const cmd = undos.pop();
|
|
41
|
+
if (cmd) {
|
|
42
|
+
cmd.undo();
|
|
43
|
+
redos.push(cmd);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
redo() {
|
|
47
|
+
const cmd = redos.pop();
|
|
48
|
+
if (cmd) {
|
|
49
|
+
cmd.execute();
|
|
50
|
+
undos.push(cmd);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
canUndo: () => undos.length > 0,
|
|
54
|
+
canRedo: () => redos.length > 0,
|
|
55
|
+
getHistorySize: () => undos.length,
|
|
56
|
+
getCursor: () => undos.length,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function stubEvents() {
|
|
60
|
+
const emitted = [];
|
|
61
|
+
return {
|
|
62
|
+
emitted,
|
|
63
|
+
on: () => () => { },
|
|
64
|
+
emit: (event, data) => {
|
|
65
|
+
emitted.push({ event, data });
|
|
66
|
+
},
|
|
67
|
+
pause: () => { },
|
|
68
|
+
resume: () => { },
|
|
69
|
+
isPaused: () => false,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** テスト用の deps(実 store + スタブ registry/commands/events)。 */
|
|
73
|
+
export function makeDeps(shapeTypes = ["rectangle", "sticky"]) {
|
|
74
|
+
return {
|
|
75
|
+
store: createBoardStore(),
|
|
76
|
+
shapes: stubShapes(shapeTypes),
|
|
77
|
+
commands: stubCommands(),
|
|
78
|
+
events: stubEvents(),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/** store に矩形を1つ追加してその id を返す。 */
|
|
82
|
+
export function addRect(deps, x, y, w = 100, h = 80) {
|
|
83
|
+
const id = `s_${x}_${y}`;
|
|
84
|
+
const shape = {
|
|
85
|
+
id,
|
|
86
|
+
type: "rectangle",
|
|
87
|
+
x,
|
|
88
|
+
y,
|
|
89
|
+
width: w,
|
|
90
|
+
height: h,
|
|
91
|
+
style: { fill: "#fff", stroke: "#000", strokeWidth: 2, opacity: 1 },
|
|
92
|
+
};
|
|
93
|
+
deps.store.addShape(shape);
|
|
94
|
+
return id;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=test-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../../src/__tests__/test-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { VimConfig } from "./config/schema.js";
|
|
2
|
+
import type { ShapeCandidate, VimDeps } from "./machine/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* insert モードの入力バッファから shape 候補を計算する。
|
|
5
|
+
*
|
|
6
|
+
* 1. `config.shapeMap` の明示マッピング(別名 → spec)
|
|
7
|
+
* 2. `deps.shapes.getAll()` のレジストリ型名(マップに無い型を型名そのままで補完)
|
|
8
|
+
*
|
|
9
|
+
* を統合し、バッファに前方一致 → 部分一致の順でフィルタ・整列して返す。
|
|
10
|
+
* バッファが空なら空配列。
|
|
11
|
+
*/
|
|
12
|
+
export declare function computeCandidates(deps: VimDeps, config: VimConfig, buffer: string): ShapeCandidate[];
|
|
13
|
+
//# sourceMappingURL=candidates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"candidates.d.ts","sourceRoot":"","sources":["../src/candidates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElE;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAChC,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,GACZ,cAAc,EAAE,CAwClB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* insert モードの入力バッファから shape 候補を計算する。
|
|
3
|
+
*
|
|
4
|
+
* 1. `config.shapeMap` の明示マッピング(別名 → spec)
|
|
5
|
+
* 2. `deps.shapes.getAll()` のレジストリ型名(マップに無い型を型名そのままで補完)
|
|
6
|
+
*
|
|
7
|
+
* を統合し、バッファに前方一致 → 部分一致の順でフィルタ・整列して返す。
|
|
8
|
+
* バッファが空なら空配列。
|
|
9
|
+
*/
|
|
10
|
+
export function computeCandidates(deps, config, buffer) {
|
|
11
|
+
const query = buffer.trim().toLowerCase();
|
|
12
|
+
if (query === "")
|
|
13
|
+
return [];
|
|
14
|
+
const byAlias = new Map();
|
|
15
|
+
// 1. 明示マッピング
|
|
16
|
+
for (const [alias, spec] of Object.entries(config.shapeMap)) {
|
|
17
|
+
byAlias.set(alias.toLowerCase(), {
|
|
18
|
+
alias,
|
|
19
|
+
spec,
|
|
20
|
+
label: spec.label ?? spec.type,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// 2. レジストリ型名(未登録の別名だけ追加)
|
|
24
|
+
for (const [type] of deps.shapes.getAll()) {
|
|
25
|
+
const key = type.toLowerCase();
|
|
26
|
+
if (!byAlias.has(key)) {
|
|
27
|
+
byAlias.set(key, { alias: type, spec: { type }, label: type });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const prefix = [];
|
|
31
|
+
const substr = [];
|
|
32
|
+
for (const cand of byAlias.values()) {
|
|
33
|
+
const a = cand.alias.toLowerCase();
|
|
34
|
+
const l = cand.label.toLowerCase();
|
|
35
|
+
if (a.startsWith(query) || l.startsWith(query)) {
|
|
36
|
+
prefix.push(cand);
|
|
37
|
+
}
|
|
38
|
+
else if (a.includes(query) || l.includes(query)) {
|
|
39
|
+
substr.push(cand);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const byAliasLength = (x, y) => x.alias.length - y.alias.length || x.alias.localeCompare(y.alias);
|
|
43
|
+
prefix.sort(byAliasLength);
|
|
44
|
+
substr.sort(byAliasLength);
|
|
45
|
+
return [...prefix, ...substr];
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=candidates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"candidates.js","sourceRoot":"","sources":["../src/candidates.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAChC,IAAa,EACb,MAAiB,EACjB,MAAc;IAEd,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAE5B,MAAM,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAElD,aAAa;IACb,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE;YAChC,KAAK;YACL,IAAI;YACJ,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI;SAC9B,CAAC,CAAC;IACJ,CAAC;IAED,yBAAyB;IACzB,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,CAAC;IACF,CAAC;IAED,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAChD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;aAAM,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACF,CAAC;IAED,MAAM,aAAa,GAAG,CAAC,CAAiB,EAAE,CAAiB,EAAE,EAAE,CAC9D,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACnE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC3B,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC3B,OAAO,CAAC,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { VimConfig } from "./config/schema.js";
|
|
2
|
+
import type { VimDeps } from "./machine/types.js";
|
|
3
|
+
export interface ExCommandResult {
|
|
4
|
+
/** ステータスラインに出すメッセージ。 */
|
|
5
|
+
message: string;
|
|
6
|
+
/** Vim を抜ける(normal へ戻さずツール切替が走る)場合 true。 */
|
|
7
|
+
exited?: boolean;
|
|
8
|
+
/** `:help` 全画面ヘルプの表示をトグルする場合 true。 */
|
|
9
|
+
toggleHelp?: boolean;
|
|
10
|
+
/** カーソルを画面中央へ移動する場合 true(cursor は machine context にあるため flag で返す)。 */
|
|
11
|
+
cursorCenter?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* ex コマンド(先頭 `:` を除いた文字列)を実行する。副作用は `deps`/`events` 経由。
|
|
15
|
+
* デモ/他プラグインは `vim:command` 系イベントを購読して bg 切替や export を実装できる。
|
|
16
|
+
*/
|
|
17
|
+
export declare function runExCommand(line: string, deps: VimDeps, config: VimConfig): ExCommandResult;
|
|
18
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAGlD,MAAM,WAAW,eAAe;IAC/B,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sCAAsC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sEAAsE;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,GAAG,eAAe,CA0D5F"}
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { screenCenterWorld } from "./viewport-utils.js";
|
|
2
|
+
/**
|
|
3
|
+
* ex コマンド(先頭 `:` を除いた文字列)を実行する。副作用は `deps`/`events` 経由。
|
|
4
|
+
* デモ/他プラグインは `vim:command` 系イベントを購読して bg 切替や export を実装できる。
|
|
5
|
+
*/
|
|
6
|
+
export function runExCommand(line, deps, config) {
|
|
7
|
+
const trimmed = line.trim();
|
|
8
|
+
if (trimmed === "")
|
|
9
|
+
return { message: "" };
|
|
10
|
+
const [cmd, ...args] = trimmed.split(/\s+/);
|
|
11
|
+
const arg = args.join(" ");
|
|
12
|
+
switch (cmd) {
|
|
13
|
+
case "q":
|
|
14
|
+
case "quit":
|
|
15
|
+
deps.store.setActiveToolId(config.exitToolId);
|
|
16
|
+
return { message: "", exited: true };
|
|
17
|
+
case "w":
|
|
18
|
+
case "write":
|
|
19
|
+
return { message: "auto-synced (no-op)" };
|
|
20
|
+
case "wq":
|
|
21
|
+
deps.store.setActiveToolId(config.exitToolId);
|
|
22
|
+
return { message: "", exited: true };
|
|
23
|
+
case "tool":
|
|
24
|
+
if (!arg)
|
|
25
|
+
return { message: "E: :tool <id>" };
|
|
26
|
+
deps.store.setActiveToolId(arg);
|
|
27
|
+
return { message: `tool → ${arg}`, exited: arg !== "vim" };
|
|
28
|
+
case "zoom": {
|
|
29
|
+
const z = Number(arg);
|
|
30
|
+
if (!Number.isFinite(z) || z <= 0)
|
|
31
|
+
return { message: "E: :zoom <number>" };
|
|
32
|
+
deps.store.zoomTo(z, screenCenterWorld(deps.store));
|
|
33
|
+
return { message: `zoom ${z}` };
|
|
34
|
+
}
|
|
35
|
+
case "set": {
|
|
36
|
+
// 例: :set bg=dots / :set bg=grid / :set bg=none
|
|
37
|
+
const m = /^bg=(dots|grid|none)$/.exec(arg);
|
|
38
|
+
if (m) {
|
|
39
|
+
deps.events.emit("vim:set-background", { value: m[1] });
|
|
40
|
+
return { message: `bg=${m[1]}` };
|
|
41
|
+
}
|
|
42
|
+
return { message: `E: unknown option ${arg}` };
|
|
43
|
+
}
|
|
44
|
+
case "export": {
|
|
45
|
+
const fmt = (arg || "png").toLowerCase();
|
|
46
|
+
deps.events.emit("vim:export", { format: fmt });
|
|
47
|
+
return { message: `export ${fmt}` };
|
|
48
|
+
}
|
|
49
|
+
case "help":
|
|
50
|
+
case "h":
|
|
51
|
+
return { message: "", toggleHelp: true };
|
|
52
|
+
case "center":
|
|
53
|
+
return { message: "", cursorCenter: true };
|
|
54
|
+
default:
|
|
55
|
+
return { message: `E: not a command: ${cmd}` };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ShapeSpec, type VimConfig, type VimConfigInput } from "./schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* insert モードの既定マッピング(短い別名 → shape)。
|
|
4
|
+
* ここに無い文字列は `ctx.shapes.getAll()` の型名そのもので自動補完される
|
|
5
|
+
* (例 "ellipse" や "triangle" はマップ不要で打てる)。
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_SHAPE_MAP: Record<string, ShapeSpec>;
|
|
8
|
+
/**
|
|
9
|
+
* 部分設定を既定値とディープマージして検証済みの {@link VimConfig} を返す。
|
|
10
|
+
* `shapeMap` と `keymap` は「上書き」ではなく「マージ」する(既定の別名を保ったまま
|
|
11
|
+
* 追加・変更できる)。それ以外のスカラ値は上書き。
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseVimConfig(input?: VimConfigInput): VimConfig;
|
|
14
|
+
//# sourceMappingURL=default-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-config.d.ts","sourceRoot":"","sources":["../../src/config/default-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,cAAc,EAAmB,MAAM,aAAa,CAAC;AAEnG;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAavD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,CAQhE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { VimConfigSchema } from "./schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* insert モードの既定マッピング(短い別名 → shape)。
|
|
4
|
+
* ここに無い文字列は `ctx.shapes.getAll()` の型名そのもので自動補完される
|
|
5
|
+
* (例 "ellipse" や "triangle" はマップ不要で打てる)。
|
|
6
|
+
*/
|
|
7
|
+
export const DEFAULT_SHAPE_MAP = {
|
|
8
|
+
rect: { type: "rectangle", width: 120, height: 80, label: "Rectangle" },
|
|
9
|
+
box: { type: "rectangle", width: 120, height: 80, label: "Rectangle" },
|
|
10
|
+
text: { type: "text", label: "Text" },
|
|
11
|
+
note: { type: "sticky", meta: { stickyColor: "#fef08a" }, label: "Sticky note" },
|
|
12
|
+
sticky: { type: "sticky", meta: { stickyColor: "#fef08a" }, label: "Sticky note" },
|
|
13
|
+
circle: { type: "ellipse", width: 100, height: 100, label: "Ellipse" },
|
|
14
|
+
line: { type: "line", label: "Line" },
|
|
15
|
+
arrow: { type: "arrow", label: "Arrow" },
|
|
16
|
+
diamond: { type: "diamond", label: "Diamond" },
|
|
17
|
+
star: { type: "star", label: "Star" },
|
|
18
|
+
tri: { type: "triangle", label: "Triangle" },
|
|
19
|
+
frame: { type: "frame", width: 320, height: 240, label: "Frame" },
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* 部分設定を既定値とディープマージして検証済みの {@link VimConfig} を返す。
|
|
23
|
+
* `shapeMap` と `keymap` は「上書き」ではなく「マージ」する(既定の別名を保ったまま
|
|
24
|
+
* 追加・変更できる)。それ以外のスカラ値は上書き。
|
|
25
|
+
*/
|
|
26
|
+
export function parseVimConfig(input) {
|
|
27
|
+
const raw = input ?? {};
|
|
28
|
+
const merged = {
|
|
29
|
+
...raw,
|
|
30
|
+
shapeMap: { ...DEFAULT_SHAPE_MAP, ...(raw.shapeMap ?? {}) },
|
|
31
|
+
keymap: raw.keymap ?? {},
|
|
32
|
+
};
|
|
33
|
+
return VimConfigSchema.parse(merged);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=default-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-config.js","sourceRoot":"","sources":["../../src/config/default-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuD,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnG;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA8B;IAC3D,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE;IACvE,GAAG,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE;IACtE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IACrC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE;IAChF,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE;IAClF,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE;IACtE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IACrC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;IACxC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;IAC9C,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IACrC,GAAG,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;IAC5C,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE;CACjE,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAAsB;IACpD,MAAM,GAAG,GAAG,KAAK,IAAI,EAAE,CAAC;IACxB,MAAM,MAAM,GAAmB;QAC9B,GAAG,GAAG;QACN,QAAQ,EAAE,EAAE,GAAG,iBAAiB,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE;QAC3D,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE;KACxB,CAAC;IACF,OAAO,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Vim プラグインの設定スキーマ(Zod)。
|
|
4
|
+
*
|
|
5
|
+
* すべてのフィールドに既定値を持たせてあるので、`VimConfigSchema.parse({})` で
|
|
6
|
+
* 完全な設定が得られる。ユーザーは `createVimToolPlugin(partial)` で一部だけ
|
|
7
|
+
* 上書きできる(`mergeConfig` がディープマージする)。
|
|
8
|
+
*/
|
|
9
|
+
/** insert モードで文字列から生成する shape の指定。 */
|
|
10
|
+
export declare const ShapeSpecSchema: z.ZodObject<{
|
|
11
|
+
type: z.ZodString;
|
|
12
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
14
|
+
style: z.ZodOptional<z.ZodObject<{
|
|
15
|
+
fill: z.ZodOptional<z.ZodString>;
|
|
16
|
+
stroke: z.ZodOptional<z.ZodString>;
|
|
17
|
+
strokeWidth: z.ZodOptional<z.ZodNumber>;
|
|
18
|
+
opacity: z.ZodOptional<z.ZodNumber>;
|
|
19
|
+
}, z.core.$strip>>;
|
|
20
|
+
meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
21
|
+
label: z.ZodOptional<z.ZodString>;
|
|
22
|
+
}, z.core.$strip>;
|
|
23
|
+
export type ShapeSpec = z.infer<typeof ShapeSpecSchema>;
|
|
24
|
+
export declare const VimConfigSchema: z.ZodObject<{
|
|
25
|
+
cursorStep: z.ZodDefault<z.ZodNumber>;
|
|
26
|
+
panStep: z.ZodDefault<z.ZodNumber>;
|
|
27
|
+
zoomStep: z.ZodDefault<z.ZodNumber>;
|
|
28
|
+
snapToGrid: z.ZodDefault<z.ZodBoolean>;
|
|
29
|
+
gridSize: z.ZodDefault<z.ZodNumber>;
|
|
30
|
+
showWhichKey: z.ZodDefault<z.ZodBoolean>;
|
|
31
|
+
showStatusLine: z.ZodDefault<z.ZodBoolean>;
|
|
32
|
+
exitToolId: z.ZodDefault<z.ZodString>;
|
|
33
|
+
hopKeys: z.ZodDefault<z.ZodString>;
|
|
34
|
+
shapeMap: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
35
|
+
type: z.ZodString;
|
|
36
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
37
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
38
|
+
style: z.ZodOptional<z.ZodObject<{
|
|
39
|
+
fill: z.ZodOptional<z.ZodString>;
|
|
40
|
+
stroke: z.ZodOptional<z.ZodString>;
|
|
41
|
+
strokeWidth: z.ZodOptional<z.ZodNumber>;
|
|
42
|
+
opacity: z.ZodOptional<z.ZodNumber>;
|
|
43
|
+
}, z.core.$strip>>;
|
|
44
|
+
meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
45
|
+
label: z.ZodOptional<z.ZodString>;
|
|
46
|
+
}, z.core.$strip>>>;
|
|
47
|
+
keymap: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
48
|
+
}, z.core.$strip>;
|
|
49
|
+
export type VimConfig = z.infer<typeof VimConfigSchema>;
|
|
50
|
+
export type VimConfigInput = z.input<typeof VimConfigSchema>;
|
|
51
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;GAMG;AAEH,sCAAsC;AACtC,eAAO,MAAM,eAAe;;;;;;;;;;;;iBAqB1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAKxD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;iBAgC1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AACxD,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { HOP_TRIGGER } from "../constants.js";
|
|
3
|
+
/**
|
|
4
|
+
* Vim プラグインの設定スキーマ(Zod)。
|
|
5
|
+
*
|
|
6
|
+
* すべてのフィールドに既定値を持たせてあるので、`VimConfigSchema.parse({})` で
|
|
7
|
+
* 完全な設定が得られる。ユーザーは `createVimToolPlugin(partial)` で一部だけ
|
|
8
|
+
* 上書きできる(`mergeConfig` がディープマージする)。
|
|
9
|
+
*/
|
|
10
|
+
/** insert モードで文字列から生成する shape の指定。 */
|
|
11
|
+
export const ShapeSpecSchema = z.object({
|
|
12
|
+
/** shape レジストリに登録された型名(例 "rectangle" / "text" / "sticky")。 */
|
|
13
|
+
type: z.string(),
|
|
14
|
+
/** 既定の幅(省略時は shape の createDefault に委ねる)。 */
|
|
15
|
+
width: z.number().positive().optional(),
|
|
16
|
+
/** 既定の高さ(省略時は shape の createDefault に委ねる)。 */
|
|
17
|
+
height: z.number().positive().optional(),
|
|
18
|
+
/** スタイルの部分上書き。 */
|
|
19
|
+
style: z
|
|
20
|
+
.object({
|
|
21
|
+
fill: z.string(),
|
|
22
|
+
stroke: z.string(),
|
|
23
|
+
strokeWidth: z.number(),
|
|
24
|
+
opacity: z.number(),
|
|
25
|
+
})
|
|
26
|
+
.partial()
|
|
27
|
+
.optional(),
|
|
28
|
+
/** shape の meta 初期値(sticky の色など)。 */
|
|
29
|
+
meta: z.record(z.string(), z.unknown()).optional(),
|
|
30
|
+
/** 候補一覧に出すラベル(省略時は type)。 */
|
|
31
|
+
label: z.string().optional(),
|
|
32
|
+
});
|
|
33
|
+
/** モードごとのキー → アクショントークンの上書きマップ。 */
|
|
34
|
+
const KeymapSchema = z.record(z.string(), z.record(z.string(), z.string()));
|
|
35
|
+
export const VimConfigSchema = z.object({
|
|
36
|
+
/** normal モードの hjkl で論理カーソルが動く距離(world px)。 */
|
|
37
|
+
cursorStep: z.number().positive().default(20),
|
|
38
|
+
/** Shift+hjkl で画角を動かす距離(screen px)。 */
|
|
39
|
+
panStep: z.number().positive().default(80),
|
|
40
|
+
/** +/- でのズーム倍率。 */
|
|
41
|
+
zoomStep: z.number().min(1.01).default(1.2),
|
|
42
|
+
/** カーソル移動をグリッドにスナップするか。 */
|
|
43
|
+
snapToGrid: z.boolean().default(true),
|
|
44
|
+
/** スナップ時のグリッド間隔(world px)。 */
|
|
45
|
+
gridSize: z.number().positive().default(20),
|
|
46
|
+
/** which-key オーバーレイを表示するか。 */
|
|
47
|
+
showWhichKey: z.boolean().default(true),
|
|
48
|
+
/** ステータスラインを表示するか。 */
|
|
49
|
+
showStatusLine: z.boolean().default(true),
|
|
50
|
+
/** Vim を抜けたとき(:q)に戻るツール ID。 */
|
|
51
|
+
exitToolId: z.string().default("select"),
|
|
52
|
+
/**
|
|
53
|
+
* hop(ラベルジャンプ)で使う文字。先頭から順に近い shape へ割り当てる。
|
|
54
|
+
* トリガー文字(`f`)はラベルから除外されるため、除外後に異なる文字が2つ以上必要。
|
|
55
|
+
*/
|
|
56
|
+
hopKeys: z
|
|
57
|
+
.string()
|
|
58
|
+
.refine((s) => new Set(s.split("").filter((c) => c !== HOP_TRIGGER)).size >= 2, `hopKeys には "${HOP_TRIGGER}" 以外の異なる文字が2つ以上必要です`)
|
|
59
|
+
.default("fjdkslaghrueiwoncm"),
|
|
60
|
+
/** insert: 文字列 → shape の明示マッピング。未定義の型はレジストリから自動補完。 */
|
|
61
|
+
shapeMap: z.record(z.string(), ShapeSpecSchema).default({}),
|
|
62
|
+
/** キーバインドのリマップ(既定キーマップへの部分上書き)。 */
|
|
63
|
+
keymap: KeymapSchema.default({}),
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,WAAW,MAAM,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC"}
|
package/dist/cursor.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Point } from "@edv4h/usketch-shared";
|
|
2
|
+
import type { Direction, VimDeps } from "./machine/types.js";
|
|
3
|
+
/** カーソル座標をグリッドにスナップする。 */
|
|
4
|
+
export declare function snapToGrid(p: Point, gridSize: number): Point;
|
|
5
|
+
/** カーソルを `dir` 方向へ `distance` だけ動かした座標を返す。 */
|
|
6
|
+
export declare function moveCursorBy(cursor: Point, dir: Direction, distance: number): Point;
|
|
7
|
+
/** shape の中心(world 座標)。見つからなければ null。 */
|
|
8
|
+
export declare function shapeCenter(deps: VimDeps, id: string): Point | null;
|
|
9
|
+
/** point に最も近い shape の ID(中心距離)。excludeIds は除外。 */
|
|
10
|
+
export declare function findNearestShape(deps: VimDeps, point: Point, excludeIds?: ReadonlySet<string>): string | null;
|
|
11
|
+
/**
|
|
12
|
+
* `from` から見て `dir` 方向の cone(±45°)に中心がある shape のうち、
|
|
13
|
+
* 最も近いものの ID を返す(spatial navigation)。excludeIds は除外。
|
|
14
|
+
*/
|
|
15
|
+
export declare function findDirectionalNearest(deps: VimDeps, from: Point, dir: Direction, excludeIds?: ReadonlySet<string>): string | null;
|
|
16
|
+
/** 全 shape を内包する world bbox の中心。shape が無ければ null。 */
|
|
17
|
+
export declare function allShapesCenter(deps: VimDeps): Point | null;
|
|
18
|
+
//# sourceMappingURL=cursor.d.ts.map
|