diff --git a/src/extension.ts b/src/extension.ts index 4a40476..5e630d7 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -45,19 +45,19 @@ export function activate(context: vscode.ExtensionContext) { state === vscode.TreeItemCheckboxState.Checked ); - // Update XML edits button text if that setting changed - if (item.settingKey === 'xmlEditsEnabled') { + // Update formatting instructions button text if that setting changed + if (item.settingKey === 'includeFormattingInstructions') { xmlEditsButton.text = prompterTreeProvider.isXmlEditsEnabled() ? - "$(check) XML Edits" : "$(diff-added) XML Edits"; + "$(check) Formatting Instructions" : "$(diff-added) Formatting Instructions"; } } } }); - // Create XML edits toggle button + // Create formatting instructions toggle button const xmlEditsButton = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); - xmlEditsButton.text = "$(diff-added) XML Edits"; - xmlEditsButton.tooltip = "Toggle XML Edits mode"; + xmlEditsButton.text = "$(diff-added) Formatting Instructions"; + xmlEditsButton.tooltip = "Toggle formatting instructions mode"; xmlEditsButton.command = 'prompter.toggleXmlEdits'; xmlEditsButton.show(); diff --git a/src/models/settings.ts b/src/models/settings.ts index 609cfef..6c2805e 100644 --- a/src/models/settings.ts +++ b/src/models/settings.ts @@ -1,15 +1,13 @@ // Settings interface for the Prompter extension export interface PrompterSettings { - xmlEditsEnabled: boolean; - includeLineNumbers: boolean; - includeComments: boolean; + includeFormattingInstructions: boolean; tokenCalculationEnabled: boolean; + includeFileMap: boolean; } // Default settings values export const DEFAULT_SETTINGS: PrompterSettings = { - xmlEditsEnabled: false, - includeLineNumbers: false, - includeComments: true, - tokenCalculationEnabled: true + includeFormattingInstructions: false, + tokenCalculationEnabled: true, + includeFileMap: true }; diff --git a/src/providers/prompterTreeProvider.ts b/src/providers/prompterTreeProvider.ts index 4c1c1a1..e968856 100644 --- a/src/providers/prompterTreeProvider.ts +++ b/src/providers/prompterTreeProvider.ts @@ -129,10 +129,9 @@ export class PrompterTreeProvider implements vscode.TreeDataProvider, settings: PrompterSettings): string { - const xmlParts = ['', '']; + const xmlParts: string[] = []; + + // Include XML formatting instructions if enabled + if (settings.includeFormattingInstructions) { + try { + // Get the workspace root path + const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri?.fsPath || ''; + const formattingInstructionsPath = path.join(workspaceRoot, '..', 'project_management', 'xml_formatting_instructions.xml'); + + if (fs.existsSync(formattingInstructionsPath)) { + const instructions = fs.readFileSync(formattingInstructionsPath, 'utf8'); + xmlParts.push(instructions); + } + } catch (error) { + console.error('Error reading XML formatting instructions:', error); + } + } - // Add files section - xmlParts.push(' '); + // Generate file map section if enabled in settings + if (settings.includeFileMap) { + xmlParts.push(''); + + // Get the workspace root path + const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri?.fsPath || ''; + xmlParts.push(workspaceRoot); + + // Create a tree representation of the files + const fileTree = this.generateFileTree(files, workspaceRoot); + xmlParts.push(fileTree); + xmlParts.push(''); + } + + // Generate file contents section + xmlParts.push(''); + + // Add each file with its content for (const [filePath, { content, tokens }] of files) { const extension = path.extname(filePath); let language = extension.substring(1); // Remove the dot - // Handle special cases + // Handle special cases for language detection if (extension === '.js' || extension === '.jsx') { language = 'javascript'; } else if (extension === '.ts' || extension === '.tsx') { language = 'typescript'; + } else if (extension === '.md') { + language = 'md'; + } else if (extension === '.py') { + language = 'python'; + } else if (extension === '.html') { + language = 'html'; + } else if (extension === '.css') { + language = 'css'; + } else if (extension === '.json') { + language = 'json'; } - xmlParts.push(' '); - xmlParts.push(` ${path.basename(filePath)}`); - xmlParts.push(` ${language}`); - xmlParts.push(` ${tokens}`); + // Use content as is + const formattedContent = content; - // 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'); - } + // Get the workspace root path if not already defined + const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri?.fsPath || ''; - xmlParts.push(` `); - xmlParts.push(' '); - } - xmlParts.push(' '); - - // Add options based on settings - xmlParts.push(' '); - if (settings.includeLineNumbers) { - xmlParts.push(' true'); - } - if (!settings.includeComments) { - xmlParts.push(' true'); + // Add file entry + xmlParts.push(`File: ${this.getRelativePath(filePath, workspaceRoot)}`); + xmlParts.push(`\`\`\`${language}`); + xmlParts.push(formattedContent); + xmlParts.push('\`\`\`'); } + + xmlParts.push(''); + + // Calculate tokens for toast notification but don't include in XML if (settings.tokenCalculationEnabled) { - xmlParts.push(` ${Array.from(files.values()).reduce((sum, { tokens }) => sum + tokens, 0)}`); + const totalTokens = Array.from(files.values()).reduce((sum, { tokens }) => sum + tokens, 0); + // We'll show this in a toast notification but not include it in the XML + vscode.window.showInformationMessage(`Total tokens: ${totalTokens}`); } - xmlParts.push(' '); - - xmlParts.push(''); + return xmlParts.join('\n'); } + + /** + * Generate a tree representation of files + * @param files Map of file paths + * @param rootPath The workspace root path + * @returns String representation of the file tree + */ + private static generateFileTree(files: Map, rootPath: string): string { + // Create a simple tree representation + const treeLines: string[] = []; + + // Group files by directory + const dirMap = new Map(); + + for (const filePath of files.keys()) { + const relativePath = this.getRelativePath(filePath, rootPath); + const dir = path.dirname(relativePath); + + if (!dirMap.has(dir)) { + dirMap.set(dir, []); + } + + dirMap.get(dir)?.push(path.basename(filePath)); + } + + // Sort directories + const sortedDirs = Array.from(dirMap.keys()).sort(); + + // Build the tree + for (let i = 0; i < sortedDirs.length; i++) { + const dir = sortedDirs[i]; + const isLast = i === sortedDirs.length - 1; + const prefix = isLast ? '└── ' : '├── '; + + // Skip root directory + if (dir !== '.') { + treeLines.push(`${prefix}${dir}`); + } + + // Add files + const files = dirMap.get(dir)?.sort() || []; + for (let j = 0; j < files.length; j++) { + const file = files[j]; + const isLastFile = j === files.length - 1; + const filePrefix = dir === '.' ? (isLastFile ? '└── ' : '├── ') : ' ' + (isLastFile ? '└── ' : '├── '); + treeLines.push(`${filePrefix}${file}`); + } + } + + return treeLines.join('\n'); + } + + /** + * Get the path relative to the workspace root + * @param filePath Absolute file path + * @param rootPath Workspace root path + * @returns Relative path + */ + private static getRelativePath(filePath: string, rootPath: string): string { + if (filePath.startsWith(rootPath)) { + const relativePath = filePath.substring(rootPath.length); + return relativePath.startsWith('/') ? relativePath.substring(1) : relativePath; + } + return filePath; + } }