pax_global_header00006660000000000000000000000064140301605560014512gustar00rootroot0000000000000052 comment=08334dcf99493b15a241d399500769139962c0e2 golang-github-aryann-difflib-0.0~git20210328.ff5ff6d/000077500000000000000000000000001403016055600217345ustar00rootroot00000000000000golang-github-aryann-difflib-0.0~git20210328.ff5ff6d/LICENSE000066400000000000000000000020411403016055600227360ustar00rootroot00000000000000Copyright (c) 2016 Aryan Naraghi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. golang-github-aryann-difflib-0.0~git20210328.ff5ff6d/README.md000066400000000000000000000022211403016055600232100ustar00rootroot00000000000000[![GoDoc](https://godoc.org/github.com/aryann/difflib?status.svg)](http://godoc.org/github.com/aryann/difflib) difflib ======= difflib is a simple library written in [Go](http://golang.org/) for diffing two sequences of text. Installing ---------- To install, issue: go get github.com/aryann/difflib Using ----- To start using difflib, create a new file in your workspace and import difflib: import ( ... "fmt" "github.com/aryann/difflib" ... ) Then call either `difflib.Diff` or `difflib.HTMLDiff`: fmt.Println(difflib.HTMLDiff([]string{"one", "two", "three"}, []string{"two", "four", "three"})) If you'd like more control over the output, see how the function `HTMLDiff` relies on `Diff` in difflib.go. Running the Demo ---------------- There is a demo application in the difflib_demo directory. To run it, navigate to your `$GOPATH` and run: go run src/github.com/aryann/difflib/difflib_server/difflib_demo.go Where `` and `` are two text files you'd like to diff. The demo will launch a web server that will contain a table of the diff results. golang-github-aryann-difflib-0.0~git20210328.ff5ff6d/difflib.go000066400000000000000000000120411403016055600236600ustar00rootroot00000000000000// Package difflib provides functionality for computing the difference // between two sequences of strings. package difflib import ( "bytes" "fmt" "math" ) // DeltaType describes the relationship of elements in two // sequences. The following table provides a summary: // // Constant Code Meaning // ---------- ------ --------------------------------------- // Common " " The element occurs in both sequences. // LeftOnly "-" The element is unique to sequence 1. // RightOnly "+" The element is unique to sequence 2. type DeltaType int const ( Common DeltaType = iota LeftOnly RightOnly ) // String returns a string representation for DeltaType. func (t DeltaType) String() string { switch t { case Common: return " " case LeftOnly: return "-" case RightOnly: return "+" } return "?" } type DiffRecord struct { Payload string Delta DeltaType } // String returns a string representation of d. The string is a // concatenation of the delta type and the payload. func (d DiffRecord) String() string { return fmt.Sprintf("%s %s", d.Delta, d.Payload) } // Diff returns the result of diffing the seq1 and seq2. func Diff(seq1, seq2 []string) (diff []DiffRecord) { // Trims any common elements at the heads and tails of the // sequences before running the diff algorithm. This is an // optimization. start, end := numEqualStartAndEndElements(seq1, seq2) for _, content := range seq1[:start] { diff = append(diff, DiffRecord{content, Common}) } diffRes := compute(seq1[start:len(seq1)-end], seq2[start:len(seq2)-end]) diff = append(diff, diffRes...) for _, content := range seq1[len(seq1)-end:] { diff = append(diff, DiffRecord{content, Common}) } return } // HTMLDiff returns the results of diffing seq1 and seq2 as an HTML // string. The resulting HTML is a table without the opening and // closing table tags. Each table row represents a DiffRecord. The // first and last columns contain the "line numbers" for seq1 and // seq2, respectively (the function assumes that seq1 and seq2 // represent the lines in a file). The second and third columns // contain the actual file contents. // // The cells that contain line numbers are decorated with the class // "line-num". The cells that contain deleted elements are decorated // with "deleted" and the cells that contain added elements are // decorated with "added". func HTMLDiff(seq1, seq2 []string) string { buf := bytes.NewBufferString("") i, j := 0, 0 for _, d := range Diff(seq1, seq2) { buf.WriteString(``) if d.Delta == Common || d.Delta == LeftOnly { i++ fmt.Fprintf(buf, "%d
%s
", d.Payload) } else { buf.WriteString("") } buf.WriteString("
%s
%d`, d.Payload, j) } else { buf.WriteString(`>`) } buf.WriteString("\n") } return buf.String() } // numEqualStartAndEndElements returns the number of elements a and b // have in common from the beginning and from the end. If a and b are // equal, start will equal len(a) == len(b) and end will be zero. func numEqualStartAndEndElements(seq1, seq2 []string) (start, end int) { for start < len(seq1) && start < len(seq2) && seq1[start] == seq2[start] { start++ } i, j := len(seq1)-1, len(seq2)-1 for i > start && j > start && seq1[i] == seq2[j] { i-- j-- end++ } return } // intMatrix returns a 2-dimensional slice of ints with the given // number of rows and columns. func intMatrix(rows, cols int) [][]int { matrix := make([][]int, rows) for i := 0; i < rows; i++ { matrix[i] = make([]int, cols) } return matrix } // longestCommonSubsequenceMatrix returns the table that results from // applying the dynamic programming approach for finding the longest // common subsequence of seq1 and seq2. func longestCommonSubsequenceMatrix(seq1, seq2 []string) [][]int { matrix := intMatrix(len(seq1)+1, len(seq2)+1) for i := 1; i < len(matrix); i++ { for j := 1; j < len(matrix[i]); j++ { if seq1[len(seq1)-i] == seq2[len(seq2)-j] { matrix[i][j] = matrix[i-1][j-1] + 1 } else { matrix[i][j] = int(math.Max(float64(matrix[i-1][j]), float64(matrix[i][j-1]))) } } } return matrix } // compute is the unexported helper for Diff that returns the results of // diffing left and right. func compute(seq1, seq2 []string) (diff []DiffRecord) { matrix := longestCommonSubsequenceMatrix(seq1, seq2) i, j := len(seq1), len(seq2) for i > 0 || j > 0 { if i > 0 && matrix[i][j] == matrix[i-1][j] { diff = append(diff, DiffRecord{seq1[len(seq1)-i], LeftOnly}) i-- } else if j > 0 && matrix[i][j] == matrix[i][j-1] { diff = append(diff, DiffRecord{seq2[len(seq2)-j], RightOnly}) j-- } else if i > 0 && j > 0 { diff = append(diff, DiffRecord{seq1[len(seq1)-i], Common}) i-- j-- } } return } golang-github-aryann-difflib-0.0~git20210328.ff5ff6d/difflib_server/000077500000000000000000000000001403016055600247215ustar00rootroot00000000000000golang-github-aryann-difflib-0.0~git20210328.ff5ff6d/difflib_server/difflib_demo.go000066400000000000000000000041271403016055600276570ustar00rootroot00000000000000// A demo for difflib. This program accepts the paths to two files and // launches a web server at port 8080 that serves the diff results. package main import ( "fmt" "github.com/aryann/difflib" "html" "html/template" "io/ioutil" "net/http" "os" "strings" ) var hostPort = "localhost:8080" var templateString = ` difflib results {{.Diff}}
{{.Filename1}} {{.Filename2}}
` func main() { if len(os.Args) != 3 { fmt.Fprintf(os.Stderr, "USAGE: %s \n", os.Args[0]) os.Exit(1) } http.HandleFunc("/", diffHandler(os.Args[1], os.Args[2])) fmt.Printf("Starting server at %s.\n", hostPort) err := http.ListenAndServe(hostPort, nil) if err != nil { panic(err) } } // diffHandler returns an http.HandlerFunc that serves the diff of the // two given files. func diffHandler(filename1, filename2 string) http.HandlerFunc { diff := difflib.HTMLDiff(fileToLines(filename1), fileToLines(filename2)) tmpl, _ := template.New("diffTemplate").Parse(templateString) return func(w http.ResponseWriter, r *http.Request) { err := tmpl.Execute(w, map[string]interface{}{ "Diff": template.HTML(diff), "Filename1": filename1, "Filename2": filename2, }) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } } // filesToLines takes a path to a file and returns a string array of // the lines in the file. Any HTML in the file is escaped. func fileToLines(filename string) []string { contents, _ := ioutil.ReadFile(filename) return strings.Split(html.EscapeString(string(contents)), "\n") } golang-github-aryann-difflib-0.0~git20210328.ff5ff6d/difflib_test.go000066400000000000000000000150401403016055600247210ustar00rootroot00000000000000package difflib import ( "reflect" "strings" "testing" ) var lcsTests = []struct { seq1 string seq2 string lcs int }{ {"", "", 0}, {"abc", "abc", 3}, {"mzjawxu", "xmjyauz", 4}, {"human", "chimpanzee", 4}, {"Hello, world!", "Hello, world!", 13}, {"Hello, world!", "H e l l o , w o r l d !", 13}, } func TestLongestCommonSubsequenceMatrix(t *testing.T) { for i, test := range lcsTests { seq1 := strings.Split(test.seq1, "") seq2 := strings.Split(test.seq2, "") matrix := longestCommonSubsequenceMatrix(seq1, seq2) lcs := matrix[len(matrix)-1][len(matrix[0])-1] // Grabs the lower, right value. if lcs != test.lcs { t.Errorf("%d. longestCommonSubsequence(%v, %v)[last][last] => %d, expected %d", i, seq1, seq2, lcs, test.lcs) } } } var numEqualStartAndEndElementsTests = []struct { seq1 string seq2 string start int end int }{ {"", "", 0, 0}, {"abc", "", 0, 0}, {"", "abc", 0, 0}, {"abc", "abc", 3, 0}, {"abhelloc", "abbyec", 2, 1}, {"abchello", "abcbye", 3, 0}, {"helloabc", "byeabc", 0, 3}, } func TestNumEqualStartAndEndElements(t *testing.T) { for i, test := range numEqualStartAndEndElementsTests { seq1 := strings.Split(test.seq1, "") seq2 := strings.Split(test.seq2, "") start, end := numEqualStartAndEndElements(seq1, seq2) if start != test.start || end != test.end { t.Errorf("%d. numEqualStartAndEndElements(%v, %v) => (%d, %d), expected (%d, %d)", i, seq1, seq2, start, end, test.start, test.end) } } } var diffTests = []struct { Seq1 string Seq2 string Diff []DiffRecord HtmlDiff string }{ { "", "", []DiffRecord{ {"", Common}, }, `1
1
`,
	},

	{
		"same",
		"same",
		[]DiffRecord{
			{"same", Common},
		},
		`1
same
same
1 `, }, { `one two three `, `one two three `, []DiffRecord{ {"one", Common}, {"two", Common}, {"three", Common}, {"", Common}, }, `1
one
one
1 2
two
two
2 3
three
three
3 4
4
`,
	},

	{
		`one
two
three
`,
		`one
five
three
`,
		[]DiffRecord{
			{"one", Common},
			{"two", LeftOnly},
			{"five", RightOnly},
			{"three", Common},
			{"", Common},
		},
		`1
one
one
1 2
two
five
2 3
three
three
3 4
4
`,
	},

	{
		`Beethoven
Bach
Mozart
Chopin
`,
		`Beethoven
Bach
Brahms
Chopin
Liszt
Wagner
`,

		[]DiffRecord{
			{"Beethoven", Common},
			{"Bach", Common},
			{"Mozart", LeftOnly},
			{"Brahms", RightOnly},
			{"Chopin", Common},
			{"Liszt", RightOnly},
			{"Wagner", RightOnly},
			{"", Common},
		},
		`1
Beethoven
Beethoven
1 2
Bach
Bach
2 3
Mozart
Brahms
3 4
Chopin
Chopin
4
Liszt
5
Wagner
6 5
7
`,
	},

	{
		`adagio
vivace
staccato legato
presto
lento
`,
		`adagio adagio
staccato
staccato legato
staccato
legato
allegro
`,
		[]DiffRecord{
			{"adagio", LeftOnly},
			{"vivace", LeftOnly},
			{"adagio adagio", RightOnly},
			{"staccato", RightOnly},
			{"staccato legato", Common},
			{"presto", LeftOnly},
			{"lento", LeftOnly},
			{"staccato", RightOnly},
			{"legato", RightOnly},
			{"allegro", RightOnly},
			{"", Common},
		},
		`1
adagio
2
vivace
adagio adagio
1
staccato
2 3
staccato legato
staccato legato
3 4
presto
5
lento
staccato
4
legato
5
allegro
6 6
7
`,
	},
}

func TestDiff(t *testing.T) {
	for i, test := range diffTests {
		seq1 := strings.Split(test.Seq1, "\n")
		seq2 := strings.Split(test.Seq2, "\n")

		diff := Diff(seq1, seq2)
		if !reflect.DeepEqual(diff, test.Diff) {
			t.Errorf("%d. Diff(%v, %v) => %v, expected %v",
				i, seq1, seq2, diff, test.Diff)
		}

		htmlDiff := HTMLDiff(seq1, seq2)
		if htmlDiff != test.HtmlDiff {
			t.Errorf("%d. HtmlDiff(%v, %v) => %v, expected %v",
				i, seq1, seq2, htmlDiff, test.HtmlDiff)
		}

	}
}