Skip to content

Commit 2e1df09

Browse files
committed
重构代码,优化数据结构
1 parent 7fc0c3a commit 2e1df09

File tree

3 files changed

+110
-84
lines changed

3 files changed

+110
-84
lines changed

src/cvbManager.ts

Lines changed: 102 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,106 @@ const languageMapping: { [key: string]: string } = {
1818
'js': 'javascript'
1919
};
2020

21+
export class Cvb {
22+
private content: string;
23+
private metadata: Record<string, string>;
24+
private files: Record<string, string>;
25+
26+
constructor(cvbContent: string) {
27+
const { cvbContent: content, metadata, files } = this.parse(cvbContent);
28+
this.content = content;
29+
this.metadata = metadata;
30+
this.files = files;
31+
}
32+
33+
getMetadata(): Record<string, string> {
34+
return this.metadata;
35+
}
36+
37+
getFiles(): Record<string, string> {
38+
return this.files;
39+
}
40+
41+
getUserRequest(): string {
42+
return this.metadata['@用户需求'] || '';
43+
}
44+
45+
getTimestamp(): string {
46+
return this.metadata['@时间戳'] || '';
47+
}
48+
49+
toString(): string {
50+
return this.content;
51+
}
52+
53+
private parse(cvbContent: string): {
54+
cvbContent: string;
55+
metadata: Record<string, string>;
56+
files: Record<string, string>;
57+
} {
58+
// 匹配## BEGIN_CVB在行首的位置
59+
const cvbStartRegex = /^## BEGIN_CVB(\s|$)/m;
60+
const cvbStartMatch = cvbStartRegex.exec(cvbContent);
61+
if (!cvbStartMatch) {
62+
throw new Error('Invalid CVB format: missing BEGIN_CVB marker.');
63+
}
64+
const cvbStartIndex = cvbStartMatch.index;
65+
66+
// 匹配## END_CVB在行首的位置
67+
const cvbEndRegex = /^## END_CVB(\s|$)/m;
68+
const cvbEndMatch = cvbEndRegex.exec(cvbContent);
69+
if (!cvbEndMatch) {
70+
throw new Error('Invalid CVB format: missing END_CVB marker.');
71+
}
72+
const cvbEndIndex = cvbEndMatch.index;
73+
74+
// 提取CVB内容,包括## BEGIN_CVB和## END_CVB
75+
const cvbContentStr = cvbContent.slice(cvbStartIndex, cvbEndIndex + cvbEndMatch[0].length);
76+
77+
// 提取元数据部分
78+
const metaRegex = /^## META\n([\s\S]*?)^## END_META(\s|$)/m;
79+
const metaMatch = metaRegex.exec(cvbContentStr);
80+
if (!metaMatch) {
81+
throw new Error('Invalid CVB format: missing META section.');
82+
}
83+
const metadata: Record<string, string> = {};
84+
const metaContent = metaMatch[1].trim().split('\n');
85+
metaContent.forEach(line => {
86+
const parts = line.split(':');
87+
if (parts.length >= 2) {
88+
const key = parts.shift()?.trim();
89+
const value = parts.join(':').trim();
90+
if (key) {
91+
metadata[key] = value;
92+
}
93+
}
94+
});
95+
96+
// 提取文件内容部分
97+
const files: Record<string, string> = {};
98+
const fileRegex = /^## FILE:(.*?)\n([\s\S]*?)(?=^## FILE:|^## END_CVB)/gm;
99+
let match: RegExpExecArray | null;
100+
101+
while ((match = fileRegex.exec(cvbContentStr)) !== null) {
102+
const filePath = match[1];
103+
let fileContent = match[2].trim();
104+
// 去除代码块标记
105+
const codeBlockRegex = /^```.*\n([\s\S]*?)\n```$/m;
106+
const codeBlockMatch = codeBlockRegex.exec(fileContent);
107+
if (codeBlockMatch) {
108+
fileContent = codeBlockMatch[1];
109+
}
110+
files[filePath] = fileContent;
111+
}
112+
113+
return {
114+
cvbContent: cvbContentStr,
115+
metadata,
116+
files,
117+
};
118+
}
119+
}
120+
21121
/**
22122
* 返回 CVB 格式介绍的静态字符串
23123
* @returns CVB 格式介绍
@@ -162,78 +262,6 @@ export async function generateCvb(filePaths: string[], userRequest: string): Pro
162262
return cvbFilePath;
163263
}
164264

165-
/**
166-
* 解析 CVB 格式内容
167-
* @param cvbContent CVB 内容
168-
* @returns 包含 CVB 字符串、元数据和文件内容的对象
169-
*/
170-
export function parseCvb(cvbContent: string): {
171-
cvbContent: string;
172-
metadata: Record<string, string>;
173-
files: Record<string, string>;
174-
} {
175-
// 匹配## BEGIN_CVB在行首的位置
176-
const cvbStartRegex = /^## BEGIN_CVB(\s|$)/m;
177-
const cvbStartMatch = cvbStartRegex.exec(cvbContent);
178-
if (!cvbStartMatch) {
179-
throw new Error('Invalid CVB format: missing BEGIN_CVB marker.');
180-
}
181-
const cvbStartIndex = cvbStartMatch.index;
182-
183-
// 匹配## END_CVB在行首的位置
184-
const cvbEndRegex = /^## END_CVB(\s|$)/m;
185-
const cvbEndMatch = cvbEndRegex.exec(cvbContent);
186-
if (!cvbEndMatch) {
187-
throw new Error('Invalid CVB format: missing END_CVB marker.');
188-
}
189-
const cvbEndIndex = cvbEndMatch.index;
190-
191-
// 提取CVB内容,包括## BEGIN_CVB和## END_CVB
192-
const cvbContentStr = cvbContent.slice(cvbStartIndex, cvbEndIndex + cvbEndMatch[0].length);
193-
194-
// 提取元数据部分
195-
const metaRegex = /^## META\n([\s\S]*?)^## END_META(\s|$)/m;
196-
const metaMatch = metaRegex.exec(cvbContentStr);
197-
if (!metaMatch) {
198-
throw new Error('Invalid CVB format: missing META section.');
199-
}
200-
const metadata: Record<string, string> = {};
201-
const metaContent = metaMatch[1].trim().split('\n');
202-
metaContent.forEach(line => {
203-
const parts = line.split(':');
204-
if (parts.length >= 2) {
205-
const key = parts.shift()?.trim();
206-
const value = parts.join(':').trim();
207-
if (key) {
208-
metadata[key] = value;
209-
}
210-
}
211-
});
212-
213-
// 提取文件内容部分
214-
const files: Record<string, string> = {};
215-
const fileRegex = /^## FILE:(.*?)\n([\s\S]*?)(?=^## FILE:|^## END_CVB)/gm;
216-
let match: RegExpExecArray | null;
217-
218-
while ((match = fileRegex.exec(cvbContentStr)) !== null) {
219-
const filePath = match[1];
220-
let fileContent = match[2].trim();
221-
// 去除代码块标记
222-
const codeBlockRegex = /^```.*\n([\s\S]*?)\n```$/m;
223-
const codeBlockMatch = codeBlockRegex.exec(fileContent);
224-
if (codeBlockMatch) {
225-
fileContent = codeBlockMatch[1];
226-
}
227-
files[filePath] = fileContent;
228-
}
229-
230-
return {
231-
cvbContent: cvbContentStr,
232-
metadata,
233-
files,
234-
};
235-
}
236-
237265
/**
238266
* 将 CVB 文件内容应用到当前工作目录
239267
* @param cvbContent CVB 文件内容
@@ -247,7 +275,8 @@ export function applyCvbToWorkspace(cvbContent: string): void {
247275
const workspacePath = workspaceFolders[0].uri.fsPath;
248276

249277
// 解析 CVB 文件内容
250-
const { files } = parseCvb(cvbContent);
278+
const cvb = new Cvb(cvbContent);
279+
const files = cvb.getFiles();
251280

252281
// 遍历文件内容
253282
for (const [filePath, fileContent] of Object.entries(files)) {

src/extension.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as vscode from 'vscode';
22
import * as path from 'path';
33
import * as fs from 'fs';
44
import { selectFiles } from './fileSelector';
5-
import { generateCvb, parseCvb, applyCvbToWorkspace, generateTimestamp } from './cvbManager';
5+
import { generateCvb, Cvb, applyCvbToWorkspace, generateTimestamp } from './cvbManager';
66
import { queryCodeReDesign, generateFilenameFromRequest, analyzeCode } from './deepseekApi';
77
import { setupCvbAsMarkdown } from './cvbMarkdownHandler';
88
import { registerCvbContextMenu } from './siderBar';
@@ -116,9 +116,9 @@ export function activate(context: vscode.ExtensionContext) {
116116

117117
const apiResponse = await queryCodeReDesign(cvbContent, userPrompt, outputChannel, getCurrentOperationController().signal);
118118
if (apiResponse) {
119-
const { cvbContent: newCvbContent, metadata, files } = parseCvb(apiResponse);
119+
const cvb = new Cvb(apiResponse);
120120
const newCvbFilePath = path.join(tmpDir, fileName);
121-
fs.writeFileSync(newCvbFilePath, newCvbContent, 'utf-8');
121+
fs.writeFileSync(newCvbFilePath, cvb.toString(), 'utf-8');
122122
vscode.window.showInformationMessage(`API response saved as CVB file: ${newCvbFilePath}`);
123123
}
124124
clearCurrentOperationController();

src/siderBar.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as vscode from 'vscode';
22
import * as path from 'path';
33
import * as fs from 'fs';
4-
import { applyCvbToWorkspace, generateTimestamp, parseCvb } from './cvbManager';
4+
import { applyCvbToWorkspace, generateTimestamp, Cvb } from './cvbManager';
55
import { queryCodeReDesign, analyzeCode, generateFilenameFromRequest } from './deepseekApi';
66
import { getCurrentOperationController, resetCurrentOperationController, clearCurrentOperationController} from './extension';
77

@@ -194,13 +194,10 @@ async function uploadThisCvb(filePath: string) {
194194

195195
const apiResponse = await queryCodeReDesign(cvbContent, userPrompt, outputChannel, getCurrentOperationController().signal);
196196
if (apiResponse) {
197-
vscode.window.showInformationMessage('API response received. Check the output channel for details.');
198-
}
199-
if (apiResponse) {
200-
const { cvbContent: newCvbContent, metadata, files } = parseCvb(apiResponse);
201-
const newCvbFilePath = path.join(tmpDir, fileName);
202-
fs.writeFileSync(newCvbFilePath, newCvbContent, 'utf-8');
203-
vscode.window.showInformationMessage(`API response saved as CVB file: ${newCvbFilePath}`);
197+
const cvb = new Cvb(apiResponse);
198+
const newCvbFilePath = path.join(tmpDir, fileName);
199+
fs.writeFileSync(newCvbFilePath, cvb.toString(), 'utf-8');
200+
vscode.window.showInformationMessage(`API response saved as CVB file: ${newCvbFilePath}`);
204201
}
205202
clearCurrentOperationController();
206203
}

0 commit comments

Comments
 (0)