2023-05-05 21:27:40 +08:00
|
|
|
import * as vscode from 'vscode';
|
|
|
|
import { sendFileSelectMessage, sendCodeSelectMessage } from './util';
|
2023-05-10 19:25:11 +08:00
|
|
|
import { logger } from '../util/logger';
|
|
|
|
import * as childProcess from 'child_process';
|
2023-05-16 14:24:24 +08:00
|
|
|
import ExtensionContextHolder from '../util/extensionContext';
|
2023-05-31 16:10:53 +08:00
|
|
|
import { TopicManager, Topic } from '../topic/topicManager';
|
|
|
|
import { TopicTreeDataProvider, TopicTreeItem } from '../panel/topicView';
|
|
|
|
import { FilePairManager } from '../util/diffFilePairs';
|
|
|
|
|
2023-05-10 19:25:11 +08:00
|
|
|
|
2023-05-19 13:09:58 +08:00
|
|
|
import * as process from 'process';
|
2023-05-31 16:10:53 +08:00
|
|
|
import { UiUtilWrapper } from '../util/uiUtil';
|
2023-05-10 19:25:11 +08:00
|
|
|
|
2023-05-31 16:10:53 +08:00
|
|
|
|
2023-05-19 13:09:58 +08:00
|
|
|
export function checkDevChatDependency(): boolean {
|
|
|
|
try {
|
2023-05-28 08:18:14 +08:00
|
|
|
// Get pipx environment
|
2023-05-19 13:09:58 +08:00
|
|
|
const pipxEnvOutput = childProcess.execSync('python3 -m pipx environment').toString();
|
|
|
|
const binPathRegex = /PIPX_BIN_DIR=\s*(.*)/;
|
|
|
|
|
2023-05-28 08:18:14 +08:00
|
|
|
// Get BIN path from pipx environment
|
2023-05-19 13:09:58 +08:00
|
|
|
const match = pipxEnvOutput.match(binPathRegex);
|
|
|
|
if (match && match[1]) {
|
|
|
|
const binPath = match[1];
|
|
|
|
|
2023-05-28 08:18:14 +08:00
|
|
|
// Add BIN path to PATH
|
2023-05-19 13:09:58 +08:00
|
|
|
process.env.PATH = `${binPath}:${process.env.PATH}`;
|
|
|
|
|
2023-05-28 08:18:14 +08:00
|
|
|
// Check if DevChat is installed
|
2023-05-19 13:09:58 +08:00
|
|
|
childProcess.execSync('devchat --help');
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} catch (error) {
|
2023-05-28 08:18:14 +08:00
|
|
|
// DevChat dependency check failed
|
2023-05-19 13:09:58 +08:00
|
|
|
return false;
|
|
|
|
}
|
2023-05-10 19:25:11 +08:00
|
|
|
}
|
|
|
|
|
2023-05-31 16:10:53 +08:00
|
|
|
export async function checkOpenAiAPIKey() {
|
|
|
|
let openaiApiKey = await UiUtilWrapper.secretStorageGet("devchat_OPENAI_API_KEY");
|
2023-05-16 14:24:24 +08:00
|
|
|
if (!openaiApiKey) {
|
2023-05-31 16:10:53 +08:00
|
|
|
openaiApiKey = UiUtilWrapper.getConfiguration('DevChat', 'API_KEY');
|
2023-05-16 14:24:24 +08:00
|
|
|
}
|
|
|
|
if (!openaiApiKey) {
|
|
|
|
openaiApiKey = process.env.OPENAI_API_KEY;
|
|
|
|
}
|
|
|
|
if (!openaiApiKey) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-05-11 10:27:54 +08:00
|
|
|
function registerOpenChatPanelCommand(context: vscode.ExtensionContext) {
|
2023-05-16 17:49:13 +08:00
|
|
|
let disposable = vscode.commands.registerCommand('devchat.openChatPanel',async () => {
|
|
|
|
await vscode.commands.executeCommand('devchat-view.focus');
|
2023-05-05 21:27:40 +08:00
|
|
|
});
|
|
|
|
context.subscriptions.push(disposable);
|
|
|
|
}
|
|
|
|
|
2023-05-16 14:35:37 +08:00
|
|
|
async function ensureChatPanel(context: vscode.ExtensionContext): Promise<boolean> {
|
2023-05-16 17:49:13 +08:00
|
|
|
await vscode.commands.executeCommand('devchat-view.focus');
|
2023-05-05 21:27:40 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
function registerAddContextCommand(context: vscode.ExtensionContext) {
|
2023-05-10 19:25:11 +08:00
|
|
|
const disposableAddContext = vscode.commands.registerCommand('devchat.addConext', async (uri: { path: any; }) => {
|
2023-05-16 14:35:37 +08:00
|
|
|
if (!await ensureChatPanel(context)) {
|
2023-05-05 21:27:40 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-16 14:35:37 +08:00
|
|
|
await sendFileSelectMessage(ExtensionContextHolder.provider?.view()!, uri.path);
|
2023-05-05 21:27:40 +08:00
|
|
|
});
|
2023-05-10 19:25:11 +08:00
|
|
|
context.subscriptions.push(disposableAddContext);
|
2023-05-16 10:40:57 +08:00
|
|
|
|
|
|
|
const disposableAddContextChinese = vscode.commands.registerCommand('devchat.addConext_chinese', async (uri: { path: any; }) => {
|
2023-05-16 14:35:37 +08:00
|
|
|
if (!await ensureChatPanel(context)) {
|
2023-05-16 10:40:57 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-16 14:35:37 +08:00
|
|
|
await sendFileSelectMessage(ExtensionContextHolder.provider?.view()!, uri.path);
|
2023-05-16 10:40:57 +08:00
|
|
|
});
|
|
|
|
context.subscriptions.push(disposableAddContextChinese);
|
2023-05-05 21:27:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function registerAskForCodeCommand(context: vscode.ExtensionContext) {
|
|
|
|
const disposableCodeContext = vscode.commands.registerCommand('devchat.askForCode', async () => {
|
|
|
|
const editor = vscode.window.activeTextEditor;
|
|
|
|
if (editor) {
|
2023-05-16 14:35:37 +08:00
|
|
|
if (!await ensureChatPanel(context)) {
|
2023-05-05 21:27:40 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const selectedText = editor.document.getText(editor.selection);
|
2023-05-16 14:35:37 +08:00
|
|
|
await sendCodeSelectMessage(ExtensionContextHolder.provider?.view()!, editor.document.fileName, selectedText);
|
2023-05-05 21:27:40 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
context.subscriptions.push(disposableCodeContext);
|
2023-05-16 10:40:57 +08:00
|
|
|
|
|
|
|
const disposableCodeContextChinese = vscode.commands.registerCommand('devchat.askForCode_chinese', async () => {
|
|
|
|
const editor = vscode.window.activeTextEditor;
|
|
|
|
if (editor) {
|
2023-05-16 14:35:37 +08:00
|
|
|
if (!await ensureChatPanel(context)) {
|
2023-05-16 10:40:57 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const selectedText = editor.document.getText(editor.selection);
|
2023-05-16 14:35:37 +08:00
|
|
|
await sendCodeSelectMessage(ExtensionContextHolder.provider?.view()!, editor.document.fileName, selectedText);
|
2023-05-16 10:40:57 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
context.subscriptions.push(disposableCodeContextChinese);
|
2023-05-05 21:27:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function registerAskForFileCommand(context: vscode.ExtensionContext) {
|
|
|
|
const disposableAskFile = vscode.commands.registerCommand('devchat.askForFile', async () => {
|
|
|
|
const editor = vscode.window.activeTextEditor;
|
|
|
|
if (editor) {
|
2023-05-16 14:35:37 +08:00
|
|
|
if (!await ensureChatPanel(context)) {
|
2023-05-05 21:27:40 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-16 14:35:37 +08:00
|
|
|
await sendFileSelectMessage(ExtensionContextHolder.provider?.view()!, editor.document.fileName);
|
2023-05-05 21:27:40 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
context.subscriptions.push(disposableAskFile);
|
2023-05-16 10:40:57 +08:00
|
|
|
|
|
|
|
const disposableAskFileChinese = vscode.commands.registerCommand('devchat.askForFile_chinese', async () => {
|
|
|
|
const editor = vscode.window.activeTextEditor;
|
|
|
|
if (editor) {
|
2023-05-16 14:35:37 +08:00
|
|
|
if (!await ensureChatPanel(context)) {
|
2023-05-16 10:40:57 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-16 14:35:37 +08:00
|
|
|
await sendFileSelectMessage(ExtensionContextHolder.provider?.view()!, editor.document.fileName);
|
2023-05-16 10:40:57 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
context.subscriptions.push(disposableAskFileChinese);
|
2023-05-05 21:27:40 +08:00
|
|
|
}
|
|
|
|
|
2023-05-31 16:10:53 +08:00
|
|
|
export function registerApiKeySettingCommand(context: vscode.ExtensionContext) {
|
|
|
|
const secretStorage: vscode.SecretStorage = context.secrets;
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('DevChat.OPENAI_API_KEY', async () => {
|
|
|
|
const passwordInput: string = await vscode.window.showInputBox({
|
|
|
|
password: true,
|
|
|
|
title: "OPENAI_API_KEY"
|
|
|
|
}) ?? '';
|
|
|
|
|
|
|
|
secretStorage.store("devchat_OPENAI_API_KEY", passwordInput);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function registerStatusBarItemClickCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devcaht.onStatusBarClick', async () => {
|
|
|
|
await vscode.commands.executeCommand('devchat-view.focus');
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function regTopicDeleteCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devchat-topicview.deleteTopic', (item: TopicTreeItem) => {
|
|
|
|
TopicManager.getInstance().deleteTopic(item.id);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function regAddTopicCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devchat-topicview.addTopic', () => {
|
|
|
|
const topic = TopicManager.getInstance().createTopic();
|
|
|
|
TopicManager.getInstance().setCurrentTopic(topic.topicId);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function regDeleteSelectTopicCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devchat-topicview.deleteSelectedTopic', () => {
|
|
|
|
const selectedItem = TopicTreeDataProvider.getInstance().selectedItem;
|
|
|
|
if (selectedItem) {
|
|
|
|
TopicManager.getInstance().deleteTopic(selectedItem.id);
|
|
|
|
} else {
|
|
|
|
vscode.window.showErrorMessage('No item selected');
|
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function regSelectTopicCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devchat-topicview.selectTopic', (item: TopicTreeItem) => {
|
|
|
|
TopicTreeDataProvider.getInstance().setSelectedItem(item);
|
|
|
|
TopicManager.getInstance().setCurrentTopic(item.id);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function regReloadTopicCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devchat-topicview.reloadTopic', async (item: TopicTreeItem) => {
|
|
|
|
TopicManager.getInstance().loadTopics();
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function regApplyDiffResultCommand(context: vscode.ExtensionContext) {
|
|
|
|
context.subscriptions.push(
|
|
|
|
vscode.commands.registerCommand('devchat.applyDiffResult', async (data) => {
|
|
|
|
const activeEditor = vscode.window.activeTextEditor;
|
|
|
|
const fileName = activeEditor!.document.fileName;
|
|
|
|
|
|
|
|
const [leftUri, rightUri] = FilePairManager.getInstance().findPair(fileName) || [undefined, undefined];
|
|
|
|
if (leftUri && rightUri) {
|
|
|
|
// 获取对比的两个文件
|
|
|
|
const leftDoc = await vscode.workspace.openTextDocument(leftUri);
|
|
|
|
const rightDoc = await vscode.workspace.openTextDocument(rightUri);
|
|
|
|
|
|
|
|
// 将右边文档的内容替换到左边文档
|
|
|
|
const leftEditor = await vscode.window.showTextDocument(leftDoc);
|
|
|
|
await leftEditor.edit(editBuilder => {
|
|
|
|
const fullRange = new vscode.Range(0, 0, leftDoc.lineCount, 0);
|
|
|
|
editBuilder.replace(fullRange, rightDoc.getText());
|
|
|
|
});
|
|
|
|
|
|
|
|
// 保存左边文档
|
|
|
|
await leftDoc.save();
|
|
|
|
} else {
|
|
|
|
vscode.window.showErrorMessage('No file to apply diff result.');
|
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-05-05 21:27:40 +08:00
|
|
|
export {
|
|
|
|
registerOpenChatPanelCommand,
|
|
|
|
registerAddContextCommand,
|
|
|
|
registerAskForCodeCommand,
|
|
|
|
registerAskForFileCommand,
|
|
|
|
};
|