Skip to content

📚 Various SequenceSet rdoc improvements #465

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 29, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 81 additions & 27 deletions lib/net/imap/sequence_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,15 @@ class IMAP
# When a set includes <tt>*</tt>, some methods may have surprising behavior.
#
# For example, #complement treats <tt>*</tt> as its own number. This way,
# the #intersection of a set and its #complement will always be empty.
# This is not how an \IMAP server interprets the set: it will convert
# <tt>*</tt> to either the number of messages in the mailbox or +UIDNEXT+,
# as appropriate. And there _will_ be overlap between a set and its
# complement after #limit is applied to each:
# the #intersection of a set and its #complement will always be empty. And
# <tt>*</tt> is sorted as greater than any other number in the set. This is
# not how an \IMAP server interprets the set: it will convert <tt>*</tt> to
# the number of messages in the mailbox, the +UID+ of the last message in
# the mailbox, or +UIDNEXT+, as appropriate. Several methods have an
# argument for how <tt>*</tt> should be interpreted.
#
# But, for example, this means that there may be overlap between a set and
# its complement after #limit is applied to each:
#
# ~Net::IMAP::SequenceSet["*"] == Net::IMAP::SequenceSet[1..(2**32-1)]
# ~Net::IMAP::SequenceSet[1..5] == Net::IMAP::SequenceSet["6:*"]
Expand Down Expand Up @@ -179,9 +183,9 @@ class IMAP
# - #include_star?: Returns whether the set contains <tt>*</tt>.
#
# <i>Minimum and maximum value elements:</i>
# - #min: Returns one or more minimum numbers in the set.
# - #max: Returns one or more maximum numbers in the set.
# - #minmax: Returns the minimum and maximum numbers in the set.
# - #min: Returns one or more of the lowest numbers in the set.
# - #max: Returns one or more of the highest numbers in the set.
# - #minmax: Returns the lowest and highest numbers in the set.
#
# <i>Accessing value by offset in sorted set:</i>
# - #[] (aliased as #slice): Returns the number or consecutive subset at a
Expand Down Expand Up @@ -643,7 +647,14 @@ def full?; @tuples == [[1, STAR_INT]] end
# Net::IMAP::SequenceSet["1:5"] | 2 | [4..6, 99]
# #=> Net::IMAP::SequenceSet["1:6,99"]
#
# Related: #add, #merge
# Related: #add, #merge, #&, #-, #^, #~
#
# ==== Set identities
#
# <tt>lhs | rhs</tt> is equivalent to:
# * <tt>rhs | lhs</tt> (commutative)
# * <tt>~(~lhs & ~rhs)</tt> (De Morgan's Law)
# * <tt>(lhs & rhs) ^ (lhs ^ rhs)</tt>
def |(other) remain_frozen dup.merge other end
alias :+ :|
alias union :|
Expand All @@ -662,7 +673,17 @@ def |(other) remain_frozen dup.merge other end
# Net::IMAP::SequenceSet[1..5] - 2 - 4 - 6
# #=> Net::IMAP::SequenceSet["1,3,5"]
#
# Related: #subtract
# Related: #subtract, #|, #&, #^, #~
#
# ==== Set identities
#
# <tt>lhs - rhs</tt> is equivalent to:
# * <tt>~r - ~l</tt>
# * <tt>lhs & ~rhs</tt>
# * <tt>~(~lhs | rhs)</tt>
# * <tt>lhs & (lhs ^ rhs)</tt>
# * <tt>lhs ^ (lhs & rhs)</tt>
# * <tt>rhs ^ (lhs | rhs)</tt>
def -(other) remain_frozen dup.subtract other end
alias difference :-

Expand All @@ -680,7 +701,17 @@ def -(other) remain_frozen dup.subtract other end
# Net::IMAP::SequenceSet[1..5] & [2, 4, 6]
# #=> Net::IMAP::SequenceSet["2,4"]
#
# <tt>(seqset & other)</tt> is equivalent to <tt>(seqset - ~other)</tt>.
# Related: #intersect?, #|, #-, #^, #~
#
# ==== Set identities
#
# <tt>lhs & rhs</tt> is equivalent to:
# * <tt>rhs & lhs</tt> (commutative)
# * <tt>~(~lhs | ~rhs)</tt> (De Morgan's Law)
# * <tt>lhs - ~rhs</tt>
# * <tt>lhs - (lhs - rhs)</tt>
# * <tt>lhs - (lhs ^ rhs)</tt>
# * <tt>lhs ^ (lhs - rhs)</tt>
def &(other)
remain_frozen dup.subtract SequenceSet.new(other).complement!
end
Expand All @@ -700,8 +731,16 @@ def &(other)
# Net::IMAP::SequenceSet[1..5] ^ [2, 4, 6]
# #=> Net::IMAP::SequenceSet["1,3,5:6"]
#
# <tt>(seqset ^ other)</tt> is equivalent to <tt>((seqset | other) -
# (seqset & other))</tt>.
# Related: #|, #&, #-, #~
#
# ==== Set identities
#
# <tt>lhs ^ rhs</tt> is equivalent to:
# * <tt>rhs ^ lhs</tt> (commutative)
# * <tt>~lhs ^ ~rhs</tt>
# * <tt>(lhs | rhs) - (lhs & rhs)</tt>
# * <tt>(lhs - rhs) | (rhs - lhs)</tt>
# * <tt>(lhs ^ other) ^ (other ^ rhs)</tt>
def ^(other) remain_frozen (dup | other).subtract(self & other) end
alias xor :^

Expand All @@ -719,7 +758,12 @@ def ^(other) remain_frozen (dup | other).subtract(self & other) end
# ~Net::IMAP::SequenceSet["6:99,223:*"]
# #=> Net::IMAP::SequenceSet["1:5,100:222"]
#
# Related: #complement!
# Related: #complement!, #|, #&, #-, #^
#
# ==== Set identities
#
# <tt>~set</tt> is equivalent to:
# * <tt>full - set</tt>, where "full" is Net::IMAP::SequenceSet.full
def ~; remain_frozen dup.complement! end
alias complement :~

Expand All @@ -731,7 +775,10 @@ def ~; remain_frozen dup.complement! end
#
# #string will be regenerated. Use #merge to add many elements at once.
#
# Related: #add?, #merge, #union
# Use #append to append new elements to #string. See
# Net::IMAP@Ordered+and+Normalized+Sets.
#
# Related: #add?, #merge, #union, #append
def add(element)
tuple_add input_to_tuple element
normalize!
Expand All @@ -742,6 +789,10 @@ def add(element)
#
# Unlike #add, #merge, or #union, the new value is appended to #string.
# This may result in a #string which has duplicates or is out-of-order.
#
# See Net::IMAP@Ordered+and+Normalized+Sets.
#
# Related: #add, #merge, #union
def append(entry)
modifying!
tuple = input_to_tuple entry
Expand Down Expand Up @@ -890,21 +941,21 @@ def subtract(*sets)
# This is useful when the given order is significant, for example in a
# ESEARCH response to IMAP#sort.
#
# See Net::IMAP@Ordered+and+Normalized+Sets.
#
# Related: #each_entry, #elements
def entries; each_entry.to_a end

# Returns an array of ranges and integers and <tt>:*</tt>.
#
# The returned elements are sorted and coalesced, even when the input
# #string is not. <tt>*</tt> will sort last. See #normalize.
# #string is not. <tt>*</tt> will sort last. See #normalize,
# Net::IMAP@Ordered+and+Normalized+Sets.
#
# By itself, <tt>*</tt> translates to <tt>:*</tt>. A range containing
# <tt>*</tt> translates to an endless range. Use #limit to translate both
# cases to a maximum value.
#
# The returned elements will be sorted and coalesced, even when the input
# #string is not. <tt>*</tt> will sort last. See #normalize.
#
# Net::IMAP::SequenceSet["2,5:9,6,*,12:11"].elements
# #=> [2, 5..9, 11..12, :*]
#
Expand All @@ -915,15 +966,13 @@ def elements; each_element.to_a end
# Returns an array of ranges
#
# The returned elements are sorted and coalesced, even when the input
# #string is not. <tt>*</tt> will sort last. See #normalize.
# #string is not. <tt>*</tt> will sort last. See #normalize,
# Net::IMAP@Ordered+and+Normalized+Sets.
#
# <tt>*</tt> translates to an endless range. By itself, <tt>*</tt>
# translates to <tt>:*..</tt>. Use #limit to set <tt>*</tt> to a maximum
# value.
#
# The returned ranges will be sorted and coalesced, even when the input
# #string is not. <tt>*</tt> will sort last. See #normalize.
#
# Net::IMAP::SequenceSet["2,5:9,6,*,12:11"].ranges
# #=> [2..2, 5..9, 11..12, :*..]
# Net::IMAP::SequenceSet["123,999:*,456:789"].ranges
Expand All @@ -935,7 +984,7 @@ def ranges; each_range.to_a end
# Returns a sorted array of all of the number values in the sequence set.
#
# The returned numbers are sorted and de-duplicated, even when the input
# #string is not. See #normalize.
# #string is not. See #normalize, Net::IMAP@Ordered+and+Normalized+Sets.
#
# Net::IMAP::SequenceSet["2,5:9,6,12:11"].numbers
# #=> [2, 5, 6, 7, 8, 9, 11, 12]
Expand Down Expand Up @@ -967,6 +1016,8 @@ def numbers; each_number.to_a end
# no sorting, deduplication, or coalescing. When #string is in its
# normalized form, this will yield the same values as #each_element.
#
# See Net::IMAP@Ordered+and+Normalized+Sets.
#
# Related: #entries, #each_element
def each_entry(&block) # :yields: integer or range or :*
return to_enum(__method__) unless block_given?
Expand All @@ -977,7 +1028,7 @@ def each_entry(&block) # :yields: integer or range or :*
# and returns self. Returns an enumerator when called without a block.
#
# The returned numbers are sorted and de-duplicated, even when the input
# #string is not. See #normalize.
# #string is not. See #normalize, Net::IMAP@Ordered+and+Normalized+Sets.
#
# Related: #elements, #each_entry
def each_element # :yields: integer or range or :*
Expand Down Expand Up @@ -1400,6 +1451,7 @@ def complement!
#
# The returned set's #string is sorted and deduplicated. Adjacent or
# overlapping elements will be merged into a single larger range.
# See Net::IMAP@Ordered+and+Normalized+Sets.
#
# Net::IMAP::SequenceSet["1:5,3:7,10:9,10:11"].normalize
# #=> Net::IMAP::SequenceSet["1:7,9:11"]
Expand All @@ -1412,7 +1464,7 @@ def normalize
end

# Resets #string to be sorted, deduplicated, and coalesced. Returns
# +self+.
# +self+. See Net::IMAP@Ordered+and+Normalized+Sets.
#
# Related: #normalize, #normalized_string
def normalize!
Expand All @@ -1422,11 +1474,13 @@ def normalize!

# Returns a normalized +sequence-set+ string representation, sorted
# and deduplicated. Adjacent or overlapping elements will be merged into
# a single larger range. Returns +nil+ when the set is empty.
# a single larger range. See Net::IMAP@Ordered+and+Normalized+Sets.
#
# Net::IMAP::SequenceSet["1:5,3:7,10:9,10:11"].normalized_string
# #=> "1:7,9:11"
#
# Returns +nil+ when the set is empty.
#
# Related: #normalize!, #normalize
def normalized_string
@tuples.empty? ? nil : [email protected] { tuple_to_str _1 }.join(",")
Expand Down