add commit message command
This commit is contained in:
parent
7f6a423045
commit
05bee3880b
@ -2,7 +2,7 @@ export interface Command {
|
||||
name: string;
|
||||
pattern: string;
|
||||
description: string;
|
||||
handler: (userInput: string) => string;
|
||||
handler: (userInput: string) => Promise<string>;
|
||||
}
|
||||
|
||||
class CommandManager {
|
||||
@ -27,21 +27,34 @@ export interface Command {
|
||||
return this.commands;
|
||||
}
|
||||
|
||||
processText(text: string): string {
|
||||
let result = text;
|
||||
async processText(text: string): Promise<string> {
|
||||
// 定义一个异步函数来处理单个命令
|
||||
const processCommand = async (commandObj: Command, userInput: string) => {
|
||||
const commandPattern = new RegExp(
|
||||
`\\/(${commandObj.pattern.replace('{{prompt}}', '(.+?)')})`,
|
||||
'g'
|
||||
);
|
||||
const matches = Array.from(text.matchAll(commandPattern));
|
||||
const replacements = await Promise.all(
|
||||
matches.map(async (match) => {
|
||||
const matchedUserInput = match[1];
|
||||
return await commandObj.handler(matchedUserInput);
|
||||
})
|
||||
);
|
||||
let result = text;
|
||||
for (let i = 0; i < matches.length; i++) {
|
||||
result = result.replace(matches[i][0], replacements[i]);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
this.commands.forEach((commandObj) => {
|
||||
const commandPattern = new RegExp(
|
||||
`\\/(${commandObj.pattern.replace("{{prompt}}", "(.+?)")})`,
|
||||
"g"
|
||||
);
|
||||
// 处理所有命令
|
||||
let result = text;
|
||||
for (const commandObj of this.commands) {
|
||||
result = await processCommand(commandObj, result);
|
||||
}
|
||||
|
||||
result = result.replace(commandPattern, (_, matchedUserInput) => {
|
||||
return commandObj.handler(matchedUserInput);
|
||||
});
|
||||
});
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
58
src/commitMessageCommand.ts
Normal file
58
src/commitMessageCommand.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import {Command} from './commandManager';
|
||||
|
||||
import { exec } from 'child_process';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { promisify } from 'util';
|
||||
|
||||
const mkdirAsync = promisify(fs.mkdir);
|
||||
const execAsync = promisify(exec);
|
||||
const writeFileAsync = promisify(fs.writeFile);
|
||||
|
||||
|
||||
async function createTempDirectory(tempDir: string): Promise<void> {
|
||||
try {
|
||||
await mkdirAsync(tempDir, {recursive: true});
|
||||
} catch (err) {
|
||||
console.error(`Error creating temporary directory: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function writeDiffFile(diff_file: string) {
|
||||
try {
|
||||
const workspaceDir = vscode.workspace.workspaceFolders?.[0].uri.fsPath;
|
||||
|
||||
const { stdout, stderr } = await execAsync('git diff --cached', {
|
||||
cwd: workspaceDir
|
||||
});
|
||||
if (stderr) {
|
||||
console.error(`Error output from git diff --cached: ${stderr}`);
|
||||
return;
|
||||
}
|
||||
// 将结果写入到临时文件中
|
||||
const tempFilePath = diff_file;
|
||||
await writeFileAsync(tempFilePath, stdout);
|
||||
} catch (err) {
|
||||
console.error(`Error executing git diff --cached: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
export const commitMessageCommand: Command = {
|
||||
name: 'commitMessageCommand',
|
||||
pattern: 'git: commit message',
|
||||
description: 'commit message for changes',
|
||||
handler: async (userInput: string) => {
|
||||
const systemTempDir = os.tmpdir();
|
||||
const tempDir = path.join(systemTempDir, 'devchat/context');
|
||||
|
||||
// 创建临时目录
|
||||
await createTempDirectory(tempDir);
|
||||
const diff_file = path.join(tempDir, 'diff_output.txt');
|
||||
await writeDiffFile(diff_file);
|
||||
|
||||
return `[instruction|./commonInstructions.txt] [instruction|./commitMessageCommandInstructions.txt] [context|${diff_file}] Write a commit message`;
|
||||
},
|
||||
};
|
9
src/commitMessageCommandInstructions.txt
Normal file
9
src/commitMessageCommandInstructions.txt
Normal file
@ -0,0 +1,9 @@
|
||||
As a software developer assistant, your task is to provide clear and concise responses and write commit messages based on given code, requirements, or conversations. Follow these guidelines:
|
||||
|
||||
1. A commit message should include a title and multiple body lines.
|
||||
2. Adhere to best practices, such as keeping titles under 50 characters and limiting body lines to under 72 characters.
|
||||
3. Enclose messages in code blocks using triple backticks (```).
|
||||
4. Utilize the <context>, if provided, to create the summary.
|
||||
5. Utilize the previous messages, if provided in the end of this prompt, to create the summary. Note that not all previous messages are necessarily relevant.
|
||||
|
||||
If you need more information, feel free to ask.
|
1
src/commonInstructions.txt
Normal file
1
src/commonInstructions.txt
Normal file
@ -0,0 +1 @@
|
||||
You are a software developer assistant
|
@ -4,7 +4,7 @@ export const exampleCommand1: Command = {
|
||||
name: 'exampleCommand1',
|
||||
pattern: 'example: command1 {{prompt}}',
|
||||
description: '这是一个示例命令1',
|
||||
handler: (userInput: string) => {
|
||||
handler: async (userInput: string) => {
|
||||
return `示例命令1处理了以下文本:${userInput}`;
|
||||
},
|
||||
};
|
||||
|
@ -4,7 +4,7 @@ export const exampleCommand2: Command = {
|
||||
name: 'exampleCommand2',
|
||||
pattern: 'example: command2 {{prompt}}',
|
||||
description: '这是一个示例命令2',
|
||||
handler: (userInput: string) => {
|
||||
handler: async (userInput: string) => {
|
||||
return `示例命令2处理了以下文本:${userInput}`;
|
||||
},
|
||||
};
|
||||
|
@ -1,9 +1,11 @@
|
||||
import CommandManager from './commandManager';
|
||||
import { exampleCommand1 } from './exampleCommand1';
|
||||
import { exampleCommand2 } from './exampleCommand2';
|
||||
import { commitMessageCommand } from './commitMessageCommand';
|
||||
|
||||
const commandManager = CommandManager.getInstance();
|
||||
|
||||
// 注册命令
|
||||
commandManager.registerCommand(exampleCommand1);
|
||||
commandManager.registerCommand(exampleCommand2);
|
||||
commandManager.registerCommand(commitMessageCommand);
|
@ -41,19 +41,43 @@ export function askAI(panel: vscode.WebviewPanel, codeBlock: string, question: s
|
||||
}
|
||||
|
||||
// Add this function to messageHandler.ts
|
||||
function parseMessageForContext(message: string): { context: string[]; text: string } {
|
||||
function parseMessage(message: string): { context: string[]; instruction: string[]; reference: string[]; text: string } {
|
||||
const contextRegex = /\[context\|(.*?)\]/g;
|
||||
const instructionRegex = /\[instruction\|(.*?)\]/g;
|
||||
const referenceRegex = /\[reference\|(.*?)\]/g;
|
||||
|
||||
const contextPaths = [];
|
||||
const instructionPaths = [];
|
||||
const referencePaths = [];
|
||||
|
||||
let match;
|
||||
|
||||
// 提取 context
|
||||
while ((match = contextRegex.exec(message)) !== null) {
|
||||
contextPaths.push(match[1]);
|
||||
}
|
||||
|
||||
const text = message.replace(contextRegex, '').trim();
|
||||
return { context: contextPaths, text };
|
||||
// 提取 instruction
|
||||
while ((match = instructionRegex.exec(message)) !== null) {
|
||||
instructionPaths.push(match[1]);
|
||||
}
|
||||
|
||||
// 提取 reference
|
||||
while ((match = referenceRegex.exec(message)) !== null) {
|
||||
referencePaths.push(match[1]);
|
||||
}
|
||||
|
||||
// 移除标签,保留纯文本
|
||||
const text = message
|
||||
.replace(contextRegex, '')
|
||||
.replace(instructionRegex, '')
|
||||
.replace(referenceRegex, '')
|
||||
.trim();
|
||||
|
||||
return { context: contextPaths, instruction: instructionPaths, reference: referencePaths, text };
|
||||
}
|
||||
|
||||
|
||||
async function handleMessage(
|
||||
message: any,
|
||||
panel: vscode.WebviewPanel
|
||||
@ -63,12 +87,21 @@ async function handleMessage(
|
||||
|
||||
switch (message.command) {
|
||||
case 'sendMessage':
|
||||
const parsedMessage = parseMessageForContext(message.text);
|
||||
const newText2 = await CommandManager.getInstance().processText(message.text);
|
||||
panel.webview.postMessage({ command: 'convertCommand', result: newText2 });
|
||||
|
||||
const parsedMessage = parseMessage(newText2);
|
||||
const chatOptions: any = lastPromptHash ? { parent: lastPromptHash } : {};
|
||||
|
||||
if (parsedMessage.context.length > 0) {
|
||||
chatOptions.context = parsedMessage.context;
|
||||
}
|
||||
if (parsedMessage.instruction.length > 0) {
|
||||
chatOptions.instruction = parsedMessage.instruction;
|
||||
}
|
||||
if (parsedMessage.reference.length > 0) {
|
||||
chatOptions.reference = parsedMessage.reference;
|
||||
}
|
||||
|
||||
let partialData = "";
|
||||
const onData = (partialResponse: string) => {
|
||||
@ -112,7 +145,7 @@ async function handleMessage(
|
||||
panel.webview.postMessage({ command: 'regCommandList', result: commandList });
|
||||
return;
|
||||
case 'convertCommand':
|
||||
const newText = CommandManager.getInstance().processText(message.text);
|
||||
const newText = await CommandManager.getInstance().processText(message.text);
|
||||
panel.webview.postMessage({ command: 'convertCommand', result: newText });
|
||||
return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user