difftastic 0.1.2-x86_64-linux → 0.3.0-x86_64-linux
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/README.md +103 -0
- data/lib/difftastic/differ.rb +18 -5
- data/lib/difftastic/version.rb +1 -1
- data/lib/difftastic.rb +84 -36
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2ed87a18ce040c8242e11953eb245c60e86bd0536b78afaf8861eed22032656
|
4
|
+
data.tar.gz: f8d7d2778862806c77234427036f1d46a419b04862e2e4b17345cb4dd4412e94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af46c40e117706a660360c11d3f3d1ad6ebe67f4cfe8e5fbcb0da43d61cd7f30e1a51d0c0d7ca24a8092d065de0cc8fddedacaa019e3c567b85ab234ffa39b8c
|
7
|
+
data.tar.gz: 11f4e80d4c369cb0f68f5b09287715322b8311d0b1d50349dce0a03a03875128b30c2018828ab6ec4f141dcc089a323daec9d6b1a53acd81a1f5729a5defee78
|
data/README.md
CHANGED
@@ -1 +1,104 @@
|
|
1
1
|
# Difftastic Ruby
|
2
|
+
|
3
|
+
A Ruby interface and wrapper for the wonderful [Difftastic](https://difftastic.wilfred.me.uk) CLI tool.
|
4
|
+
|
5
|
+
## Creating a Differ
|
6
|
+
|
7
|
+
First, create a differ with your configuration:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
MY_DIFFER = Difftastic::Differ.new(
|
11
|
+
background: :dark,
|
12
|
+
color: :always,
|
13
|
+
left_label: "Expected",
|
14
|
+
right_label: "Actual"
|
15
|
+
)
|
16
|
+
```
|
17
|
+
|
18
|
+
## Diffing Objects
|
19
|
+
|
20
|
+
You can diff objects with different configurations:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
a = { foo: 1, bar: [2, 3, 4] }
|
24
|
+
b = { foo: 1, bar: [2, 4, 3] }
|
25
|
+
|
26
|
+
puts MY_DIFFER.diff_objects(a, b)
|
27
|
+
```
|
28
|
+
|
29
|
+
## Diffing Ruby Code
|
30
|
+
|
31
|
+
You can diff Ruby code:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
a = <<~RUBY
|
35
|
+
def hello
|
36
|
+
puts "Hello, world!"
|
37
|
+
end
|
38
|
+
RUBY
|
39
|
+
|
40
|
+
b = <<~RUBY
|
41
|
+
def hello
|
42
|
+
puts "Goodbye, world!"
|
43
|
+
end
|
44
|
+
RUBY
|
45
|
+
|
46
|
+
puts MY_DIFFER.diff_ruby(a, b)
|
47
|
+
```
|
48
|
+
|
49
|
+
## Additional File Type Methods
|
50
|
+
|
51
|
+
You can also diff other file types using the following methods:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
a = "<html>\n\t<body>\n\t\t<h1>Hello, world!</h1>\n\t</body>\n</html>"
|
55
|
+
b = "<html>\n\t<body>\n\t\t<h1>Goodbye, world!</h1>\n\t</body>\n</html>"
|
56
|
+
|
57
|
+
puts MY_DIFFER.diff_html(a, b)
|
58
|
+
|
59
|
+
a = '{ "foo": 1, "bar": 2 }'
|
60
|
+
b = '{ "foo": 1, "bar": 3 }'
|
61
|
+
|
62
|
+
puts MY_DIFFER.diff_json(a, b)
|
63
|
+
|
64
|
+
a = "body { color: red; }"
|
65
|
+
b = "body { color: blue; }"
|
66
|
+
|
67
|
+
puts MY_DIFFER.diff_css(a, b)
|
68
|
+
|
69
|
+
a = "<note><to>Tove</to><from>Jani</from></note>"
|
70
|
+
b = "<note><to>Tove</to><from>John</from></note>"
|
71
|
+
|
72
|
+
puts MY_DIFFER.diff_xml(a, b)
|
73
|
+
|
74
|
+
a = "foo: 1\nbar: 2"
|
75
|
+
b = "foo: 1\nbar: 3"
|
76
|
+
|
77
|
+
puts MY_DIFFER.diff_yaml(a, b)
|
78
|
+
```
|
79
|
+
|
80
|
+
## Configuring Difftastic::Differ
|
81
|
+
|
82
|
+
You can configure the `Difftastic::Differ` instance with various options:
|
83
|
+
|
84
|
+
- `background`: Set the background color (`:dark` or `:light`).
|
85
|
+
- `color`: Set the color mode (`:always`, `:never`, or `:auto`).
|
86
|
+
- `syntax_highlight`: Enable or disable syntax highlighting (`:on` or `:off`).
|
87
|
+
- `context`: Set the number of context lines to display.
|
88
|
+
- `width`: Use this many columns when calculating line wrapping. If not specified, difftastic will detect the terminal width.
|
89
|
+
- `tab_width`: Set the tab width for indentation.
|
90
|
+
- `parse_error_limit`: Set the limit for parse errors.
|
91
|
+
- `underline_highlights`: Enable or disable underlining highlights (`true` or `false`).
|
92
|
+
- `left_label`: Set the label for the left side of the diff.
|
93
|
+
- `right_label`: Set the label for the right side of the diff.
|
94
|
+
- `display`: Set the display mode (`"side-by-side-show-both"`, `"side-by-side"`, or `"inline"`).
|
95
|
+
|
96
|
+
## Pretty Method
|
97
|
+
|
98
|
+
The `Difftastic` module includes a `pretty` method for formatting objects:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
object = { foo: 1, bar: [2, 3, 4] }
|
102
|
+
formatted_object = Difftastic.pretty(object)
|
103
|
+
puts formatted_object
|
104
|
+
```
|
data/lib/difftastic/differ.rb
CHANGED
@@ -1,22 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Difftastic::Differ
|
4
|
-
|
4
|
+
DEFAULT_TAB_WIDTH = 2
|
5
|
+
|
6
|
+
def initialize(background: nil, color: nil, syntax_highlight: nil, context: nil, width: nil, tab_width: nil, parse_error_limit: nil, underline_highlights: true, left_label: nil, right_label: nil, display: "side-by-side-show-both")
|
5
7
|
@show_paths = false
|
6
8
|
@background = background => :dark | :light | nil
|
7
9
|
@color = color => :always | :never | :auto | nil
|
8
10
|
@syntax_highlight = syntax_highlight => :on | :off | nil
|
9
11
|
@context = context => Integer | nil
|
12
|
+
@width = width => Integer | nil
|
10
13
|
@tab_width = tab_width => Integer | nil
|
11
14
|
@parse_error_limit = parse_error_limit => Integer | nil
|
12
15
|
@underline_highlights = underline_highlights => true | false
|
13
16
|
@left_label = left_label => String | nil
|
14
17
|
@right_label = right_label => String | nil
|
18
|
+
@display = display
|
15
19
|
end
|
16
20
|
|
17
21
|
def diff_objects(old, new)
|
18
|
-
|
19
|
-
|
22
|
+
tab_width = @tab_width || DEFAULT_TAB_WIDTH
|
23
|
+
|
24
|
+
old = Difftastic.pretty(old, tab_width:)
|
25
|
+
new = Difftastic.pretty(new, tab_width:)
|
20
26
|
|
21
27
|
diff_strings(old, new, file_extension: "rb")
|
22
28
|
end
|
@@ -290,6 +296,8 @@ class Difftastic::Differ
|
|
290
296
|
("--background=#{@background}" if @background),
|
291
297
|
("--syntax-highlight=#{@syntax_highlight}" if @syntax_highlight),
|
292
298
|
("--tab-width=#{@tab_width}" if @tab_width),
|
299
|
+
("--display=#{@display}" if @display),
|
300
|
+
("--width=#{@width}" if @width),
|
293
301
|
].compact!
|
294
302
|
|
295
303
|
result = Difftastic.execute(options.join(" "))
|
@@ -341,10 +349,15 @@ class Difftastic::Differ
|
|
341
349
|
private
|
342
350
|
|
343
351
|
def right_label_offset(line)
|
352
|
+
tab_width = @tab_width || DEFAULT_TAB_WIDTH
|
344
353
|
stripped_line = ::Difftastic::ANSI.strip_formatting(line)
|
345
|
-
_lhs, rhs = stripped_line.split(/\s{#{
|
354
|
+
_lhs, rhs = stripped_line.split(/\s{#{tab_width},}/, 2)
|
355
|
+
|
356
|
+
index = stripped_line.index("#{' ' * tab_width}#{rhs}")
|
357
|
+
index = @width / 2 if @width && index.nil?
|
358
|
+
index = 0 if index.nil?
|
346
359
|
|
347
|
-
offset =
|
360
|
+
offset = index + tab_width
|
348
361
|
minimum_offset = 29
|
349
362
|
|
350
363
|
[minimum_offset, offset].max
|
data/lib/difftastic/version.rb
CHANGED
data/lib/difftastic.rb
CHANGED
@@ -11,6 +11,9 @@ module Difftastic
|
|
11
11
|
GEM_NAME = "difftastic"
|
12
12
|
DEFAULT_DIR = File.expand_path(File.join(__dir__, "..", "exe"))
|
13
13
|
|
14
|
+
class ExecutableNotFoundException < StandardError
|
15
|
+
end
|
16
|
+
|
14
17
|
def self.execute(command)
|
15
18
|
`#{executable} #{command}`
|
16
19
|
end
|
@@ -71,57 +74,102 @@ module Difftastic
|
|
71
74
|
exe_file
|
72
75
|
end
|
73
76
|
|
74
|
-
def self.pretty(object,
|
77
|
+
def self.pretty(object, indent: 0, tab_width: 2, max_width: 60, max_depth: 5, max_instance_variables: 10, original_object: nil)
|
78
|
+
return "self" if object && object == original_object
|
79
|
+
|
80
|
+
original_object ||= object
|
81
|
+
|
75
82
|
case object
|
76
83
|
when Hash
|
77
|
-
|
84
|
+
return "{}" if object.empty?
|
85
|
+
|
86
|
+
buffer = +"{\n"
|
78
87
|
indent += 1
|
79
88
|
object.each do |key, value|
|
80
|
-
buffer << ("
|
81
|
-
|
82
|
-
|
83
|
-
|
89
|
+
buffer << ("\t" * indent)
|
90
|
+
case key
|
91
|
+
when Symbol
|
92
|
+
buffer << "#{key.name}: "
|
93
|
+
else
|
94
|
+
buffer << pretty(key, indent:, original_object:)
|
95
|
+
buffer << " => "
|
96
|
+
end
|
97
|
+
buffer << pretty(value, indent:, original_object:)
|
84
98
|
buffer << ",\n"
|
85
99
|
end
|
86
100
|
indent -= 1
|
87
|
-
buffer << ("
|
101
|
+
buffer << ("\t" * indent)
|
88
102
|
buffer << "}"
|
89
103
|
when Array
|
90
|
-
|
91
|
-
|
92
|
-
object.
|
93
|
-
|
94
|
-
|
95
|
-
|
104
|
+
new_lines = false
|
105
|
+
length = 0
|
106
|
+
items = object.map do |item|
|
107
|
+
pretty_item = pretty(item, indent: indent + 1, original_object:)
|
108
|
+
new_lines = true if pretty_item.include?("\n")
|
109
|
+
length += pretty_item.bytesize
|
110
|
+
pretty_item
|
111
|
+
end
|
112
|
+
|
113
|
+
if new_lines || length > max_width - (indent * tab_width)
|
114
|
+
"[\n#{"\t" * (indent + 1)}#{items.join(",\n#{"\t" * (indent + 1)}")},\n#{"\t" * indent}]"
|
115
|
+
else
|
116
|
+
"[#{items.join(', ')}]"
|
96
117
|
end
|
97
|
-
indent -= 1
|
98
|
-
buffer << (" " * indent)
|
99
|
-
buffer << "]"
|
100
118
|
when Set
|
101
|
-
|
102
|
-
|
103
|
-
object.to_a.sort!.
|
104
|
-
|
105
|
-
|
106
|
-
|
119
|
+
new_lines = false
|
120
|
+
length = 0
|
121
|
+
items = object.to_a.sort!.map do |item|
|
122
|
+
pretty_item = pretty(item, indent: indent + 1, original_object:)
|
123
|
+
new_lines = true if pretty_item.include?("\n")
|
124
|
+
length += pretty_item.bytesize
|
125
|
+
pretty_item
|
107
126
|
end
|
108
|
-
|
109
|
-
|
110
|
-
|
127
|
+
|
128
|
+
if new_lines || length > max_width - (indent * tab_width)
|
129
|
+
"Set[\n#{"\t" * (indent + 1)}#{items.join(",\n#{"\t" * (indent + 1)}")},\n#{"\t" * indent}]"
|
130
|
+
else
|
131
|
+
"Set[#{items.join(', ')}]"
|
132
|
+
end
|
133
|
+
when Module
|
134
|
+
object.name
|
135
|
+
when Pathname
|
136
|
+
%(Pathname("#{object.to_path}"))
|
111
137
|
when Symbol, String, Integer, Float, Regexp, Range, Rational, Complex, true, false, nil
|
112
|
-
|
138
|
+
object.inspect
|
113
139
|
else
|
114
|
-
buffer
|
115
|
-
|
116
|
-
|
117
|
-
buffer << ("
|
118
|
-
|
119
|
-
|
120
|
-
|
140
|
+
buffer = +""
|
141
|
+
instance_variables = object.instance_variables
|
142
|
+
if instance_variables.length > 0 && indent < max_depth
|
143
|
+
buffer << "#{object.class.name}(\n"
|
144
|
+
indent += 1
|
145
|
+
|
146
|
+
if indent < max_depth
|
147
|
+
object.instance_variables.take(max_instance_variables).each do |name|
|
148
|
+
buffer << ("\t" * indent)
|
149
|
+
buffer << name.name
|
150
|
+
buffer << " = "
|
151
|
+
|
152
|
+
buffer << pretty(object.instance_variable_get(name), indent:, original_object:)
|
153
|
+
buffer << ",\n"
|
154
|
+
end
|
155
|
+
|
156
|
+
if object.instance_variables.count > max_instance_variables
|
157
|
+
buffer << ("\t" * indent)
|
158
|
+
buffer << "...\n"
|
159
|
+
end
|
160
|
+
else
|
161
|
+
buffer << ("\t" * indent)
|
162
|
+
buffer << "...\n"
|
163
|
+
end
|
164
|
+
|
165
|
+
indent -= 1
|
166
|
+
buffer << ("\t" * indent)
|
167
|
+
buffer << ")"
|
168
|
+
elsif indent >= max_depth
|
169
|
+
buffer << "#{object.class.name}(...)"
|
170
|
+
else
|
171
|
+
buffer << "#{object.class.name}()"
|
121
172
|
end
|
122
|
-
indent -= 1
|
123
|
-
buffer << (" " * indent)
|
124
|
-
buffer << ")"
|
125
173
|
end
|
126
174
|
end
|
127
175
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: difftastic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: x86_64-linux
|
6
6
|
authors:
|
7
7
|
- Joel Drapper
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-01-
|
10
|
+
date: 2025-01-30 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
email:
|
13
13
|
- joel@drapper.me
|