@nghyane/arcane 0.1.15 → 0.1.16

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@nghyane/arcane",
4
- "version": "0.1.15",
4
+ "version": "0.1.16",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://github.com/nghyane/arcane",
7
7
  "author": "Can Bölük",
@@ -116,10 +116,12 @@ function isAppAction(action: string): action is AppAction {
116
116
  /**
117
117
  * Key hint formatting utilities for UI labels.
118
118
  */
119
+ const IS_MACOS = process.platform === "darwin";
120
+
119
121
  const MODIFIER_LABELS: Record<string, string> = {
120
- ctrl: "Ctrl",
121
- shift: "Shift",
122
- alt: "Alt",
122
+ ctrl: IS_MACOS ? "⌃" : "Ctrl",
123
+ shift: IS_MACOS ? "⇧" : "Shift",
124
+ alt: IS_MACOS ? "⌥" : "Alt",
123
125
  };
124
126
 
125
127
  const KEY_LABELS: Record<string, string> = {
@@ -154,7 +156,8 @@ function formatKeyPart(part: string): string {
154
156
  }
155
157
 
156
158
  export function formatKeyHint(key: KeyId): string {
157
- return key.split("+").map(formatKeyPart).join("+");
159
+ const parts = key.split("+").map(formatKeyPart);
160
+ return IS_MACOS ? parts.join("") : parts.join("+");
158
161
  }
159
162
 
160
163
  export function formatKeyHints(keys: KeyId | KeyId[]): string {
@@ -253,13 +256,12 @@ export class KeybindingsManager {
253
256
  }
254
257
 
255
258
  /**
256
- * Get display string for an action.
259
+ * Get display string for an action, formatted for the current platform.
257
260
  */
258
261
  getDisplayString(action: AppAction): string {
259
262
  const keys = this.getKeys(action);
260
263
  if (keys.length === 0) return "";
261
- if (keys.length === 1) return keys[0]!;
262
- return keys.join("/");
264
+ return formatKeyHints(keys);
263
265
  }
264
266
 
265
267
  /**
@@ -14,6 +14,7 @@ import { Snowflake } from "@nghyane/arcane-utils";
14
14
  import { setProjectDir } from "@nghyane/arcane-utils/dirs";
15
15
  import { $ } from "bun";
16
16
  import { reset as resetCapabilities } from "../../capability";
17
+ import { formatKeyHint, type KeyId } from "../../config/keybindings";
17
18
  import { loadCustomShare } from "../../export/custom-share";
18
19
  import type { CompactOptions } from "../../extensibility/extensions/types";
19
20
  import { getGatewayStatus } from "../../ipy/gateway-coordinator";
@@ -362,43 +363,44 @@ export class CommandController {
362
363
  }
363
364
 
364
365
  handleHotkeysCommand(): void {
365
- const expandToolsKey = this.ctx.keybindings.getDisplayString("expandTools") || "Ctrl+O";
366
- const sttKey = this.ctx.keybindings.getDisplayString("toggleSTT") || "Alt+H";
366
+ const k = (id: string) => formatKeyHint(id as KeyId);
367
+ const expandToolsKey = this.ctx.keybindings.getDisplayString("expandTools") || k("ctrl+o");
368
+ const sttKey = this.ctx.keybindings.getDisplayString("toggleSTT") || k("alt+h");
367
369
  const hotkeys = `
368
370
  **Navigation**
369
371
  | Key | Action |
370
372
  |-----|--------|
371
373
  | \`Arrow keys\` | Move cursor / browse history (Up when empty) |
372
- | \`Option+Left/Right\` | Move by word |
373
- | \`Ctrl+A\` / \`Home\` / \`Cmd+Left\` | Start of line |
374
- | \`Ctrl+E\` / \`End\` / \`Cmd+Right\` | End of line |
374
+ | \`${k("alt+left")}/${k("alt+right")}\` | Move by word |
375
+ | \`${k("ctrl+a")}\` / \`Home\` | Start of line |
376
+ | \`${k("ctrl+e")}\` / \`End\` | End of line |
375
377
 
376
378
  **Editing**
377
379
  | Key | Action |
378
380
  |-----|--------|
379
381
  | \`Enter\` | Send message |
380
- | \`Shift+Enter\` / \`Alt+Enter\` | New line |
381
- | \`Ctrl+W\` / \`Option+Backspace\` | Delete word backwards |
382
- | \`Ctrl+U\` | Delete to start of line |
383
- | \`Ctrl+K\` | Delete to end of line |
382
+ | \`${k("shift+enter")}\` / \`${k("alt+enter")}\` | New line |
383
+ | \`${k("ctrl+w")}\` / \`${k("alt+backspace")}\` | Delete word backwards |
384
+ | \`${k("ctrl+u")}\` | Delete to start of line |
385
+ | \`${k("ctrl+k")}\` | Delete to end of line |
384
386
 
385
387
  **Other**
386
388
  | Key | Action |
387
389
  |-----|--------|
388
390
  | \`Tab\` | Path completion / accept autocomplete |
389
391
  | \`Escape\` | Cancel autocomplete / abort streaming |
390
- | \`Ctrl+C\` | Clear editor (first) / exit (second) |
391
- | \`Ctrl+D\` | Exit (when editor is empty) |
392
- | \`Ctrl+Z\` | Suspend to background |
393
- | \`Shift+Tab\` | Cycle thinking level |
394
- | \`Ctrl+P\` | Cycle role models (slow/default/fast) |
395
- | \`Shift+Ctrl+P\` | Cycle role models (temporary) |
396
- | \`Alt+P\` | Select model (temporary) |
397
- | \`Ctrl+L\` | Select model (set roles) |
398
- | \`Ctrl+R\` | Search prompt history |
392
+ | \`${k("ctrl+c")}\` | Clear editor (first) / exit (second) |
393
+ | \`${k("ctrl+d")}\` | Exit (when editor is empty) |
394
+ | \`${k("ctrl+z")}\` | Suspend to background |
395
+ | \`${k("shift+tab")}\` | Cycle thinking level |
396
+ | \`${k("ctrl+p")}\` | Cycle role models (slow/default/fast) |
397
+ | \`${k("shift+ctrl+p")}\` | Cycle role models (temporary) |
398
+ | \`${k("alt+p")}\` | Select model (temporary) |
399
+ | \`${k("ctrl+l")}\` | Select model (set roles) |
400
+ | \`${k("ctrl+r")}\` | Search prompt history |
399
401
  | \`${expandToolsKey}\` | Toggle tool output expansion |
400
- | \`Ctrl+T\` | Toggle todo list expansion |
401
- | \`Ctrl+G\` | Edit message in external editor |
402
+ | \`${k("ctrl+t")}\` | Toggle todo list expansion |
403
+ | \`${k("ctrl+g")}\` | Edit message in external editor |
402
404
  | \`${sttKey}\` | Toggle speech-to-text recording |
403
405
  | \`/\` | Slash commands |
404
406
  | \`!\` | Run bash command |
@@ -1,6 +1,7 @@
1
1
  import type { AgentMessage } from "@nghyane/arcane-agent";
2
2
  import type { AssistantMessage, Message } from "@nghyane/arcane-ai";
3
3
  import { Spacer, Text, TruncatedText } from "@nghyane/arcane-tui";
4
+ import { formatKeyHint, type KeyId } from "../../config/keybindings";
4
5
  import { settings } from "../../config/settings";
5
6
  import { AssistantMessageComponent } from "../../modes/components/assistant-message";
6
7
  import { BashExecutionComponent } from "../../modes/components/bash-execution";
@@ -385,7 +386,7 @@ export class UiHelpers {
385
386
  const queuedText = theme.fg("dim", `${entry.label}: ${entry.message}`);
386
387
  this.ctx.pendingMessagesContainer.addChild(new TruncatedText(queuedText, 1, 0));
387
388
  }
388
- const dequeueKey = this.ctx.keybindings.getDisplayString("dequeue") || "Alt+Up";
389
+ const dequeueKey = this.ctx.keybindings.getDisplayString("dequeue") || formatKeyHint("alt+up" as KeyId);
389
390
  const hintText = theme.fg("dim", `${theme.tree.hook} ${dequeueKey} to edit`);
390
391
  this.ctx.pendingMessagesContainer.addChild(new TruncatedText(hintText, 1, 0));
391
392
  }