feat(processor): integrate config-based comment preservation in git mode

- Load .shush.toml configuration for pattern-based comment preservation
- Add preserved comment tracking and display in dry-run output
- Enhance preview with cyan 'P' indicators for preserved comments
- Add preserved count to summary statistics and totals
- Support both line and block comment preservation based on patterns
This commit is contained in:
carraes
2025-07-05 23:43:59 -03:00
parent f53439ddda
commit 20135b3a7f
+91 -33
View File
@@ -6,19 +6,19 @@ import (
"os"
"strings"
"github.com/carlosarraes/shush/internal/config"
"github.com/carlosarraes/shush/internal/git"
"github.com/carlosarraes/shush/internal/types"
"github.com/fatih/color"
)
type GitTotals struct {
FilesProcessed int
TotalChanged int
TotalKept int
TotalPreserved int
}
func (p *Processor) processGitChanges() error {
gitStatus, err := git.DetectRepo()
@@ -34,7 +34,6 @@ func (p *Processor) processGitChanges() error {
fmt.Printf("Git repository detected: %s\n", gitStatus.RootDir)
}
var changes []git.FileChange
switch {
case p.cli.ChangesOnly:
@@ -59,21 +58,28 @@ func (p *Processor) processGitChanges() error {
return nil
}
supportedChanges := make([]git.FileChange, 0, len(changes))
for _, change := range changes {
if IsSupportedFile(change.Path) {
supportedChanges = append(supportedChanges, change)
} else if p.cli.Verbose {
fmt.Printf("Skipping unsupported file: %s\n", change.Path)
}
}
if len(supportedChanges) == 0 {
fmt.Println("No supported files found to process")
return nil
}
if p.cli.Verbose {
fmt.Printf("Found %d files with changes to process\n", len(changes))
fmt.Printf("Found %d supported files with changes to process\n", len(supportedChanges))
}
totals := &GitTotals{}
for _, change := range changes {
if !IsSupportedFile(change.Path) {
if p.cli.Verbose {
fmt.Printf("Skipping unsupported file: %s\n", change.Path)
}
continue
}
for _, change := range supportedChanges {
if p.cli.Verbose {
fmt.Printf("Processing: %s\n", change.Path)
@@ -93,7 +99,6 @@ func (p *Processor) processGitChanges() error {
totals.FilesProcessed++
}
if p.cli.DryRun && totals.FilesProcessed > 0 {
p.showGitTotals(totals)
}
@@ -101,13 +106,19 @@ func (p *Processor) processGitChanges() error {
return nil
}
func (p *Processor) processFileWithLineRanges(filename string, lineRanges []git.LineRange) error {
language, err := DetectLanguage(filename)
if err != nil {
return err
}
cfg, _, err := config.Load()
if err != nil && p.cli.Verbose {
fmt.Printf("Warning: failed to load config, using defaults: %v\n", err)
cfg = config.Default()
}
if p.cli.Verbose {
fmt.Printf("Processing %s (language: %s)\n", filename, GetLanguageName(filename))
if len(lineRanges) == 0 {
@@ -117,9 +128,6 @@ func (p *Processor) processFileWithLineRanges(filename string, lineRanges []git.
}
}
file, err := os.Open(filename)
if err != nil {
return err
@@ -136,7 +144,6 @@ func (p *Processor) processFileWithLineRanges(filename string, lineRanges []git.
return err
}
if p.cli.Backup {
if err := p.createBackup(filename); err != nil {
return fmt.Errorf("failed to create backup: %v", err)
@@ -146,8 +153,7 @@ func (p *Processor) processFileWithLineRanges(filename string, lineRanges []git.
}
}
processEntireFile := len(lineRanges) == 0
processEntireFile := len(lineRanges) == 0
modified := false
for i, line := range lines {
@@ -155,7 +161,7 @@ processEntireFile := len(lineRanges) == 0
shouldProcess := processEntireFile || git.IsInLineRanges(lineNum, lineRanges)
if shouldProcess {
newLine := p.removeCommentsFromLine(line, language)
newLine := p.removeCommentsFromLine(line, language, cfg)
if newLine != line {
lines[i] = newLine
modified = true
@@ -163,7 +169,6 @@ processEntireFile := len(lineRanges) == 0
}
}
if modified {
outFile, err := os.Create(filename)
if err != nil {
@@ -187,24 +192,28 @@ processEntireFile := len(lineRanges) == 0
return nil
}
func (p *Processor) removeCommentsFromLine(line string, language types.Language) string {
func (p *Processor) removeCommentsFromLine(line string, language types.Language, cfg *config.Config) string {
result := line
hasChanges := false
if !p.cli.Block && language.LineComment != "" {
if idx := strings.Index(result, language.LineComment); idx != -1 {
comment := strings.TrimSpace(result[idx:])
if cfg.ShouldPreserveComment(comment) {
return line
}
result = result[:idx]
hasChanges = true
}
}
if !p.cli.Inline && language.BlockComment != nil {
startComment := language.BlockComment.Start
endComment := language.BlockComment.End
@@ -217,18 +226,28 @@ func (p *Processor) removeCommentsFromLine(line string, language types.Language)
endIdx := strings.Index(result[startIdx:], endComment)
if endIdx == -1 {
comment := strings.TrimSpace(result[startIdx:])
if cfg.ShouldPreserveComment(comment) {
return line
}
result = result[:startIdx]
hasChanges = true
break
}
blockComment := strings.TrimSpace(result[startIdx:startIdx+endIdx+len(endComment)])
if cfg.ShouldPreserveComment(blockComment) {
return line
}
endIdx += startIdx + len(endComment)
result = result[:startIdx] + result[endIdx:]
hasChanges = true
}
}
if hasChanges {
result = strings.TrimSpace(result)
}
@@ -236,13 +255,18 @@ func (p *Processor) removeCommentsFromLine(line string, language types.Language)
return result
}
func (p *Processor) showGitPreviewWithTotals(filename string, lineRanges []git.LineRange, totals *GitTotals) error {
language, err := DetectLanguage(filename)
if err != nil {
return err
}
cfg, _, err := config.Load()
if err != nil {
cfg = config.Default()
}
file, err := os.Open(filename)
if err != nil {
return err
@@ -267,6 +291,7 @@ func (p *Processor) showGitPreviewWithTotals(filename string, lineRanges []git.L
lineNum := 0
keptCount := 0
changedCount := 0
preservedCount := 0
processEntireFile := len(lineRanges) == 0
@@ -278,17 +303,25 @@ func (p *Processor) showGitPreviewWithTotals(filename string, lineRanges []git.L
lineNumStr := gray.Sprintf("%4d", lineNum)
if shouldProcess {
newLine := p.removeCommentsFromLine(line, language)
newLine := p.removeCommentsFromLine(line, language, cfg)
if newLine != line {
changedCount++
fmt.Printf("%s %s %s\n", lineNumStr, red.Sprint("~"), red.Sprint(line))
if strings.TrimSpace(newLine) != "" {
fmt.Printf("%s %s %s\n", lineNumStr, green.Sprint("+"), green.Sprint(newLine))
}
} else {
// Check if this line has comments that were preserved
hasComment := p.lineHasComment(line, language)
if hasComment {
preservedCount++
cyan := color.New(color.FgCyan)
fmt.Printf("%s %s %s\n", lineNumStr, cyan.Sprint("P"), line)
} else {
keptCount++
fmt.Printf("%s %s %s\n", lineNumStr, green.Sprint(" "), line)
}
}
} else {
keptCount++
fmt.Printf("%s %s %s\n", lineNumStr, gray.Sprint(" "), gray.Sprint(line))
@@ -301,20 +334,42 @@ func (p *Processor) showGitPreviewWithTotals(filename string, lineRanges []git.L
fmt.Printf("\n%s\n", strings.Repeat("-", 50))
fmt.Printf("%s %d lines would be changed\n", yellow.Sprint("~"), changedCount)
fmt.Printf("%s %d lines would be kept\n\n", green.Sprint("✓"), keptCount)
fmt.Printf("%s %d lines would be kept\n", green.Sprint("✓"), keptCount)
if preservedCount > 0 {
cyan := color.New(color.FgCyan)
fmt.Printf("%s %d comments would be preserved\n", cyan.Sprint("P"), preservedCount)
}
fmt.Println()
totals.TotalChanged += changedCount
totals.TotalKept += keptCount
totals.TotalPreserved += preservedCount
return nil
}
// lineHasComment checks if a line contains comments
func (p *Processor) lineHasComment(line string, language types.Language) bool {
// Check for line comments
if language.LineComment != "" && strings.Contains(line, language.LineComment) {
return true
}
// Check for block comments
if language.BlockComment != nil {
if strings.Contains(line, language.BlockComment.Start) || strings.Contains(line, language.BlockComment.End) {
return true
}
}
return false
}
func (p *Processor) showGitTotals(totals *GitTotals) {
yellow := color.New(color.FgYellow)
green := color.New(color.FgGreen)
blue := color.New(color.FgBlue)
cyan := color.New(color.FgCyan)
fmt.Printf("\n%s\n", strings.Repeat("=", 60))
fmt.Printf("%s\n", blue.Sprint("GIT PROCESSING TOTALS"))
@@ -322,5 +377,8 @@ func (p *Processor) showGitTotals(totals *GitTotals) {
fmt.Printf("%s %d files processed\n", blue.Sprint("📁"), totals.FilesProcessed)
fmt.Printf("%s %d lines would be changed\n", yellow.Sprint("~"), totals.TotalChanged)
fmt.Printf("%s %d lines would be kept\n", green.Sprint("✓"), totals.TotalKept)
if totals.TotalPreserved > 0 {
fmt.Printf("%s %d comments would be preserved\n", cyan.Sprint("P"), totals.TotalPreserved)
}
fmt.Printf("%s\n", strings.Repeat("=", 60))
}