Skip to content

Commit 573a591

Browse files
committed
🥅💄 Auto-highlight parse error based on env vars
Highlighting will be used when either: * `ENV["TERM"]` is set, and not empty, "dumb", or "unknown" * `ENV["FORCE_COLOR"]` is set, and not empty, or "0" I originally checked `$stderr.tty?`, but I think that, in this case, using ENV vars is both simpler and better.
1 parent d6809ff commit 573a591

2 files changed

Lines changed: 45 additions & 3 deletions

File tree

lib/net/imap/errors.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,12 @@ def initialize(message = "unspecified parse error",
116116
# containing only frames for methods in parser_class (since ruby 3.4) or
117117
# which have "net/imap/response_parser" in the path (before ruby 3.4).
118118
# Most parser method names are based on rules in the IMAP grammar.
119+
#
120+
# When +highlight+ is not explicitly set, highlights may be enabled
121+
# automatically, based on +TERM+ and +FORCE_COLOR+ environment variables.
119122
def detailed_message(parser_state: Net::IMAP.debug,
120123
parser_backtrace: false,
121-
highlight: false,
124+
highlight: default_highlight_from_env,
122125
**)
123126
return super unless parser_state || parser_backtrace
124127
msg = super.dup
@@ -161,6 +164,12 @@ def detailed_message(parser_state: Net::IMAP.debug,
161164
def processed_string = string && pos && string[...pos]
162165
def remaining_string = string && pos && string[pos..]
163166

167+
private
168+
169+
def default_highlight_from_env
170+
(ENV["FORCE_COLOR"] || "") !~ /\A(?:0|)\z/ ||
171+
(ENV["TERM"] || "") !~ /\A(?:dumb|unknown|)\z/i
172+
end
164173
end
165174

166175
# Superclass of all errors used to encapsulate "fail" responses

test/net/imap/test_errors.rb

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ def self.SGR(*attr) = CSI attr.join(?;), ?m
1212
BOLD = SGR 1
1313
BOLD_UNDERLINE = SGR 1, 4
1414

15+
setup do
16+
@term_env_vars = ENV["TERM"], ENV["NO_COLOR"], ENV["FORCE_COLOR"]
17+
ENV["TERM"], ENV["NO_COLOR"], ENV["FORCE_COLOR"] = nil, nil, nil
18+
end
19+
20+
teardown do
21+
ENV["TERM"], ENV["NO_COLOR"], ENV["FORCE_COLOR"] = @term_env_vars
22+
end
23+
1524
test "ResponseParseError" do
1625
# The first examples don't add parser state, so this makes no difference.
1726
# It affects the last example, which has parser state.
@@ -64,15 +73,16 @@ def self.SGR(*attr) = CSI attr.join(?;), ?m
6473
"#{BOLD}#{msg} (#{BOLD_UNDERLINE}#{name}#{RESET}#{BOLD})#{RESET}",
6574
err.detailed_message(highlight: true, parser_state: false)
6675
)
67-
assert_equal(<<~MSG.strip, err.detailed_message)
76+
77+
expected_no_hl = <<~MSG.strip
6878
#{msg} (#{name})
6979
processed : "tag OK [Error=\\"Microsoft.Exchange.Error: foo\\""
7080
remaining : "] done\\r\\n"
7181
pos : 45
7282
lex_state : :EXPR_BEG
7383
token : :QUOTED => "Microsoft.Exchange.Error: foo"
7484
MSG
75-
assert_equal(<<~MSG.strip, err.detailed_message(highlight: true))
85+
expected_no_color = <<~MSG.strip
7686
#{BOLD}#{msg} (#{BOLD_UNDERLINE}#{name}#{RESET}#{BOLD})#{RESET}
7787
processed : #{BOLD}"tag OK [Error=\\"Microsoft.Exchange.Error: foo\\""#{RESET}
7888
remaining : #{BOLD_UNDERLINE}"] done\\r\\n"#{RESET}
@@ -81,6 +91,29 @@ def self.SGR(*attr) = CSI attr.join(?;), ?m
8191
token : #{BOLD}:QUOTED#{RESET} => #{BOLD}"Microsoft.Exchange.Error: foo"#{RESET}
8292
MSG
8393

94+
ENV["TERM"], ENV["NO_COLOR"], ENV["FORCE_COLOR"] = nil, nil, "0"
95+
assert_equal(expected_no_hl, err.detailed_message)
96+
assert_equal(expected_no_color, err.detailed_message(highlight: true))
97+
98+
ENV["TERM"], ENV["NO_COLOR"], ENV["FORCE_COLOR"] = "dumb", "1", nil
99+
assert_equal(expected_no_hl, err.detailed_message)
100+
assert_equal(expected_no_color, err.detailed_message(highlight: true))
101+
102+
ENV["TERM"], ENV["NO_COLOR"], ENV["FORCE_COLOR"] = "xterm", nil, nil
103+
assert_equal(expected_no_color, err.detailed_message)
104+
assert_equal(expected_no_hl, err.detailed_message(highlight: false))
105+
106+
ENV["TERM"], ENV["NO_COLOR"], ENV["FORCE_COLOR"] = "dumb", nil, "1"
107+
assert_equal(expected_no_color, err.detailed_message)
108+
assert_equal(expected_no_hl, err.detailed_message(highlight: false))
109+
110+
ENV["TERM"], ENV["NO_COLOR"], ENV["FORCE_COLOR"] = "unknown", "1", "1"
111+
assert_equal(expected_no_color, err.detailed_message)
112+
assert_equal(expected_no_hl, err.detailed_message(highlight: false))
113+
114+
# reset to nil
115+
ENV["TERM"], ENV["NO_COLOR"], ENV["FORCE_COLOR"] = nil, nil, nil
116+
84117
# `parser_state` defaults to `Net::IMAP.debug`:
85118
Net::IMAP.debug = false
86119
assert_equal("#{msg} (#{name})", err.detailed_message)

0 commit comments

Comments
 (0)