Skip to content
Open
Show file tree
Hide file tree
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
10 changes: 2 additions & 8 deletions .github/workflows/swift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ jobs:
- name: Build Package
run: swift build -v

- name: Test & publish code coverage to Code Climate
uses: paambaati/[email protected]
env:
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
with:
coverageCommand: swift test --enable-code-coverage
debug: true
coverageLocations: ${{github.workspace}}/.build/debug/codecov/*.json:lcov-json
- name: Test
run: swift test -v


46 changes: 42 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,28 @@ let result = !(text.contains("cat") && text.contains("bird"))
let result = try text.contains(!("cat" && "bird"))
```

## `^` Operator (Prefix)
The ^ operator (when used as a prefix) checks if a string starts with a given value (prefix check). It returns a StringPredicate that represents the prefix search condition.

```swift
// Swift native implementation
let result = text.hasPrefix("My")

// StringContainsOperators implementation
let result = try text.contains(^"My")
```

## `^` Operator (Suffix)
When used as a postfix operator, ^ checks if a string ends with a given value (suffix check). It returns a StringPredicate that represents the suffix search condition.

```swift
// Swift native implementation
let result = text.hasSuffix("Victor")

// StringContainsOperators implementation
let result = try text.contains("Victor"^)
```

## `=~` Operator
The =~ operator creates a StringPredicate that performs a regular expression search for a given pattern.

Expand Down Expand Up @@ -113,14 +135,30 @@ print(result7) // false
let result8 = try text.contains(!~"cat")
print(result8) // true

// Check if text contains "quick" OR "jumps" AND "fox" using a regular expression
let result9 = try text.contains(=~"(quick|jumps).*fox")
// Check if text starts with "The"
let result9 = try text.contains(^"The")
print(result9) // true

// Check if text contains "jumps" OR "swift" AND "fox" using a regular expression
let result10 = try text.contains(=~"(jumps|swift).*fox")
// Check if text starts with "The" AND contains "fox"
let result10 = try text.contains(^"The" && "fox")
print(result10) // true

// Check if text ends with "dog"
let result11 = try text.contains("dog"^)
print(result11) // true

// Check if text ends with "fox" AND contains "quick"
let result12 = try text.contains("fox"^ && "quick")
print(result12) // true

// Check if text contains "quick" OR "jumps" AND "fox" using a regular expression
let result13 = try text.contains(=~"(quick|jumps).*fox")
print(result13) // true

// Check if text contains "jumps" OR "swift" AND "fox" using a regular expression
let result12 = try text.contains(=~"(jumps|swift).*fox")
print(result12) // true

```

### Complex Usage
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// PrefixSearchStrategy.swift
//
//
// Created by Victor C Tavernari on 23/03/2023.
//

import Foundation

/// `PrefixSearchStrategy` is a type of `SearchStrategy` that searches for a `String` that starts with a given value.
final class PrefixSearchStrategy: SearchStrategy {

enum InternalError: Error {
case notAvailableToPredicates
}

/// An StringPredicateInputKind to search.
let input: StringPredicateInputKind

/// Initializes an instance of `PrefixSearchStrategy`.
/// - Parameter input: An StringPredicateInputKind to search.
init(input: StringPredicateInputKind) {
self.input = input
}

/// Evaluates if a given string starts with the `value` string.
///
/// - Parameter string: The string to be evaluated.
/// - Returns: `true` if the string starts with the `value` string, `false` otherwise.
func evaluate(string: String) throws -> Bool {
switch self.input {
case let .string(value):
return string.hasPrefix(value)

case .predicate:
throw InternalError.notAvailableToPredicates
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// SuffixSearchStrategy.swift
//
//
// Created by Victor C Tavernari on 23/03/2023.
//

import Foundation

/// `SuffixSearchStrategy` is a type of `SearchStrategy` that searches for a `String` that ends with a given value.
final class SuffixSearchStrategy: SearchStrategy {

enum InternalError: Error {
case notAvailableToPredicates
}

/// An StringPredicateInputKind to search.
let input: StringPredicateInputKind

/// Initializes an instance of `SuffixSearchStrategy`.
/// - Parameter input: An StringPredicateInputKind to search.
init(input: StringPredicateInputKind) {
self.input = input
}

/// Evaluates if a given string ends with the `value` string.
///
/// - Parameter string: The string to be evaluated.
/// - Returns: `true` if the string ends with the `value` string, `false` otherwise.
func evaluate(string: String) throws -> Bool {
switch self.input {
case let .string(value):
return string.hasSuffix(value)

case .predicate:
throw InternalError.notAvailableToPredicates
}
}
}
6 changes: 6 additions & 0 deletions Sources/StringContainsOperators/SearchStrategyMaker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ enum SearchStrategyMaker {

case let .negatable(input):
return NegatableSearchStrategy(input: input)

case let .prefix(input):
return PrefixSearchStrategy(input: input)

case let .suffix(input):
return SuffixSearchStrategy(input: input)
}
}
}
44 changes: 44 additions & 0 deletions Sources/StringContainsOperators/StringContainsOperators.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ infix operator && : LogicalConjunctionPrecedence
prefix operator ~
prefix operator =~
prefix operator !
prefix operator ^
postfix operator ^


public enum StringPredicateInputKind {
Expand All @@ -37,6 +39,12 @@ public indirect enum StringPredicate {

/// Represents a negatable search predicate for a given string.
case negatable(StringPredicateInputKind)

/// Represents a prefix search - checks if a string starts with a given value.
case prefix(StringPredicateInputKind)

/// Represents a suffix search - checks if a string ends with a given value.
case suffix(StringPredicateInputKind)
}

/// Returns a `StringPredicate` that performs a logical OR operation between two strings.
Expand Down Expand Up @@ -155,6 +163,42 @@ public prefix func ! (value: String) -> StringPredicate {
return .negatable(.string(value))
}

/// Returns a `StringPredicate` that checks if a string starts with a given value.
///
/// - Parameter value: The value to check as a prefix.
/// - Returns: A `StringPredicate` that checks if the string starts with the given value.
public prefix func ^ (value: String) -> StringPredicate {

return .prefix(.string(value))
}

/// Returns a `StringPredicate` that checks if a string starts with a value from another predicate.
///
/// - Parameter predicate: The predicate to check as a prefix.
/// - Returns: A `StringPredicate` that checks if the string starts with the given predicate.
public prefix func ^ (predicate: StringPredicate) -> StringPredicate {

return .prefix(.predicate(predicate))
}

/// Returns a `StringPredicate` that checks if a string ends with a given value.
///
/// - Parameter value: The value to check as a suffix.
/// - Returns: A `StringPredicate` that checks if the string ends with the given value.
public postfix func ^ (value: String) -> StringPredicate {

return .suffix(.string(value))
}

/// Returns a `StringPredicate` that checks if a string ends with a value from another predicate.
///
/// - Parameter predicate: The predicate to check as a suffix.
/// - Returns: A `StringPredicate` that checks if the string ends with the given predicate.
public postfix func ^ (predicate: StringPredicate) -> StringPredicate {

return .suffix(.predicate(predicate))
}

public extension String {

/// Returns a Boolean value indicating whether the string contains the given `StringPredicate`.
Expand Down
Loading