Skip to content

Commit

Permalink
Merge branch 'release/3.3.0' into versions
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeehut committed Jan 16, 2021
2 parents 4f1f96b + 63127a8 commit 50b84f0
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 18 deletions.
7 changes: 7 additions & 0 deletions .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 11 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ If needed, pluralize to `Tasks`, `PRs` or `Authors` and list multiple entries se

## [Unreleased]
### Added
- None.
- Added `round(fractionDigits:rule:)` & `rounded(fractionDigits:rule:)` methods to `Double` type.
Author: [Cihat Gündüz](https://github.com/Jeehut)
### Changed
- None.
### Deprecated
Expand All @@ -31,6 +32,11 @@ If needed, pluralize to `Tasks`, `PRs` or `Authors` and list multiple entries se
### Security
- None.

## [3.3.0] - 2021-01-16
### Added
- Added `round(fractionDigits:rule:)` & `rounded(fractionDigits:rule:)` methods to `Double` type.
Author: [Cihat Gündüz](https://github.com/Jeehut)

## [3.2.1] - 2020-10-03
### Changed
- `Withable` doesn't require an empty `init()` method anymore. Instead, it can be combined with any initializer. If you used the `Foo { $0.bar = 5 }` type of initializer, you will need to add `().with` behind the type like so: `Foo().with { $0.bar = 5 }`.
Expand All @@ -54,15 +60,15 @@ If needed, pluralize to `Tasks`, `PRs` or `Authors` and list multiple entries se
## [3.1.0] - 2019-09-01
### Added
- New `Comparable.clamped(to:)` and `Comparable.clamp(to:)` interfaces for any `Comparable`, e. g. `Int`.

## [3.0.0] - 2019-04-30
### Added
- New `Withable` protocol to init/copy objects and set properties in a convenient way on a single line.
### Changed
- Upgraded to Swift 5 & Xcode 10.2.
### Removed
- Remove `ExpressibleByStringLiteral` conformance of `Regex` type to only allow initialization via `init(_:options:) throws` interface.

## [2.8.0] - 2019-02-11
### Added
- New `NSRange(_:in:)` initializer for converting from `Range<String.Index>`
Expand All @@ -71,13 +77,13 @@ If needed, pluralize to `Tasks`, `PRs` or `Authors` and list multiple entries se
- New `fullRange` and `fullNSRange` computed properties on `String`
### Changed
- Made some APIs available in wider contexts (like `sample` in `RandomAccessCollection` instead of `Array`)

## [2.7.0] - 2018-09-27
### Added
- Official support for Linux & Swift Package Manager.
### Removed
- Support for Swift 4.1 and lower was dropped.

## [2.6.0] - 2018-04-22
### Added
- New swifty `Regex` type built on top of the NSRegularExpression API.
2 changes: 1 addition & 1 deletion HandySwift.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = "HandySwift"
s.version = "3.2.1"
s.version = "3.3.0"
s.summary = "Handy Swift features that didn't make it into the Swift standard library"

s.description = <<-DESC
Expand Down
28 changes: 26 additions & 2 deletions HandySwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,21 @@
objects = {

/* Begin PBXBuildFile section */
2E18AD5A2531DD3D00D44748 /* DoubleExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E18AD592531DD3D00D44748 /* DoubleExt.swift */; };
2E18AD5B2531DD3D00D44748 /* DoubleExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E18AD592531DD3D00D44748 /* DoubleExt.swift */; };
2E18AD5C2531DD3D00D44748 /* DoubleExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E18AD592531DD3D00D44748 /* DoubleExt.swift */; };
2E18AD732531E0FD00D44748 /* DoubleExtTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E18AD632531E0F800D44748 /* DoubleExtTests.swift */; };
2E18AD7A2531E0FD00D44748 /* DoubleExtTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E18AD632531E0F800D44748 /* DoubleExtTests.swift */; };
2E18AD812531E0FE00D44748 /* DoubleExtTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E18AD632531E0F800D44748 /* DoubleExtTests.swift */; };
2E18B292242DECCA000C7776 /* NSObjectExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E18B291242DECCA000C7776 /* NSObjectExt.swift */; };
2E18B293242DECCA000C7776 /* NSObjectExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E18B291242DECCA000C7776 /* NSObjectExt.swift */; };
2E18B294242DECCA000C7776 /* NSObjectExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E18B291242DECCA000C7776 /* NSObjectExt.swift */; };
2E18B296242DF436000C7776 /* NSObjectExtTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E18B295242DF436000C7776 /* NSObjectExtTests.swift */; };
2E18B297242DF436000C7776 /* NSObjectExtTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E18B295242DF436000C7776 /* NSObjectExtTests.swift */; };
2E18B298242DF436000C7776 /* NSObjectExtTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E18B295242DF436000C7776 /* NSObjectExtTests.swift */; };
2E5A375425655F55003704D0 /* StringProtocolExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E5A375325655F55003704D0 /* StringProtocolExt.swift */; };
2E5A375525655F55003704D0 /* StringProtocolExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E5A375325655F55003704D0 /* StringProtocolExt.swift */; };
2E5A375625655F55003704D0 /* StringProtocolExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E5A375325655F55003704D0 /* StringProtocolExt.swift */; };
2E61DF7A249E1CA9000AF3C5 /* Withable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E61DF79249E1CA9000AF3C5 /* Withable.swift */; };
2E61DF7B249E1CA9000AF3C5 /* Withable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E61DF79249E1CA9000AF3C5 /* Withable.swift */; };
2E61DF7C249E1CA9000AF3C5 /* Withable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E61DF79249E1CA9000AF3C5 /* Withable.swift */; };
Expand Down Expand Up @@ -139,9 +148,12 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
2E18AD592531DD3D00D44748 /* DoubleExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleExt.swift; sourceTree = "<group>"; };
2E18AD632531E0F800D44748 /* DoubleExtTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleExtTests.swift; sourceTree = "<group>"; };
2E18B291242DECCA000C7776 /* NSObjectExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSObjectExt.swift; sourceTree = "<group>"; };
2E18B295242DF436000C7776 /* NSObjectExtTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSObjectExtTests.swift; sourceTree = "<group>"; };
2E4189DB231B971E00C65B81 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = "<group>"; };
2E5A375325655F55003704D0 /* StringProtocolExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringProtocolExt.swift; sourceTree = "<group>"; };
2E61DF79249E1CA9000AF3C5 /* Withable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Withable.swift; sourceTree = "<group>"; };
2E61DF7D249E1D37000AF3C5 /* WithableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WithableTests.swift; sourceTree = "<group>"; };
3F95C8D120F22A3C0045AFD0 /* CollectionExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionExt.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -188,7 +200,7 @@
C5C89B9320B0A0C10048B07C /* Weak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; };
C5CFB6AB20B0A70300830511 /* Unowned.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Unowned.swift; sourceTree = "<group>"; };
CC120CC1205FDB9300C37D7C /* Regex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Regex.swift; sourceTree = "<group>"; };
CC4AE0CD2087D895009931F6 /* RegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegexTests.swift; sourceTree = "<group>"; };
CC4AE0CD2087D895009931F6 /* RegexTests.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = RegexTests.swift; sourceTree = "<group>"; tabWidth = 4; };
CC66E046228199A0007ABF61 /* ComparableExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComparableExt.swift; sourceTree = "<group>"; };
CC66E12322819FCF007ABF61 /* ComparableExtTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComparableExtTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -256,8 +268,8 @@
8203930420F3A63F0074974F /* HandySwiftTests */ = {
isa = PBXGroup;
children = (
82812A9E1D06926800CD5B6C /* GlobalsTests.swift */,
823B2B4E1C24ABD8007B3CDD /* Extensions */,
82812A9E1D06926800CD5B6C /* GlobalsTests.swift */,
8251AA23227875A10022B277 /* Protocols */,
8258E4571C2E196B0031CBFF /* Structs */,
);
Expand Down Expand Up @@ -295,10 +307,12 @@
CC66E046228199A0007ABF61 /* ComparableExt.swift */,
8280D7DB1C4A6EC9001172EF /* DictionaryExt.swift */,
A1F221631E3CC05100419B06 /* DispatchTimeIntervalExt.swift */,
2E18AD592531DD3D00D44748 /* DoubleExt.swift */,
823B2B4C1C24ABA4007B3CDD /* IntExt.swift */,
2E18B291242DECCA000C7776 /* NSObjectExt.swift */,
8218E4D52211D193007AAAF3 /* NSRangeExt.swift */,
82CAE2911C2ED1A200F934A7 /* StringExt.swift */,
2E5A375325655F55003704D0 /* StringProtocolExt.swift */,
A11830D21E589F6700CBE087 /* TimeIntervalExt.swift */,
);
path = Extensions;
Expand All @@ -312,6 +326,7 @@
CC66E12322819FCF007ABF61 /* ComparableExtTests.swift */,
8280D7DF1C4A6FF3001172EF /* DictionaryExtTests.swift */,
827599631E520FB800787F99 /* DispatchTimeIntervalExtTests.swift */,
2E18AD632531E0F800D44748 /* DoubleExtTests.swift */,
823B2B4F1C24AC00007B3CDD /* IntExtTests.swift */,
2E18B295242DF436000C7776 /* NSObjectExtTests.swift */,
8218E4D92211D270007AAAF3 /* NSRangeExtTests.swift */,
Expand Down Expand Up @@ -775,10 +790,12 @@
CC66E047228199A0007ABF61 /* ComparableExt.swift in Sources */,
C5C89B9420B0A0C10048B07C /* Weak.swift in Sources */,
82CAE2921C2ED1A200F934A7 /* StringExt.swift in Sources */,
2E18AD5A2531DD3D00D44748 /* DoubleExt.swift in Sources */,
82CAE2961C2EE64900F934A7 /* ArrayExt.swift in Sources */,
2E61DF7A249E1CA9000AF3C5 /* Withable.swift in Sources */,
C5CFB6AC20B0A70300830511 /* Unowned.swift in Sources */,
82812A9B1D06877B00CD5B6C /* Globals.swift in Sources */,
2E5A375425655F55003704D0 /* StringProtocolExt.swift in Sources */,
63651F90231BFF2000E022DA /* DivisibleArithmetic.swift in Sources */,
8280D7DC1C4A6EC9001172EF /* DictionaryExt.swift in Sources */,
A11830D31E589F6700CBE087 /* TimeIntervalExt.swift in Sources */,
Expand All @@ -804,6 +821,7 @@
3F95C8D520F22DEE0045AFD0 /* CollectionExtTests.swift in Sources */,
2E18B296242DF436000C7776 /* NSObjectExtTests.swift in Sources */,
CC4AE0CF2087D8A7009931F6 /* RegexTests.swift in Sources */,
2E18AD732531E0FD00D44748 /* DoubleExtTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -822,10 +840,12 @@
CC66E048228199DE007ABF61 /* ComparableExt.swift in Sources */,
C5CFB6AF20B0A78F00830511 /* Weak.swift in Sources */,
A1F221651E3CC05100419B06 /* DispatchTimeIntervalExt.swift in Sources */,
2E18AD5B2531DD3D00D44748 /* DoubleExt.swift in Sources */,
825EFE021C33358400558497 /* SortedArray.swift in Sources */,
2E61DF7B249E1CA9000AF3C5 /* Withable.swift in Sources */,
825EFE031C33358400558497 /* IntExt.swift in Sources */,
82812A9C1D06877B00CD5B6C /* Globals.swift in Sources */,
2E5A375525655F55003704D0 /* StringProtocolExt.swift in Sources */,
63651F91231BFF2000E022DA /* DivisibleArithmetic.swift in Sources */,
8280D7DD1C4A6EC9001172EF /* DictionaryExt.swift in Sources */,
A11830D41E589F6700CBE087 /* TimeIntervalExt.swift in Sources */,
Expand All @@ -851,6 +871,7 @@
3F95C8D620F22DEF0045AFD0 /* CollectionExtTests.swift in Sources */,
2E18B297242DF436000C7776 /* NSObjectExtTests.swift in Sources */,
CC4AE0D02087D8A8009931F6 /* RegexTests.swift in Sources */,
2E18AD7A2531E0FD00D44748 /* DoubleExtTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -869,10 +890,12 @@
CC66E049228199DF007ABF61 /* ComparableExt.swift in Sources */,
C5CFB6B020B0A79000830511 /* Weak.swift in Sources */,
A1F221661E3CC05100419B06 /* DispatchTimeIntervalExt.swift in Sources */,
2E18AD5C2531DD3D00D44748 /* DoubleExt.swift in Sources */,
825EFE081C33358500558497 /* SortedArray.swift in Sources */,
2E61DF7C249E1CA9000AF3C5 /* Withable.swift in Sources */,
825EFE091C33358500558497 /* IntExt.swift in Sources */,
82812A9D1D06877B00CD5B6C /* Globals.swift in Sources */,
2E5A375625655F55003704D0 /* StringProtocolExt.swift in Sources */,
63651F92231BFF2800E022DA /* DivisibleArithmetic.swift in Sources */,
8280D7DE1C4A6EC9001172EF /* DictionaryExt.swift in Sources */,
A11830D51E589F6700CBE087 /* TimeIntervalExt.swift in Sources */,
Expand All @@ -898,6 +921,7 @@
3F95C8D720F22DEF0045AFD0 /* CollectionExtTests.swift in Sources */,
2E18B298242DF436000C7776 /* NSObjectExtTests.swift in Sources */,
CC4AE0D12087D8A9009931F6 /* RegexTests.swift in Sources */,
2E18AD812531E0FE00D44748 /* DoubleExtTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
29 changes: 27 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
alt="Coverage"/>
</a>
<a href="https://github.com/Flinesoft/HandySwift/releases">
<img src="https://img.shields.io/badge/Version-3.2.1-blue.svg"
alt="Version: 3.2.1">
<img src="https://img.shields.io/badge/Version-3.3.0-blue.svg"
alt="Version: 3.3.0">
</a>
<img src="https://img.shields.io/badge/Swift-5.1-FFAC45.svg" alt="Swift: 5.1">
<img src="https://img.shields.io/badge/Platforms-iOS%20%7C%20tvOS%20%7C%20macOS%20%7C%20Linux-FF69B4.svg"
Expand Down Expand Up @@ -74,6 +74,7 @@ Open the Playground from within the `.xcworkspace` in order for it to work.
- Extensions
- [IntExtension](#intextension)
- [IntegerTypeExtension](#integertypeextension)
- [DoubleExtension](#doubleextension)
- [StringExtension](#stringextension)
- [NSRangeExtension](#nsrangeextension)
- [CollectionExtension](#collectionextension)
Expand Down Expand Up @@ -166,6 +167,30 @@ myNum.clamp(to: 0...2)
myNum // => 2
```

### DoubleExtension

#### round(fractionDigits:rule:)

Rounds the value to an integral value using the specified fraction digits and rounding rule.

``` Swift
var price: Double = 2.875
price.round(fractionDigits: 2) // => 2.88
// OR with explicit rule:
price.round(fractionDigits: 2, rule: .down) // 2.87
```

#### rounded(fractionDigits:rule:) -> Double

Returns this value rounded to an integral value using the specified fraction digits and rounding rule.

``` Swift
let price: Double = 2.875
price.rounded(fractionDigits: 2) // => 2.88
// OR with explicit rule:
price.rounded(fractionDigits: 2, rule: .down) // => 2.87
```

### StringExtension

#### .stripped()
Expand Down
21 changes: 21 additions & 0 deletions Sources/HandySwift/Extensions/DoubleExt.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright © 2020 Flinesoft. All rights reserved.

import Foundation

extension Double {
/// Rounds the value to an integral value using the specified fraction digits and rounding rule.
///
/// - NOTE: Dropping the `rule` parameter will default to “schoolbook rounding”.
public mutating func round(fractionDigits: Int, rule: FloatingPointRoundingRule = .toNearestOrAwayFromZero) {
let divisor = pow(10.0, Double(fractionDigits))
self = (self * divisor).rounded(rule) / divisor
}

/// Returns this value rounded to an integral value using the specified fraction digits and rounding rule.
///
/// - NOTE: Dropping the `rule` parameter will default to “schoolbook rounding”.
public func rounded(fractionDigits: Int, rule: FloatingPointRoundingRule = .toNearestOrAwayFromZero) -> Double {
let divisor = pow(10.0, Double(fractionDigits))
return (self * divisor).rounded(rule) / divisor
}
}
14 changes: 14 additions & 0 deletions Sources/HandySwift/Extensions/StringProtocolExt.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright © 2020 Flinesoft. All rights reserved.

import Foundation

extension StringProtocol {
/// Returns a variation with the first character uppercased.
public var firstUppercased: String { prefix(1).uppercased() + dropFirst() }

/// Returns a variation with the first character capitalized.
public var firstCapitalized: String { prefix(1).capitalized + dropFirst() }

/// Returns a variation with the first character lowercased.
public var firstLowercased: String { prefix(1).lowercased() + dropFirst() }
}
10 changes: 3 additions & 7 deletions Sources/HandySwift/Structs/Regex.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,9 @@ public struct Regex {
/// - returns: An optional `Match` describing the first match, or `nil`.
@inlinable
public func firstMatch(in string: String) -> Match? {
let firstMatch = regularExpression
regularExpression
.firstMatch(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count))
.map { Match(result: $0, in: string) }
return firstMatch
}

/// If the regex matches `string`, returns an array of `Match`, describing
Expand All @@ -62,10 +61,9 @@ public struct Regex {
/// - returns: An array of `Match` describing every match in `string`.
@inlinable
public func matches(in string: String) -> [Match] {
let matches = regularExpression
regularExpression
.matches(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count))
.map { Match(result: $0, in: string) }
return matches
}

// MARK: Replacing
Expand Down Expand Up @@ -246,14 +244,12 @@ extension Regex {
///
/// - returns: A string with `template` applied to the matched string.
public func string(applyingTemplate template: String) -> String {
let replacement = result.regularExpression!.replacementString(
result.regularExpression!.replacementString(
for: result,
in: baseString,
offset: 0,
template: template
)

return replacement
}

// MARK: - CustomStringConvertible
Expand Down
2 changes: 1 addition & 1 deletion Sources/SupportingFiles/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>3.2.1</string>
<string>3.3.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
22 changes: 22 additions & 0 deletions Tests/HandySwiftTests/Extensions/DoubleExtTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright © 2020 Flinesoft. All rights reserved.

@testable import HandySwift
import XCTest

class DoubleExtTests: XCTestCase {
func testRound() {
var price: Double = 2.875
price.round(fractionDigits: 2)
XCTAssertEqual(price, 2.88)

price = 2.875
price.round(fractionDigits: 2, rule: .down)
XCTAssertEqual(price, 2.87)
}

func testRounded() {
let price: Double = 2.875
XCTAssertEqual(price.rounded(fractionDigits: 2), 2.88)
XCTAssertEqual(price.rounded(fractionDigits: 2, rule: .down), 2.87)
}
}
10 changes: 10 additions & 0 deletions Tests/HandySwiftTests/Structs/RegexTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ class RegexTests: XCTestCase {
func testMatches() {
let regex = try? Regex("[1-9]+")
XCTAssertEqual(regex?.matches(in: "5 432 11").map { $0.string }, ["5", "432", "11"])

let key = "bi"
let complexRegex = try? Regex(#"<\#(key)>([^<>]+)</\#(key)>"#)
XCTAssertEqual(
complexRegex?.matches(
in:
"Add all your <bi>tasks</bi> in here. We will guide you with the right questions to get them <bi>organized</bi>."
).map { $0.string },
["<bi>tasks</bi>", "<bi>organized</bi>"]
)
}

func testReplacingMatches() {
Expand Down
Loading

0 comments on commit 50b84f0

Please sign in to comment.