Files
IC-Coder-Plugin/src/views/ICViewProvider.ts
Roe-xin 8af5976501 feat:实现对文件的创建和删除
- 还涵盖了对已存在的文件进行覆盖
- 对不存在的文件创建
- 还可以创建目录
- 可以一次创建多个文件
2025-12-12 09:10:34 +08:00

269 lines
6.8 KiB
TypeScript

import * as vscode from "vscode";
import { getWebviewContent } from "./webviewContent";
import {
handleUserMessage,
insertCodeToEditor,
handleReadFile,
handleCreateFile,
} from "../utils/messageHandler";
/**
* 创建并显示IC 侧边栏视图
*/
export function showICHelperPanel(content: vscode.ExtensionContext) {
// 创建WebView面板
const panel = vscode.window.createWebviewPanel(
"icCoder", // 面板ID
"IC Coder", // 面板标题
vscode.ViewColumn.Beside, // 显示在旁边
{
enableScripts: true,
retainContextWhenHidden: true,
localResourceRoots: [vscode.Uri.joinPath(content.extensionUri, "media")],
}
);
// 设置标签页图标
panel.iconPath = vscode.Uri.joinPath(
content.extensionUri,
"media",
"图案(方底).png"
);
// 获取页面内图标URI
const iconUri = panel.webview.asWebviewUri(
vscode.Uri.joinPath(content.extensionUri, "media", "图案(方底).png")
);
// 设置HTML内容
panel.webview.html = getWebviewContent(iconUri.toString());
// 处理消息
panel.webview.onDidReceiveMessage(
(message) => {
switch (message.command) {
case "sendMessage":
handleUserMessage(panel, message.text);
break;
case "readFile":
handleReadFile(panel, message.filePath);
break;
case "insertCode":
insertCodeToEditor(message.code);
break;
case "createFile":
handleCreateFile(
panel,
message.filePath,
message.content,
message.overwrite
);
break;
case "showInfo":
vscode.window.showInformationMessage(message.text);
break;
}
},
undefined,
content.subscriptions
);
}
/**
* 侧边栏视图提供者
*/
export class ICViewProvider implements vscode.WebviewViewProvider {
constructor(private readonly extensionUri: vscode.Uri) {}
resolveWebviewView(webviewView: vscode.WebviewView) {
webviewView.webview.options = {
enableScripts: true,
localResourceRoots: [vscode.Uri.joinPath(this.extensionUri, "media")],
};
webviewView.webview.html = this.getWebviewContent(webviewView.webview);
// 处理侧边栏的消息
webviewView.webview.onDidReceiveMessage((message) => {
if (message.command === "openChat") {
vscode.commands.executeCommand("ic-coder.openChat");
}
});
}
private getWebviewContent(webview: vscode.Webview): string {
const logoUri = webview.asWebviewUri(
vscode.Uri.joinPath(this.extensionUri, "media", "ICCoder主页标志.png")
);
return `
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
padding: 0;
font-family: var(--vscode-font-family);
color: var(--vscode-foreground);
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(135deg,
var(--vscode-editor-background) 0%,
color-mix(in srgb, var(--vscode-editor-background) 85%, var(--vscode-button-background) 15%) 50%,
color-mix(in srgb, var(--vscode-editor-background) 90%, var(--vscode-button-background) 10%) 100%);
}
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 20px;
}
.container img {
margin-bottom: 16px;
}
.container h2 {
margin: 0 0 16px 0;
}
.btn {
width: 200px;
padding: 8px 12px;
margin: 4px 0;
background: var(--vscode-button-background);
color: var(--vscode-button-foreground);
border: none;
border-radius: 4px;
cursor: pointer;
text-align: center;
}
.btn:hover {
background: var(--vscode-button-hoverBackground);
}
h3 {
margin: 0 0 8px 0;
font-size: 12px;
color: var(--vscode-descriptionForeground);
}
</style>
</head>
<body>
<div class="container">
<img src="${logoUri}" alt="IC Coder" width="120" />
<h2>欢迎使用 IC Coder</h2>
<button class="btn" onclick="openChat()">开始创作</button>
</div>
<script>
const vscode = acquireVsCodeApi();
function openChat() {
vscode.postMessage({ command: 'openChat' });
}
function generateCode(type) {
const code = getCodeTemplate(type);
vscode.postMessage({
command: 'insertCode',
code: code
});
}
function getCodeTemplate(type) {
const templates = {
counter: \`module counter #(
parameter WIDTH = 4
)(
input wire clk,
input wire rst_n,
input wire enable,
output reg [WIDTH-1:0] count
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
count <= 0;
end else if (enable) begin
count <= count + 1;
end
end
endmodule\`,
fsm: \`module fsm (
input wire clk,
input wire rst_n,
input wire start,
output reg done
);
parameter IDLE = 2'b00;
parameter STATE1 = 2'b01;
parameter STATE2 = 2'b10;
reg [1:0] state, next_state;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
end else begin
state <= next_state;
end
end
always @(*) begin
case (state)
IDLE: next_state = start ? STATE1 : IDLE;
STATE1: next_state = STATE2;
STATE2: next_state = IDLE;
default: next_state = IDLE;
endcase
end
assign done = (state == STATE2);
endmodule\`,
fifo: \`module sync_fifo #(
parameter DATA_WIDTH = 8,
parameter DEPTH = 16
)(
input wire clk,
input wire rst_n,
input wire wr_en,
input wire [DATA_WIDTH-1:0] din,
input wire rd_en,
output reg [DATA_WIDTH-1:0] dout,
output wire full,
output wire empty
);
reg [DATA_WIDTH-1:0] mem [0:DEPTH-1];
reg [$clog2(DEPTH):0] wr_ptr, rd_ptr;
assign full = (wr_ptr == rd_ptr + DEPTH);
assign empty = (wr_ptr == rd_ptr);
always @(posedge clk) begin
if (!rst_n) wr_ptr <= 0;
else if (wr_en && !full) begin
mem[wr_ptr] <= din;
wr_ptr <= wr_ptr + 1;
end
end
always @(posedge clk) begin
if (!rst_n) begin
rd_ptr <= 0;
dout <= 0;
end else if (rd_en && !empty) begin
dout <= mem[rd_ptr];
rd_ptr <= rd_ptr + 1;
end
end
endmodule\`
};
return templates[type] || '// 代码模板';
}
</script>
</body>
</html>
`;
}
}