Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions examples/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module github.com/aymanbagabas/go-udiff/cmd

go 1.23.0

replace github.com/aymanbagabas/go-udiff => ./..

require (
github.com/aymanbagabas/go-udiff v0.3.1
github.com/mattn/go-isatty v0.0.20
github.com/spf13/pflag v1.0.5
)

require golang.org/x/sys v0.6.0 // indirect
6 changes: 6 additions & 0 deletions examples/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
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=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
155 changes: 155 additions & 0 deletions examples/udiff/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package main

import (
"fmt"
"io"
"os"
"strings"

"github.com/aymanbagabas/go-udiff"
"github.com/mattn/go-isatty"
"github.com/spf13/pflag"
)

const (
redSeq = "\033[31m"
greenSeq = "\033[32m"
resetSeq = "\033[0m"
)

var (
contextLines int
color string
)

func init() {
pflag.Usage = usage
pflag.IntVarP(&contextLines, "context", "C", udiff.DefaultContextLines, "number of context lines")
pflag.StringVarP(&color, "color", "", "auto", "colorize the output; can be 'always', 'never', or 'auto'")
}

func usage() {
fmt.Fprintf(os.Stderr, "Usage: %s [options] file1 file2\n", os.Args[0])
pflag.PrintDefaults()
}

func main() {
pflag.Parse()
args := pflag.Args()
if len(args) != 2 {
pflag.Usage()
os.Exit(1)
}

var colorize bool
switch strings.ToLower(color) {
case "always":
colorize = true
case "auto":
colorize = isatty.IsTerminal(os.Stdout.Fd())
}

f1, err := os.Open(args[0])
if err != nil {
fmt.Fprintf(os.Stderr, "couldn't open file: %s\n", err)
os.Exit(1)
}

defer f1.Close()
f2, err := os.Open(args[1])
if err != nil {
fmt.Fprintf(os.Stderr, "couldn't open file: %s\n", err)
os.Exit(1)
}

defer f2.Close()
s1, err := io.ReadAll(f1)
if err != nil {
fmt.Fprintf(os.Stderr, "couldn't read file: %s\n", err)
os.Exit(1)
}

s2, err := io.ReadAll(f2)
if err != nil {
fmt.Fprintf(os.Stderr, "couldn't read file: %s\n", err)
os.Exit(1)
}

edits := udiff.Strings(string(s1), string(s2))
u, err := udiff.ToUnifiedDiff(f1.Name(), f2.Name(), string(s1), edits, contextLines)
if err != nil {
fmt.Fprintf(os.Stderr, "couldn't generate diff: %s\n", err)
os.Exit(1)
}

fmt.Println(toString(u, colorize))
}

// String converts a unified diff to the standard textual form for that diff.
// The output of this function can be passed to tools like patch.
func toString(u udiff.UnifiedDiff, colorize bool) string {
if len(u.Hunks) == 0 {
return ""
}
b := new(strings.Builder)
fmt.Fprintf(b, "--- %s\n", u.From)
fmt.Fprintf(b, "+++ %s\n", u.To)
for _, hunk := range u.Hunks {
fromCount, toCount := 0, 0
for _, l := range hunk.Lines {
switch l.Kind {
case udiff.Delete:
fromCount++
case udiff.Insert:
toCount++
default:
fromCount++
toCount++
}
}
fmt.Fprint(b, "@@")
if fromCount > 1 {
fmt.Fprintf(b, " -%d,%d", hunk.FromLine, fromCount)
} else if hunk.FromLine == 1 && fromCount == 0 {
// Match odd GNU diff -u behavior adding to empty file.
fmt.Fprintf(b, " -0,0")
} else {
fmt.Fprintf(b, " -%d", hunk.FromLine)
}
if toCount > 1 {
fmt.Fprintf(b, " +%d,%d", hunk.ToLine, toCount)
} else if hunk.ToLine == 1 && toCount == 0 {
// Match odd GNU diff -u behavior adding to empty file.
fmt.Fprintf(b, " +0,0")
} else {
fmt.Fprintf(b, " +%d", hunk.ToLine)
}
fmt.Fprint(b, " @@\n")
for _, l := range hunk.Lines {
switch l.Kind {
case udiff.Delete:
if colorize {
fmt.Fprint(b, redSeq)
}
fmt.Fprintf(b, "-%s", l.Content)
if colorize {
fmt.Fprint(b, resetSeq)
}
case udiff.Insert:
if colorize {
fmt.Fprint(b, greenSeq)
}
fmt.Fprintf(b, "+%s", l.Content)
if colorize {
fmt.Fprint(b, resetSeq)
}
default:
fmt.Fprintf(b, " %s", l.Content)
}
if !strings.HasSuffix(l.Content, "\n") {
fmt.Fprintf(b, "\n\\ No newline at end of file\n")
}
}
}
return b.String()
}
Loading