Skip to content

Commit 7b737e3

Browse files
authored
Add @RegexComponentBuilder overloads for string processing algorithm. (#334)
* Add `@RegexComponentBuilder` overloads for string processing algorithm. These overloads will allow you to write, e.g. ```swift let _ = str.wholeMatch { OneOrMore("a") "+" OneOrMore("a") } ``` instead of ```swift let _ = str.wholeMatch(of: Regex { OneOrMore("a") "+" OneOrMore("a") }) ```
1 parent 6fab471 commit 7b737e3

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed

Documentation/Evolution/StringProcessingAlgorithms.md

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,16 @@ extension BidirectionalCollection where SubSequence == Substring {
245245
/// - Returns: `true` if the regex was found in the collection, otherwise
246246
/// `false`.
247247
public func contains(_ regex: some RegexComponent) -> Bool
248+
249+
/// Returns a Boolean value indicating whether the collection contains the
250+
/// given regex.
251+
/// - Parameter content: A closure to produce a `RegexComponent` to search for
252+
/// within this collection.
253+
/// - Returns: `true` if the regex was found in the collection, otherwise
254+
/// `false`.
255+
public func contains(
256+
@RegexComponentBuilder _ content: () -> some RegexComponent
257+
) -> Bool
248258
}
249259
```
250260

@@ -258,6 +268,15 @@ extension BidirectionalCollection where SubSequence == Substring {
258268
/// - Returns: `true` if the initial elements of the sequence matches the
259269
/// beginning of `regex`; otherwise, `false`.
260270
public func starts(with regex: some RegexComponent) -> Bool
271+
272+
/// Returns a Boolean value indicating whether the initial elements of the
273+
/// sequence are the same as the elements in the specified regex.
274+
/// - Parameter content: A closure to produce a `RegexComponent` to compare.
275+
/// - Returns: `true` if the initial elements of the sequence matches the
276+
/// beginning of `regex`; otherwise, `false`.
277+
public func starts(
278+
@RegexComponentBuilder with content: () -> some RegexComponent
279+
) -> Bool
261280
}
262281
```
263282

@@ -324,6 +343,15 @@ extension BidirectionalCollection where SubSequence == Substring {
324343
/// - Returns: A new subsequence containing the elements of the collection
325344
/// that does not match `prefix` from the start.
326345
public func trimmingPrefix(_ regex: some RegexComponent) -> SubSequence
346+
347+
/// Returns a new collection of the same type by removing `prefix` from the
348+
/// start.
349+
/// - Parameter _content A closure to produce a `RegexComponent` to be removed.
350+
/// - Returns: A collection containing the elements that does not match
351+
/// `prefix` from the start.
352+
public func trimmingPrefix(
353+
@RegexComponentBuilder _ content: () -> some RegexComponent
354+
) -> SubSequence
327355
}
328356

329357
extension RangeReplaceableCollection
@@ -332,6 +360,12 @@ extension RangeReplaceableCollection
332360
/// Removes the initial elements that matches the given regex.
333361
/// - Parameter regex: The regex to remove from this collection.
334362
public mutating func trimPrefix(_ regex: some RegexComponent)
363+
364+
/// Removes the initial elements that matches the given regex.
365+
/// - Parameter content: A closure to produce a `RegexComponent` to be removed.
366+
public mutating func trimPrefix(
367+
@RegexComponentBuilder _ content: () -> some RegexComponent
368+
)
335369
}
336370
```
337371

@@ -365,6 +399,16 @@ extension BidirectionalCollection where SubSequence == Substring {
365399
/// - Returns: A range in the collection of the first occurrence of `regex`.
366400
/// Returns `nil` if `regex` is not found.
367401
public func firstRange(of regex: some RegexComponent) -> Range<Index>?
402+
403+
/// Finds and returns the range of the first occurrence of a given regex
404+
/// within the collection.
405+
/// - Parameter content: A closure to produce a `RegexComponent` to search for
406+
/// within this collection.
407+
/// - Returns: A range in the collection of the first occurrence of regex.
408+
/// Returns `nil` if not found.
409+
public func firstRange(
410+
@RegexComponentBuilder of content: () -> some RegexComponent
411+
) -> Range<Index>?
368412
}
369413
```
370414

@@ -388,6 +432,16 @@ extension BidirectionalCollection where SubSequence == Substring {
388432
/// - Returns: A collection or ranges in the receiver of all occurrences of
389433
/// `regex`. Returns an empty collection if `regex` is not found.
390434
public func ranges(of regex: some RegexComponent) -> some Collection<Range<Index>>
435+
436+
/// Finds and returns the ranges of the all occurrences of a given sequence
437+
/// within the collection.
438+
/// - Parameter content: A closure to produce a `RegexComponent` to search for
439+
/// within this collection.
440+
/// - Returns: A collection or ranges in the receiver of all occurrences of
441+
/// regex. Returns an empty collection if not found.
442+
public func ranges(
443+
@RegexComponentBuilder of content: () -> some RegexComponent
444+
) -> some Collection<Range<Index>>
391445
}
392446
```
393447

@@ -401,15 +455,37 @@ extension BidirectionalCollection where SubSequence == Substring {
401455
/// there isn't a match.
402456
public func firstMatch<R: RegexComponent>(of regex: R) -> Regex<R.RegexOutput>.Match?
403457

458+
/// Returns the first match of the specified regex within the collection.
459+
/// - Parameter content: A closure to produce a `RegexComponent` to search for.
460+
/// - Returns: The first match of regex in the collection, or `nil` if
461+
/// there isn't a match.
462+
public func firstMatch<R: RegexComponent>(
463+
@RegexComponentBuilder of content: () -> R
464+
) -> Regex<R.RegexOutput>.Match?
465+
404466
/// Match a regex in its entirety.
405467
/// - Parameter regex: The regex to match against.
406468
/// - Returns: The match if there is one, or `nil` if none.
407469
public func wholeMatch<R: RegexComponent>(of regex: R) -> Regex<R.RegexOutput>.Match?
408470

471+
/// Match a regex in its entirety.
472+
/// - Parameter content: A closure to produce a `RegexComponent` to match against.
473+
/// - Returns: The match if there is one, or `nil` if none.
474+
public func wholeMatch<R: RegexComponent>(
475+
@RegexComponentBuilder of content: () -> R
476+
) -> Regex<R.RegexOutput>.Match?
477+
409478
/// Match part of the regex, starting at the beginning.
410479
/// - Parameter regex: The regex to match against.
411480
/// - Returns: The match if there is one, or `nil` if none.
412481
public func prefixMatch<R: RegexComponent>(of regex: R) -> Regex<R.RegexOutput>.Match?
482+
483+
/// Match part of the regex, starting at the beginning.
484+
/// - Parameter content: A closure to produce a `RegexComponent` to match against.
485+
/// - Returns: The match if there is one, or `nil` if none.
486+
public func prefixMatch<R: RegexComponent>(
487+
@RegexComponentBuilder of content: () -> R
488+
) -> Regex<R.RegexOutput>.Match?
413489
}
414490
```
415491

@@ -421,6 +497,13 @@ extension BidirectionalCollection where SubSequence == Substring {
421497
/// - Parameter regex: The regex to search for.
422498
/// - Returns: A collection of matches of `regex`.
423499
public func matches<R: RegexComponent>(of regex: R) -> some Collection<Regex<R.RegexOuput>.Match>
500+
501+
/// Returns a collection containing all matches of the specified regex.
502+
/// - Parameter content: A closure to produce a `RegexComponent` to search for.
503+
/// - Returns: A collection of matches of `regex`.
504+
public func matches<R: RegexComponent>(
505+
@RegexComponentBuilder of content: () -> R
506+
) -> some Collection<Regex<R.RegexOutput>.Match>
424507
}
425508
```
426509

@@ -490,6 +573,23 @@ extension RangeReplaceableCollection where SubSequence == Substring {
490573
subrange: Range<Index>,
491574
maxReplacements: Int = .max
492575
) -> Self where Replacement.Element == Element
576+
577+
/// Returns a new collection in which all occurrences of a sequence matching
578+
/// the given regex are replaced by another collection.
579+
/// - Parameters:
580+
/// - replacement: The new elements to add to the collection.
581+
/// - subrange: The range in the collection in which to search for `regex`.
582+
/// - maxReplacements: A number specifying how many occurrences of the
583+
/// sequence matching `regex` to replace. Default is `Int.max`.
584+
/// - content: A closure to produce a `RegexComponent` to replace.
585+
/// - Returns: A new collection in which all occurrences of subsequence
586+
/// matching `regex` in `subrange` are replaced by `replacement`.
587+
public func replacing<Replacement: Collection>(
588+
with replacement: Replacement,
589+
subrange: Range<Index>,
590+
maxReplacements: Int = .max,
591+
@RegexComponentBuilder content: () -> some RegexComponent
592+
) -> Self where Replacement.Element == Element
493593

494594
/// Returns a new collection in which all occurrences of a sequence matching
495595
/// the given regex are replaced by another collection.
@@ -506,6 +606,21 @@ extension RangeReplaceableCollection where SubSequence == Substring {
506606
maxReplacements: Int = .max
507607
) -> Self where Replacement.Element == Element
508608

609+
/// Returns a new collection in which all occurrences of a sequence matching
610+
/// the given regex are replaced by another collection.
611+
/// - Parameters:
612+
/// - replacement: The new elements to add to the collection.
613+
/// - maxReplacements: A number specifying how many occurrences of the
614+
/// sequence matching `regex` to replace. Default is `Int.max`.
615+
/// - content: A closure to produce a `RegexComponent` to replace.
616+
/// - Returns: A new collection in which all occurrences of subsequence
617+
/// matching `regex` are replaced by `replacement`.
618+
public func replacing<Replacement: Collection>(
619+
with replacement: Replacement,
620+
maxReplacements: Int = .max,
621+
@RegexComponentBuilder content: () -> some RegexComponent
622+
) -> Self where Replacement.Element == Element
623+
509624
/// Replaces all occurrences of the sequence matching the given regex with
510625
/// a given collection.
511626
/// - Parameters:
@@ -518,6 +633,19 @@ extension RangeReplaceableCollection where SubSequence == Substring {
518633
with replacement: Replacement,
519634
maxReplacements: Int = .max
520635
) where Replacement.Element == Element
636+
637+
/// Replaces all occurrences of the sequence matching the given regex with
638+
/// a given collection.
639+
/// - Parameters:
640+
/// - replacement: The new elements to add to the collection.
641+
/// - maxReplacements: A number specifying how many occurrences of the
642+
/// sequence matching `regex` to replace. Default is `Int.max`.
643+
/// - content: A closure to produce a `RegexComponent` to replace.
644+
public mutating func replace<Replacement: Collection>(
645+
with replacement: Replacement,
646+
maxReplacements: Int = .max,
647+
@RegexComponentBuilder content: () -> some RegexComponent
648+
) -> Self where Replacement.Element == Element
521649

522650
/// Returns a new collection in which all occurrences of a sequence matching
523651
/// the given regex are replaced by another regex match.
@@ -536,6 +664,24 @@ extension RangeReplaceableCollection where SubSequence == Substring {
536664
maxReplacements: Int = .max,
537665
with replacement: (Regex<R.RegexOutput>.Match) throws -> Replacement
538666
) rethrows -> Self where Replacement.Element == Element
667+
668+
/// Returns a new collection in which all occurrences of a sequence matching
669+
/// the given regex are replaced by another regex match.
670+
/// - Parameters:
671+
/// - subrange: The range in the collection in which to search for `regex`.
672+
/// - maxReplacements: A number specifying how many occurrences of the
673+
/// sequence matching `regex` to replace. Default is `Int.max`.
674+
/// - content: A closure to produce a `RegexComponent` to replace.
675+
/// - replacement: A closure that receives the full match information,
676+
/// including captures, and returns a replacement collection.
677+
/// - Returns: A new collection in which all occurrences of subsequence
678+
/// matching `regex` are replaced by `replacement`.
679+
public func replacing<R: RegexComponent, Replacement: Collection>(
680+
subrange: Range<Index>,
681+
maxReplacements: Int = .max,
682+
@RegexComponentBuilder content: () -> R,
683+
with replacement: (Regex<R.RegexOutput>.Match) throws -> Replacement
684+
) rethrows -> Self where Replacement.Element == Element
539685

540686
/// Returns a new collection in which all occurrences of a sequence matching
541687
/// the given regex are replaced by another collection.
@@ -552,6 +698,22 @@ extension RangeReplaceableCollection where SubSequence == Substring {
552698
maxReplacements: Int = .max,
553699
with replacement: (Regex<R.RegexOuput>.Match) throws -> Replacement
554700
) rethrows -> Self where Replacement.Element == Element
701+
702+
/// Returns a new collection in which all occurrences of a sequence matching
703+
/// the given regex are replaced by another collection.
704+
/// - Parameters:
705+
/// - maxReplacements: A number specifying how many occurrences of the
706+
/// sequence matching `regex` to replace. Default is `Int.max`.
707+
/// - content: A closure to produce a `RegexComponent` to replace.
708+
/// - replacement: A closure that receives the full match information,
709+
/// including captures, and returns a replacement collection.
710+
/// - Returns: A new collection in which all occurrences of subsequence
711+
/// matching `regex` are replaced by `replacement`.
712+
public func replacing<R: RegexComponent, Replacement: Collection>(
713+
maxReplacements: Int = .max,
714+
@RegexComponentBuilder content: () -> R,
715+
with replacement: (Regex<R.RegexOutput>.Match) throws -> Replacement
716+
) rethrows -> Self where Replacement.Element == Element
555717

556718
/// Replaces all occurrences of the sequence matching the given regex with
557719
/// a given collection.
@@ -566,6 +728,20 @@ extension RangeReplaceableCollection where SubSequence == Substring {
566728
maxReplacements: Int = .max,
567729
with replacement: (Regex<R.RegexOutput>.Match) throws -> Replacement
568730
) rethrows where Replacement.Element == Element
731+
732+
/// Replaces all occurrences of the sequence matching the given regex with
733+
/// a given collection.
734+
/// - Parameters:
735+
/// - maxReplacements: A number specifying how many occurrences of the
736+
/// sequence matching `regex` to replace. Default is `Int.max`.
737+
/// - content: A closure to produce a `RegexComponent` to replace.
738+
/// - replacement: A closure that receives the full match information,
739+
/// including captures, and returns a replacement collection.
740+
public mutating func replace<R: RegexComponent, Replacement: Collection>(
741+
maxReplacements: Int = .max,
742+
@RegexComponentBuilder content: () -> R,
743+
with replacement: (Regex<R.RegexOutput>.Match) throws -> Replacement
744+
) rethrows where Replacement.Element == Element
569745
}
570746
```
571747

@@ -613,6 +789,25 @@ extension BidirectionalCollection where SubSequence == Substring {
613789
maxSplits: Int = Int.max,
614790
omittingEmptySubsequences: Bool = true
615791
) -> some Collection<Substring>
792+
793+
/// Returns the longest possible subsequences of the collection, in order,
794+
/// around subsequence that match the given separator regex.
795+
///
796+
/// - Parameters:
797+
/// - maxSplits: The maximum number of times to split the collection,
798+
/// or one less than the number of subsequences to return.
799+
/// - omittingEmptySubsequences: If `false`, an empty subsequence is
800+
/// returned in the result for each consecutive pair of matches
801+
/// and for each match at the start or end of the collection. If
802+
/// `true`, only nonempty subsequences are returned.
803+
/// - separator: A closure to produce a `RegexComponent` to be split upon.
804+
/// - Returns: A collection of substrings, split from this collection's
805+
/// elements.
806+
public func split(
807+
maxSplits: Int = Int.max,
808+
omittingEmptySubsequences: Bool = true,
809+
@RegexComponentBuilder separator: () -> some RegexComponent
810+
) -> some Collection<Substring>
616811
}
617812
```
618813

0 commit comments

Comments
 (0)