modular code
This commit is contained in:
135
src/utils/promptGenerator.ts
Normal file
135
src/utils/promptGenerator.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { PrompterSettings } from '../models/settings';
|
||||
import { FileReader } from './fileReader';
|
||||
import { TokenEstimator } from './tokenEstimator';
|
||||
|
||||
/**
|
||||
* Utility class for generating prompts from selected files
|
||||
*/
|
||||
export class PromptGenerator {
|
||||
/**
|
||||
* Generate a prompt from the selected files
|
||||
* @param selectedFiles Set of file paths to include in the prompt
|
||||
* @param settings Settings to apply when generating the prompt
|
||||
* @returns The generated prompt text
|
||||
*/
|
||||
static async generatePrompt(selectedFiles: Set<string>, settings: PrompterSettings): Promise<string> {
|
||||
if (selectedFiles.size === 0) {
|
||||
throw new Error('No files selected');
|
||||
}
|
||||
|
||||
let totalTokens = 0;
|
||||
const fileContents = new Map<string, { content: string; tokens: number }>();
|
||||
|
||||
// Process each selected file
|
||||
for (const filePath of selectedFiles) {
|
||||
const content = await FileReader.readFileContent(filePath);
|
||||
const tokens = TokenEstimator.estimateTokens(content);
|
||||
totalTokens += tokens;
|
||||
fileContents.set(filePath, { content, tokens });
|
||||
}
|
||||
|
||||
// Generate the prompt based on settings
|
||||
if (settings.xmlEditsEnabled) {
|
||||
return this.generateXMLPrompt(fileContents, settings);
|
||||
} else {
|
||||
return this.generatePlainPrompt(fileContents, settings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a plain text prompt
|
||||
* @param files Map of file paths to content and token counts
|
||||
* @param settings Settings to apply
|
||||
* @returns Plain text prompt
|
||||
*/
|
||||
private static generatePlainPrompt(files: Map<string, { content: string; tokens: number }>, settings: PrompterSettings): string {
|
||||
let promptText = '';
|
||||
let totalTokenCount = 0;
|
||||
|
||||
for (const [filePath, { content, tokens }] of files) {
|
||||
const fileName = path.basename(filePath);
|
||||
totalTokenCount += tokens;
|
||||
|
||||
// Add the file to the prompt
|
||||
promptText += `File: ${fileName}\n`;
|
||||
|
||||
// Add line numbers if enabled
|
||||
if (settings.includeLineNumbers) {
|
||||
const lines = content.split('\n');
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
promptText += `${i + 1}: ${lines[i]}\n`;
|
||||
}
|
||||
} else {
|
||||
promptText += `${content}\n`;
|
||||
}
|
||||
|
||||
promptText += '\n';
|
||||
}
|
||||
|
||||
// Add token count if enabled
|
||||
if (settings.tokenCalculationEnabled) {
|
||||
promptText += `\nEstimated token count: ${totalTokenCount}`;
|
||||
}
|
||||
|
||||
return promptText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an XML formatted prompt
|
||||
* @param files Map of file paths to content and token counts
|
||||
* @param settings Settings to apply
|
||||
* @returns XML formatted prompt
|
||||
*/
|
||||
private static generateXMLPrompt(files: Map<string, { content: string; tokens: number }>, settings: PrompterSettings): string {
|
||||
const xmlParts = ['<?xml version="1.0" encoding="UTF-8"?>', '<prompt>'];
|
||||
|
||||
// Add files section
|
||||
xmlParts.push(' <files>');
|
||||
for (const [filePath, { content, tokens }] of files) {
|
||||
const extension = path.extname(filePath);
|
||||
let language = extension.substring(1); // Remove the dot
|
||||
|
||||
// Handle special cases
|
||||
if (extension === '.js' || extension === '.jsx') {
|
||||
language = 'javascript';
|
||||
} else if (extension === '.ts' || extension === '.tsx') {
|
||||
language = 'typescript';
|
||||
}
|
||||
|
||||
xmlParts.push(' <file>');
|
||||
xmlParts.push(` <path>${path.basename(filePath)}</path>`);
|
||||
xmlParts.push(` <type>${language}</type>`);
|
||||
xmlParts.push(` <tokens>${tokens}</tokens>`);
|
||||
|
||||
// Format content based on settings
|
||||
let formattedContent = content;
|
||||
if (settings.includeLineNumbers) {
|
||||
const lines = content.split('\n');
|
||||
formattedContent = lines.map((line, i) => `${i + 1}: ${line}`).join('\n');
|
||||
}
|
||||
|
||||
xmlParts.push(` <content><![CDATA[${formattedContent}]]></content>`);
|
||||
xmlParts.push(' </file>');
|
||||
}
|
||||
xmlParts.push(' </files>');
|
||||
|
||||
// Add options based on settings
|
||||
xmlParts.push(' <options>');
|
||||
if (settings.includeLineNumbers) {
|
||||
xmlParts.push(' <include_line_numbers>true</include_line_numbers>');
|
||||
}
|
||||
if (!settings.includeComments) {
|
||||
xmlParts.push(' <exclude_comments>true</exclude_comments>');
|
||||
}
|
||||
if (settings.tokenCalculationEnabled) {
|
||||
xmlParts.push(` <total_tokens>${Array.from(files.values()).reduce((sum, { tokens }) => sum + tokens, 0)}</total_tokens>`);
|
||||
}
|
||||
xmlParts.push(' </options>');
|
||||
|
||||
xmlParts.push('</prompt>');
|
||||
return xmlParts.join('\n');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user