feat: add colored preview for dry-run mode
- Add fatih/color for terminal colors - Show lines to be deleted in red with strikethrough - Show lines to be kept in green - Display line numbers and summary counts - Much more helpful than just showing sed command
This commit is contained in:
@@ -7,7 +7,14 @@
|
|||||||
"Bash(find:*)",
|
"Bash(find:*)",
|
||||||
"Bash(mkdir:*)",
|
"Bash(mkdir:*)",
|
||||||
"Bash(chmod:*)",
|
"Bash(chmod:*)",
|
||||||
"Bash(git add:*)"
|
"Bash(git add:*)",
|
||||||
|
"Bash(git commit:*)",
|
||||||
|
"Bash(git tag:*)",
|
||||||
|
"Bash(git push:*)",
|
||||||
|
"Bash(gh run list:*)",
|
||||||
|
"Bash(gh release view:*)",
|
||||||
|
"Bash(gh repo edit:*)",
|
||||||
|
"Bash(rm:*)"
|
||||||
],
|
],
|
||||||
"deny": []
|
"deny": []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,10 @@ module github.com/carlosarraes/shush
|
|||||||
|
|
||||||
go 1.24.4
|
go 1.24.4
|
||||||
|
|
||||||
require github.com/alecthomas/kong v1.12.0 // indirect
|
require (
|
||||||
|
github.com/alecthomas/kong v1.12.0 // indirect
|
||||||
|
github.com/fatih/color v1.18.0 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,2 +1,13 @@
|
|||||||
github.com/alecthomas/kong v1.12.0 h1:oKd/0fHSdajj5PfGDd3ScvEvpVJf9mT2mb5r9xYadYM=
|
github.com/alecthomas/kong v1.12.0 h1:oKd/0fHSdajj5PfGDd3ScvEvpVJf9mT2mb5r9xYadYM=
|
||||||
github.com/alecthomas/kong v1.12.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
|
github.com/alecthomas/kong v1.12.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
|
||||||
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
|
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
|
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
"github.com/alecthomas/kong"
|
||||||
|
"github.com/fatih/color"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CLI struct {
|
type CLI struct {
|
||||||
@@ -51,7 +54,7 @@ func main() {
|
|||||||
kong.Parse(&cli, kong.Description("Remove comments from source code files"))
|
kong.Parse(&cli, kong.Description("Remove comments from source code files"))
|
||||||
|
|
||||||
if cli.Version {
|
if cli.Version {
|
||||||
fmt.Println("shush version 0.0.1")
|
fmt.Println("shush version 0.0.2")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,13 +90,12 @@ func processFile(cli CLI) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sedCmd := buildSedCommand(language, cli)
|
|
||||||
|
|
||||||
if cli.DryRun {
|
if cli.DryRun {
|
||||||
fmt.Printf("Would execute: %s\n", sedCmd)
|
return showPreview(cli.File, language, cli)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sedCmd := buildSedCommand(language, cli)
|
||||||
|
|
||||||
if cli.Backup {
|
if cli.Backup {
|
||||||
if err := createBackup(cli.File); err != nil {
|
if err := createBackup(cli.File); err != nil {
|
||||||
return fmt.Errorf("failed to create backup: %v", err)
|
return fmt.Errorf("failed to create backup: %v", err)
|
||||||
@@ -227,3 +229,78 @@ func createBackup(filename string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func showPreview(filename string, language Language, cli CLI) error {
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
red := color.New(color.FgRed, color.CrossedOut)
|
||||||
|
green := color.New(color.FgGreen)
|
||||||
|
gray := color.New(color.FgHiBlack)
|
||||||
|
yellow := color.New(color.FgYellow)
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
lineNum := 0
|
||||||
|
deletedCount := 0
|
||||||
|
keptCount := 0
|
||||||
|
|
||||||
|
// Compile regex patterns once
|
||||||
|
var lineRegex, blockStartRegex, blockEndRegex *regexp.Regexp
|
||||||
|
if language.LineComment != "" && !cli.Block {
|
||||||
|
escaped := regexp.QuoteMeta(language.LineComment)
|
||||||
|
lineRegex = regexp.MustCompile(fmt.Sprintf(`^\s*%s|%s.*$`, escaped, escaped))
|
||||||
|
}
|
||||||
|
if language.BlockComment != nil && !cli.Inline {
|
||||||
|
blockStartRegex = regexp.MustCompile(regexp.QuoteMeta(language.BlockComment.Start))
|
||||||
|
blockEndRegex = regexp.MustCompile(regexp.QuoteMeta(language.BlockComment.End))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\n%s %s\n\n", yellow.Sprint("Preview:"), filename)
|
||||||
|
|
||||||
|
inBlockComment := false
|
||||||
|
for scanner.Scan() {
|
||||||
|
lineNum++
|
||||||
|
line := scanner.Text()
|
||||||
|
shouldDelete := false
|
||||||
|
|
||||||
|
// Check if line should be deleted
|
||||||
|
if inBlockComment && blockEndRegex != nil {
|
||||||
|
shouldDelete = true
|
||||||
|
if blockEndRegex.MatchString(line) {
|
||||||
|
inBlockComment = false
|
||||||
|
}
|
||||||
|
} else if blockStartRegex != nil && blockStartRegex.MatchString(line) {
|
||||||
|
shouldDelete = true
|
||||||
|
if !blockEndRegex.MatchString(line) {
|
||||||
|
inBlockComment = true
|
||||||
|
}
|
||||||
|
} else if lineRegex != nil && lineRegex.MatchString(line) {
|
||||||
|
shouldDelete = true
|
||||||
|
} else if strings.TrimSpace(line) == "" {
|
||||||
|
shouldDelete = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the line with appropriate formatting
|
||||||
|
lineNumStr := gray.Sprintf("%4d", lineNum)
|
||||||
|
if shouldDelete {
|
||||||
|
deletedCount++
|
||||||
|
fmt.Printf("%s %s %s\n", lineNumStr, red.Sprint("-"), red.Sprint(line))
|
||||||
|
} else {
|
||||||
|
keptCount++
|
||||||
|
fmt.Printf("%s %s %s\n", lineNumStr, green.Sprint(" "), line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\n%s\n", strings.Repeat("-", 50))
|
||||||
|
fmt.Printf("%s %d lines would be removed\n", red.Sprint("✗"), deletedCount)
|
||||||
|
fmt.Printf("%s %d lines would be kept\n\n", green.Sprint("✓"), keptCount)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user