fix(gpt-context): Fixes the layout and the options with the selected files

This commit is contained in:
Christopher 2023-06-18 16:30:57 -04:00
parent 98c894fe6e
commit 93be5cbce3

View File

@ -1,11 +1,14 @@
const vscode = require('vscode');
const path = require('path');
// Represents a file item in the file explorer
class FileItem {
constructor(uri, checked) {
constructor(uri, selected = false) {
this.uri = uri;
this.checked = checked || false;
this.selected = selected;
}
toggleSelected() {
this.selected = !this.selected;
}
}
@ -17,7 +20,6 @@ class FileDataProvider {
constructor() {
this._onDidChangeTreeData = new vscode.EventEmitter();
this.onDidChangeTreeData = this._onDidChangeTreeData.event;
this.filterPatterns = ['*.*']; // Default filter pattern
}
refresh() {
@ -27,8 +29,7 @@ class FileDataProvider {
getTreeItem(element) {
return {
label: element.uri.fsPath,
collapsibleState: vscode.TreeItemCollapsibleState.None,
checked: element.checked
collapsibleState: vscode.TreeItemCollapsibleState.None
};
}
@ -36,57 +37,33 @@ class FileDataProvider {
if (element) {
return [];
}
return selectedFiles;
}
setFilter(filter) {
this.filterPatterns = filter.split(',').map(pattern => pattern.trim());
this.refresh();
}
filterFiles(files) {
return files.filter(file => {
const extension = path.extname(file.uri.fsPath);
return this.filterPatterns.some(pattern => {
const regex = new RegExp(pattern.replace(/\./g, '\\.').replace(/\*/g, '.*'));
return regex.test(extension);
});
});
// Return only the selected files
return selectedFiles.filter(file => file.selected);
}
}
// Command for adding files to gpt-contextfiles
const addFilesCommand = vscode.commands.registerCommand('extension.addFilesToGPTContext', () => {
const workspaceFolders = vscode.workspace.workspaceFolders;
if (workspaceFolders && workspaceFolders.length > 0) {
const workspacePath = workspaceFolders[0].uri.fsPath;
vscode.workspace.findFiles('**/*', '', 1000).then(files => {
const fileItems = files.map(file => new FileItem(file));
selectedFiles.splice(0, selectedFiles.length, ...fileItems);
const editor = vscode.window.activeTextEditor;
if (editor) {
const uri = editor.document.uri;
const existingFileIndex = selectedFiles.findIndex(file => file.uri.fsPath === uri.fsPath);
if (existingFileIndex !== -1) {
// File already exists, remove it from the list
selectedFiles.splice(existingFileIndex, 1);
} else {
// Add the file to the list with selected state
selectedFiles.push(new FileItem(uri, true));
}
fileDataProvider.refresh();
});
}
});
// Refresh the file list when workspace changes (file creation, deletion, renaming)
vscode.workspace.onDidChangeWorkspaceFolders(() => {
vscode.commands.executeCommand('extension.addFilesToGPTContext');
});
vscode.workspace.onDidCreateFiles(() => {
vscode.commands.executeCommand('extension.addFilesToGPTContext');
});
vscode.workspace.onDidDeleteFiles(() => {
vscode.commands.executeCommand('extension.addFilesToGPTContext');
});
vscode.workspace.onDidRenameFiles(() => {
vscode.commands.executeCommand('extension.addFilesToGPTContext');
});
const fileDataProvider = new FileDataProvider();
// Command for displaying the webview panel
@ -105,46 +82,52 @@ const openGPTContextPanelCommand = vscode.commands.registerCommand('extension.op
panel.webview.onDidReceiveMessage(message => {
if (message.command === 'submitQuestion') {
const question = message.text;
const selectedFilePaths = selectedFiles
.filter(file => file.checked)
.map(file => file.uri.fsPath);
const fileContents = selectedFilePaths
.map(filePath => {
const document = vscode.workspace.textDocuments.find(doc => doc.uri.fsPath === filePath);
const fileContents = selectedFiles
.map(file => {
const document = vscode.workspace.textDocuments.find(doc => doc.uri.fsPath === file.uri.fsPath);
if (document) {
const lines = document.getText().split('\n');
return `${filePath}\n${lines.join('\n')}`;
return `${file.uri.fsPath}\n${lines.join('\n')}`;
}
return '';
})
.join('\n\n');
panel.webview.html = getWebviewContent(fileContents, question);
} else if (message.command === 'fileSelectionChanged') {
const { filePath, checked } = message;
const file = selectedFiles.find(file => file.uri.fsPath === filePath);
} else if (message.command === 'toggleFileSelection') {
const uri = message.uri;
const file = selectedFiles.find(file => file.uri.fsPath === uri);
if (file) {
file.checked = checked;
file.toggleSelected();
fileDataProvider.refresh();
}
} else if (message.command === 'filterFiles') {
const { filter } = message;
fileDataProvider.setFilter(filter);
} else if (message.command === 'clearSelectedFiles') {
selectedFiles.forEach(file => {
file.selected = false;
});
selectedFiles.length = 0; // Clear the array
fileDataProvider.refresh();
} else if (message.command === 'refreshSelectedFiles') {
fileDataProvider.refresh();
}
});
});
// Command for refreshing the selected files
const refreshSelectedFilesCommand = vscode.commands.registerCommand('extension.refreshSelectedFiles', () => {
fileDataProvider.refresh();
});
// Helper function to generate the HTML content for the webview panel
function getWebviewContent(fileContents, question) {
const fileItems = fileDataProvider
.filterFiles(selectedFiles)
.map(file => `
<div>
<input type="checkbox" id="${file.uri.fsPath}" name="file" value="${file.uri.fsPath}" ${file.checked ? 'checked' : ''}>
<label for="${file.uri.fsPath}">${file.uri.fsPath}</label>
</div>
`)
.join('\n');
const fileList = selectedFiles
.map(
file =>
`<div><input type="checkbox" ${
file.selected ? 'checked' : ''
} onchange="toggleFileSelection('${file.uri.fsPath}')" /> ${file.uri.fsPath}</div>`
)
.join('');
return `
<html>
@ -154,23 +137,39 @@ function getWebviewContent(fileContents, question) {
<label for="question">Enter your question:</label>
<input type="text" id="question" name="question" required>
<button type="submit">Submit</button>
<button type="button" onclick="clearSelectedFiles()">Clear</button>
<button type="button" onclick="refreshSelectedFiles()">Refresh</button>
</form>
<div>
<h3>Select Files:</h3>
<div>
<label for="filter">Filter:</label>
<input type="text" id="filter" name="filter" value="${fileDataProvider.filterPatterns.join(', ')}">
<button id="applyFilter">Apply</button>
</div>
${fileItems}
</div>
${
fileContents ? `<div><pre>${fileContents}</pre></div>` : ''
}
<div>
<h2>Selected Files:</h2>
${fileList}
</div>
<div><pre>${question ? question : ''}</pre></div>
<script>
const vscode = acquireVsCodeApi();
function toggleFileSelection(uri) {
vscode.postMessage({
command: 'toggleFileSelection',
uri: uri
});
}
function clearSelectedFiles() {
vscode.postMessage({
command: 'clearSelectedFiles'
});
}
function refreshSelectedFiles() {
vscode.postMessage({
command: 'refreshSelectedFiles'
});
}
const form = document.getElementById('questionForm');
form.addEventListener('submit', event => {
event.preventDefault();
@ -180,29 +179,6 @@ function getWebviewContent(fileContents, question) {
text: question
});
});
const fileCheckboxes = document.querySelectorAll('input[name="file"]');
fileCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', event => {
const filePath = event.target.value;
const checked = event.target.checked;
vscode.postMessage({
command: 'fileSelectionChanged',
filePath: filePath,
checked: checked
});
});
});
const applyFilterButton = document.getElementById('applyFilter');
applyFilterButton.addEventListener('click', () => {
const filterInput = document.getElementById('filter');
const filterValue = filterInput.value;
vscode.postMessage({
command: 'filterFiles',
filter: filterValue
});
});
</script>
</body>
</html>
@ -217,6 +193,7 @@ function activate(context) {
// Register the commands
context.subscriptions.push(addFilesCommand);
context.subscriptions.push(openGPTContextPanelCommand);
context.subscriptions.push(refreshSelectedFilesCommand);
// Refresh the file data provider when a file is added or removed from the workspace
vscode.workspace.onDidChangeWorkspaceFolders(() => {