From 3325d1165c6850e00404df5b6c1327f45277bc5e Mon Sep 17 00:00:00 2001 From: Mathew Cruz Date: Mon, 12 Aug 2013 13:35:02 -0400 Subject: [PATCH 1/3] Removed all javascript-like functionality and syntax. This is Objective C --- README.md | 27 +- VerbalExpressions.xcodeproj/project.pbxproj | 8 + VerbalExpressions/AppDelegate.m | 36 +- VerbalExpressions/OCVerbalExpression.h | 56 +++ VerbalExpressions/OCVerbalExpression.m | 319 ++++++++++++++++++ .../VerbalExpressionsTests.m | 184 +++++----- 6 files changed, 515 insertions(+), 115 deletions(-) create mode 100644 VerbalExpressions/OCVerbalExpression.h create mode 100644 VerbalExpressions/OCVerbalExpression.m diff --git a/README.md b/README.md index ef15ece..0f15d02 100644 --- a/README.md +++ b/README.md @@ -14,20 +14,20 @@ Here's a couple of simple examples to give an idea of how VerbalExpressions work ```objc // Create an example of how to test for correctly formed URLs -VerbalExpressions *tester = VerEx() -.startOfLine(YES) -.then(@"http") -.maybe(@"s") -.then(@"://") -.maybe(@"www") -.anythingBut(@" ") -.endOfLine(YES); +OCVerbalExpression *expressions = [[OCVerbalExpression alloc] init]; +[expressions startOfLine:YES]; +[expressions then:@"http"]; +[expressions maybe:@"s"]; +[expressions then:@"://"]; +[expressions maybe:@"www"]; +[expressions anythingBut:@" "]; +[expressions endOfLine:YES]; // Create an example URL NSString *testMe = @"https://www.google.com"; -// Use test() method -if (tester.test(testMe)) { +// Use test: method +if ([expressions test:testMe]) { NSLog(@"%@", @"We have a correct URL"); // This output will fire } else { NSLog(@"%@", @"The URL is incorrect"); @@ -42,10 +42,11 @@ NSLog(@"%@", tester); // Ouputs the actual expression used: "^(http)(s)?(: NSString *replaceMe = @"Replace bird with a duck"; // Create an expression that seeks for word "bird" -VerbalExpressions *verEx = VerEx().find(@"bird"); +OCVerbalExpression *expressions1 = [[OCVerbalExpression alloc] init]; +[expressions1 find:@"bird"]; // Execute the expression like a normal RegExp object -NSString *result = verEx.replace(replaceMe, @"duck" ); +NSString *result = [expressions1 replaceWithSource:replaceMe value:@"duck"]; NSLog(@"%@", result); // Outputs "Replace duck with a duck" ``` @@ -53,7 +54,7 @@ NSLog(@"%@", result); // Outputs "Replace duck with a duck" ### Shorthand for string replace: ```objc -NSString *result2 = VerEx().find(@"red").replace(@"We have a red house", @"blue"); +NSString *result2 = [[[OCVerbalExpression new] find:@"red"] replaceWithSource:@"We have a red house" value:@"blue"]; NSLog(@"%@", result2); // Outputs "We have a blue house" ``` diff --git a/VerbalExpressions.xcodeproj/project.pbxproj b/VerbalExpressions.xcodeproj/project.pbxproj index 8342c93..dac52e0 100644 --- a/VerbalExpressions.xcodeproj/project.pbxproj +++ b/VerbalExpressions.xcodeproj/project.pbxproj @@ -23,6 +23,8 @@ 1481B6C017B8127400EA9DA4 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1481B6BD17B8127400EA9DA4 /* Default-568h@2x.png */; }; 1481B6C317B8AEDA00EA9DA4 /* VerbalExpressions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1481B6C217B8AEDA00EA9DA4 /* VerbalExpressions.m */; }; 1481B6C417B8AEDA00EA9DA4 /* VerbalExpressions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1481B6C217B8AEDA00EA9DA4 /* VerbalExpressions.m */; }; + F98A791417B950B100B0871D /* OCVerbalExpression.m in Sources */ = {isa = PBXBuildFile; fileRef = F98A791317B950B100B0871D /* OCVerbalExpression.m */; }; + F98A791517B950B100B0871D /* OCVerbalExpression.m in Sources */ = {isa = PBXBuildFile; fileRef = F98A791317B950B100B0871D /* OCVerbalExpression.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -57,6 +59,8 @@ 1481B6BD17B8127400EA9DA4 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 1481B6C117B8AEDA00EA9DA4 /* VerbalExpressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VerbalExpressions.h; path = Lib/VerbalExpressions.h; sourceTree = SOURCE_ROOT; }; 1481B6C217B8AEDA00EA9DA4 /* VerbalExpressions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VerbalExpressions.m; path = Lib/VerbalExpressions.m; sourceTree = SOURCE_ROOT; }; + F98A791217B950B100B0871D /* OCVerbalExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCVerbalExpression.h; sourceTree = ""; }; + F98A791317B950B100B0871D /* OCVerbalExpression.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCVerbalExpression.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -159,6 +163,8 @@ 1481B6C517B8AEDF00EA9DA4 /* Lib */ = { isa = PBXGroup; children = ( + F98A791217B950B100B0871D /* OCVerbalExpression.h */, + F98A791317B950B100B0871D /* OCVerbalExpression.m */, 1481B6C117B8AEDA00EA9DA4 /* VerbalExpressions.h */, 1481B6C217B8AEDA00EA9DA4 /* VerbalExpressions.m */, ); @@ -284,6 +290,7 @@ buildActionMask = 2147483647; files = ( 1481B64517B7FE7200EA9DA4 /* main.m in Sources */, + F98A791417B950B100B0871D /* OCVerbalExpression.m in Sources */, 1481B64917B7FE7200EA9DA4 /* AppDelegate.m in Sources */, 1481B6C317B8AEDA00EA9DA4 /* VerbalExpressions.m in Sources */, ); @@ -293,6 +300,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F98A791517B950B100B0871D /* OCVerbalExpression.m in Sources */, 1481B6C417B8AEDA00EA9DA4 /* VerbalExpressions.m in Sources */, 1481B66417B7FE7300EA9DA4 /* VerbalExpressionsTests.m in Sources */, ); diff --git a/VerbalExpressions/AppDelegate.m b/VerbalExpressions/AppDelegate.m index 51ec577..48dc612 100644 --- a/VerbalExpressions/AppDelegate.m +++ b/VerbalExpressions/AppDelegate.m @@ -7,7 +7,7 @@ // #import "AppDelegate.h" -#import "VerbalExpressions.h" +#import "OCVerbalExpression.h" @implementation AppDelegate @@ -17,26 +17,27 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( * Testing if we have a valid URL */ // Create an example of how to test for correctly formed URLs - VerbalExpressions *tester = VerEx() - .startOfLine(YES) - .then(@"http") - .maybe(@"s") - .then(@"://") - .maybe(@"www") - .anythingBut(@" ") - .endOfLine(YES); + OCVerbalExpression *expressions = [[OCVerbalExpression alloc] init]; + [expressions startOfLine:YES]; + [expressions then:@"http"]; + [expressions maybe:@"s"]; + [expressions then:@"://"]; + [expressions maybe:@"www"]; + [expressions anythingBut:@" "]; + [expressions endOfLine:YES]; // Create an example URL NSString *testMe = @"https://www.google.com"; - // Use test() method - if (tester.test(testMe)) { + // Use test: method + + if ([expressions test:testMe]) { NSLog(@"%@", @"We have a correct URL"); // This output will fire } else { NSLog(@"%@", @"The URL is incorrect"); } - NSLog(@"%@", tester); // Ouputs the actual expression used: "^(http)(s)?(:\/\/)(www)?([^ ]*)$" + NSLog(@"%@", expressions); // Ouputs the actual expression used: "^(http)(s)?(:\/\/)(www)?([^ ]*)$" /* * Replacing strings @@ -45,19 +46,16 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( NSString *replaceMe = @"Replace bird with a duck"; // Create an expression that seeks for word "bird" - VerbalExpressions *verEx = VerEx().find(@"bird"); + + OCVerbalExpression *expressions1 = [[OCVerbalExpression alloc] init]; + [expressions1 find:@"bird"]; // Execute the expression like a normal RegExp object - NSString *result1 = verEx.replace(replaceMe, @"duck" ); + NSString *result1 = [expressions1 replaceWithSource:replaceMe value:@"duck"]; //expression.replace(replaceMe, @"duck" ); NSLog(@"%@", result1); // Outputs "Replace duck with a duck" - /* - * Shorthand for string replace: - */ - NSString *result2 = VerEx().find(@"red").replace(@"We have a red house", @"blue"); - NSLog(@"%@", result2); // Outputs "We have a blue house" self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; diff --git a/VerbalExpressions/OCVerbalExpression.h b/VerbalExpressions/OCVerbalExpression.h new file mode 100644 index 0000000..0bf8113 --- /dev/null +++ b/VerbalExpressions/OCVerbalExpression.h @@ -0,0 +1,56 @@ +// +// OCVerbalExpression.h +// VerbalExpressions +// +// The MIT License (MIT) +// +// Copyright (c) 2013 Mathew Cruz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#import + +@interface OCVerbalExpression : NSObject + +@property (nonatomic, readonly) NSRegularExpression *regularExpression; + +- (OCVerbalExpression *)startOfLine:(BOOL)enable; +- (OCVerbalExpression *)endOfLine:(BOOL)enable; +- (OCVerbalExpression *)find:(NSString *)value; +- (OCVerbalExpression *)then:(NSString *)value; +- (OCVerbalExpression *)maybe:(NSString *)value; +- (OCVerbalExpression *)anything; +- (OCVerbalExpression *)anythingBut:(NSString *)value; +- (OCVerbalExpression *)something; +- (OCVerbalExpression *)somethingBut:(NSString *)value; +- (OCVerbalExpression *)lineBreak; +- (OCVerbalExpression *)br; +- (OCVerbalExpression *)tab; +- (OCVerbalExpression *)word; +- (OCVerbalExpression *)anyOf:(NSString *)value; +- (OCVerbalExpression *)any:(NSString *)value; +- (OCVerbalExpression *)range:(NSArray *)args; +- (OCVerbalExpression *)withAnyCase:(BOOL)enable; +- (OCVerbalExpression *)searchOneLine:(BOOL)enable; +- (OCVerbalExpression *)multiple:(NSString *)value; +- (OCVerbalExpression *)or:(NSString *)value; + +- (BOOL)test:(NSString *)toTest; +- (NSString *)replaceWithSource:(NSString *)source value:(NSString *)value; + +@end diff --git a/VerbalExpressions/OCVerbalExpression.m b/VerbalExpressions/OCVerbalExpression.m new file mode 100644 index 0000000..3709dfc --- /dev/null +++ b/VerbalExpressions/OCVerbalExpression.m @@ -0,0 +1,319 @@ +// +// OCVerbalExpression.m +// OCVerbalExpression +// +// Created by Mathew Cruz on 8/12/13. +// Copyright (c) 2013 kishikawa katsumi. All rights reserved. +// + +#import "OCVerbalExpression.h" + +@interface OCVerbalExpression () +@property (nonatomic, strong) NSString *prefixes; +@property (nonatomic, strong) NSString *source; +@property (nonatomic, strong) NSString *suffixes; +@property (nonatomic, strong) NSString *pattern; +@property (nonatomic) NSRegularExpressionOptions modifiers; +@end + +@implementation OCVerbalExpression + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.prefixes = @""; + self.source = @""; + self.suffixes = @""; + self.pattern = @""; + } + + return self; +} + +- (OCVerbalExpression *)startOfLine:(BOOL)enable +{ + self.prefixes = enable ? @"^" : @""; + [self add:@""]; + return self; +} + +- (OCVerbalExpression *)endOfLine:(BOOL)enable +{ + self.suffixes = enable ? @"$" : @""; + [self add:@""]; + return self; +} + +- (OCVerbalExpression *)find:(NSString *)value +{ + return [self then:value]; +} + +- (OCVerbalExpression *)then:(NSString *)value +{ + value = [self sanitize:value]; + [self add:[NSString stringWithFormat:@"(%@)", value]]; + return self; +} + +- (OCVerbalExpression *)maybe:(NSString *)value +{ + value = [self sanitize:value]; + [self add:[NSString stringWithFormat:@"(%@)?", value]]; + return self; +} + +- (OCVerbalExpression *)anything +{ + [self add:@"(.*)"]; + return self; +} + +- (OCVerbalExpression *)anythingBut:(NSString *)value +{ + value = [self sanitize:value]; + [self add:[NSString stringWithFormat:@"([^%@]*)", value]]; + return self; +} + +- (OCVerbalExpression *)something +{ + [self add:@"(.+)"]; + return self; +} + +- (OCVerbalExpression *)somethingBut:(NSString *)value +{ + value = [self sanitize:value]; + [self add:[NSString stringWithFormat:@"([^%@]+)", value]]; + return self; +} + +- (NSString *)replaceWithSource:(NSString *)source value:(NSString *)value +{ + [self add:@""]; + return [self.regularExpression stringByReplacingMatchesInString:source options:kNilOptions range:NSMakeRange(0, source.length) withTemplate:value]; +} + +- (OCVerbalExpression *)lineBreak +{ + [self add:@"(\\n|(\\r\\n))"]; + return self; +} + +- (OCVerbalExpression *)br +{ + [self lineBreak]; + return self; +} + +- (OCVerbalExpression *)tab +{ + [self add:@"\\t"]; + return self; +} + +- (OCVerbalExpression *)word +{ + [self add:@"\\w+"]; + return self; +} + +- (OCVerbalExpression *)anyOf:(NSString *)value +{ + value = [self sanitize:value]; + [self add:[NSString stringWithFormat:@"[%@]", value]]; + return self; +} + +- (OCVerbalExpression *)any:(NSString *)value +{ + [self anyOf:value]; + return self; +} + +- (OCVerbalExpression *)range:(NSArray *)args +{ + NSString *value = @"["; + for (NSInteger fromIndex = 0; fromIndex < args.count; fromIndex += 2) { + NSInteger toIndex = fromIndex + 1; + if (args.count <= toIndex) { + break; + } + + NSString *from = [self sanitize:args[fromIndex]]; + NSString *to = [self sanitize:args[toIndex]]; + value = [value stringByAppendingFormat:@"%@-%@", from, to]; + } + + value = [value stringByAppendingString:@"]"]; + + [self add:value]; + return self; +} + +- (OCVerbalExpression *)withAnyCase:(BOOL)enable +{ + if (enable) { + [self addModifier:'i']; + } else { + [self removeModifier:'i']; + } + [self add:@""]; + return self; +} + +- (OCVerbalExpression *)searchOneLine:(BOOL)enable +{ + if (enable) { + [self removeModifier:'m']; + } else { + [self addModifier:'m']; + } + [self add:@""]; + return self; +} + +- (OCVerbalExpression *)multiple:(NSString *)value +{ + value = [self sanitize:value]; + switch ([value characterAtIndex:0]) { + case '*': + case '+': + break; + default: + value = [value stringByAppendingString:@"+"]; + } + [self add:@""]; + return self; +} + +- (OCVerbalExpression *)or:(NSString *)value +{ + if ([self.prefixes rangeOfString:@"("].location == NSNotFound) { + self.prefixes = [self.prefixes stringByAppendingString:@"("]; + } + if ([self.suffixes rangeOfString:@")"].location == NSNotFound) { + self.suffixes = [self.suffixes stringByAppendingString:@")"]; + } + [self add:@")|("]; + if (value) { + [self then:value]; + } + return self; +} + +- (BOOL)test:(NSString *)toTest +{ + [self add:@""]; + + NSRegularExpression *regex = self.regularExpression; + NSUInteger matches = [regex numberOfMatchesInString:toTest options:kNilOptions range:NSMakeRange(0, toTest.length)]; + + return matches > 0; +} + +- (NSRegularExpression *)regularExpression +{ + NSError *error = nil; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:self.pattern + options:self.modifiers + error:&error]; + if (error) { + return nil; + } + + return regex; +} + +- (NSString *)description +{ + [self add:@""]; + return self.regularExpression.pattern; +} + +#pragma mark praivate methods + +- (NSString *)sanitize:(NSString *)value +{ + if (!value) { + return nil; + } + return [NSRegularExpression escapedPatternForString:value]; +} + +- (OCVerbalExpression *)add:(NSString *)value +{ + self.source = self.source ? [self.source stringByAppendingString:value] : value; + if (self.source) { + self.pattern = [NSString stringWithFormat:@"%@%@%@", self.prefixes, self.source, self.suffixes]; + } + + return self; +} + +- (OCVerbalExpression *)addModifier:(unichar)modifier +{ + switch (modifier) { + case 'd': // UREGEX_UNIX_LINES + self.modifiers |= NSRegularExpressionUseUnixLineSeparators; + break; + case 'i': // UREGEX_CASE_INSENSITIVE + self.modifiers |= NSRegularExpressionCaseInsensitive; + break; + case 'x': // UREGEX_COMMENTS + self.modifiers |= NSRegularExpressionAllowCommentsAndWhitespace; + break; + case 'm': // UREGEX_MULTILINE + self.modifiers |= NSRegularExpressionAnchorsMatchLines; + break; + case 's': // UREGEX_DOTALL + self.modifiers |= NSRegularExpressionDotMatchesLineSeparators; + break; + case 'u': // UREGEX_UWORD + self.modifiers |= NSRegularExpressionUseUnicodeWordBoundaries; + break; + case 'U': // UREGEX_LITERAL + self.modifiers |= NSRegularExpressionIgnoreMetacharacters; + break; + default: + break; + } + + [self add:@""]; + return self; +} + +- (OCVerbalExpression *)removeModifier:(unichar)modifier +{ + switch (modifier) { + case 'd': // UREGEX_UNIX_LINES + self.modifiers ^= NSRegularExpressionUseUnixLineSeparators; + break; + case 'i': // UREGEX_CASE_INSENSITIVE + self.modifiers ^= NSRegularExpressionCaseInsensitive; + break; + case 'x': // UREGEX_COMMENTS + self.modifiers ^= NSRegularExpressionAllowCommentsAndWhitespace; + break; + case 'm': // UREGEX_MULTILINE + self.modifiers ^= NSRegularExpressionAnchorsMatchLines; + break; + case 's': // UREGEX_DOTALL + self.modifiers ^= NSRegularExpressionDotMatchesLineSeparators; + break; + case 'u': // UREGEX_UWORD + self.modifiers ^= NSRegularExpressionUseUnicodeWordBoundaries; + break; + case 'U': // UREGEX_LITERAL + self.modifiers ^= NSRegularExpressionIgnoreMetacharacters; + break; + default: + break; + } + + [self add:@""]; + return self; +} +@end diff --git a/VerbalExpressionsTests/VerbalExpressionsTests.m b/VerbalExpressionsTests/VerbalExpressionsTests.m index e372fde..2cff2e9 100644 --- a/VerbalExpressionsTests/VerbalExpressionsTests.m +++ b/VerbalExpressionsTests/VerbalExpressionsTests.m @@ -7,7 +7,7 @@ // #import "VerbalExpressionsTests.h" -#import "VerbalExpressions.h" +#import "OCVerbalExpression.h" @implementation VerbalExpressionsTests @@ -21,153 +21,171 @@ - (void)tearDown [super tearDown]; } -- (void)testStartOfLine +- (void)testSomething { - VerbalExpressions *verEx = VerEx().startOfLine(YES).then(@"a"); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [verEx something]; - STAssertTrue(verEx.test(@"a"), @"starts with a"); - STAssertFalse(verEx.test(@"ba"), @"doesn't start with a"); + STAssertFalse([verEx test:@""], @"empty string doesn't have something"); + STAssertTrue([verEx test:@"a"], @"a is something"); } -- (void)testEndOfLine +- (void)testAnything { - VerbalExpressions *verEx = VerEx().find(@"a").endOfLine(YES); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [verEx startOfLine:YES]; + [verEx anything]; + - STAssertTrue(verEx.test(@"a"), @"ends with a"); - STAssertFalse(verEx.test(@"ab"), @"doesn't end with a"); + + STAssertTrue([verEx test:@"what"], @"anything is matched"); } -- (void)testMaybe +- (void)testAnythingBut { - VerbalExpressions *verEx = VerEx().startOfLine(YES).then(@"a").maybe(@"b"); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [verEx startOfLine:YES]; + [verEx anythingBut:@"w"]; - STAssertTrue(verEx.test(@"acb"), @"maybe has a b after an a"); - STAssertTrue(verEx.test(@"abc"), @"maybe has a b after an a"); + STAssertTrue([verEx test:@"what"], @"starts with w"); } -- (void)testAnything +- (void)testSomethingBut { - VerbalExpressions *verEx = VerEx().startOfLine(YES).anything(); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [verEx somethingBut:@"a"]; - STAssertTrue(verEx.test(@"what"), @"anything is matched"); + STAssertFalse([verEx test:@""], @"empty string doesn't have something"); + STAssertTrue([verEx test:@"b"], @"doesn't start with a"); + STAssertFalse([verEx test:@"a"], @"starts with a"); } -- (void)testAnythingBut +- (void)testStartOfLine { - VerbalExpressions *verEx = VerEx().startOfLine(YES).anythingBut(@"w"); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [[verEx startOfLine:YES] then:@"a"]; - STAssertTrue(verEx.test(@"what"), @"starts with w"); + STAssertTrue([verEx test:@"a"], @"starts with a"); + STAssertFalse([verEx test:@"ba" ], @"doesn't start with a"); } -- (void)testSomething +- (void)testEndOfLine { - VerbalExpressions *verEx = VerEx().something(); - - STAssertFalse(verEx.test(@""), @"empty string doesn't have something"); - STAssertTrue(verEx.test(@"a"), @"a is something"); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [[verEx find:@"a"] endOfLine:YES]; + STAssertTrue([verEx test:@"a"], @"ends with a"); + STAssertFalse([verEx test:@"ab"], @"doesn't end with a"); } -- (void)testSomethingBut +- (void)testMaybe { - VerbalExpressions *verEx = VerEx().somethingBut(@"a"); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [[[verEx startOfLine:YES] then:@"a"] maybe:@"b"]; - STAssertFalse(verEx.test(@""), @"empty string doesn't have something"); - STAssertTrue(verEx.test(@"b"), @"doesn't start with a"); - STAssertFalse(verEx.test(@"a"), @"starts with a"); + STAssertTrue([verEx test:@"acb"], @"maybe has a b after an a"); + STAssertTrue([verEx test:@"abc"], @"maybe has a b after an a"); } -- (void)testReplace +- (void)testAnyOf { - NSString *testString = @"replace bird with a duck"; + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [[[verEx startOfLine:YES] then:@"a"] anyOf:@"xyz"]; - VerbalExpressions *verEx = VerEx().find(@"bird"); - - NSString *testStringAfterReplacement = verEx.replace(testString, @"duck"); - NSString *expectedStringAfterReplacement = @"replace duck with a duck"; - - STAssertEqualObjects(testStringAfterReplacement, expectedStringAfterReplacement, @"replaced 'bird' with 'duck'"); + STAssertTrue([verEx test:@"ay"], @"has an x, y, or z after a"); + STAssertFalse([verEx test:@"abc"], @"doesn't have an x, y, or z after a"); } -- (void)testLineBreak +- (void)testOr { - VerbalExpressions *verEx = VerEx().startOfLine(YES).then(@"abc").lineBreak().then(@"def"); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [[[verEx startOfLine:YES] then:@"abc"] or:@"def"]; - STAssertTrue(verEx.test(@"abc\r\ndef"), @"abc then line break then def"); - STAssertFalse(verEx.test(@"abc\r\n def"), @"abc then line break then space then def"); + STAssertTrue([verEx test:@"defzzz"], @"starts with abc or def"); + STAssertFalse([verEx test:@"xyzabc"], @"doesn't start with abc or def"); } -- (void)testBR +- (void)testLineBreak { - VerbalExpressions *verEx = VerEx().startOfLine(YES).then(@"abc").lineBreak().then(@"def"); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [[[[verEx startOfLine:YES] then:@"abc"] lineBreak] then:@"def"]; - STAssertTrue(verEx.test(@"abc\r\ndef"), @"abc then line break then def"); - STAssertFalse(verEx.test(@"abc\r\n def"), @"abc then line break then space then def"); + STAssertTrue([verEx test:@"abc\r\ndef"], @"abc then line break then def"); + STAssertFalse([verEx test:@"abc\r\n def"], @"abc then line break then space then def"); } -- (void)testTab +- (void)testBR { - VerbalExpressions *verEx = VerEx().startOfLine(YES).tab().then(@"abc"); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [[[[verEx startOfLine:YES] then:@"abc"] lineBreak] then:@"def"]; - STAssertTrue(verEx.test(@"\tabc"), @"tab then abc"); - STAssertFalse(verEx.test(@"abc"), @"no tab then abc"); + STAssertTrue([verEx test:@"abc\r\ndef"], @"abc then line break then def"); + STAssertFalse([verEx test:@"abc\r\n def"], @"abc then line break then space then def"); } -- (void)testAnyOf +- (void)testTab { - VerbalExpressions *verEx = VerEx().startOfLine(YES).then(@"a").anyOf(@"xyz"); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [[[verEx startOfLine:YES] tab] then:@"abc"]; - STAssertTrue(verEx.test(@"ay"), @"has an x, y, or z after a"); - STAssertFalse(verEx.test(@"abc"), @"doesn't have an x, y, or z after a"); + STAssertTrue([verEx test:@"\tabc"], @"tab then abc"); + STAssertFalse([verEx test:@"abc"], @"no tab then abc"); } - (void)testWithAnyCase { - VerbalExpressions *verEx = VerEx().startOfLine(YES).then(@"a"); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [[verEx startOfLine:YES] then:@"a"]; - STAssertFalse(verEx.test(@"A"), @"not case insensitive"); + STAssertFalse([verEx test:@"A"], @"not case insensitive"); - verEx.withAnyCase(YES); + [verEx withAnyCase:YES]; - STAssertTrue(verEx.test(@"A"), @"case insensitive"); - STAssertTrue(verEx.test(@"a"), @"case insensitive"); + STAssertTrue([verEx test:@"A"], @"case insensitive"); + STAssertTrue([verEx test:@"a"], @"case insensitive"); } - (void)testSearchOneLine { - VerbalExpressions *verEx = VerEx().startOfLine(YES).then(@"a").br().then(@"b").endOfLine(YES); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [[[[[verEx startOfLine:YES] then:@"a"] br] then:@"b"] endOfLine:YES]; - STAssertTrue(verEx.test(@"a\nb"), @"b is on the second line"); + STAssertTrue([verEx test:@"a\nb"], @"b is on the second line"); - verEx.searchOneLine(YES); + [verEx searchOneLine:YES]; - STAssertTrue(verEx.test(@"a\nb"), @"b is on the second line but we are only searching the first"); + STAssertTrue([verEx test:@"a\nb"], @"b is on the second line but we are only searching the first"); } -- (void)testOr +- (void)testReplace { - VerbalExpressions *verEx = VerEx().startOfLine(YES).then(@"abc").or(@"def"); + NSString *testString = @"Replace bird with a duck"; - STAssertTrue(verEx.test(@"defzzz"), @"starts with abc or def"); - STAssertFalse(verEx.test(@"xyzabc"), @"doesn't start with abc or def"); + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [verEx find:@"bird"]; + + NSString *testStringAfterReplacement = [verEx replaceWithSource:testString value:@"duck"]; + NSString *expectedStringAfterReplacement = @"Replace duck with a duck"; + + STAssertEqualObjects(testStringAfterReplacement, expectedStringAfterReplacement, @"Replaced 'bird' with 'duck'"); } -- (void)testURL -{ - VerbalExpressions *verEx = VerEx() - .startOfLine(YES) - .find(@"http") - .maybe(@"s") - .find(@"://") - .maybe(@"www") - .anythingBut(@" ") - .endOfLine(YES); - - STAssertEqualObjects(verEx.description, @"^(http)(s)?(:\\/\\/)(www)?([^ ]*)$", @"successfully builds regex for matching URLs"); - STAssertTrue(verEx.test(@"http://google.com"), @"matches regular http URL"); - STAssertTrue(verEx.test(@"https://google.com"), @"matches https URL"); - STAssertTrue(verEx.test(@"https://www.google.com"), @"matches a URL with www"); - STAssertFalse(verEx.test(@"http://goo gle.com"), @"fails to match when URL has a space"); - STAssertFalse(verEx.test(@"htp://google.com"), @"fails to match with htp:// is malformed"); +- (void)testURL { + + OCVerbalExpression *verEx = [[OCVerbalExpression alloc] init]; + [verEx startOfLine:YES]; + [verEx find:@"http"]; + [verEx maybe:@"s"]; + [verEx find:@"://"]; + [verEx maybe:@"www"]; + [verEx anythingBut:@" "]; + [verEx endOfLine:YES]; + + STAssertEqualObjects([verEx description], @"^(http)(s)?(:\\/\\/)(www)?([^ ]*)$", @"successfully builds regex for matching URLs"); + STAssertTrue([verEx test:@"http://google.com"], @"matches regular http URL"); + STAssertTrue([verEx test:@"https://google.com"], @"matches https URL"); + STAssertTrue([verEx test:@"https://www.google.com"], @"matches a URL with www"); + STAssertFalse([verEx test:@"http://goo gle.com"], @"fails to match when URL has a space"); + STAssertFalse([verEx test:@"htp://google.com"], @"fails to match with htp:// is malformed"); } @end From 0d2f7be4fb146a239f1d5d1beed47bccc60e7485 Mon Sep 17 00:00:00 2001 From: mathew cruz Date: Mon, 7 Oct 2013 15:21:55 -0400 Subject: [PATCH 2/3] Added some methods to handle grouping of evaluations and an example. --- VerbalExpressions/AppDelegate.m | 32 +++++++++++++++++++ VerbalExpressions/OCVerbalExpression.h | 7 +++++ VerbalExpressions/OCVerbalExpression.m | 43 ++++++++++++++++++++++++-- 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/VerbalExpressions/AppDelegate.m b/VerbalExpressions/AppDelegate.m index 48dc612..6a0970e 100644 --- a/VerbalExpressions/AppDelegate.m +++ b/VerbalExpressions/AppDelegate.m @@ -55,7 +55,39 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( NSLog(@"%@", result1); // Outputs "Replace duck with a duck" + // Example where you have an HTML string where you want to take out img tags that have either no extension or a + // pdf, doc, docx, xls, xlsx extension + NSString *HTML = @"
"; + OCVerbalExpression *complexExpr = [OCVerbalExpression new]; + [[[[[[[complexExpr find:@"
"] + anyWhiteSpace] + then:@"src"] + anyWhiteSpace] + then:@"="] + anyWhiteSpace]; + + [complexExpr then:[OCVerbalExpression orWithObjects:@[@"'", @"\""]]]; + [complexExpr anythingBut:[OCVerbalExpression orWithObjects:@[@"'", @".", @"\""]]]; + [complexExpr thenWithGroup:^{ + [complexExpr thenWithGroup:^{ + [complexExpr then:@"."]; + [complexExpr then:[OCVerbalExpression orWithObjects:@[@"pdf", @"doc", @"docx", @"xls", @"xlsx"]]]; + [complexExpr then:[OCVerbalExpression orWithObjects:@[@"'", @"\""]]]; + }]; + [complexExpr orWithGroup:^{ + [complexExpr then:@"'"]; + [complexExpr or:@"\""]; + }]; + }]; + [[[[complexExpr anyWhiteSpace] then:@">"] anyWhiteSpace] then:@"
"]; + + + + NSString *result2 = [complexExpr replaceWithSource:HTML value:@""]; + + NSLog(@"%@", result2); self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; diff --git a/VerbalExpressions/OCVerbalExpression.h b/VerbalExpressions/OCVerbalExpression.h index 0bf8113..c49e41e 100644 --- a/VerbalExpressions/OCVerbalExpression.h +++ b/VerbalExpressions/OCVerbalExpression.h @@ -33,6 +33,7 @@ - (OCVerbalExpression *)endOfLine:(BOOL)enable; - (OCVerbalExpression *)find:(NSString *)value; - (OCVerbalExpression *)then:(NSString *)value; +- (OCVerbalExpression *)thenWithGroup:(void(^)(void))valuesToGroup; - (OCVerbalExpression *)maybe:(NSString *)value; - (OCVerbalExpression *)anything; - (OCVerbalExpression *)anythingBut:(NSString *)value; @@ -42,6 +43,7 @@ - (OCVerbalExpression *)br; - (OCVerbalExpression *)tab; - (OCVerbalExpression *)word; +- (OCVerbalExpression *)anyWhiteSpace; - (OCVerbalExpression *)anyOf:(NSString *)value; - (OCVerbalExpression *)any:(NSString *)value; - (OCVerbalExpression *)range:(NSArray *)args; @@ -49,8 +51,13 @@ - (OCVerbalExpression *)searchOneLine:(BOOL)enable; - (OCVerbalExpression *)multiple:(NSString *)value; - (OCVerbalExpression *)or:(NSString *)value; +- (OCVerbalExpression *)orWithGroup:(void(^)(void))valuesToGroup; + ++ (NSString *)orWithObjects:(NSArray *)objects; - (BOOL)test:(NSString *)toTest; - (NSString *)replaceWithSource:(NSString *)source value:(NSString *)value; +- (NSString *)expressionString; + @end diff --git a/VerbalExpressions/OCVerbalExpression.m b/VerbalExpressions/OCVerbalExpression.m index 3709dfc..e2c8a05 100644 --- a/VerbalExpressions/OCVerbalExpression.m +++ b/VerbalExpressions/OCVerbalExpression.m @@ -52,8 +52,15 @@ - (OCVerbalExpression *)find:(NSString *)value - (OCVerbalExpression *)then:(NSString *)value { - value = [self sanitize:value]; - [self add:[NSString stringWithFormat:@"(%@)", value]]; + //value = [self sanitize:value]; + [self add:[NSString stringWithFormat:@"%@", value]]; + return self; +} + +- (OCVerbalExpression *)thenWithGroup:(void(^)(void))valuesToGroup { + [self add:@"("]; + valuesToGroup(); + [self add:@")"]; return self; } @@ -83,6 +90,31 @@ - (OCVerbalExpression *)something return self; } +- (OCVerbalExpression *)anyWhiteSpace +{ + [self add:@"\\s*"]; + return self; +} + ++ (NSString *)orWithObjects:(NSArray *)objects { + NSMutableString *orString = [NSMutableString stringWithString:@"("]; + [objects enumerateObjectsUsingBlock:^(NSString *value, NSUInteger idx, BOOL *stop) { + [orString appendString:[NSString stringWithFormat:@"%@", value]]; + if (idx < [objects count] - 1) { + [orString appendString:@"|"]; + } + }]; + [orString appendString:@")"]; + return orString; +} + +- (OCVerbalExpression *)orWithGroup:(void(^)(void))valuesToGroup { + [self add:@"|("]; + valuesToGroup(); + [self add:@")"]; + return self; +} + - (OCVerbalExpression *)somethingBut:(NSString *)value { value = [self sanitize:value]; @@ -217,7 +249,7 @@ - (BOOL)test:(NSString *)toTest - (NSRegularExpression *)regularExpression { NSError *error = nil; - NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:self.pattern + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:[self sanitize:self.pattern] options:self.modifiers error:&error]; if (error) { @@ -233,10 +265,15 @@ - (NSString *)description return self.regularExpression.pattern; } +- (NSString *)expressionString { + return self.pattern; +} + #pragma mark praivate methods - (NSString *)sanitize:(NSString *)value { + return value; if (!value) { return nil; } From 1c4682160085b55b943119441ba150e946ef2a16 Mon Sep 17 00:00:00 2001 From: mathew cruz Date: Mon, 7 Oct 2013 15:30:44 -0400 Subject: [PATCH 3/3] Updated docs --- README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/README.md b/README.md index 0f15d02..a90d598 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,41 @@ NSString *result2 = [[[OCVerbalExpression new] find:@"red"] replaceWithSource:@" NSLog(@"%@", result2); // Outputs "We have a blue house" ``` +### Complex example: + +```objc +// Example where you have an HTML string where you want to take out img tags that have either no extension or a +// pdf, doc, docx, xls, xlsx extension +NSString *HTML = @"
"; + +OCVerbalExpression *complexExpr = [OCVerbalExpression new]; +[[[[[[[complexExpr find:@"
"] + anyWhiteSpace] + then:@"src"] + anyWhiteSpace] + then:@"="] + anyWhiteSpace]; + +[complexExpr then:[OCVerbalExpression orWithObjects:@[@"'", @"\""]]]; +[complexExpr anythingBut:[OCVerbalExpression orWithObjects:@[@"'", @".", @"\""]]]; +[complexExpr thenWithGroup:^{ + [complexExpr thenWithGroup:^{ + [complexExpr then:@"."]; + [complexExpr then:[OCVerbalExpression orWithObjects:@[@"pdf", @"doc", @"docx", @"xls", @"xlsx"]]]; + [complexExpr then:[OCVerbalExpression orWithObjects:@[@"'", @"\""]]]; + }]; + [complexExpr orWithGroup:^{ + [complexExpr then:@"'"]; + [complexExpr or:@"\""]; + }]; +}]; +[[[[complexExpr anyWhiteSpace] then:@">"] anyWhiteSpace] then:@"
"]; + +NSString *result2 = [complexExpr replaceWithSource:HTML value:@""]; +NSLog(@"%@", result2); //
+``` + ## API documentation I haven't added much documentation to this repo yet, but you can find the documentation for the original JavaScript repo on their [wiki](https://github.com/jehna/VerbalExpressions/wiki). Most of the methods have been ported as of v0.1.0 of the JavaScript repo. Just be sure to use the syntax explained above rather than the dot notation :)