diff --git a/Guitar.podspec b/Guitar.podspec index 39660b1..b0f7be2 100644 --- a/Guitar.podspec +++ b/Guitar.podspec @@ -1,10 +1,10 @@ Pod::Spec.new do |s| s.name = 'Guitar' - s.version = '0.0.8' - s.summary = 'A Cross-Platform String Library Written in Swift.' + s.version = '0.0.9' + s.summary = 'A Cross-Platform String and Regular Expression Library Written in Swift.' description = <<-DESC -A Cross-Platform String Library Written in Swift. +A Cross-Platform String and Regular Expression Library Written in Swift. DESC s.ios.deployment_target = '9.0' diff --git a/GuitarExample/GuitarExample.xcodeproj/project.pbxproj b/GuitarExample/GuitarExample.xcodeproj/project.pbxproj index 5e464d5..842ce15 100644 --- a/GuitarExample/GuitarExample.xcodeproj/project.pbxproj +++ b/GuitarExample/GuitarExample.xcodeproj/project.pbxproj @@ -16,8 +16,8 @@ 55A36A171E71228300DC6BBF /* GuitarCharacter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A36A121E71228300DC6BBF /* GuitarCharacter.swift */; }; 55A36A181E71228300DC6BBF /* GuitarPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A36A131E71228300DC6BBF /* GuitarPadding.swift */; }; 55A36A191E71228300DC6BBF /* GuitarTrimming.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A36A141E71228300DC6BBF /* GuitarTrimming.swift */; }; - 55A36A1B1E7124E100DC6BBF /* GuitarRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A36A1A1E7124E100DC6BBF /* GuitarRegex.swift */; }; - 55A36A1D1E712B1300DC6BBF /* GuitarRegexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A36A1C1E712B1300DC6BBF /* GuitarRegexTests.swift */; }; + 55A36A1B1E7124E100DC6BBF /* Guitar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A36A1A1E7124E100DC6BBF /* Guitar.swift */; }; + 55A36A1D1E712B1300DC6BBF /* GuitarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A36A1C1E712B1300DC6BBF /* GuitarTests.swift */; }; 55DA075A1E66AF2200080633 /* GuitarBooleanTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DA07591E66AF2200080633 /* GuitarBooleanTests.swift */; }; 55EC366B1E6BBDAC00726F13 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55EC36631E6BBDAC00726F13 /* AppDelegate.swift */; }; 55EC366C1E6BBDAC00726F13 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 55EC36641E6BBDAC00726F13 /* Assets.xcassets */; }; @@ -27,7 +27,6 @@ 55EC367A1E6BBDD500726F13 /* Guitar.h in Headers */ = {isa = PBXBuildFile; fileRef = 55EC36781E6BBDD400726F13 /* Guitar.h */; settings = {ATTRIBUTES = (Public, ); }; }; 55EC367D1E6BBDD500726F13 /* Guitar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55EC36761E6BBDD400726F13 /* Guitar.framework */; }; 55EC367F1E6BBDD500726F13 /* Guitar.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 55EC36761E6BBDD400726F13 /* Guitar.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 55EC36841E6BBDDD00726F13 /* Guitar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55EC36831E6BBDDD00726F13 /* Guitar.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -81,8 +80,8 @@ 55A36A121E71228300DC6BBF /* GuitarCharacter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GuitarCharacter.swift; path = ../../Sources/GuitarCharacter.swift; sourceTree = ""; }; 55A36A131E71228300DC6BBF /* GuitarPadding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GuitarPadding.swift; path = ../../Sources/GuitarPadding.swift; sourceTree = ""; }; 55A36A141E71228300DC6BBF /* GuitarTrimming.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GuitarTrimming.swift; path = ../../Sources/GuitarTrimming.swift; sourceTree = ""; }; - 55A36A1A1E7124E100DC6BBF /* GuitarRegex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GuitarRegex.swift; path = ../../Sources/GuitarRegex.swift; sourceTree = ""; }; - 55A36A1C1E712B1300DC6BBF /* GuitarRegexTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GuitarRegexTests.swift; sourceTree = ""; }; + 55A36A1A1E7124E100DC6BBF /* Guitar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Guitar.swift; path = ../../Sources/Guitar.swift; sourceTree = ""; }; + 55A36A1C1E712B1300DC6BBF /* GuitarTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GuitarTests.swift; sourceTree = ""; }; 55DA07571E66AF2200080633 /* GuitarExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GuitarExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 55DA07591E66AF2200080633 /* GuitarBooleanTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuitarBooleanTests.swift; sourceTree = ""; }; 55DA075B1E66AF2200080633 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -95,7 +94,6 @@ 55EC36761E6BBDD400726F13 /* Guitar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Guitar.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 55EC36781E6BBDD400726F13 /* Guitar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Guitar.h; sourceTree = ""; }; 55EC36791E6BBDD400726F13 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 55EC36831E6BBDDD00726F13 /* Guitar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Guitar.swift; path = ../../Sources/Guitar.swift; sourceTree = ""; }; 8EDB77C11E0A516B00B13A61 /* GuitarExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GuitarExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -128,11 +126,11 @@ 55DA07581E66AF2200080633 /* GuitarExampleTests */ = { isa = PBXGroup; children = ( + 55A36A1C1E712B1300DC6BBF /* GuitarTests.swift */, 55DA07591E66AF2200080633 /* GuitarBooleanTests.swift */, 554046B21E67BDAB009B317A /* GuitarCaseTests.swift */, 554046B61E67D925009B317A /* GuitarCharacterTests.swift */, 554046B81E67E6F2009B317A /* GuitarPaddingTests.swift */, - 55A36A1C1E712B1300DC6BBF /* GuitarRegexTests.swift */, 554046BA1E67FC78009B317A /* GuitarTrimmingTests.swift */, 55DA075B1E66AF2200080633 /* Info.plist */, ); @@ -155,12 +153,11 @@ 55EC36771E6BBDD400726F13 /* Guitar */ = { isa = PBXGroup; children = ( - 55EC36831E6BBDDD00726F13 /* Guitar.swift */, + 55A36A1A1E7124E100DC6BBF /* Guitar.swift */, 55A36A101E71228300DC6BBF /* GuitarBoolean.swift */, 55A36A111E71228300DC6BBF /* GuitarCase.swift */, 55A36A121E71228300DC6BBF /* GuitarCharacter.swift */, 55A36A131E71228300DC6BBF /* GuitarPadding.swift */, - 55A36A1A1E7124E100DC6BBF /* GuitarRegex.swift */, 55A36A141E71228300DC6BBF /* GuitarTrimming.swift */, 55EC36781E6BBDD400726F13 /* Guitar.h */, 55EC36791E6BBDD400726F13 /* Info.plist */, @@ -362,7 +359,7 @@ 554046B71E67D925009B317A /* GuitarCharacterTests.swift in Sources */, 554046B31E67BDAB009B317A /* GuitarCaseTests.swift in Sources */, 554046B91E67E6F2009B317A /* GuitarPaddingTests.swift in Sources */, - 55A36A1D1E712B1300DC6BBF /* GuitarRegexTests.swift in Sources */, + 55A36A1D1E712B1300DC6BBF /* GuitarTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -372,8 +369,7 @@ files = ( 55A36A151E71228300DC6BBF /* GuitarBoolean.swift in Sources */, 55A36A161E71228300DC6BBF /* GuitarCase.swift in Sources */, - 55EC36841E6BBDDD00726F13 /* Guitar.swift in Sources */, - 55A36A1B1E7124E100DC6BBF /* GuitarRegex.swift in Sources */, + 55A36A1B1E7124E100DC6BBF /* Guitar.swift in Sources */, 55A36A191E71228300DC6BBF /* GuitarTrimming.swift in Sources */, 55A36A181E71228300DC6BBF /* GuitarPadding.swift in Sources */, 55A36A171E71228300DC6BBF /* GuitarCharacter.swift in Sources */, diff --git a/GuitarExample/GuitarExampleTests/GuitarRegexTests.swift b/GuitarExample/GuitarExampleTests/GuitarRegexTests.swift deleted file mode 100644 index cbc9729..0000000 --- a/GuitarExample/GuitarExampleTests/GuitarRegexTests.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// GuitarRegexTests.swift -// GuitarExample -// -// Created by Sabintsev, Arthur on 3/9/17. -// Copyright © 2017 Arthur Ariel Sabintsev. All rights reserved. -// - -import XCTest -@testable import Guitar - -class GuitarRegexTests: XCTestCase { - - func testEmailMatching() { - XCTAssertEqual(GuitarRegex(pattern: GuitarPattern.email).evaluate(string: "This is one email addresses: arthur@sabintsev.com. This is another [arthur@example.com].").count, 2) - } - - func testAlphanumericMatching() { - var string = "Hello World, and Hello Guitar Users! ^_^" - let ranges = GuitarRegex(pattern: GuitarPattern.nonAlphanumeric).evaluate(string: string) - - XCTAssertEqual(ranges.count, 5) - - for range in ranges { - string.replaceSubrange(range, with: "*") - } - - XCTAssertEqual(string, "Hello World* and Hello Guitar Users* ***") - } - - func testIsValidEmail() { - XCTAssertTrue(GuitarRegex.isValidEmail(email: "arthur@sabintsev.com")) - XCTAssertTrue(GuitarRegex.isValidEmail(email: "arthur.sabintsev@example.com")) - XCTAssertFalse(GuitarRegex.isValidEmail(email: "arthur.sabintsev@example")) - XCTAssertFalse(GuitarRegex.isValidEmail(email: "arthur.sabintsev@x.y.z")) - } - -} diff --git a/GuitarExample/GuitarExampleTests/GuitarTests.swift b/GuitarExample/GuitarExampleTests/GuitarTests.swift new file mode 100644 index 0000000..ccd1ed8 --- /dev/null +++ b/GuitarExample/GuitarExampleTests/GuitarTests.swift @@ -0,0 +1,37 @@ +// +// GuitarTests.swift +// GuitarExample +// +// Created by Sabintsev, Arthur on 3/9/17. +// Copyright © 2017 Arthur Ariel Sabintsev. All rights reserved. +// + +import XCTest +@testable import Guitar + +class GuitarTests: XCTestCase { + + func testEmailMatching() { + XCTAssertEqual(Guitar(chord: Guitar.Chord.email).evaluate(string: "This is one email address: arthur@sabintsev.com. This is another [arthur@example.com].").count, 2) + } + + func testAlphanumericMatching() { + let string = "Hello World, and Hello Guitar Users! ^_^" + let newString = Guitar(chord: Guitar.Chord.nonAlphanumeric).replaceOccurences(in: string, with: "*") + XCTAssertEqual(newString, "Hello World* and Hello Guitar Users* ***") + } + + func testIsValidEmail() { + XCTAssertTrue(Guitar.isValidEmail(email: "arthur@sabintsev.com")) + XCTAssertTrue(Guitar.isValidEmail(email: "arthur.sabintsev@example.com")) + XCTAssertFalse(Guitar.isValidEmail(email: "arthur.sabintsev@example")) + XCTAssertFalse(Guitar.isValidEmail(email: "arthur.sabintsev@x.y.z")) + } + + func testSanitize() { + let string = "Hello, World! This is Arthur. My email is arthur@sabintsev.com! Who misses Obj-C []?" + let newString = Guitar.sanitze(string: string) + XCTAssertEqual(newString, "Hello World This is Arthur My email is arthur sabintsev com Who misses Obj C ") + } + +} diff --git a/README.md b/README.md index 7a658f9..ce5baa3 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # Guitar -### A Cross-Platform String Library Written in Swift. +### A Cross-Platform String and Regular Expression Library Written in Swift. [![BuddyBuild](https://dashboard.buddybuild.com/api/statusImage?appID=58b67d22d21c470100b0c394&branch=master&build=latest)](https://dashboard.buddybuild.com/apps/58b67d22d21c470100b0c394/build/latest?branch=master) [![Documentation](https://cdn.rawgit.com/ArtSabintsev/Guitar/master/docs/badge.svg)](http://sabintsev.com/Guitar/) [![Platform](https://img.shields.io/cocoapods/p/Guitar.svg?style=flat)](http://cocoadocs.org/docsets/Guitar) [![CocoaPods](https://img.shields.io/cocoapods/v/Guitar.svg)](https://cocoapods.org/pods/Guitar) [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![SwiftPM Compatible](https://img.shields.io/badge/SwiftPM-Compatible-brightgreen.svg)](https://swift.org/package-manager/) [![CocoaPods](https://img.shields.io/cocoapods/dt/Guitarn.svg)](https://cocoapods.org/pods/Guitar) [![CocoaPods](https://img.shields.io/cocoapods/dm/Guitar.svg)](https://cocoapods.org/pods/Guitar) ## About -This library seeks to add common string manipulation functions that are needed in both mobile and server-side development, but are missing in Swift's Foundation library. +This library seeks to add common string manipulation functions, including common regular expression capabilities, that are needed in both mobile and server-side development, but are missing in Swift's Foundation library. The full documentation can be found at http://www.sabintsev.com/Guitar/. @@ -40,269 +40,10 @@ github "ArtSabintsev/Guitar" .Package(url: "https://github.com/ArtSabintsev/Guitar.git", majorVersion: 0) ``` -## Implemented Functions +## Example +Guitar is currently in Alpha (until v0.1.0). During this stage, the API is unstable. Therefore, it does not make sense to retain example until the API is stabilized. -### Boolean Operations - -#### isAlpha() -```swift -let string = "HelloWorld" -string.isAlpha() // True - -let string = "Hell0World" -string.isAlpha() // False -``` - -#### isAlphanumeric() -```swift -let string = "HelloWorld" -string.isAlphanumeric() // True - -let string = "Hell0World" -string.isAlphanumeric() // True - -let string = "Hell0 World" -string.isAlphanumeric() // False -``` - -#### isCapitalized() -```swift -let string = "Hello World" -string.isCapitalized() // True - -let string = "hello World" -string.isCapitalized() // False - -let string = "Hello-World" -string.isCapitalized() // True -``` - -#### isDecapitalized() -```swift -let string = "hello World" -string.isDecapitalized() // True - -let string = "Hello World" -string.isDecapitalized() // False - -let string = "hello-World" -string.isDecapitalized() // True -``` - -#### isLowercased() -```swift -// Note, Swift treats non-alphabetical characters as Uppercased. - -let string = "helloworld" -string.isLowercased() // True - -let string = "hello world" -string.isLowercased() // False - -let string = "hello-world" -string.isLowercased() // False -``` - -#### isNumeric() -```swift -let string = "73110" -string.isNumeric() // True - -let string = "73110 1337" -string.isNumeric() // False - -let string = "73110World" -string.isNumeric() // False -``` - -#### isUpppercased() -```swift - -// Note, Swift treats non-alphabetical characters as Uppercased. - -let string = "HELLOWORLD" -string.isUpppercased() // True - -let string = "HELLO WORLD" -string.isUpppercased() // True - -let string = "HELLO-W0RLD" -string.isUpppercased() // True - -let string = "HeLLoW0RLD" -string.isUpppercased() // False -``` - -### Case Operations - -#### camelCased() -```swift -let string = "Hello World" -string.camelCased() // "helloWorld" - -let string = "hello_world" -string.camelCased() // "helloWorld" -``` - -#### capitalized() -```swift -// Implementation is currently broken. -``` - -#### decapitalized() -```swift -// Implementation is currently broken. -``` - -#### kebabCased() -```swift -let string = "Hello World" -string.kebabCased() // "-Hello-World-" - -let string = "hello_world" -string.kebabCased() // "-hello-world-" -``` - -#### pascalCased() -```swift -let string = "Hello World" -string.pascalCased() // "HelloWorld" - -let string = "hello_world" -string.pascalCased() // "HelloWorld" -``` - -#### slugCased() -```swift -let string = "Hello World" -string.slugCased() // "Hello-World" -``` - -#### snakeCased() -```swift -let string = "Hello World" -string.snakeCased() // "Hello_World" -``` -#### swapCased() -```swift -let string = "Hello World" -string.swapCased() // "hELLO wORLD" -``` - -### Character Operations - -#### first() -```swift -let string = "Hello World" -string.first() // "H" -``` - -#### last() -```swift -let string = "Hello World" -string.last() // "d" -``` - -#### length() -```swift -let string = "Hello World" -string.length() // "11" -``` - -#### reversed() -```swift -let string = "Hello World" -string.reversed() // "dlroW olleH" -``` - -### Padding Operations - -#### padLeft() -```swift -let string = "Hello World" // 11 Characters -string.padLeft(length: 15) // " Hello World" - -let string = "Hello World" // 11 Characters -string.padLeft(length: 15, withToken: "*") // "****Hello World" - -let string = "Hello World" // 11 Characters -string.padLeft(length: 5) // Returns the original string, "Hello World" -``` - -#### padRight() -```swift -let string = "Hello World" // 11 Characters -string.padRight(length: 15) // "Hello World " - -let string = "Hello World" // 11 Characters -string.padRight(length: 15, withToken: "*") // "Hello World****" - -let string = "Hello World" // 11 Characters -string.padRight(length: 5) // Returns the original string, "Hello World" -``` - -#### pad() -```swift -let string = "Hello World" // 11 Characters -string.pad(length: 15) // " Hello World " - -let string = "Hello World" // 11 Characters -string.pad(length: 5) // Returns the original string, "Hello World" - -let string = "Hello World" // 11 Characters -string.pad(length: 15, withToken: "*") // "**Hello World**" - -/* Note: If the difference between the final length - and number of characters in the original string is odd, - the string is padded extra on the right side. - */ -let string = "Hello World" // 11 Characters -string.pad(length: 16) // " Hello World " - -let string = "Hello World" // 11 Characters -string.pad(length: 16) // "**Hello World***" -``` - -### Trimming Operations - -#### trimLeft(byKeeping:) -```swift -let string = "Hello World" -string.trimLeft(byKeeping: 7) // "Hello W" -``` - -#### trimRight(byKeeping:) -```swift -let string = "Hello World" -string.trimRight(byKeeping: 7) // "o World" -``` - -#### trimLeft(byRemoving:) -```swift -let string = "Hello World" -string.trimLeft(byRemoving: 7) // "orld" -``` - -#### trimRight(byRemoving:) -```swift -let string = "Hello World" -string.trimRight(byRemoving: 7) // "Hell" -``` - -#### truncated() -```swift -let string = "Hello World" -string.truncated(length: 7) // "Hell..." (Appends an ellipsis, ..., to the end of the string.) -``` - -### Regex Operations -`GuitarRegex` is a syntactic-sugar struct built on top of NSRegularExpression. It also introduces the `GuitarPattern` struct which represents common Regex patterns. - -Example usage: -```swift -GuitarRegex(pattern: GuitarPattern.email).evaluate(string: "This string contains an email address, guitar@swift.org") -// Returns an [Range] which is easily used to make substitutions/replacements in the String API found within Foundation. -``` +For the time being, check out the [tests](https://github.com/ArtSabintsev/Guitar/tree/master/GuitarExample/GuitarExampleTests) to see the library in action. ## Inspiration This project was inspired by [Voca](https://vocajs.com/). diff --git a/Sources/Guitar.swift b/Sources/Guitar.swift index 150c0fa..0475689 100644 --- a/Sources/Guitar.swift +++ b/Sources/Guitar.swift @@ -1,19 +1,124 @@ // // Guitar.swift -// Guitar +// GuitarExample // -// Created by Arthur Sabintsev on 12/21/16. +// Created by Sabintsev, Arthur on 3/9/17. // Copyright © 2017 Arthur Ariel Sabintsev. All rights reserved. // +// Adapted from: +// http://benscheirman.com/2014/06/regex-in-swift/ +// https://www.hackingwithswift.com/example-code/language/how-to-convert-an-nsrange-to-a-swift-string-index import Foundation -prefix operator - +// MARK - Guitar -/// Sanitizes strings by replacing underscores and dashes with whitespaces using the custom `-` prefix operator. -/// -/// - Parameter string: The string that will be sanitzed. -/// - Returns: The sanitized string. -prefix func - (string: String) -> String { - return string.replacingOccurrences(of: "_", with: " ").replacingOccurrences(of: "-", with: " ") +public struct Guitar { + /// Common Regular Expression Patterns + public struct Chord { + /// Pattern matches email addresses. + public static let email = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}" + + /// Pattern matches non-Alphanumeric and non-Whitespace characters. + public static let nonAlphanumeric = "[^a-zA-Z\\d\\s]" + } + + /// Regular expression pattern that will be used to evaluate a specific string. + let chord: String + + /// Designated Initializer for *GuitarRegex* + /// + /// - Parameters: + /// - chord: The pattern (also known as a `chord`) that will be used to perform the match. Common patterns (or chords) can be found in the `Chord` struct. + /// + /// - Returns: A list of matches. + public init(chord: String) { + self.chord = chord + } + + /// Evaluates a string for all instances of a regular expression pattern. + /// + /// - Parameters: + /// - string: The string that will be evaluated. + /// - options: Regular expression options that are applied to the string during matching. Defaults to []. + /// + /// - Returns: A list of matches. + public func evaluate(string: String, options: NSRegularExpression.Options = []) -> [Range] { + let range = NSRange(location: 0, length: string.characters.count) + guard let regex = try? NSRegularExpression(pattern: chord, options: options) else { + return [] + } + + let matches = regex.matches(in: string, options: [], range: range) + + let ranges = matches.flatMap { (match) -> Range? in + let nsRange = match.range + return nsRange.range(for: string) + } + + return ranges + } + + public func replaceOccurences(in string: String, with character: String) -> String { + let ranges = Guitar(chord: chord).evaluate(string: string) + + var newString = string + for range in ranges { + newString.replaceSubrange(range, with: character) + } + + return newString + } + + /// Tests a string to see if it matches the regular expression pattern. + /// + /// - Parameters: + /// - string: The string that will be evaluated. + /// - options: Regular expression options that are applied to the string during matching. Defaults to []. + /// + /// - Returns: `true` if string passes the test, otherwise, `false`. + public func test(string: String, options: NSRegularExpression.Options = []) -> Bool { + return evaluate(string: string, options: options).count > 0 + } +} + +// MARK: - Regular Expressions (Common Evaluations and Tests) + +public extension Guitar { + /// Tests a string to check if it is a valid email address by using a regular expression. + /// + /// - Parameters: + /// - email: The string that needs to be evaluated. + /// + /// - Returns: `true` if `string` is a valid email address, otherwise `false`. + static func isValidEmail(email: String) -> Bool { + return Guitar(chord: Chord.email).test(string: email) + } + + /// Sanitizes of a string by removing all non-Alphanumeric characters (excluding whitespaces) + /// + /// - Parameter string: The string that should be sanitized. + /// - Returns: The sanitized string. + static func sanitze(string: String) -> String { + return Guitar(chord: Chord.nonAlphanumeric).replaceOccurences(in: string, with: " ") + } +} + +// MARK: - NSRange Helpers + +private extension NSRange { + /// Converts NSRange to Range + /// + /// - Parameter string: The string from which the NSRange was extracted. + /// - Returns: The `Range` representation of the NSRange. + func range(for string: String) -> Range? { + guard location != NSNotFound else { return nil } + + guard let fromUTFIndex = string.utf16.index(string.utf16.startIndex, offsetBy: location, limitedBy: string.utf16.endIndex) else { return nil } + guard let toUTFIndex = string.utf16.index(fromUTFIndex, offsetBy: length, limitedBy: string.utf16.endIndex) else { return nil } + guard let fromIndex = String.Index(fromUTFIndex, within: string) else { return nil } + guard let toIndex = String.Index(toUTFIndex, within: string) else { return nil } + + return fromIndex ..< toIndex + } } diff --git a/Sources/GuitarCase.swift b/Sources/GuitarCase.swift index 6779578..daa2c8e 100644 --- a/Sources/GuitarCase.swift +++ b/Sources/GuitarCase.swift @@ -33,13 +33,12 @@ public extension String { /// /// let string = "helloworld" /// print(string.capitalized()) - /// // Prints "HELLOWORLD" + /// // Prints "Helloworld" /// /// - Returns: A capitalized copy of the string. - @available(*, unavailable) @discardableResult func capitalized() -> String { - return "" + return first().uppercased() + String(characters.dropFirst()) } /// Returns a decapitalized version of the string. @@ -48,7 +47,7 @@ public extension String { /// /// let string = "HELLOWORLD" /// print(string.decapitalized()) - /// // Prints "helloworld" + /// // Prints "hELLOWORLD" /// /// - Returns: A decapitalized copy of the string. @discardableResult @@ -81,7 +80,7 @@ public extension String { /// - Returns: A pascal cased copy of the string. @discardableResult func pascalCased() -> String { - return (-self).components(separatedBy: .whitespaces).joined() + return Guitar.sanitze(string: self).capitalized().components(separatedBy: .whitespaces).joined() } /// Returns the slug version of the string. @@ -95,7 +94,7 @@ public extension String { /// - Returns: The slug copy of the string. @discardableResult func slugCased() -> String { - return (-self).replacingOccurrences(of: " ", with: "-").lowercased() + return Guitar.sanitze(string: self).replacingOccurrences(of: " ", with: "-").lowercased() } /// Returns the snake cased version of the string. @@ -109,7 +108,7 @@ public extension String { /// - Returns: The slug copy of the string. @discardableResult func snakeCased() -> String { - return (-self).replacingOccurrences(of: " ", with: "_") + return Guitar.sanitze(string: self).replacingOccurrences(of: " ", with: "_") } /// Returns the swap cased version of the string. diff --git a/Sources/GuitarRegex.swift b/Sources/GuitarRegex.swift deleted file mode 100644 index a51d3d0..0000000 --- a/Sources/GuitarRegex.swift +++ /dev/null @@ -1,109 +0,0 @@ -// -// GuitarRegex.swift -// GuitarExample -// -// Created by Sabintsev, Arthur on 3/9/17. -// Copyright © 2017 Arthur Ariel Sabintsev. All rights reserved. -// -// Adapted from: -// http://benscheirman.com/2014/06/regex-in-swift/ -// https://www.hackingwithswift.com/example-code/language/how-to-convert-an-nsrange-to-a-swift-string-index - -import Foundation - -// MARK: - Regular Expression (Common Patterns) - -/// Common Regular Expression Patterns -public struct GuitarPattern { - /// Pattern matches email addresses. - public static let email = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}" - - /// Pattern matches non-Alphanumeric and non-Whitespace characters. - public static let nonAlphanumeric = "[^a-zA-Z\\d\\s]" -} - -// MARK - GuitarRegex - -public struct GuitarRegex { - - /// Regular expression pattern that will be used to evaluate a specific string. - let pattern: String - - /// Designated Initializer for *GuitarRegex* - /// - /// - Parameters: - /// - pattern: The pattern that will be used to perform the match. - /// - /// - Returns: A list of matches. - public init(pattern: String) { - self.pattern = pattern - } - - /// Tests a string to see if it matches the regular expression pattern. - /// - /// - Parameters: - /// - string: The string that will be evaluated. - /// - options: Regular expression options that are applied to the string during matching. Defaults to []. - /// - /// - Returns: A list of matches. - public func evaluate(string: String, options: NSRegularExpression.Options = []) -> [Range] { - let range = NSRange(location: 0, length: string.characters.count) - guard let regex = try? NSRegularExpression(pattern: pattern, options: options) else { - return [] - } - - let matches = regex.matches(in: string, options: [], range: range) - - let ranges = matches.flatMap { (match) -> Range? in - let nsRange = match.range - return nsRange.range(for: string) - } - - return ranges - } - - /// Evaluates a string for all instances of a regular expression pattern. - /// - /// - Parameters: - /// - string: The string that will be evaluated. - /// - options: Regular expression options that are applied to the string during matching. Defaults to []. - /// - /// - Returns: `true` if string passes evaluation, otherwise, `false`. - public func test(string: String, options: NSRegularExpression.Options = []) -> Bool { - return evaluate(string: string, options: options).count > 0 - } -} - -// MARK: - Regular Expressions (Common Evaluations) - -public extension GuitarRegex { - /// Evaluates a string to check if it is a valid email address by using a regular expression. - /// - /// - Parameters: - /// - email: The string that needs to be evaluated. - /// - /// - Returns: `true` if `string` is a valid email address, otherwise `false`. - static func isValidEmail(email: String) -> Bool { - return GuitarRegex(pattern: GuitarPattern.email).test(string: email) - } -} - -// MARK: - NSRange Helpers - -private extension NSRange { - - /// Converts NSRange to Range - /// - /// - Parameter string: The string from which the NSRange was extracted. - /// - Returns: The `Range` representation of the NSRange. - func range(for string: String) -> Range? { - guard location != NSNotFound else { return nil } - - guard let fromUTFIndex = string.utf16.index(string.utf16.startIndex, offsetBy: location, limitedBy: string.utf16.endIndex) else { return nil } - guard let toUTFIndex = string.utf16.index(fromUTFIndex, offsetBy: length, limitedBy: string.utf16.endIndex) else { return nil } - guard let fromIndex = String.Index(fromUTFIndex, within: string) else { return nil } - guard let toIndex = String.Index(toUTFIndex, within: string) else { return nil } - - return fromIndex ..< toIndex - } -} diff --git a/docs/Extensions.html b/docs/Extensions.html index b63d1d6..a5571ad 100644 --- a/docs/Extensions.html +++ b/docs/Extensions.html @@ -39,10 +39,10 @@ Structs diff --git a/docs/Extensions/String.html b/docs/Extensions/String.html index e9c7cd5..979da92 100644 --- a/docs/Extensions/String.html +++ b/docs/Extensions/String.html @@ -40,10 +40,10 @@ Structs @@ -331,6 +331,51 @@

Return Value

+
  • +
    + + + + capitalized() + +
    +
    +
    +
    +
    +
    +

    Returns a capitalized version of the string.

    + +
    +

    Warning

    + This method is a modified implementation of Swift stdlib’s capitalized computer variabled. + +
    + +

    Example:

    + +
    let string = "helloworld"
    +print(string.capitalized())
    +// Prints "Helloworld"
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func capitalized() -> String
    + +
    +
    +
    +

    Return Value

    +

    A capitalized copy of the string.

    + +
    +
    +
    +
  • @@ -350,7 +395,7 @@

    Return Value

    let string = "HELLOWORLD"
     print(string.decapitalized())
    -// Prints "helloworld"
    +// Prints "hELLOWORLD"
     
    diff --git a/docs/Structs.html b/docs/Structs.html index b26644d..721e271 100644 --- a/docs/Structs.html +++ b/docs/Structs.html @@ -39,10 +39,10 @@ Structs
  • @@ -57,48 +57,13 @@

    Structs

    -
    diff --git a/docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs/GuitarRegex.html b/docs/Structs/Guitar.html similarity index 64% rename from docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs/GuitarRegex.html rename to docs/Structs/Guitar.html index e76cb94..129bce2 100644 --- a/docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs/GuitarRegex.html +++ b/docs/Structs/Guitar.html @@ -1,7 +1,7 @@ - GuitarRegex Struct Reference + Guitar Struct Reference @@ -10,8 +10,8 @@ - - + +

    Guitar Docs (100% documented)

    @@ -22,7 +22,7 @@
    @@ -40,10 +40,10 @@ Structs @@ -52,7 +52,7 @@
    -

    GuitarRegex

    +

    Guitar

    Undocumented

    @@ -62,9 +62,37 @@

    GuitarRegex

  • - - - init(pattern:) + + + Chord + +
    +
    +
    +
    +
    +
    +

    Common Regular Expression Patterns

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct Chord
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(chord:)
    @@ -79,7 +107,7 @@

    GuitarRegex

    Declaration

    Swift

    -
    public init(pattern: String)
    +
    public init(chord: String)
    @@ -90,12 +118,12 @@

    Parameters

    - pattern + chord
    -

    The pattern that will be used to perform the match.

    +

    The pattern (also known as a chord) that will be used to perform the match. Common patterns (or chords) can be found in the Chord struct.

    @@ -114,9 +142,9 @@

    Return Value

  • @@ -124,7 +152,7 @@

    Return Value

    -

    Tests a string to see if it matches the regular expression pattern.

    +

    Evaluates a string for all instances of a regular expression pattern.

    @@ -179,9 +207,28 @@

    Return Value

  • +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    @@ -189,7 +236,7 @@

    Return Value

    -

    Evaluates a string for all instances of a regular expression pattern.

    +

    Tests a string to see if it matches the regular expression pattern.

    @@ -235,7 +282,7 @@

    Parameters

    Return Value

    -

    true if string passes evaluation, otherwise, false.

    +

    true if string passes the test, otherwise, false.

    @@ -248,9 +295,9 @@

    Return Value

  • @@ -258,7 +305,7 @@

    Return Value

    -

    Evaluates a string to check if it is a valid email address by using a regular expression.

    +

    Tests a string to check if it is a valid email address by using a regular expression.

    @@ -297,6 +344,58 @@

    Return Value

  • +
  • +
    + + + + sanitze(string:) + +
    +
    +
    +
    +
    +
    +

    Sanitizes of a string by removing all non-Alphanumeric characters (excluding whitespaces)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    static func sanitze(string: String) -> String
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + string + + +
    +

    The string that should be sanitized.

    + +
    +
    +
    +
    +

    Return Value

    +

    The sanitized string.

    + +
    +
    +
    +
  • diff --git a/docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs/GuitarPattern.html b/docs/Structs/Guitar/Chord.html similarity index 74% rename from docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs/GuitarPattern.html rename to docs/Structs/Guitar/Chord.html index f71d180..a03e105 100644 --- a/docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs/GuitarPattern.html +++ b/docs/Structs/Guitar/Chord.html @@ -1,49 +1,49 @@ - GuitarPattern Struct Reference - - + Chord Struct Reference + + - - + + - - + +
    -

    Guitar Docs (100% documented)

    -

    View on GitHub

    +

    Guitar Docs (100% documented)

    +

    View on GitHub

  • +
  • +
    + + + + capitalized() + +
    +
    +
    +
    +
    +
    +

    Returns a capitalized version of the string.

    + +
    +

    Warning

    + This method is a modified implementation of Swift stdlib’s capitalized computer variabled. + +
    + +

    Example:

    + +
    let string = "helloworld"
    +print(string.capitalized())
    +// Prints "Helloworld"
    +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    func capitalized() -> String
    + +
    +
    +
    +

    Return Value

    +

    A capitalized copy of the string.

    + +
    +
    +
    +
  • @@ -350,7 +395,7 @@

    Return Value

    let string = "HELLOWORLD"
     print(string.decapitalized())
    -// Prints "helloworld"
    +// Prints "hELLOWORLD"
     
    diff --git a/docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs.html b/docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs.html index b26644d..721e271 100644 --- a/docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs.html +++ b/docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs.html @@ -39,10 +39,10 @@ Structs
  • @@ -57,48 +57,13 @@

    Structs

    -
    diff --git a/docs/Structs/GuitarRegex.html b/docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs/Guitar.html similarity index 64% rename from docs/Structs/GuitarRegex.html rename to docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs/Guitar.html index e76cb94..129bce2 100644 --- a/docs/Structs/GuitarRegex.html +++ b/docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs/Guitar.html @@ -1,7 +1,7 @@ - GuitarRegex Struct Reference + Guitar Struct Reference @@ -10,8 +10,8 @@ - - + +

    Guitar Docs (100% documented)

    @@ -22,7 +22,7 @@
    @@ -40,10 +40,10 @@ Structs @@ -52,7 +52,7 @@
    -

    GuitarRegex

    +

    Guitar

    Undocumented

    @@ -62,9 +62,37 @@

    GuitarRegex

  • - - - init(pattern:) + + + Chord + +
    +
    +
    +
    +
    +
    +

    Common Regular Expression Patterns

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct Chord
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + init(chord:)
    @@ -79,7 +107,7 @@

    GuitarRegex

    Declaration

    Swift

    -
    public init(pattern: String)
    +
    public init(chord: String)
    @@ -90,12 +118,12 @@

    Parameters

    - pattern + chord
    -

    The pattern that will be used to perform the match.

    +

    The pattern (also known as a chord) that will be used to perform the match. Common patterns (or chords) can be found in the Chord struct.

    @@ -114,9 +142,9 @@

    Return Value

  • @@ -124,7 +152,7 @@

    Return Value

    -

    Tests a string to see if it matches the regular expression pattern.

    +

    Evaluates a string for all instances of a regular expression pattern.

    @@ -179,9 +207,28 @@

    Return Value

  • +
    +
    +
    +
    +
    +

    Undocumented

    + +
    +
    +
    +
  • +
  • +
    @@ -189,7 +236,7 @@

    Return Value

    -

    Evaluates a string for all instances of a regular expression pattern.

    +

    Tests a string to see if it matches the regular expression pattern.

    @@ -235,7 +282,7 @@

    Parameters

    Return Value

    -

    true if string passes evaluation, otherwise, false.

    +

    true if string passes the test, otherwise, false.

    @@ -248,9 +295,9 @@

    Return Value

  • @@ -258,7 +305,7 @@

    Return Value

    -

    Evaluates a string to check if it is a valid email address by using a regular expression.

    +

    Tests a string to check if it is a valid email address by using a regular expression.

    @@ -297,6 +344,58 @@

    Return Value

  • +
  • +
    + + + + sanitze(string:) + +
    +
    +
    +
    +
    +
    +

    Sanitizes of a string by removing all non-Alphanumeric characters (excluding whitespaces)

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    static func sanitze(string: String) -> String
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + string + + +
    +

    The string that should be sanitized.

    + +
    +
    +
    +
    +

    Return Value

    +

    The sanitized string.

    + +
    +
    +
    +
  • diff --git a/docs/Structs/GuitarPattern.html b/docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs/Guitar/Chord.html similarity index 74% rename from docs/Structs/GuitarPattern.html rename to docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs/Guitar/Chord.html index f71d180..a03e105 100644 --- a/docs/Structs/GuitarPattern.html +++ b/docs/docsets/Guitar.docset/Contents/Resources/Documents/Structs/Guitar/Chord.html @@ -1,49 +1,49 @@ - GuitarPattern Struct Reference - - + Chord Struct Reference + + - - + + - - + +
    -

    Guitar Docs (100% documented)

    -

    View on GitHub

    +

    Guitar Docs (100% documented)

    +

    View on GitHub