diffing 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +3 -3
- data/LICENSE.txt +1 -1
- data/README.md +107 -1
- data/lib/diffing.rb +3 -2
- data/lib/diffing/diff.rb +104 -101
- data/lib/diffing/formats/ascii.rb +33 -33
- data/lib/diffing/formats/html.rb +33 -0
- data/lib/diffing/part.rb +31 -31
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00a7b9d972e0846119c0771badcf7f95b7caf1d3
|
4
|
+
data.tar.gz: 5174c797bcb153d30fb75e1caa22cb909e0d0736
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60aaebb3b18e13ede7385c6979081b0a118d2c2d5c1efb78f67d71b44ef77c84cd8f66e1f61da2618b767884f66a92ad8589ad90f7379cd22e8ab1d68f5a8942
|
7
|
+
data.tar.gz: 40bc19b32d599b8c5c51f38b37a94e0883526a13ab1c9c7ebd689ab1e252de3cd60e0f189b03dd5697aa2f14307d160a75064db0a71ac604e2283a64f08a2017
|
data/Gemfile
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
from 'https://rubygems.org'
|
2
|
-
|
3
|
-
gemspec
|
1
|
+
from 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1 +1,107 @@
|
|
1
|
-
Diffing
|
1
|
+
# Diffing
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
```
|
6
|
+
sudo gem install differ
|
7
|
+
```
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
require 'diffing'
|
13
|
+
|
14
|
+
from = "Hello! I am string for diffing test"
|
15
|
+
to = "Hi! I am two string for diffing"
|
16
|
+
```
|
17
|
+
|
18
|
+
#### By chars
|
19
|
+
```ruby
|
20
|
+
diff = Diffing.by_chars( from, to )
|
21
|
+
|
22
|
+
diff.as_ascii
|
23
|
+
# => H{"ello" >> "i"}! I am{+" two"} string for diffing{-" test"}
|
24
|
+
diff.as_html
|
25
|
+
# => H<del>ello</del><ins>i</ins>! I am<ins> two</ins> string for diffing<del> test</del>
|
26
|
+
```
|
27
|
+
|
28
|
+
#### By words
|
29
|
+
```ruby
|
30
|
+
diff = Diffing.by_words( from, to )
|
31
|
+
|
32
|
+
diff.as_ascii
|
33
|
+
# => {"Hello!" >> "Hi!"} I am {+"two"} string for diffing {-"test"}
|
34
|
+
diff.as_html
|
35
|
+
# => <del>Hello!</del><ins>Hi!</ins> I am <ins>two</ins> string for diffing <del>test</del>
|
36
|
+
```
|
37
|
+
|
38
|
+
#### By lines
|
39
|
+
```ruby
|
40
|
+
diff = Diffing.by_lines( from, to )
|
41
|
+
|
42
|
+
diff.as_ascii
|
43
|
+
# => {"Hello! I am string for diffing test" >> "Hi! I am two string for diffing"}
|
44
|
+
diff.as_html
|
45
|
+
# => <del>Hello! I am string for diffing test</del><ins>Hi! I am two string for diffing</ins>
|
46
|
+
```
|
47
|
+
|
48
|
+
## Custom format
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
module CustomFormat
|
52
|
+
class << self
|
53
|
+
|
54
|
+
def source( value )
|
55
|
+
value
|
56
|
+
end
|
57
|
+
|
58
|
+
def insert( value )
|
59
|
+
"(++#{ value })"
|
60
|
+
end
|
61
|
+
|
62
|
+
def delete( value )
|
63
|
+
"(--#{ value })"
|
64
|
+
end
|
65
|
+
|
66
|
+
def replace( from, to )
|
67
|
+
"(#{ from } => #{ to })"
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
Diffing.by_chars.format( CustomFormat )
|
75
|
+
# => H(ello => i)! I am(++ two) string for diffing(-- test)
|
76
|
+
Diffing.by_words.format( CustomFormat )
|
77
|
+
# => (Hello! => Hi!) I am (++two) string for diffing (--test)
|
78
|
+
Diffing.by_lines.format( CustomFormat )
|
79
|
+
# => (Hello! I am string for diffing test => Hi! I am two string for diffing)
|
80
|
+
|
81
|
+
```
|
82
|
+
|
83
|
+
## Custom delimiter
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
Diffing::Diff.new( from, to, 'i' ).as_ascii
|
87
|
+
# => {"Hello! I am str" >> "Hi! I am two str"}ing for diffi{"ng test" >> "ng"}
|
88
|
+
```
|
89
|
+
|
90
|
+
## Custom use separated parts
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
Diffing.by_words( from, to ).parts.map { |part|
|
94
|
+
|
95
|
+
result = ''
|
96
|
+
result << "<source:#{ part.source }>" if part.source?
|
97
|
+
result << "<insert:#{ part.insert }>" if part.insert?
|
98
|
+
result << "<delete:#{ part.delete }>" if part.delete?
|
99
|
+
result
|
100
|
+
|
101
|
+
}.join( '' )
|
102
|
+
# => <insert:Hi!><delete:Hello!><source:I am><insert:two><source:string for diffing><delete:test>
|
103
|
+
```
|
104
|
+
|
105
|
+
## Copyright
|
106
|
+
|
107
|
+
Copyright © 2015 Denis Churbanov
|
data/lib/diffing.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'diffing/diff'
|
2
2
|
require 'diffing/part'
|
3
3
|
require 'diffing/formats/ascii'
|
4
|
+
require 'diffing/formats/html'
|
4
5
|
|
5
6
|
|
6
7
|
module Diffing
|
7
8
|
|
8
9
|
class << self
|
9
|
-
|
10
|
+
|
10
11
|
|
11
12
|
def by_lines( from, to )
|
12
13
|
Diff.new from, to, "\n"
|
@@ -19,7 +20,7 @@ module Diffing
|
|
19
20
|
def by_chars( from, to )
|
20
21
|
Diff.new from, to
|
21
22
|
end
|
22
|
-
|
23
|
+
|
23
24
|
|
24
25
|
end
|
25
26
|
|
data/lib/diffing/diff.rb
CHANGED
@@ -1,101 +1,104 @@
|
|
1
|
-
module Diffing
|
2
|
-
|
3
|
-
class Diff
|
4
|
-
|
5
|
-
|
6
|
-
attr_reader :parts
|
7
|
-
|
8
|
-
def initialize( from, to, delimiter = '' )
|
9
|
-
@delimiter = delimiter
|
10
|
-
@parts = calcucate( split( from.to_s ), split( to.to_s ) ).flatten
|
11
|
-
end
|
12
|
-
|
13
|
-
def format( format
|
14
|
-
result = []
|
15
|
-
@parts.each do |part|
|
16
|
-
result << format.source( part.source ) if part.source?
|
17
|
-
if part.replace? and format.respond_to?( :replace )
|
18
|
-
result << format.replace( part.delete, part.insert )
|
19
|
-
else
|
20
|
-
result << format.insert( part.insert ) if part.insert?
|
21
|
-
result << format.delete( part.delete ) if part.delete?
|
22
|
-
end
|
23
|
-
end
|
24
|
-
result.join @delimiter
|
25
|
-
end
|
26
|
-
|
27
|
-
def
|
28
|
-
format
|
29
|
-
end
|
30
|
-
|
31
|
-
def
|
32
|
-
format
|
33
|
-
end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
1
|
+
module Diffing
|
2
|
+
|
3
|
+
class Diff
|
4
|
+
|
5
|
+
|
6
|
+
attr_reader :parts
|
7
|
+
|
8
|
+
def initialize( from, to, delimiter = '' )
|
9
|
+
@delimiter = delimiter
|
10
|
+
@parts = calcucate( split( from.to_s ), split( to.to_s ) ).flatten
|
11
|
+
end
|
12
|
+
|
13
|
+
def format( format )
|
14
|
+
result = []
|
15
|
+
@parts.each do |part|
|
16
|
+
result << format.source( part.source ) if part.source?
|
17
|
+
if part.replace? and format.respond_to?( :replace )
|
18
|
+
result << format.replace( part.delete, part.insert )
|
19
|
+
else
|
20
|
+
result << format.insert( part.insert ) if part.insert?
|
21
|
+
result << format.delete( part.delete ) if part.delete?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
result.join @delimiter
|
25
|
+
end
|
26
|
+
|
27
|
+
def as_ascii
|
28
|
+
format Format::Ascii
|
29
|
+
end
|
30
|
+
|
31
|
+
def as_html
|
32
|
+
format Format::Html
|
33
|
+
end
|
34
|
+
|
35
|
+
alias :to_s :as_ascii
|
36
|
+
alias :inspect :as_ascii
|
37
|
+
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def calcucate( from, to )
|
42
|
+
if found = find_middle( from, to )
|
43
|
+
from_l, to_l, source, from_r, to_r = found
|
44
|
+
[ calcucate( from_l, to_l ), Part.new( source: join( source ) ), calcucate( from_r, to_r ) ]
|
45
|
+
else
|
46
|
+
[ Part.new( insert: join( to ), delete: join( from ) ) ]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def find_middle( from, to, min = 0, max = nil )
|
51
|
+
|
52
|
+
return nil if from.empty? or to.empty?
|
53
|
+
|
54
|
+
max = from.size unless max
|
55
|
+
size = min + ( ( max - min ) / 2.to_f ).round
|
56
|
+
|
57
|
+
subsets_each( from, size ) do |subset, first, last|
|
58
|
+
|
59
|
+
if found = find_middle_index( to, subset )
|
60
|
+
|
61
|
+
return (
|
62
|
+
size != min and find_middle( from, to, size, max ) or
|
63
|
+
(
|
64
|
+
from_l = from[ 0...first ]
|
65
|
+
to_l = to[ 0...found ]
|
66
|
+
from_r = from[ last...from.size ]
|
67
|
+
to_r = to[ found + subset.size...to.size ]
|
68
|
+
[ from_l, to_l, subset, from_r, to_r ]
|
69
|
+
)
|
70
|
+
)
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
size != max and find_middle( from, to, min, size ) or nil
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
def find_middle_index( set, search_subset )
|
81
|
+
return set.index( search_subset ) if @delimiter == ''
|
82
|
+
subsets_each( set, search_subset.size ){ |subset, first, last| return first if subset == search_subset }
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
def subsets_each( from, size )
|
87
|
+
( from.size - size + 1 ).times do |first|
|
88
|
+
last = first + size
|
89
|
+
subset = from[ first...last ]
|
90
|
+
yield subset, first, last
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def split( set )
|
95
|
+
@delimiter == '' ? set : set.split( @delimiter )
|
96
|
+
end
|
97
|
+
|
98
|
+
def join( set )
|
99
|
+
@delimiter == '' ? set : set.join( @delimiter )
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
@@ -1,33 +1,33 @@
|
|
1
|
-
module Diffing
|
2
|
-
|
3
|
-
module Format
|
4
|
-
|
5
|
-
module Ascii
|
6
|
-
|
7
|
-
class << self
|
8
|
-
|
9
|
-
|
10
|
-
def source( value )
|
11
|
-
value
|
12
|
-
end
|
13
|
-
|
14
|
-
def insert( value )
|
15
|
-
"{+\"#{ value }\"}"
|
16
|
-
end
|
17
|
-
|
18
|
-
def delete( value )
|
19
|
-
"{-\"#{ value }\"}"
|
20
|
-
end
|
21
|
-
|
22
|
-
def replace( from, to )
|
23
|
-
"{\"#{ from }\" >> \"#{ to }\"}"
|
24
|
-
end
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
1
|
+
module Diffing
|
2
|
+
|
3
|
+
module Format
|
4
|
+
|
5
|
+
module Ascii
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
|
10
|
+
def source( value )
|
11
|
+
value
|
12
|
+
end
|
13
|
+
|
14
|
+
def insert( value )
|
15
|
+
"{+\"#{ value }\"}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def delete( value )
|
19
|
+
"{-\"#{ value }\"}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def replace( from, to )
|
23
|
+
"{\"#{ from }\" >> \"#{ to }\"}"
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Diffing
|
2
|
+
|
3
|
+
module Format
|
4
|
+
|
5
|
+
module Html
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
|
10
|
+
def source( value )
|
11
|
+
value
|
12
|
+
end
|
13
|
+
|
14
|
+
def insert( value )
|
15
|
+
"<ins>#{ value }</ins>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def delete( value )
|
19
|
+
"<del>#{ value }</del>"
|
20
|
+
end
|
21
|
+
|
22
|
+
def replace( from, to )
|
23
|
+
delete( from ) + insert( to )
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/lib/diffing/part.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
|
-
module Diffing
|
2
|
-
|
3
|
-
|
4
|
-
class Part
|
5
|
-
|
6
|
-
attr_reader :source, :insert, :delete
|
7
|
-
|
8
|
-
def initialize( source: '', insert: '', delete: '' )
|
9
|
-
@source, @insert, @delete = source, insert, delete
|
10
|
-
end
|
11
|
-
|
12
|
-
def source?
|
13
|
-
not @source.empty?
|
14
|
-
end
|
15
|
-
|
16
|
-
def insert?
|
17
|
-
not @insert.empty?
|
18
|
-
end
|
19
|
-
|
20
|
-
def delete?
|
21
|
-
not @delete.empty?
|
22
|
-
end
|
23
|
-
|
24
|
-
def replace?
|
25
|
-
not @insert.empty? and not @delete.empty?
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
|
31
|
-
end
|
1
|
+
module Diffing
|
2
|
+
|
3
|
+
|
4
|
+
class Part
|
5
|
+
|
6
|
+
attr_reader :source, :insert, :delete
|
7
|
+
|
8
|
+
def initialize( source: '', insert: '', delete: '' )
|
9
|
+
@source, @insert, @delete = source, insert, delete
|
10
|
+
end
|
11
|
+
|
12
|
+
def source?
|
13
|
+
not @source.empty?
|
14
|
+
end
|
15
|
+
|
16
|
+
def insert?
|
17
|
+
not @insert.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete?
|
21
|
+
not @delete.empty?
|
22
|
+
end
|
23
|
+
|
24
|
+
def replace?
|
25
|
+
not @insert.empty? and not @delete.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
metadata
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diffing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Denis Churbanov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2015-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: Diffing two strings
|
14
|
-
email:
|
15
|
-
- 4urbanoff@gmail.com
|
13
|
+
description: Diffing of two strings
|
14
|
+
email: 4urbanoff@gmail.com
|
16
15
|
executables: []
|
17
16
|
extensions: []
|
18
17
|
extra_rdoc_files: []
|
19
18
|
files:
|
20
19
|
- lib/diffing/diff.rb
|
21
20
|
- lib/diffing/formats/ascii.rb
|
21
|
+
- lib/diffing/formats/html.rb
|
22
22
|
- lib/diffing/part.rb
|
23
23
|
- lib/diffing.rb
|
24
24
|
- LICENSE.txt
|
@@ -48,5 +48,5 @@ rubyforge_project:
|
|
48
48
|
rubygems_version: 2.0.14
|
49
49
|
signing_key:
|
50
50
|
specification_version: 4
|
51
|
-
summary:
|
51
|
+
summary: Gem for calculating two strings difference
|
52
52
|
test_files: []
|