preview_changes_enhanced
Preview code changes in multiple formats like unified, side-by-side, stat, or word-diff. Control context lines, ignore whitespace, filter by file pattern, and set working directory.
Instructions
Enhanced change preview with multiple format options
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | Preview format | |
| contextLines | No | Number of context lines | |
| ignoreWhitespace | No | Ignore whitespace changes | |
| filePattern | No | File pattern filter | |
| cwd | No | Working directory |
Implementation Reference
- src/services/GitService.ts:1410-1598 (handler)The main handler function for 'preview_changes_enhanced'. Accepts options: format, contextLines, ignoreWhitespace, filePattern, cwd. Checks git repo, retrieves staged/unstaged diffs (with optional file pattern filtering), builds an enhanced preview output with summary stats.
async previewChangesEnhanced(options: { format?: 'unified' | 'side-by-side' | 'stat' | 'word-diff'; contextLines?: number; ignoreWhitespace?: boolean; filePattern?: string; cwd?: string; } = {}): Promise<ToolResult> { try { const { format = 'unified', contextLines = 3, ignoreWhitespace = false, filePattern, cwd } = options; const workingDir = cwd || this.workspaceService.getCurrentWorkspace(); // Check if we're in a git repository first const gitCheckResult = await this.gitCommand(['rev-parse', '--git-dir'], workingDir); if (gitCheckResult.isError) { return { isError: true, content: [{ type: 'text', text: `Failed to preview changes: ${gitCheckResult.content[0]?.text || 'Not a git repository'}` }] }; } let output = `Change Preview (${format} format):\n\n`; // Add format-specific headers and options if (format === 'side-by-side') { output += 'Side-by-side comparison:\n\n'; } else if (ignoreWhitespace) { output += 'Ignoring whitespace changes:\n\n'; } else if (filePattern) { output += `File Pattern: ${filePattern}\n\n`; } output += 'Enhanced Change Preview:\n\n'; // Get unstaged changes const unstagedOptions: GitDiffOptions = { staged: false, format, contextLines, ignoreWhitespace, cwd: workingDir }; // Get staged changes const stagedOptions: GitDiffOptions = { staged: true, format, contextLines, ignoreWhitespace, cwd: workingDir }; // Apply file pattern filtering if specified if (filePattern) { // Get list of files matching pattern first const statusResult = await this.gitStatus({ cwd: workingDir }); if (!statusResult.isError && statusResult.content[0]?.text) { const statusLines = statusResult.content[0].text.split('\n').filter(line => line.trim()); const matchingFiles = statusLines .map(line => line.substring(2).trim()) // Remove git status prefix .filter(filename => { // Simple glob matching for *.ext pattern if (filePattern.startsWith('*.')) { const ext = filePattern.substring(2); return filename.endsWith(ext); } // For other patterns, use simple includes for now return filename.includes(filePattern.replace('*', '')); }); // If we have matching files, process them individually if (matchingFiles.length > 0) { let unstagedChanges = ''; let stagedChanges = ''; for (const file of matchingFiles) { const unstagedFileResult = await this.enhancedGitDiff({ ...unstagedOptions, file }); const stagedFileResult = await this.enhancedGitDiff({ ...stagedOptions, file }); if (!unstagedFileResult.isError && unstagedFileResult.content[0]?.text?.trim() && !unstagedFileResult.content[0].text.includes('No changes found')) { unstagedChanges += unstagedFileResult.content[0].text + '\n'; } if (!stagedFileResult.isError && stagedFileResult.content[0]?.text?.trim() && !stagedFileResult.content[0].text.includes('No changes found')) { stagedChanges += stagedFileResult.content[0].text + '\n'; } } // Display filtered results if (stagedChanges) { output += 'Staged Changes:\n'; output += stagedChanges; output += '\n'; } if (unstagedChanges) { output += 'Unstaged Changes:\n'; output += unstagedChanges; output += '\n'; } } else { output += `No files matching pattern "${filePattern}" have changes.\n`; } } } else { // No file pattern filtering - get all changes const unstagedResult = await this.enhancedGitDiff(unstagedOptions); const stagedResult = await this.enhancedGitDiff(stagedOptions); // Display staged changes if (!stagedResult.isError && stagedResult.content[0]?.text?.trim() && !stagedResult.content[0].text.includes('Command completed successfully') && !stagedResult.content[0].text.includes('No changes found')) { output += 'Staged Changes:\n'; output += stagedResult.content[0].text; output += '\n\n'; } // Display unstaged changes if (!unstagedResult.isError && unstagedResult.content[0]?.text?.trim() && !unstagedResult.content[0].text.includes('Command completed successfully') && !unstagedResult.content[0].text.includes('No changes found')) { output += 'Unstaged Changes:\n'; output += unstagedResult.content[0].text; output += '\n\n'; } } // Get stats for both const stagedStats = await this.getDiffStats({ staged: true, cwd: workingDir }); const unstagedStats = await this.getDiffStats({ staged: false, cwd: workingDir }); output += '=== SUMMARY ===\n'; if (!stagedStats.isError && stagedStats.content[0]?._meta) { const meta = stagedStats.content[0]._meta as any; if (meta.filesChanged > 0) { output += `Staged: ${meta.filesChanged} files, +${meta.insertions}/-${meta.deletions} lines\n`; } } if (!unstagedStats.isError && unstagedStats.content[0]?._meta) { const meta = unstagedStats.content[0]._meta as any; if (meta.filesChanged > 0) { output += `Unstaged: ${meta.filesChanged} files, +${meta.insertions}/-${meta.deletions} lines\n`; } } if (!output.includes('STAGED CHANGES') && !output.includes('UNSTAGED CHANGES')) { output += 'No changes to preview'; } return { content: [{ type: 'text', text: output, _meta: { format, stagedStats: stagedStats.content[0]?._meta, unstagedStats: unstagedStats.content[0]?._meta } }] }; } catch (error) { return { isError: true, content: [{ type: 'text', text: `Enhanced preview failed: ${error instanceof Error ? error.message : String(error)}` }] }; - src/toolDefinitions.ts:824-843 (schema)Input schema definition for 'preview_changes_enhanced' tool. Defines properties: format (enum: unified, side-by-side, stat, word-diff), contextLines, ignoreWhitespace, filePattern, cwd.
{ name: 'preview_changes_enhanced', description: 'Enhanced change preview with multiple format options', inputSchema: { type: 'object', properties: { format: { type: 'string', enum: ['unified', 'side-by-side', 'stat', 'word-diff'], description: 'Preview format' }, contextLines: { type: 'number', description: 'Number of context lines' }, ignoreWhitespace: { type: 'boolean', description: 'Ignore whitespace changes' }, filePattern: { type: 'string', description: 'File pattern filter' }, cwd: { type: 'string', description: 'Working directory' } } } }, // Enhanced File Operations & Diff Management - src/index.ts:450-451 (registration)Registration/case branch in index.ts that routes 'preview_changes_enhanced' to gitService.previewChangesEnhanced(args).
case 'preview_changes_enhanced': return await this.gitService.previewChangesEnhanced(args); - src/services/GitService.ts:1454-1469 (helper)Helper calls to getDiffStats and enhancedGitDiff used within the previewChangesEnhanced handler to retrieve and format diff data for both staged and unstaged changes.
const unstagedOptions: GitDiffOptions = { staged: false, format, contextLines, ignoreWhitespace, cwd: workingDir }; // Get staged changes const stagedOptions: GitDiffOptions = { staged: true, format, contextLines, ignoreWhitespace, cwd: workingDir };