semver_dialects 2.0.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,288 +0,0 @@
1
- module IntervalType
2
- UNKNOWN = 0
3
- LEFT_OPEN = 1
4
- LEFT_CLOSED = 2
5
- RIGHT_OPEN = 4
6
- RIGHT_CLOSED = 8
7
- end
8
-
9
- class VersionInterval
10
- attr_accessor :type, :start_cut, :end_cut
11
-
12
- def initialize(type, start_cut, end_cut)
13
- @type = type
14
- @start_cut = start_cut
15
- @end_cut = end_cut
16
- end
17
-
18
- def intersect(other_interval)
19
- return EmptyInterval.new if self.empty?
20
-
21
- # this look odd -- we have to use it here though, because it may be that placeholders are present inside
22
- # the version for which > and < would yield true
23
- return EmptyInterval.new if !(@start_cut <= other_interval.end_cut) || !(other_interval.start_cut <= @end_cut)
24
-
25
- start_cut_new = max(@start_cut, other_interval.start_cut)
26
- end_cut_new = min(@end_cut, other_interval.end_cut)
27
-
28
- # compute the boundaries for the intersection
29
- type = compute_intersection_boundary(self, other_interval, start_cut_new, end_cut_new)
30
- interval = VersionInterval.new(type, start_cut_new, end_cut_new)
31
- half_open = !(interval.bit_set?(IntervalType::RIGHT_CLOSED) && interval.bit_set?(IntervalType::LEFT_CLOSED))
32
-
33
- interval.singleton? && half_open ? EmptyInterval.new : interval
34
- end
35
-
36
- def union(other_interval)
37
- return EmptyInterval.new if self.intersect(other_interval).instance_of?(EmptyInterval)
38
-
39
- start_cut_new = min(@start_cut, other_interval.start_cut)
40
- end_cut_new = max(@end_cut, other_interval.end_cut)
41
-
42
- # compute the boundaries for the union
43
- type = compute_union_boundary(self, other_interval, start_cut_new, end_cut_new)
44
- VersionInterval.new(type, start_cut_new, end_cut_new)
45
- end
46
-
47
- def collapse(other_interval)
48
- return EmptyInterval.new if self.intersect(other_interval).instance_of?(EmptyInterval)
49
-
50
- frame = [@start_cut, other_interval.start_cut, @end_cut, other_interval.end_cut].reject { |cut| special(cut) }
51
- min_cut = frame.reduce { |smallest, current| smallest < current ? smallest : current }
52
- max_cut = frame.reduce { |biggest, current| biggest > current ? biggest : current }
53
-
54
- # compute the boundaries for the union
55
- type = compute_union_boundary(self, other_interval, min_cut, max_cut)
56
- VersionInterval.new(type, min_cut, max_cut)
57
- end
58
-
59
- def special(cut)
60
- cut.instance_of?(AboveAll) || cut.instance_of?(BelowAll)
61
- end
62
-
63
- def to_s
64
- s = ""
65
- s += bit_set?(IntervalType::LEFT_CLOSED) ? "[" : ""
66
- s += bit_set?(IntervalType::LEFT_OPEN) ? "(" : ""
67
- s += [@start_cut, @end_cut].join(",")
68
- s += bit_set?(IntervalType::RIGHT_CLOSED) ? "]" : ""
69
- s += bit_set?(IntervalType::RIGHT_OPEN) ? ")" : ""
70
- s
71
- end
72
-
73
- # this function returns a human-readable descriptions of the version strings
74
- def to_description_s
75
- s = ""
76
- if self.distinct?
77
- s = "version #{@start_cut.to_s}"
78
- elsif self.universal?
79
- s = "all versions "
80
- else
81
- s = "all versions "
82
- s += start_cut.instance_of?(BelowAll) ? "" : bit_set?(IntervalType::LEFT_OPEN) ? "after #{@start_cut.to_s} " : bit_set?(IntervalType::LEFT_CLOSED) ? "starting from #{@start_cut.to_s} " : ""
83
- s += end_cut.instance_of?(AboveAll) ? "" : bit_set?(IntervalType::RIGHT_OPEN) ? "before #{@end_cut.to_s}" : bit_set?(IntervalType::RIGHT_CLOSED) ? "up to #{@end_cut.to_s}" : ""
84
- end
85
- s.strip
86
- end
87
-
88
- def to_nuget_s
89
- to_maven_s
90
- end
91
-
92
- def to_maven_s
93
- s = ""
94
- # special case -- distinct version
95
- if self.distinct?
96
- s += "[#{@start_cut.to_s}]"
97
- else
98
- s += start_cut.instance_of?(BelowAll) ? "(," : bit_set?(IntervalType::LEFT_OPEN) ? "[#{@start_cut.to_s}," : bit_set?(IntervalType::LEFT_CLOSED) ? "[#{@start_cut.to_s}," : ""
99
- s += end_cut.instance_of?(AboveAll) ? ")" : bit_set?(IntervalType::RIGHT_OPEN) ? "#{@end_cut.to_s})" : bit_set?(IntervalType::RIGHT_CLOSED) ? "#{@end_cut.to_s}]" : ""
100
- end
101
- s
102
- end
103
-
104
- def distinct?
105
- bit_set?(IntervalType::LEFT_CLOSED) && bit_set?(IntervalType::RIGHT_CLOSED) && @start_cut == @end_cut
106
- end
107
-
108
- def subsumes?(other)
109
- @start_cut <= other.start_cut && @end_cut >= other.end_cut
110
- end
111
-
112
- def universal?
113
- (bit_set?(IntervalType::LEFT_OPEN) && bit_set?(IntervalType::RIGHT_OPEN) && @start_cut.instance_of?(BelowAll) && @end_cut.instance_of?(AboveAll)) || @start_cut.is_initial_version? && @end_cut.instance_of?(AboveAll)
114
- end
115
-
116
- def to_gem_s
117
- get_canoncial_s
118
- end
119
-
120
- def to_ruby_s
121
- get_canoncial_s
122
- end
123
-
124
- def to_npm_s
125
- get_canoncial_s
126
- end
127
-
128
- def to_conan_s
129
- get_canoncial_s
130
- end
131
-
132
- def to_go_s
133
- get_canoncial_s
134
- end
135
-
136
- def to_pypi_s
137
- get_canoncial_s(',', '==')
138
- end
139
-
140
- def to_packagist_s
141
- get_canoncial_s(',')
142
- end
143
-
144
- def empty?
145
- self.instance_of?(EmptyInterval)
146
- end
147
-
148
- def singleton?
149
- @start_cut == @end_cut && @start_cut.value == @end_cut.value
150
- end
151
-
152
- def diff(other_interval, abs = true)
153
- if self.distinct? && other_interval.distinct?
154
- self.start_cut.diff(other_interval.start_cut, abs)
155
- else
156
- EmptyInterval.new()
157
- end
158
- end
159
-
160
- def joinable?(other_interval)
161
- other_interval.start_cut.is_successor_of?(self.end_cut) || universal?
162
- end
163
-
164
- def join(other_interval)
165
- if self.joinable?(other_interval)
166
- _join(self, other_interval)
167
- elsif other_interval.joinable?(self)
168
- _join(other_interval, self)
169
- else
170
- EmptyInterval.new()
171
- end
172
- end
173
-
174
- def cross_total
175
- if distinct?
176
- @start_cut.cross_total
177
- else
178
- @start_cut.cross_total + @end_cut.cross_total
179
- end
180
- end
181
-
182
- def ==(other_interval)
183
- @start_cut == other_interval.start_cut && @end_cut == other_interval.end_cut && @type == other_interval.type
184
- end
185
-
186
- # inverts the given version interval -- note that this function amy return two version intervals
187
- # e.g., (2,10] -> (-inf, 2], (10, +inf)
188
- # left right
189
- def invert
190
- intervals = []
191
- left_type = bit_set?(IntervalType::LEFT_OPEN) ? IntervalType::RIGHT_CLOSED : IntervalType::RIGHT_OPEN
192
- left_type = left_type | IntervalType::LEFT_OPEN
193
- right_type = bit_set?(IntervalType::RIGHT_OPEN) ? IntervalType::LEFT_CLOSED : IntervalType::LEFT_OPEN
194
- right_type = right_type | IntervalType::RIGHT_OPEN
195
-
196
- intervals << VersionInterval.new(left_type, BelowAll.new, @start_cut) unless @start_cut.instance_of?(BelowAll)
197
- intervals << VersionInterval.new(right_type, @end_cut, AboveAll.new) unless @end_cut.instance_of?(AboveAll)
198
- intervals
199
- end
200
-
201
- def bit_set?(interval_type)
202
- @type & interval_type != 0
203
- end
204
-
205
- protected
206
-
207
- # computes the boundary type for union operation
208
- def compute_union_boundary(interval_a, interval_b, start_cut_new, end_cut_new)
209
- compute_boundary(interval_a, interval_b, start_cut_new, end_cut_new, IntervalType::LEFT_CLOSED, IntervalType::RIGHT_CLOSED)
210
- end
211
-
212
- def compute_intersection_boundary(interval_a, interval_b, start_cut_new, end_cut_new)
213
- compute_boundary(interval_a, interval_b,start_cut_new, end_cut_new, IntervalType::LEFT_OPEN, IntervalType::RIGHT_OPEN)
214
- end
215
-
216
- def compute_boundary(interval_a, interval_b, start_cut_new, end_cut_new, left_check, right_check)
217
- start_cut_a = interval_a.start_cut
218
- end_cut_a = interval_a.end_cut
219
- type_a = interval_a.type
220
-
221
- start_cut_b = interval_b.start_cut
222
- end_cut_b = interval_b.end_cut
223
- type_b = interval_b.type
224
-
225
- left_fill = left_check == IntervalType::LEFT_OPEN ? IntervalType::LEFT_CLOSED : IntervalType::LEFT_OPEN
226
- right_fill = right_check == IntervalType::RIGHT_OPEN ? IntervalType::RIGHT_CLOSED : IntervalType::RIGHT_OPEN
227
-
228
- # compute the boundaries for the union
229
- if start_cut_b == start_cut_a && start_cut_b == start_cut_b
230
- one_left_closed = left_type(type_a) == left_check || left_type(type_b) == left_check
231
- left_type = one_left_closed ? left_check : left_fill
232
- else
233
- left_type = start_cut_new == start_cut_a ? left_type(type_a) : left_type(type_b)
234
- end
235
-
236
- if end_cut_b == end_cut_a && end_cut_b == end_cut_b
237
- one_right_closed = right_type(type_a) == right_check || right_type(type_b) == right_check
238
- right_type = one_right_closed ? right_check : right_fill
239
- else
240
- right_type = end_cut_new == end_cut_a ? right_type(type_a) : right_type(type_b)
241
- end
242
-
243
- left_type | right_type
244
- end
245
-
246
- def _join(first_interval, second_interval)
247
- if first_interval.joinable?(second_interval)
248
- VersionInterval.new(first_interval.type, first_interval.start_cut.dup, second_interval.end_cut.dup)
249
- else
250
- EmptyInterval.new()
251
- end
252
- end
253
-
254
- def get_canoncial_s(delimiter = " ", eq = '=')
255
- if self.distinct?
256
- "#{eq}#{@start_cut.to_s}"
257
- else
258
- first = start_cut.instance_of?(BelowAll) ? "" : bit_set?(IntervalType::LEFT_OPEN) ? ">#{@start_cut.to_s}" : bit_set?(IntervalType::LEFT_CLOSED) ? ">=#{@start_cut.to_s}" : ""
259
- second = end_cut.instance_of?(AboveAll) ? "" : bit_set?(IntervalType::RIGHT_OPEN) ? "<#{@end_cut.to_s}" : bit_set?(IntervalType::RIGHT_CLOSED) ? "<=#{@end_cut.to_s}" : ""
260
- !first.empty? && !second.empty? ? "#{first}#{delimiter}#{second}" : first + second
261
- end
262
- end
263
-
264
- def max(cut_a, cut_b)
265
- cut_a > cut_b ? cut_a : cut_b
266
- end
267
-
268
- def min(cut_a, cut_b)
269
- cut_a < cut_b ? cut_a : cut_b
270
- end
271
-
272
- def right_type(type)
273
- (IntervalType::RIGHT_OPEN | IntervalType::RIGHT_CLOSED) & type
274
- end
275
-
276
- def left_type(type)
277
- (IntervalType::LEFT_OPEN | IntervalType::LEFT_CLOSED) & type
278
- end
279
- end
280
-
281
- class EmptyInterval < VersionInterval
282
- def initialize()
283
- end
284
-
285
- def to_s
286
- "empty"
287
- end
288
- end
@@ -1,40 +0,0 @@
1
- require_relative "version_cut"
2
- require_relative "version_interval"
3
-
4
- module VersionParser
5
- # A constraint is made of an operator followed by a version string.
6
- CONSTRAINT_REGEXP = Regexp.new("(?<op>[><=]+) *(?<version>#{SemanticVersion::VERSION_PATTERN})").freeze
7
-
8
- def self.parse(versionstring)
9
- if (versionstring == "=*")
10
- # special case = All Versions
11
- return VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_OPEN, BelowAll.new(), AboveAll.new())
12
- end
13
-
14
- version_items = versionstring.split(" ")
15
- interval = VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_OPEN, BelowAll.new(), AboveAll.new())
16
- version_items.each do |version_item|
17
- matches = version_item.match CONSTRAINT_REGEXP
18
- raise SemverDialects::InvalidConstraintError, versionstring if matches.nil?
19
- version_string = matches[:version]
20
- case matches[:op]
21
- when ">="
22
- new_interval = VersionInterval.new(IntervalType::LEFT_CLOSED | IntervalType::RIGHT_OPEN, VersionCut.new(version_string), AboveAll.new())
23
- interval = interval.intersect(new_interval)
24
- when "<="
25
- new_interval = VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_CLOSED, BelowAll.new(), VersionCut.new(version_string))
26
- interval = interval.intersect(new_interval)
27
- when "<"
28
- new_interval = VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_OPEN, BelowAll.new(), VersionCut.new(version_string))
29
- interval = interval.intersect(new_interval)
30
- when ">"
31
- new_interval = VersionInterval.new(IntervalType::LEFT_OPEN | IntervalType::RIGHT_OPEN, VersionCut.new(version_string), AboveAll.new())
32
- interval = interval.intersect(new_interval)
33
- when "=", "=="
34
- new_interval = VersionInterval.new(IntervalType::LEFT_CLOSED | IntervalType::RIGHT_CLOSED, VersionCut.new(version_string), VersionCut.new(version_string))
35
- interval = interval.intersect(new_interval)
36
- end
37
- end
38
- interval
39
- end
40
- end
@@ -1,191 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'version_parser'
4
- require 'set'
5
-
6
- # VersionRange is a utility class that helps managing consecutive version ranges automatically
7
- # given that they are added in-order
8
- # Note that join_if_possible should be only activated in case the ranges are added in consecutive order!!
9
- class VersionRange
10
- attr_reader :version_intervals, :join_if_possible
11
-
12
- def initialize(join_if_possible = true)
13
- @version_intervals = []
14
- @version_interval_set = Set.new
15
- @join_if_possible = join_if_possible
16
- end
17
-
18
- def add_all(version_range)
19
- version_range.version_intervals.each { |interval| add(interval) }
20
- end
21
-
22
- def add(version_interval)
23
- return if @version_interval_set.include?(version_interval)
24
-
25
- if @join_if_possible
26
- if @version_intervals.empty?
27
- @version_intervals << version_interval
28
- @version_interval_set.add(version_interval)
29
- else
30
- last = @version_intervals.last
31
- # nothing to do
32
- return if last.end_cut == version_interval.start_cut && last.end_cut.value == version_interval.start_cut.value
33
-
34
- if last.joinable?(version_interval)
35
- @version_intervals[@version_intervals.size - 1] = last.join(version_interval)
36
- else
37
- @version_intervals << version_interval
38
- @version_interval_set.add(version_interval)
39
- end
40
- end
41
- else
42
- @version_intervals << version_interval
43
- @version_interval_set.add(version_interval)
44
- end
45
- end
46
-
47
- def <<(item)
48
- add(item)
49
- end
50
-
51
- def size
52
- @version_intervals.size
53
- end
54
-
55
- def to_s
56
- @version_intervals.map(&:to_s).join(',')
57
- end
58
-
59
- def to_description_s
60
- @version_intervals.map(&:to_description_s).join(', ').capitalize
61
- end
62
-
63
- def to_npm_s
64
- @version_intervals.map(&:to_npm_s).join('||')
65
- end
66
-
67
- def to_conan_s
68
- to_npm_s
69
- end
70
-
71
- def to_nuget_s
72
- to_maven_s
73
- end
74
-
75
- def to_maven_s
76
- @version_intervals.map(&:to_maven_s).join(',')
77
- end
78
-
79
- def to_gem_s
80
- @version_intervals.map(&:to_gem_s).join('||')
81
- end
82
-
83
- def to_pypi_s
84
- @version_intervals.map(&:to_pypi_s).join('||')
85
- end
86
-
87
- def to_go_s
88
- @version_intervals.map(&:to_go_s).join('||')
89
- end
90
-
91
- def to_packagist_s
92
- @version_intervals.map(&:to_packagist_s).join('||')
93
- end
94
-
95
- def to_version_s(package_type)
96
- case package_type
97
- when 'npm'
98
- to_npm_s
99
- when 'nuget'
100
- to_nuget_s
101
- when 'maven'
102
- to_maven_s
103
- when 'gem'
104
- to_gem_s
105
- when 'pypi'
106
- to_pypi_s
107
- when 'packagist'
108
- to_packagist_s
109
- when 'go'
110
- to_go_s
111
- when 'conan'
112
- to_conan_s
113
- else
114
- ''
115
- end
116
- end
117
-
118
- # inverts the given version interval -- note that this function amy return two version intervals
119
- # e.g., (2,10], (12, 13], [15, +inf)
120
- # 1) invert: (-inf, 2], (10, +inf), (-inf, 12], (13, +inf), (15)
121
- # 2) collapse (-inf, 2], (10, 12], (13, 15)
122
- #
123
- # the collapsed inverted ranges can potentially contain fixed versions
124
- def invert
125
- inverted = @version_intervals.map(&:invert).flatten
126
- version_intervals = collapse_intervals(inverted)
127
- version_intervals_to_range(version_intervals)
128
- end
129
-
130
- def collapse
131
- version_intervals = collapse_intervals(@version_intervals)
132
- version_intervals_to_range(version_intervals)
133
- end
134
-
135
- def includes?(version_interval)
136
- @version_interval_set.include?(version_interval)
137
- end
138
-
139
- def overlaps_with?(version_interval)
140
- @version_interval_set.each do |interval|
141
- return true unless interval.intersect(version_interval).instance_of? EmptyInterval
142
- end
143
- false
144
- end
145
-
146
- def first
147
- @version_intervals.first
148
- end
149
-
150
- def empty?
151
- @version_intervals.empty?
152
- end
153
-
154
- def any?
155
- @version_intervals.any?
156
- end
157
-
158
- def universal?
159
- @version_intervals.each do |version_interval|
160
- return true if version_interval.universal?
161
- end
162
- false
163
- end
164
-
165
- private
166
-
167
- def version_intervals_to_range(version_intervals)
168
- ret = VersionRange.new(false)
169
- version_intervals.each do |version_interval|
170
- ret << version_interval
171
- end
172
- ret
173
- end
174
-
175
- def collapse_intervals(version_intervals)
176
- interval_cp = []
177
- interval_cp += version_intervals
178
- ret = [interval_cp.shift]
179
-
180
- interval_cp.each do |item|
181
- last = ret.last
182
- if last.intersect(item).instance_of?(EmptyInterval)
183
- ret << item
184
- else
185
- ret.pop
186
- ret << last.collapse(item)
187
- end
188
- end
189
- ret
190
- end
191
- end
@@ -1,172 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../utils.rb'
4
-
5
- # A prepropcessor -- convert different version strings to something that can be digested by the
6
- # version parser
7
- module VersionTranslator
8
- def self.translate_npm(version_string)
9
- version_string.split('||').map do |item|
10
- add_missing_operator(single_space_after_operator(item.strip.gsub(/&&/, ' ')))
11
- end
12
- end
13
-
14
- def self.translate_conan(version_string)
15
- translate_npm(version_string)
16
- end
17
-
18
- def self.translate_go(version_string)
19
- translate_gem(version_string)
20
- end
21
-
22
- def self.translate_gem(version_string)
23
- version_string.split('||').map do |item|
24
- add_missing_operator(single_space_after_operator(item.strip.gsub(/\s+/, ' ')))
25
- end
26
- end
27
-
28
- def self.translate_packagist(version_string)
29
- translate_pypi(version_string)
30
- end
31
-
32
- def self.translate_pypi(version_string)
33
- version_string.split('||').map do |item|
34
- add_missing_operator(single_space_after_operator(comma_to_space(item)))
35
- end
36
- end
37
-
38
- def self.translate_nuget(version_string)
39
- translate_maven(version_string)
40
- end
41
-
42
- def self.translate_maven(version_string)
43
- lexing_maven_version_string(version_string).map { |item| translate_mvn_version_item(item) }
44
- end
45
-
46
- def self.add_missing_operator(version_string)
47
- starts_with_operator?(version_string) ? version_string : "=#{version_string}"
48
- end
49
-
50
- def self.single_space_after_operator(version_string)
51
- version_string.gsub(/([>=<]+) +/, '\1').gsub(/\s+/, ' ')
52
- end
53
-
54
- def self.starts_with_operator?(version_item)
55
- version_item.match(/^[=><]/) ? true : false
56
- end
57
-
58
- def self.comma_to_space(version_string)
59
- version_string.strip.gsub(/,/, ' ')
60
- end
61
-
62
- def self.lexing_maven_version_string(version_string)
63
- open = false
64
- substring = ''
65
- ret = []
66
- version_string.each_char do |c|
67
- case c
68
- when '(', '['
69
- if open
70
- puts "malformed maven version string #{version_string}"
71
- exit(-1)
72
- else
73
- unless substring.empty?
74
- ret << substring
75
- substring = ''
76
- end
77
- open = true
78
- substring += c
79
- end
80
- when ')', ']'
81
- if !open
82
- puts "malformed maven version string #{version_string}"
83
- exit(-1)
84
- else
85
- open = false
86
- substring += c
87
- ret << substring
88
- substring = ''
89
- end
90
- when ','
91
- substring += c if open
92
- when ' '
93
- # nothing to do
94
- substring += ''
95
- else
96
- substring += c
97
- end
98
- end
99
- if open
100
- puts "malformed maven version string #{version_string}"
101
- exit(-1)
102
- end
103
- ret << substring unless substring.empty?
104
- ret
105
- end
106
-
107
- def self.parenthesized?(version_item)
108
- version_item.match(/^[\(\[]/) && version_item.match(/[\]\)]$/) ? true : false
109
- end
110
-
111
- def self.translate_mvn_version_item(version_item)
112
- content = ''
113
- parens_pattern = ''
114
- if parenthesized?(version_item)
115
- content = version_item[1, version_item.size - 2]
116
- parens_pattern = version_item[0] + version_item[version_item.size - 1]
117
- # special case -- unversal version range
118
- return '=*' if content.strip == ','
119
- else
120
- # according to the doc, if there is a plain version string in maven, it means 'starting from version x'
121
- # https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN8903
122
- content = "#{version_item},"
123
- parens_pattern = '[)'
124
- end
125
-
126
- args = content.split(',')
127
- first_non_empty_arg = args.find(&:range_present?)
128
-
129
- if content.start_with?(',')
130
- # {,y}
131
- case parens_pattern
132
- when '[]'
133
- "<=#{first_non_empty_arg}"
134
- when '()'
135
- "<#{first_non_empty_arg}"
136
- when '[)'
137
- "<#{first_non_empty_arg}"
138
- else
139
- # par_pattern == "(]"
140
- "<=#{first_non_empty_arg}"
141
- end
142
- elsif content.end_with?(',')
143
- # {x,}
144
- case parens_pattern
145
- when '[]'
146
- ">=#{first_non_empty_arg}"
147
- when '()'
148
- ">#{first_non_empty_arg}"
149
- when '[)'
150
- ">=#{first_non_empty_arg}"
151
- else
152
- # par_pattern == "(]"
153
- ">#{first_non_empty_arg}"
154
- end
155
- elsif content[','].nil?
156
- # [x,x]
157
- "=#{content}"
158
- else
159
- case parens_pattern
160
- when '[]'
161
- ">=#{args[0]} <=#{args[1]}"
162
- when '()'
163
- ">#{args[0]} <#{args[1]}"
164
- when '[)'
165
- ">=#{args[0]} <#{args[1]}"
166
- else
167
- # par_pattern == "(]"
168
- ">#{args[0]} <=#{args[1]}"
169
- end
170
- end
171
- end
172
- end