Ver Fonte

refactor: split command registration for single and multi selection

- Remove copyWorkspaceFiles (dialog-based), replace with copySingleItem
- Split copySelectedFiles into copySingleItem (single) and copyMultiFiles (multi)
- Simplify explorer context menu conditions (use listMultiSelection)
- Remove keybindings (ctrl+alt+c, cmd+alt+c / ctrl+alt+f, cmd+alt+f)
- Update publisher to fivesay
- Update command titles to 'Copy to AI' prefix
- Bump version 0.1.1 -> 0.2.2
Developer há 1 mês atrás
pai
commit
a23e200afb
7 ficheiros alterados com 125 adições e 792 exclusões
  1. 6 10
      README.md
  2. 0 0
      dist/extension.js
  3. 0 0
      dist/extension.js.map
  4. 51 680
      package-lock.json
  5. 34 35
      package.json
  6. 22 53
      src/copyContext.ts
  7. 12 14
      src/extension.ts

+ 6 - 10
README.md

@@ -1,13 +1,13 @@
 # Copy AI Context
 
-A VS Code extension to copy code context formatted for AI assistants (Claude, ChatGPT, pi agent, etc.).
+A VS Code extension to copy file/folder paths formatted for AI assistants (Claude, ChatGPT, pi agent, etc.).
 
 ## Features
 
-- **Copy Selection** (`Ctrl+Alt+C` / `Cmd+Alt+C`) — 复制选区引用头 `[path LnCn-LnCn]`
-- **Copy Active File** (`Ctrl+Alt+F` / `Cmd+Alt+F`) — 复制当前文件引用头 `[path]`
-- **Copy Workspace Files** — 弹窗选文件,批量复制引用
-- **Copy Selected Files** — 资源管理器多选文件,批量复制引用
+- **Copy Selection** — 编辑器右键(有选中代码时),复制引用头 `[path LnCn-LnCn]`
+- **Copy Active File** — 编辑器右键(无选中代码时),复制路径 `[path]`
+- **Copy Single Item** — 资源管理器右键单文件/单文件夹,复制路径
+- **Copy Multi Items** — 资源管理器右键多选(文件/文件夹),批量复制路径(文件夹递归展开)
 
 ## Output Format
 
@@ -18,7 +18,7 @@ A VS Code extension to copy code context formatted for AI assistants (Claude, Ch
 ### 多文件
 
 ```
-[src/extension.ts][src/copyContext.ts L10C1-L45C20]
+[src/file1.ts][src/file2.ts]
 ```
 
 ## Requirements
@@ -33,7 +33,3 @@ npm run build
 ```
 
 Press `F5` in VS Code to launch a development extension host.
-
-## Changes
-
-See [CHANGELOG.md](CHANGELOG.md).

Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/extension.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/extension.js.map


Diff do ficheiro suprimidas por serem muito extensas
+ 51 - 680
package-lock.json


+ 34 - 35
package.json

@@ -2,44 +2,42 @@
   "name": "vsix-cp-ai-ctx",
   "displayName": "Copy AI Context",
   "description": "Copy code context for AI assistants — selected code, file contents, with paths and formatting",
-  "version": "0.1.1",
-  "publisher": "your-publisher",
+  "version": "0.2.2",
+  "publisher": "fivesay",
   "engines": {
     "vscode": "^1.85.0"
   },
-  "categories": ["Other"],
-  "keywords": ["ai", "context", "copy", "clipboard", "chatgpt", "claude", "pi"],
+  "categories": [
+    "Other"
+  ],
+  "keywords": [
+    "ai",
+    "context",
+    "copy",
+    "clipboard",
+    "chatgpt",
+    "claude",
+    "pi"
+  ],
   "activationEvents": [],
   "main": "./dist/extension.js",
   "contributes": {
     "commands": [
       {
         "command": "vsix-cp-ai-ctx.copySelection",
-        "title": "复制 AI 上下文: 选区"
+        "title": "Copy to AI: 选中区域"
       },
       {
         "command": "vsix-cp-ai-ctx.copyFile",
-        "title": "复制 AI 上下文: 文件"
-      },
-      {
-        "command": "vsix-cp-ai-ctx.copyWorkspaceFiles",
-        "title": "复制 AI 上下文: 工作区文件"
+        "title": "Copy to AI: 当前文件"
       },
       {
         "command": "vsix-cp-ai-ctx.copySelectedFiles",
-        "title": "复制 AI 上下文: 选中文件"
-      }
-    ],
-    "keybindings": [
-      {
-        "command": "vsix-cp-ai-ctx.copySelection",
-        "key": "ctrl+alt+c",
-        "mac": "cmd+alt+c"
+        "title": "Copy to AI: 单选"
       },
       {
-        "command": "vsix-cp-ai-ctx.copyFile",
-        "key": "ctrl+alt+f",
-        "mac": "cmd+alt+f"
+        "command": "vsix-cp-ai-ctx.copyMultiFiles",
+        "title": "Copy to AI: 多选"
       }
     ],
     "menus": {
@@ -48,23 +46,24 @@
           "command": "vsix-cp-ai-ctx.copySelection",
           "when": "editorHasSelection",
           "group": "9_cutcopypaste@10"
-        }
-      ],
-      "explorer/context": [
+        },
         {
           "command": "vsix-cp-ai-ctx.copyFile",
-          "when": "!editorHasSelection && !explorerResourceIsFolder",
+          "when": "!editorHasSelection",
           "group": "9_cutcopypaste@10"
-        },
+        }
+      ],
+      "explorer/context": [
         {
-          "command": "vsix-cp-ai-ctx.copySelectedFiles",
-          "when": "explorerResourceIsFolder",
+          "command": "vsix-cp-ai-ctx.copyMultiFiles",
+          "when": "listMultiSelection && explorerViewletVisible",
           "group": "9_cutcopypaste@10"
         },
         {
           "command": "vsix-cp-ai-ctx.copySelectedFiles",
-          "when": "listMultiSelection && explorerViewletVisible",
-          "group": "9_cutcopypaste@10"
+          "when": "!listMultiSelection",
+          "group": "9_cutcopypaste@10",
+          "title": "Copy to AI: 单选"
         }
       ]
     }
@@ -78,14 +77,14 @@
     "publish": "vsce publish"
   },
   "devDependencies": {
-    "@types/vscode": "^1.85.0",
     "@types/node": "^20.0.0",
-    "esbuild": "^0.20.0",
-    "typescript": "^5.3.0",
-    "eslint": "^8.56.0",
+    "@types/vscode": "^1.85.0",
     "@typescript-eslint/eslint-plugin": "^6.0.0",
     "@typescript-eslint/parser": "^6.0.0",
-    "@vscode/vsce": "^2.22.0"
+    "@vscode/vsce": "^2.19.0",
+    "esbuild": "^0.20.0",
+    "eslint": "^8.56.0",
+    "typescript": "^5.3.0"
   },
   "repository": {
     "type": "git",

+ 22 - 53
src/copyContext.ts

@@ -1,4 +1,3 @@
-import * as path from 'path';
 import * as vscode from 'vscode';
 
 /**
@@ -72,39 +71,28 @@ export async function copyActiveFile(): Promise<void> {
 }
 
 /**
- * Select files from the workspace and copy their contents.
+ * Copy a single file/folder path to clipboard with AI-friendly formatting.
+ * Output: [src/utils] or [src/file.ts]
  */
-export async function copyWorkspaceFiles(): Promise<void> {
-  const workspaceFolders = vscode.workspace.workspaceFolders;
-  if (!workspaceFolders || workspaceFolders.length === 0) return;
-
-  const uris = await vscode.window.showOpenDialog({
-    canSelectFiles: true,
-    canSelectFolders: false,
-    canSelectMany: true,
-    openLabel: 'Select files to copy as context',
-  });
-
-  if (!uris || uris.length === 0) return;
-
-  await copyFilesFromUris(uris);
+export async function copySingleItem(itemUri: vscode.Uri): Promise<void> {
+  const itemPath = vscode.workspace.asRelativePath(itemUri);
+  const result = `[${itemPath}]`;
+  await vscode.env.clipboard.writeText(result);
+  showStatus(`$(clippy) Copied: ${itemPath}`);
 }
 
 /**
- * Copy a single folder path to clipboard with AI-friendly formatting.
- * Output: [src/utils]
+ * Copy files selected in the explorer context menu.
  */
-export async function copyFolderPath(folderUri: vscode.Uri): Promise<void> {
-  const folderPath = vscode.workspace.asRelativePath(folderUri);
-  const result = `[${folderPath}]`;
-  await vscode.env.clipboard.writeText(result);
-  showStatus(`$(clippy) Copied folder: ${folderPath}`);
+export async function copySelectedFiles(selectedUris: vscode.Uri[]): Promise<void> {
+  if (!selectedUris || selectedUris.length === 0) return;
+  await copyFilesFromUris(selectedUris);
 }
 
 /**
- * Copy files selected in the explorer context menu.
+ * Copy multiple selected files from explorer multi-selection.
  */
-export async function copySelectedFiles(selectedUris: vscode.Uri[]): Promise<void> {
+export async function copyMultiFiles(selectedUris: vscode.Uri[]): Promise<void> {
   if (!selectedUris || selectedUris.length === 0) return;
   await copyFilesFromUris(selectedUris);
 }
@@ -128,45 +116,26 @@ async function collectFilesRecursively(dirUri: vscode.Uri): Promise<vscode.Uri[]
 
   return result;
 }
-
 /**
- * Expand a mixed list of file/directory URIs into a flat list of file URIs.
+ * Read and format multiple files, then copy to clipboard.
  */
-async function expandUris(uris: vscode.Uri[]): Promise<vscode.Uri[]> {
-  const result: vscode.Uri[] = [];
+async function copyFilesFromUris(uris: vscode.Uri[]): Promise<void> {
+  const entries: { filePath: string }[] = [];
 
   for (const uri of uris) {
+    let fileUris: vscode.Uri[] = [uri];
+
     try {
       const stat = await vscode.workspace.fs.stat(uri);
       if (stat.type === vscode.FileType.Directory) {
-        const children = await collectFilesRecursively(uri);
-        result.push(...children);
-      } else if (stat.type === vscode.FileType.File) {
-        result.push(uri);
+        fileUris = await collectFilesRecursively(uri);
       }
     } catch {
-      // skip inaccessible paths
+      // stat failed, use the uri as-is
     }
-  }
-
-  return result;
-}
 
-/**
- * Read and format multiple files, then copy to clipboard.
- */
-async function copyFilesFromUris(uris: vscode.Uri[]): Promise<void> {
-  const fileUris = await expandUris(uris);
-
-  const entries: { filePath: string }[] = [];
-
-  for (const uri of fileUris) {
-    try {
-      await vscode.workspace.openTextDocument(uri);
-      const filePath = vscode.workspace.asRelativePath(uri);
-      entries.push({ filePath });
-    } catch {
-      // skip binary or unreadable files
+    for (const fu of fileUris) {
+      entries.push({ filePath: vscode.workspace.asRelativePath(fu) });
     }
   }
 

+ 12 - 14
src/extension.ts

@@ -2,9 +2,9 @@ import * as vscode from 'vscode';
 import {
   copySelection,
   copyActiveFile,
-  copyFolderPath,
-  copyWorkspaceFiles,
+  copySingleItem,
   copySelectedFiles,
+  copyMultiFiles,
 } from './copyContext';
 
 export function activate(context: vscode.ExtensionContext) {
@@ -23,22 +23,20 @@ export function activate(context: vscode.ExtensionContext) {
   );
 
   context.subscriptions.push(
-    vscode.commands.registerCommand('vsix-cp-ai-ctx.copyWorkspaceFiles', () => {
-      copyWorkspaceFiles();
+    vscode.commands.registerCommand('vsix-cp-ai-ctx.copySelectedFiles', (args) => {
+      if (!args) return;
+      copySingleItem(args as vscode.Uri);
     }),
   );
 
   context.subscriptions.push(
-    vscode.commands.registerCommand('vsix-cp-ai-ctx.copySelectedFiles', (args) => {
-      if (!args) return;
-      // Single item right-click: args is the URI directly.
-      if (args instanceof vscode.Uri) {
-        copyFolderPath(args);
-        return;
-      }
-      // Multi-selection: args.selectedResources contains the URIs.
-      const uris: vscode.Uri[] = args.selectedResources || [];
-      copySelectedFiles(uris);
+    vscode.commands.registerCommand('vsix-cp-ai-ctx.copyMultiFiles', (...args) => {
+      if (args.length < 2) return;
+      // args[0] = clicked resource URI
+      // args[1] might be array (standard) or individual URI (variadic)
+      const resources = Array.isArray(args[1]) ? args[1] : args.slice(1);
+      if (resources.length === 0) return;
+      copyMultiFiles(resources);
     }),
   );
 

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff