difftastic 0.1.2-arm64-linux → 0.3.0-arm64-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f8cbb936322c76af988d7bf714f2d8f31c51bad304ca669365e5aff37b8982c
4
- data.tar.gz: 886a81849018435199ec93c5b35d7e703cdd47bac8836eab74736441b74ad858
3
+ metadata.gz: b417791c10125ffd8626f8c8bb068cb71576190bf5e8bd314378fda4a6e84ed4
4
+ data.tar.gz: af6277b6456026983fbb0f55ce328feea536c12affcf8984c214ad8a9986ffd0
5
5
  SHA512:
6
- metadata.gz: dac982dbb4b2fc13ad6c6e2c857735c9e9983c5eb187a16466bc855ff248b176b64afd1ff9b2187adec15f0005521193122afce7f47ea7a1970f37752bd676bf
7
- data.tar.gz: ecb237465ed4aa8581c39ed41c264f9afbfa284417ebbafd4b58735481dbe2191f5b061c44f76b74f8b0fe545f15dc43fc0414e47e1e92217e70338c50b563bb
6
+ metadata.gz: b6c93293b33ede5f620e339c5e98ecef184d2779172537ed9de0c2de75bb6c1b0666be036e84f6806858ae527e932719c33f665a1d75b0d1cf15c7e6ed9f8f22
7
+ data.tar.gz: 7cb643d1b4bc1553bac9a75fd2a71b2de11d373996d6f660e54858fd7fea031a7357be41fcb9900a10e2bfac8a86c04618a9013801ed666a94fb0493511e0e34
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
+ ```
@@ -1,22 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Difftastic::Differ
4
- def initialize(background: nil, color: nil, syntax_highlight: nil, context: nil, tab_width: nil, parse_error_limit: nil, underline_highlights: true, left_label: nil, right_label: nil)
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
- old = Difftastic.pretty(old)
19
- new = Difftastic.pretty(new)
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{#{@tab_width},}/, 2)
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 = (stripped_line.index("#{' ' * @tab_width}#{rhs}") || 0) + @tab_width
360
+ offset = index + tab_width
348
361
  minimum_offset = 29
349
362
 
350
363
  [minimum_offset, offset].max
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Difftastic
4
- VERSION = "0.1.2"
4
+ VERSION = "0.3.0"
5
5
  end
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, buffer: +"", indent: 0)
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
- buffer << "{\n"
84
+ return "{}" if object.empty?
85
+
86
+ buffer = +"{\n"
78
87
  indent += 1
79
88
  object.each do |key, value|
80
- buffer << (" " * indent)
81
- pretty(key, buffer:, indent:)
82
- buffer << " => "
83
- pretty(value, buffer:, indent:)
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 << (" " * indent)
101
+ buffer << ("\t" * indent)
88
102
  buffer << "}"
89
103
  when Array
90
- buffer << "[\n"
91
- indent += 1
92
- object.each do |value|
93
- buffer << (" " * indent)
94
- pretty(value, buffer:, indent:)
95
- buffer << ",\n"
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
- buffer << "Set[\n"
102
- indent += 1
103
- object.to_a.sort!.each do |value|
104
- buffer << (" " * indent)
105
- pretty(value, buffer:, indent:)
106
- buffer << ",\n"
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
- indent -= 1
109
- buffer << (" " * indent)
110
- buffer << "]"
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
- buffer << object.inspect
138
+ object.inspect
113
139
  else
114
- buffer << "#{object.class.name}(\n"
115
- indent += 1
116
- object.instance_variables.each do |name|
117
- buffer << (" " * indent)
118
- buffer << ":#{name} => "
119
- pretty(object.instance_variable_get(name), buffer:, indent:)
120
- buffer << ",\n"
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.1.2
4
+ version: 0.3.0
5
5
  platform: arm64-linux
6
6
  authors:
7
7
  - Joel Drapper
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-01-22 00:00:00.000000000 Z
10
+ date: 2025-01-30 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  email:
13
13
  - joel@drapper.me