error_highlight 0.5.1 → 0.7.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/.github/workflows/ruby.yml +21 -2
- data/lib/error_highlight/base.rb +318 -2
- data/lib/error_highlight/formatter.rb +57 -6
- data/lib/error_highlight/version.rb +1 -1
- metadata +4 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c61fd8e89a64b337d10859ca487015ad69c87555057ce7f15b274ce799a5beb3
|
|
4
|
+
data.tar.gz: 946058938dc70f583672f9adf1450a1514e4922638e051b2755545017f266963
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b5a627e7b0a5710be27e62444a5127353e592cb5dd075ec0a25aa957fdf92e7c3e730b30a0fe5b4d1d35eabd9cde9dd6abafbc22a3f071ad7af8f39f991ee634
|
|
7
|
+
data.tar.gz: 6e72a445acf82b23d8a6deb6537504dfe64b50d74a808ff33104da5dccad6970256f115ef1dc786a25136457ce18b801d0d466b7b8c8dac4ba0d70ab3b5732cc
|
data/.github/workflows/ruby.yml
CHANGED
|
@@ -9,13 +9,20 @@ on:
|
|
|
9
9
|
- 'master'
|
|
10
10
|
|
|
11
11
|
jobs:
|
|
12
|
+
ruby-versions:
|
|
13
|
+
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
|
|
14
|
+
with:
|
|
15
|
+
engine: cruby
|
|
16
|
+
min_version: 3.1
|
|
17
|
+
|
|
12
18
|
build:
|
|
19
|
+
needs: ruby-versions
|
|
13
20
|
runs-on: ubuntu-latest
|
|
14
21
|
strategy:
|
|
15
22
|
matrix:
|
|
16
|
-
ruby:
|
|
23
|
+
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
|
|
17
24
|
steps:
|
|
18
|
-
- uses: actions/checkout@
|
|
25
|
+
- uses: actions/checkout@v4
|
|
19
26
|
- uses: ruby/setup-ruby@v1
|
|
20
27
|
with:
|
|
21
28
|
ruby-version: ${{ matrix.ruby }}
|
|
@@ -25,3 +32,15 @@ jobs:
|
|
|
25
32
|
- name: Run the test suite
|
|
26
33
|
run: |
|
|
27
34
|
RUBYOPT=--disable-error_highlight bundle exec rake TESTOPT=-v
|
|
35
|
+
|
|
36
|
+
prism:
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
- uses: ruby/setup-ruby@v1
|
|
41
|
+
with:
|
|
42
|
+
ruby-version: head
|
|
43
|
+
bundler-cache: true
|
|
44
|
+
- name: Run the test suite
|
|
45
|
+
run: |
|
|
46
|
+
RUBYOPT="--disable-error_highlight --parser=prism" bundle exec rake TESTOPT=-v
|
data/lib/error_highlight/base.rb
CHANGED
|
@@ -54,11 +54,20 @@ module ErrorHighlight
|
|
|
54
54
|
|
|
55
55
|
return nil unless Thread::Backtrace::Location === loc
|
|
56
56
|
|
|
57
|
-
node =
|
|
57
|
+
node =
|
|
58
|
+
begin
|
|
59
|
+
RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
|
|
60
|
+
rescue RuntimeError => error
|
|
61
|
+
# RubyVM::AbstractSyntaxTree.of raises an error with a message that
|
|
62
|
+
# includes "prism" when the ISEQ was compiled with the prism compiler.
|
|
63
|
+
# In this case, we'll try to parse again with prism instead.
|
|
64
|
+
raise unless error.message.include?("prism")
|
|
65
|
+
prism_find(loc)
|
|
66
|
+
end
|
|
58
67
|
|
|
59
68
|
Spotter.new(node, **opts).spot
|
|
60
69
|
|
|
61
|
-
when RubyVM::AbstractSyntaxTree::Node
|
|
70
|
+
when RubyVM::AbstractSyntaxTree::Node, Prism::Node
|
|
62
71
|
Spotter.new(obj, **opts).spot
|
|
63
72
|
|
|
64
73
|
else
|
|
@@ -72,6 +81,21 @@ module ErrorHighlight
|
|
|
72
81
|
return nil
|
|
73
82
|
end
|
|
74
83
|
|
|
84
|
+
# Accepts a Thread::Backtrace::Location object and returns a Prism::Node
|
|
85
|
+
# corresponding to the backtrace location in the source code.
|
|
86
|
+
def self.prism_find(location)
|
|
87
|
+
require "prism"
|
|
88
|
+
return nil if Prism::VERSION < "1.0.0"
|
|
89
|
+
|
|
90
|
+
absolute_path = location.absolute_path
|
|
91
|
+
return unless absolute_path
|
|
92
|
+
|
|
93
|
+
node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(location)
|
|
94
|
+
Prism.parse_file(absolute_path).value.breadth_first_search { |node| node.node_id == node_id }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private_class_method :prism_find
|
|
98
|
+
|
|
75
99
|
class Spotter
|
|
76
100
|
class NonAscii < Exception; end
|
|
77
101
|
private_constant :NonAscii
|
|
@@ -98,9 +122,58 @@ module ErrorHighlight
|
|
|
98
122
|
end
|
|
99
123
|
end
|
|
100
124
|
|
|
125
|
+
OPT_GETCONSTANT_PATH = (RUBY_VERSION.split(".").map {|s| s.to_i } <=> [3, 2]) >= 0
|
|
126
|
+
private_constant :OPT_GETCONSTANT_PATH
|
|
127
|
+
|
|
101
128
|
def spot
|
|
102
129
|
return nil unless @node
|
|
103
130
|
|
|
131
|
+
if OPT_GETCONSTANT_PATH
|
|
132
|
+
# In Ruby 3.2 or later, a nested constant access (like `Foo::Bar::Baz`)
|
|
133
|
+
# is compiled to one instruction (opt_getconstant_path).
|
|
134
|
+
# @node points to the node of the whole `Foo::Bar::Baz` even if `Foo`
|
|
135
|
+
# or `Foo::Bar` causes NameError.
|
|
136
|
+
# So we try to spot the sub-node that causes the NameError by using
|
|
137
|
+
# `NameError#name`.
|
|
138
|
+
case @node.type
|
|
139
|
+
when :COLON2
|
|
140
|
+
subnodes = []
|
|
141
|
+
node = @node
|
|
142
|
+
while node.type == :COLON2
|
|
143
|
+
node2, const = node.children
|
|
144
|
+
subnodes << node if const == @name
|
|
145
|
+
node = node2
|
|
146
|
+
end
|
|
147
|
+
if node.type == :CONST || node.type == :COLON3
|
|
148
|
+
if node.children.first == @name
|
|
149
|
+
subnodes << node
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# If we found only one sub-node whose name is equal to @name, use it
|
|
153
|
+
return nil if subnodes.size != 1
|
|
154
|
+
@node = subnodes.first
|
|
155
|
+
else
|
|
156
|
+
# Do nothing; opt_getconstant_path is used only when the const base is
|
|
157
|
+
# NODE_CONST (`Foo`) or NODE_COLON3 (`::Foo`)
|
|
158
|
+
end
|
|
159
|
+
when :constant_path_node
|
|
160
|
+
subnodes = []
|
|
161
|
+
node = @node
|
|
162
|
+
|
|
163
|
+
begin
|
|
164
|
+
subnodes << node if node.name == @name
|
|
165
|
+
end while (node = node.parent).is_a?(Prism::ConstantPathNode)
|
|
166
|
+
|
|
167
|
+
if node.is_a?(Prism::ConstantReadNode) && node.name == @name
|
|
168
|
+
subnodes << node
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# If we found only one sub-node whose name is equal to @name, use it
|
|
172
|
+
return nil if subnodes.size != 1
|
|
173
|
+
@node = subnodes.first
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
104
177
|
case @node.type
|
|
105
178
|
|
|
106
179
|
when :CALL, :QCALL
|
|
@@ -165,6 +238,48 @@ module ErrorHighlight
|
|
|
165
238
|
|
|
166
239
|
when :OP_CDECL
|
|
167
240
|
spot_op_cdecl
|
|
241
|
+
|
|
242
|
+
when :call_node
|
|
243
|
+
case @point_type
|
|
244
|
+
when :name
|
|
245
|
+
prism_spot_call_for_name
|
|
246
|
+
when :args
|
|
247
|
+
prism_spot_call_for_args
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
when :local_variable_operator_write_node
|
|
251
|
+
case @point_type
|
|
252
|
+
when :name
|
|
253
|
+
prism_spot_local_variable_operator_write_for_name
|
|
254
|
+
when :args
|
|
255
|
+
prism_spot_local_variable_operator_write_for_args
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
when :call_operator_write_node
|
|
259
|
+
case @point_type
|
|
260
|
+
when :name
|
|
261
|
+
prism_spot_call_operator_write_for_name
|
|
262
|
+
when :args
|
|
263
|
+
prism_spot_call_operator_write_for_args
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
when :index_operator_write_node
|
|
267
|
+
case @point_type
|
|
268
|
+
when :name
|
|
269
|
+
prism_spot_index_operator_write_for_name
|
|
270
|
+
when :args
|
|
271
|
+
prism_spot_index_operator_write_for_args
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
when :constant_read_node
|
|
275
|
+
prism_spot_constant_read
|
|
276
|
+
|
|
277
|
+
when :constant_path_node
|
|
278
|
+
prism_spot_constant_path
|
|
279
|
+
|
|
280
|
+
when :constant_path_operator_write_node
|
|
281
|
+
prism_spot_constant_path_operator_write
|
|
282
|
+
|
|
168
283
|
end
|
|
169
284
|
|
|
170
285
|
if @snippet && @beg_column && @end_column && @beg_column < @end_column
|
|
@@ -508,6 +623,207 @@ module ErrorHighlight
|
|
|
508
623
|
@beg_lineno = @end_lineno = lineno
|
|
509
624
|
@snippet = @fetch[lineno]
|
|
510
625
|
end
|
|
626
|
+
|
|
627
|
+
# Take a location from the prism parser and set the necessary instance
|
|
628
|
+
# variables.
|
|
629
|
+
def prism_location(location)
|
|
630
|
+
@beg_lineno = location.start_line
|
|
631
|
+
@beg_column = location.start_column
|
|
632
|
+
@end_lineno = location.end_line
|
|
633
|
+
@end_column = location.end_column
|
|
634
|
+
@snippet = @fetch[@beg_lineno, @end_lineno]
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
# Example:
|
|
638
|
+
# x.foo
|
|
639
|
+
# ^^^^
|
|
640
|
+
# x.foo(42)
|
|
641
|
+
# ^^^^
|
|
642
|
+
# x&.foo
|
|
643
|
+
# ^^^^^
|
|
644
|
+
# x[42]
|
|
645
|
+
# ^^^^
|
|
646
|
+
# x.foo = 1
|
|
647
|
+
# ^^^^^^
|
|
648
|
+
# x[42] = 1
|
|
649
|
+
# ^^^^^^
|
|
650
|
+
# x + 1
|
|
651
|
+
# ^
|
|
652
|
+
# +x
|
|
653
|
+
# ^
|
|
654
|
+
# foo(42)
|
|
655
|
+
# ^^^
|
|
656
|
+
# foo 42
|
|
657
|
+
# ^^^
|
|
658
|
+
# foo
|
|
659
|
+
# ^^^
|
|
660
|
+
def prism_spot_call_for_name
|
|
661
|
+
# Explicitly turn off foo.() syntax because error_highlight expects this
|
|
662
|
+
# to not work.
|
|
663
|
+
return nil if @node.name == :call && @node.message_loc.nil?
|
|
664
|
+
|
|
665
|
+
location = @node.message_loc || @node.call_operator_loc || @node.location
|
|
666
|
+
location = @node.call_operator_loc.join(location) if @node.call_operator_loc&.start_line == location.start_line
|
|
667
|
+
|
|
668
|
+
# If the method name ends with "=" but the message does not, then this is
|
|
669
|
+
# a method call using the "attribute assignment" syntax
|
|
670
|
+
# (e.g., foo.bar = 1). In this case we need to go retrieve the = sign and
|
|
671
|
+
# add it to the location.
|
|
672
|
+
if (name = @node.name).end_with?("=") && !@node.message.end_with?("=")
|
|
673
|
+
location = location.adjoin("=")
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
prism_location(location)
|
|
677
|
+
|
|
678
|
+
if !name.end_with?("=") && !name.match?(/[[:alpha:]_\[]/)
|
|
679
|
+
# If the method name is an operator, then error_highlight only
|
|
680
|
+
# highlights the first line.
|
|
681
|
+
fetch_line(location.start_line)
|
|
682
|
+
end
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
# Example:
|
|
686
|
+
# x.foo(42)
|
|
687
|
+
# ^^
|
|
688
|
+
# x[42]
|
|
689
|
+
# ^^
|
|
690
|
+
# x.foo = 1
|
|
691
|
+
# ^
|
|
692
|
+
# x[42] = 1
|
|
693
|
+
# ^^^^^^^
|
|
694
|
+
# x[] = 1
|
|
695
|
+
# ^^^^^
|
|
696
|
+
# x + 1
|
|
697
|
+
# ^
|
|
698
|
+
# foo(42)
|
|
699
|
+
# ^^
|
|
700
|
+
# foo 42
|
|
701
|
+
# ^^
|
|
702
|
+
def prism_spot_call_for_args
|
|
703
|
+
# Disallow highlighting arguments if there are no arguments.
|
|
704
|
+
return if @node.arguments.nil?
|
|
705
|
+
|
|
706
|
+
# Explicitly turn off foo.() syntax because error_highlight expects this
|
|
707
|
+
# to not work.
|
|
708
|
+
return nil if @node.name == :call && @node.message_loc.nil?
|
|
709
|
+
|
|
710
|
+
if @node.name == :[]= && @node.opening == "[" && (@node.arguments&.arguments || []).length == 1
|
|
711
|
+
prism_location(@node.opening_loc.copy(start_offset: @node.opening_loc.start_offset + 1).join(@node.arguments.location))
|
|
712
|
+
else
|
|
713
|
+
prism_location(@node.arguments.location)
|
|
714
|
+
end
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
# Example:
|
|
718
|
+
# x += 1
|
|
719
|
+
# ^
|
|
720
|
+
def prism_spot_local_variable_operator_write_for_name
|
|
721
|
+
prism_location(@node.binary_operator_loc.chop)
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
# Example:
|
|
725
|
+
# x += 1
|
|
726
|
+
# ^
|
|
727
|
+
def prism_spot_local_variable_operator_write_for_args
|
|
728
|
+
prism_location(@node.value.location)
|
|
729
|
+
end
|
|
730
|
+
|
|
731
|
+
# Example:
|
|
732
|
+
# x.foo += 42
|
|
733
|
+
# ^^^ (for foo)
|
|
734
|
+
# x.foo += 42
|
|
735
|
+
# ^ (for +)
|
|
736
|
+
# x.foo += 42
|
|
737
|
+
# ^^^^^^^ (for foo=)
|
|
738
|
+
def prism_spot_call_operator_write_for_name
|
|
739
|
+
if !@name.start_with?(/[[:alpha:]_]/)
|
|
740
|
+
prism_location(@node.binary_operator_loc.chop)
|
|
741
|
+
else
|
|
742
|
+
location = @node.message_loc
|
|
743
|
+
if @node.call_operator_loc.start_line == location.start_line
|
|
744
|
+
location = @node.call_operator_loc.join(location)
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
location = location.adjoin("=") if @name.end_with?("=")
|
|
748
|
+
prism_location(location)
|
|
749
|
+
end
|
|
750
|
+
end
|
|
751
|
+
|
|
752
|
+
# Example:
|
|
753
|
+
# x.foo += 42
|
|
754
|
+
# ^^
|
|
755
|
+
def prism_spot_call_operator_write_for_args
|
|
756
|
+
prism_location(@node.value.location)
|
|
757
|
+
end
|
|
758
|
+
|
|
759
|
+
# Example:
|
|
760
|
+
# x[1] += 42
|
|
761
|
+
# ^^^ (for [])
|
|
762
|
+
# x[1] += 42
|
|
763
|
+
# ^ (for +)
|
|
764
|
+
# x[1] += 42
|
|
765
|
+
# ^^^^^^ (for []=)
|
|
766
|
+
def prism_spot_index_operator_write_for_name
|
|
767
|
+
case @name
|
|
768
|
+
when :[]
|
|
769
|
+
prism_location(@node.opening_loc.join(@node.closing_loc))
|
|
770
|
+
when :[]=
|
|
771
|
+
prism_location(@node.opening_loc.join(@node.closing_loc).adjoin("="))
|
|
772
|
+
else
|
|
773
|
+
# Explicitly turn off foo[] += 1 syntax when the operator is not on
|
|
774
|
+
# the same line because error_highlight expects this to not work.
|
|
775
|
+
return nil if @node.binary_operator_loc.start_line != @node.opening_loc.start_line
|
|
776
|
+
|
|
777
|
+
prism_location(@node.binary_operator_loc.chop)
|
|
778
|
+
end
|
|
779
|
+
end
|
|
780
|
+
|
|
781
|
+
# Example:
|
|
782
|
+
# x[1] += 42
|
|
783
|
+
# ^^^^^^^^
|
|
784
|
+
def prism_spot_index_operator_write_for_args
|
|
785
|
+
opening_loc =
|
|
786
|
+
if @node.arguments.nil?
|
|
787
|
+
@node.opening_loc.copy(start_offset: @node.opening_loc.start_offset + 1)
|
|
788
|
+
else
|
|
789
|
+
@node.arguments.location
|
|
790
|
+
end
|
|
791
|
+
|
|
792
|
+
prism_location(opening_loc.join(@node.value.location))
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
# Example:
|
|
796
|
+
# Foo
|
|
797
|
+
# ^^^
|
|
798
|
+
def prism_spot_constant_read
|
|
799
|
+
prism_location(@node.location)
|
|
800
|
+
end
|
|
801
|
+
|
|
802
|
+
# Example:
|
|
803
|
+
# Foo::Bar
|
|
804
|
+
# ^^^^^
|
|
805
|
+
def prism_spot_constant_path
|
|
806
|
+
if @node.parent && @node.parent.location.end_line == @node.location.end_line
|
|
807
|
+
fetch_line(@node.parent.location.end_line)
|
|
808
|
+
prism_location(@node.delimiter_loc.join(@node.name_loc))
|
|
809
|
+
else
|
|
810
|
+
fetch_line(@node.location.end_line)
|
|
811
|
+
location = @node.name_loc
|
|
812
|
+
location = @node.delimiter_loc.join(location) if @node.delimiter_loc.end_line == location.start_line
|
|
813
|
+
prism_location(location)
|
|
814
|
+
end
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
# Example:
|
|
818
|
+
# Foo::Bar += 1
|
|
819
|
+
# ^^^^^^^^
|
|
820
|
+
def prism_spot_constant_path_operator_write
|
|
821
|
+
if @name == (target = @node.target).name
|
|
822
|
+
prism_location(target.delimiter_loc.join(target.name_loc))
|
|
823
|
+
else
|
|
824
|
+
prism_location(@node.binary_operator_loc.chop)
|
|
825
|
+
end
|
|
826
|
+
end
|
|
511
827
|
end
|
|
512
828
|
|
|
513
829
|
private_constant :Spotter
|
|
@@ -1,15 +1,66 @@
|
|
|
1
1
|
module ErrorHighlight
|
|
2
2
|
class DefaultFormatter
|
|
3
|
+
MIN_SNIPPET_WIDTH = 20
|
|
4
|
+
|
|
3
5
|
def self.message_for(spot)
|
|
4
6
|
# currently only a one-line code snippet is supported
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
return "" unless spot[:first_lineno] == spot[:last_lineno]
|
|
8
|
+
|
|
9
|
+
snippet = spot[:snippet]
|
|
10
|
+
first_column = spot[:first_column]
|
|
11
|
+
last_column = spot[:last_column]
|
|
12
|
+
ellipsis = "..."
|
|
13
|
+
|
|
14
|
+
# truncate snippet to fit in the viewport
|
|
15
|
+
if max_snippet_width && snippet.size > max_snippet_width
|
|
16
|
+
available_width = max_snippet_width - ellipsis.size
|
|
17
|
+
center = first_column - max_snippet_width / 2
|
|
18
|
+
|
|
19
|
+
visible_start = last_column < available_width ? 0 : [center, 0].max
|
|
20
|
+
visible_end = visible_start + max_snippet_width
|
|
21
|
+
visible_start = snippet.size - max_snippet_width if visible_end > snippet.size
|
|
22
|
+
|
|
23
|
+
prefix = visible_start.positive? ? ellipsis : ""
|
|
24
|
+
suffix = visible_end < snippet.size ? ellipsis : ""
|
|
8
25
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
26
|
+
snippet = prefix + snippet[(visible_start + prefix.size)...(visible_end - suffix.size)] + suffix
|
|
27
|
+
snippet << "\n" unless snippet.end_with?("\n")
|
|
28
|
+
|
|
29
|
+
first_column -= visible_start
|
|
30
|
+
last_column = [last_column - visible_start, snippet.size - 1].min
|
|
12
31
|
end
|
|
32
|
+
|
|
33
|
+
indent = snippet[0...first_column].gsub(/[^\t]/, " ")
|
|
34
|
+
marker = indent + "^" * (last_column - first_column)
|
|
35
|
+
|
|
36
|
+
"\n\n#{ snippet }#{ marker }"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.max_snippet_width
|
|
40
|
+
return if Ractor.current[:__error_highlight_max_snippet_width__] == :disabled
|
|
41
|
+
|
|
42
|
+
Ractor.current[:__error_highlight_max_snippet_width__] ||= terminal_width
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.max_snippet_width=(width)
|
|
46
|
+
return Ractor.current[:__error_highlight_max_snippet_width__] = :disabled if width.nil?
|
|
47
|
+
|
|
48
|
+
width = width.to_i
|
|
49
|
+
|
|
50
|
+
if width < MIN_SNIPPET_WIDTH
|
|
51
|
+
warn "'max_snippet_width' adjusted to minimum value of #{MIN_SNIPPET_WIDTH}."
|
|
52
|
+
width = MIN_SNIPPET_WIDTH
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
Ractor.current[:__error_highlight_max_snippet_width__] = width
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.terminal_width
|
|
59
|
+
# lazy load io/console, so it's not loaded when 'max_snippet_width' is set
|
|
60
|
+
require "io/console"
|
|
61
|
+
STDERR.winsize[1] if STDERR.tty?
|
|
62
|
+
rescue LoadError, NoMethodError, SystemCallError
|
|
63
|
+
# do not truncate when window size is not available
|
|
13
64
|
end
|
|
14
65
|
end
|
|
15
66
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: error_highlight
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
|
+
original_platform: ''
|
|
6
7
|
authors:
|
|
7
8
|
- Yusuke Endoh
|
|
8
|
-
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-12-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: The gem enhances Exception#message by adding a short explanation where
|
|
14
14
|
the exception is raised
|
|
@@ -35,7 +35,6 @@ homepage: https://github.com/ruby/error_highlight
|
|
|
35
35
|
licenses:
|
|
36
36
|
- MIT
|
|
37
37
|
metadata: {}
|
|
38
|
-
post_install_message:
|
|
39
38
|
rdoc_options: []
|
|
40
39
|
require_paths:
|
|
41
40
|
- lib
|
|
@@ -50,8 +49,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
50
49
|
- !ruby/object:Gem::Version
|
|
51
50
|
version: '0'
|
|
52
51
|
requirements: []
|
|
53
|
-
rubygems_version: 3.
|
|
54
|
-
signing_key:
|
|
52
|
+
rubygems_version: 3.6.0.dev
|
|
55
53
|
specification_version: 4
|
|
56
54
|
summary: Shows a one-line code snippet with an underline in the error backtrace
|
|
57
55
|
test_files: []
|