Skip to content

Commit eae2879

Browse files
authored
Respect RSpec color mode when applicable (#261)
Default to RSpec color mode when SuperDIff RSpec extensions are loaded (and when `ENV["CI"]` isn't set to `true`). ⚠️ This is technically a breaking change. Before this PR, `SuperDiff.configuration.color_enabled = nil` turned colors off. As of this PR, it indicates that SuperDiff should decide based on the environment.
1 parent 2d06e39 commit eae2879

File tree

10 files changed

+268
-56
lines changed

10 files changed

+268
-56
lines changed

.github/workflows/super_diff.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ jobs:
143143
env:
144144
IS_NEW_RELEASE: ${{ needs.collect-release-info.outputs.IS_NEW_RELEASE }}
145145
RELEASE_VERSION: ${{ needs.collect-release-info.outputs.RELEASE_VERSION }}
146-
BRANCH_NAME: ${{ github.ref_name }}
146+
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
147147
COMMIT_ID: ${{ github.event.pull_request.head.sha }}
148148
outputs:
149149
DOCSITE_RELEASE_VERSION: ${{ steps.command.outputs.DOCSITE_RELEASE_VERSION }}

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44

55
### Features
66

7-
- Add better support for Data object diffing. [#259](https://github.com/splitwise/super_diff/pull/224)
7+
- Add better support for Data object diffing. [#259](https://github.com/splitwise/super_diff/pull/259)
8+
- Fall back on RSpec color mode when `SuperDiff.configuration.color_enabled` is unspecified or nil. [#261](https://github.com/splitwise/super_diff/pull/261)
9+
10+
### Breaking changes
11+
12+
- Removed several `SuperDiff::Csi` methods. This will break any code that uses those parts of the `SuperDiff::Csi` (which is private in general).
13+
- `SuperDiff.configuration.color_enabled = nil` used to disable color output. It now allows SuperDiff to determine whether to colorize output based on the environment (namely RSpec color mode and whether stdout is a TTY).
814

915
## 0.12.1 - 2024-04-26
1016

docs/users/customization.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ end
1414
The following is a list of options you can set on the configuration object
1515
along with their defaults:
1616

17-
| name | description | default |
18-
| ---------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------- |
19-
| `actual_color` | The color used to display "actual" values in diffs | `:yellow` |
20-
| `border_color` | The color used to display the border in diff keys | `:blue` |
21-
| `color_enabled` | Whether to colorize output | `true` if `ENV["CI"]` or stdout is a TTY, `false` otherwise |
22-
| `diff_elision_enabled` | Whether to elide (remove) unchanged lines in diff | `false` |
23-
| `diff_elision_maximum` | How large a section of consecutive unchanged lines can be before being elided | `0` |
24-
| `elision_marker_color` | The color used to display the marker substituted for elided lines in a diff | `:cyan` |
25-
| `expected_color` | The color used to display "expected" values in diffs | `:magenta` |
26-
| `header_color` | The color used to display the "Diff:" header in failure messages | `:white` |
27-
| `key_enabled` | Whether to show the key above diffs | `true` |
17+
| name | description | default |
18+
| ---------------------- | ------------------------------------------------------------------------------------- | ---------- |
19+
| `actual_color` | The color used to display "actual" values in diffs | `:yellow` |
20+
| `border_color` | The color used to display the border in diff keys | `:blue` |
21+
| `color_enabled` | Whether to colorize output, or `nil` to let SuperDiff decide based on the environment | `nil` |
22+
| `diff_elision_enabled` | Whether to elide (remove) unchanged lines in diff | `false` |
23+
| `diff_elision_maximum` | How large a section of consecutive unchanged lines can be before being elided | `0` |
24+
| `elision_marker_color` | The color used to display the marker substituted for elided lines in a diff | `:cyan` |
25+
| `expected_color` | The color used to display "expected" values in diffs | `:magenta` |
26+
| `header_color` | The color used to display the "Diff:" header in failure messages | `:white` |
27+
| `key_enabled` | Whether to show the key above diffs | `true` |
2828

2929
The following is a list of methods you can call on the configuration object:
3030

lib/super_diff.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ def self.const_missing(missing_const_name)
3636

3737
def self.configure
3838
yield configuration
39-
configuration.updated
4039
end
4140

4241
def self.configuration

lib/super_diff/core/configuration.rb

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class Configuration
2323
def initialize(options = {})
2424
@actual_color = :yellow
2525
@border_color = :blue
26-
@color_enabled = color_enabled_by_default?
26+
@color_enabled = nil
2727
@diff_elision_enabled = false
2828
@diff_elision_maximum = 0
2929
@elision_marker_color = :cyan
@@ -41,6 +41,8 @@ def initialize(options = {})
4141

4242
def initialize_dup(original)
4343
super
44+
@extra_diff_formatter_classes =
45+
original.extra_diff_formatter_classes.dup.freeze
4446
@extra_differ_classes = original.extra_differ_classes.dup.freeze
4547
@extra_operation_tree_builder_classes =
4648
original.extra_operation_tree_builder_classes.dup.freeze
@@ -51,6 +53,8 @@ def initialize_dup(original)
5153
end
5254

5355
def color_enabled?
56+
return color_enabled_by_default? if @color_enabled.nil?
57+
5458
@color_enabled
5559
end
5660

@@ -71,12 +75,6 @@ def merge!(configuration_or_options)
7175
end
7276

7377
options.each { |key, value| instance_variable_set("@#{key}", value) }
74-
75-
updated
76-
end
77-
78-
def updated
79-
SuperDiff::Csi.color_enabled = color_enabled?
8078
end
8179

8280
def add_extra_diff_formatter_classes(*classes)
@@ -165,7 +163,7 @@ def to_h
165163
{
166164
actual_color: actual_color,
167165
border_color: border_color,
168-
color_enabled: color_enabled?,
166+
color_enabled: @color_enabled,
169167
diff_elision_enabled: diff_elision_enabled?,
170168
diff_elision_maximum: diff_elision_maximum,
171169
elision_marker_color: elision_marker_color,
@@ -185,7 +183,13 @@ def to_h
185183
private
186184

187185
def color_enabled_by_default?
188-
ENV["CI"] == "true" || $stdout.respond_to?(:tty?) && $stdout.tty?
186+
return true if ENV["CI"] == "true"
187+
188+
if defined?(::SuperDiff::RSpec)
189+
return ::RSpec.configuration.color_enabled?
190+
end
191+
192+
$stdout.respond_to?(:tty?) && $stdout.tty?
189193
end
190194
end
191195
end

lib/super_diff/core/helpers.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module Helpers
66
# TODO: Simplify this
77
def style(*args, color_enabled: true, **opts, &block)
88
klass =
9-
if color_enabled && Csi.color_enabled?
9+
if color_enabled && SuperDiff.configuration.color_enabled?
1010
Csi::ColorizedDocument
1111
else
1212
Csi::UncolorizedDocument

lib/super_diff/csi.rb

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,48 +12,16 @@ module Csi
1212
autoload :TwentyFourBitColor, "super_diff/csi/twenty_four_bit_color"
1313
autoload :UncolorizedDocument, "super_diff/csi/uncolorized_document"
1414

15-
class << self
16-
attr_writer :color_enabled
17-
end
18-
1915
def self.reset_sequence
2016
ResetSequence.new
2117
end
2218

23-
def self.color_enabled?
24-
@color_enabled
25-
end
26-
27-
def self.colorize(*args, **opts, &block)
28-
if color_enabled?
29-
ColorizedDocument.new(*args, **opts, &block)
30-
else
31-
UncolorizedDocument.new(*args, **opts, &block)
32-
end
33-
end
34-
3519
def self.decolorize(text)
3620
text.gsub(/\e\[\d+(?:;\d+)*m(.+?)\e\[0m/, '\1')
3721
end
3822

3923
def self.already_colorized?(text)
4024
text.match?(/\e\[\d+m/)
4125
end
42-
43-
def self.inspect_colors_in(text)
44-
[FourBitColor, EightBitColor, TwentyFourBitColor].reduce(
45-
text
46-
) do |str, klass|
47-
klass.sub_colorized_areas_in(str) do |area, color|
48-
color_block = colorize("◼︎", color.to_foreground)
49-
50-
layer_indicator = (color.foreground? ? "(fg)" : "(bg)")
51-
52-
"#{color_block} #{layer_indicator}#{area}❯"
53-
end
54-
end
55-
end
56-
57-
self.color_enabled = false
5826
end
5927
end

spec/spec_helper.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
unless defined?(ActiveSupport)
6969
config.filter_run_excluding active_support: true
7070
end
71+
config.filter_run_excluding with_superdiff_rspec: false
7172

7273
config.order = :random
7374
Kernel.srand config.seed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
require "delegate"
2+
require "super_diff"
3+
4+
class FakeTTYDecorator < SimpleDelegator
5+
def initialize(obj, is_tty:)
6+
super(obj)
7+
@is_tty = is_tty
8+
end
9+
10+
def isatty = @is_tty
11+
def tty? = isatty
12+
end
13+
14+
RSpec.describe SuperDiff::Core::Configuration, with_superdiff_rspec: false do
15+
describe "#color_enabled?" do
16+
it "is true when stdout is a TTY" do
17+
original_stdout = $stdout
18+
color_enabled = nil
19+
begin
20+
$stdout = FakeTTYDecorator.new(StringIO.new, is_tty: true)
21+
color_enabled = SuperDiff.configuration.color_enabled?
22+
ensure
23+
$stdout = original_stdout
24+
end
25+
expect(color_enabled).to be(true)
26+
end
27+
28+
it "is false when stdout is not a TTY but we are in CI" do
29+
original_stdout = $stdout
30+
original_ci = ENV["CI"]
31+
color_enabled = nil
32+
begin
33+
$stdout = FakeTTYDecorator.new(StringIO.new, is_tty: false)
34+
ENV["CI"] = "true"
35+
color_enabled = SuperDiff.configuration.color_enabled?
36+
ensure
37+
$stdout = original_stdout
38+
ENV["CI"] = original_ci
39+
end
40+
expect(color_enabled).to be(true)
41+
end
42+
43+
it "is false when stdout is not a TTY and we are not in CI" do
44+
original_stdout = $stdout
45+
original_ci = ENV["CI"]
46+
color_enabled = nil
47+
begin
48+
$stdout = FakeTTYDecorator.new(StringIO.new, is_tty: false)
49+
ENV["CI"] = nil
50+
color_enabled = SuperDiff.configuration.color_enabled?
51+
ensure
52+
$stdout = original_stdout
53+
ENV["CI"] = original_ci
54+
end
55+
expect(color_enabled).to be(false)
56+
end
57+
end
58+
end

0 commit comments

Comments
 (0)