Просмотр исходного кода

feat: support folder right-click and fix vsix output path

- 右键单文件夹时复制文件夹路径 [path] 而非递归内容
- 右键多选时递归展开文件夹内的文件
- 菜单条件拆分为单文件夹和多选两种场景
- 修复参数处理:单 URI 走 copyFolderPath,多选走 copySelectedFiles
- vsce package 输出路径改为 dist/
Developer 1 месяц назад
Родитель
Сommit
74ecc84e47
5 измененных файлов с 76 добавлено и 8 удалено
  1. 0 0
      dist/extension.js
  2. 0 0
      dist/extension.js.map
  3. 8 3
      package.json
  4. 58 1
      src/copyContext.ts
  5. 10 4
      src/extension.ts

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/extension.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/extension.js.map


+ 8 - 3
package.json

@@ -2,7 +2,7 @@
   "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.0",
+  "version": "0.1.1",
   "publisher": "your-publisher",
   "engines": {
     "vscode": "^1.85.0"
@@ -58,7 +58,12 @@
         },
         {
           "command": "vsix-cp-ai-ctx.copySelectedFiles",
-          "when": "explorerResourceIsFolder && explorerViewletVisible && listMultiSelection",
+          "when": "explorerResourceIsFolder",
+          "group": "9_cutcopypaste@10"
+        },
+        {
+          "command": "vsix-cp-ai-ctx.copySelectedFiles",
+          "when": "listMultiSelection && explorerViewletVisible",
           "group": "9_cutcopypaste@10"
         }
       ]
@@ -69,7 +74,7 @@
     "build": "node esbuild.js",
     "watch": "node esbuild.js --watch",
     "lint": "eslint src --ext .ts",
-    "package": "vsce package",
+    "package": "vsce package --out ./dist/",
     "publish": "vsce publish"
   },
   "devDependencies": {

+ 58 - 1
src/copyContext.ts

@@ -1,3 +1,4 @@
+import * as path from 'path';
 import * as vscode from 'vscode';
 
 /**
@@ -89,6 +90,17 @@ export async function copyWorkspaceFiles(): Promise<void> {
   await copyFilesFromUris(uris);
 }
 
+/**
+ * Copy a single folder path to clipboard with AI-friendly formatting.
+ * Output: [src/utils]
+ */
+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}`);
+}
+
 /**
  * Copy files selected in the explorer context menu.
  */
@@ -97,13 +109,58 @@ export async function copySelectedFiles(selectedUris: vscode.Uri[]): Promise<voi
   await copyFilesFromUris(selectedUris);
 }
 
+/**
+ * Recursively collect all file URIs under a directory.
+ */
+async function collectFilesRecursively(dirUri: vscode.Uri): Promise<vscode.Uri[]> {
+  const result: vscode.Uri[] = [];
+  const entries = await vscode.workspace.fs.readDirectory(dirUri);
+
+  for (const [name, type] of entries) {
+    const childUri = vscode.Uri.joinPath(dirUri, name);
+    if (type === vscode.FileType.Directory) {
+      const children = await collectFilesRecursively(childUri);
+      result.push(...children);
+    } else if (type === vscode.FileType.File) {
+      result.push(childUri);
+    }
+  }
+
+  return result;
+}
+
+/**
+ * Expand a mixed list of file/directory URIs into a flat list of file URIs.
+ */
+async function expandUris(uris: vscode.Uri[]): Promise<vscode.Uri[]> {
+  const result: vscode.Uri[] = [];
+
+  for (const uri of uris) {
+    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);
+      }
+    } catch {
+      // skip inaccessible paths
+    }
+  }
+
+  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 uris) {
+  for (const uri of fileUris) {
     try {
       await vscode.workspace.openTextDocument(uri);
       const filePath = vscode.workspace.asRelativePath(uri);

+ 10 - 4
src/extension.ts

@@ -2,6 +2,7 @@ import * as vscode from 'vscode';
 import {
   copySelection,
   copyActiveFile,
+  copyFolderPath,
   copyWorkspaceFiles,
   copySelectedFiles,
 } from './copyContext';
@@ -29,10 +30,15 @@ export function activate(context: vscode.ExtensionContext) {
 
   context.subscriptions.push(
     vscode.commands.registerCommand('vsix-cp-ai-ctx.copySelectedFiles', (args) => {
-      // When triggered from explorer context menu, args contains the clicked file URI.
-      // selectedResources from multi-selection is passed as a property.
-      const selectedResources: vscode.Uri[] = args?.selectedResources || [];
-      copySelectedFiles(selectedResources);
+      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);
     }),
   );
 

Некоторые файлы не были показаны из-за большого количества измененных файлов