├── .gitignore ├── .travis.yml ├── LICENSE ├── NSString+Ruby.podspec ├── NSString+Ruby.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── zair.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcshareddata │ └── xcschemes │ └── NSStringRubyTests.xcscheme ├── NSString+Ruby.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── NSString+Ruby.xccheckout ├── NSString+Ruby ├── NSMutableString+Ruby.h ├── NSMutableString+Ruby.m ├── NSString+Ruby-Prefix.pch ├── NSString+Ruby.h └── NSString+Ruby.m ├── NSStringRubyTests ├── NSMutableStringRubyTests.m ├── NSStringRubyTests-Info.plist ├── NSStringRubyTests-Prefix.pch ├── NSStringRubyTests.m └── en.lproj │ └── InfoPlist.strings ├── Podfile ├── Podfile.lock └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | Pods/ 2 | Build/ 3 | DerivedData/ 4 | */xcuserdata/* 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | before_install: 3 | - gem install cocoapods --no-rdoc --no-ri --no-document --quiet 4 | - brew update 5 | - brew uninstall xctool 6 | - brew install xctool --HEAD 7 | - pod install 8 | script: xctool -workspace NSString+Ruby.xcworkspace -scheme "NSStringRubyTests" test -sdk iphonesimulator -arch i386 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Zachary Davison 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. -------------------------------------------------------------------------------- /NSString+Ruby.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "NSString+Ruby" 3 | s.version = "1.1" 4 | s.summary = "NSString category providing common Ruby String methods." 5 | s.homepage = "https://github.com/zdavison/NSString-Ruby" 6 | s.license = 'MIT' 7 | s.author = { "zdavison" => "zac.developer@gmail.com" } 8 | s.source = { :git => "https://github.com/zdavison/NSString-Ruby.git", :tag => "1.1" } 9 | s.source_files = 'NSString+Ruby/*.{h,m}' 10 | s.public_header_files = 'NSString+Ruby/*.h' 11 | s.requires_arc = true 12 | end 13 | -------------------------------------------------------------------------------- /NSString+Ruby.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 873D10F61804A51700BCAC49 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 873D10D81804A33900BCAC49 /* XCTest.framework */; }; 11 | 873D10F71804A51800BCAC49 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1DB17C316DE6A6F005DF97A /* Foundation.framework */; }; 12 | 873D10F81804A51800BCAC49 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1DB17D416DE6A6F005DF97A /* UIKit.framework */; }; 13 | 873D10FE1804A51800BCAC49 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 873D10FC1804A51800BCAC49 /* InfoPlist.strings */; }; 14 | 873D11001804A51800BCAC49 /* NSStringRubyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 873D10FF1804A51800BCAC49 /* NSStringRubyTests.m */; }; 15 | 87600EA31804A63B0095E6CC /* NSString+Ruby.m in Sources */ = {isa = PBXBuildFile; fileRef = B1DB17EC16DE6AB8005DF97A /* NSString+Ruby.m */; }; 16 | 87600EA41804A63B0095E6CC /* NSMutableString+Ruby.m in Sources */ = {isa = PBXBuildFile; fileRef = B1D4F38B177C4DAF001CFD4E /* NSMutableString+Ruby.m */; }; 17 | 879051241806E8840016DA9E /* NSMutableStringRubyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 879051231806E8840016DA9E /* NSMutableStringRubyTests.m */; }; 18 | B1D4F38C177C4DAF001CFD4E /* NSMutableString+Ruby.m in Sources */ = {isa = PBXBuildFile; fileRef = B1D4F38B177C4DAF001CFD4E /* NSMutableString+Ruby.m */; }; 19 | B1DB17C416DE6A6F005DF97A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1DB17C316DE6A6F005DF97A /* Foundation.framework */; }; 20 | B1DB17ED16DE6AB8005DF97A /* NSString+Ruby.m in Sources */ = {isa = PBXBuildFile; fileRef = B1DB17EC16DE6AB8005DF97A /* NSString+Ruby.m */; }; 21 | E047A00C4F564FA3BE77CAA5 /* libPods-NSStringRubyTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B9EF9EDC4BA4DE2B789CC05 /* libPods-NSStringRubyTests.a */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXCopyFilesBuildPhase section */ 25 | B1DB17BE16DE6A6F005DF97A /* CopyFiles */ = { 26 | isa = PBXCopyFilesBuildPhase; 27 | buildActionMask = 2147483647; 28 | dstPath = "include/${PRODUCT_NAME}"; 29 | dstSubfolderSpec = 16; 30 | files = ( 31 | ); 32 | runOnlyForDeploymentPostprocessing = 0; 33 | }; 34 | /* End PBXCopyFilesBuildPhase section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | 5B9EF9EDC4BA4DE2B789CC05 /* libPods-NSStringRubyTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NSStringRubyTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 873D10D81804A33900BCAC49 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 39 | 873D10F51804A51700BCAC49 /* NSStringRubyTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NSStringRubyTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 873D10FB1804A51800BCAC49 /* NSStringRubyTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "NSStringRubyTests-Info.plist"; sourceTree = ""; }; 41 | 873D10FD1804A51800BCAC49 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 42 | 873D10FF1804A51800BCAC49 /* NSStringRubyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSStringRubyTests.m; sourceTree = ""; }; 43 | 873D11011804A51800BCAC49 /* NSStringRubyTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSStringRubyTests-Prefix.pch"; sourceTree = ""; }; 44 | 879051231806E8840016DA9E /* NSMutableStringRubyTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSMutableStringRubyTests.m; sourceTree = ""; }; 45 | B1D4F38A177C4DAF001CFD4E /* NSMutableString+Ruby.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableString+Ruby.h"; sourceTree = ""; }; 46 | B1D4F38B177C4DAF001CFD4E /* NSMutableString+Ruby.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableString+Ruby.m"; sourceTree = ""; }; 47 | B1DB17C016DE6A6F005DF97A /* libNSStringRuby.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libNSStringRuby.a; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | B1DB17C316DE6A6F005DF97A /* Foundation.framework */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 49 | B1DB17C716DE6A6F005DF97A /* NSString+Ruby-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSString+Ruby-Prefix.pch"; sourceTree = ""; }; 50 | B1DB17D216DE6A6F005DF97A /* SenTestingKit.framework */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 51 | B1DB17D416DE6A6F005DF97A /* UIKit.framework */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 52 | B1DB17EB16DE6AB8005DF97A /* NSString+Ruby.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Ruby.h"; sourceTree = ""; }; 53 | B1DB17EC16DE6AB8005DF97A /* NSString+Ruby.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Ruby.m"; sourceTree = ""; }; 54 | E5FA76D7C8CC44E2B5F8F775 /* Pods-NSStringRubyTests.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NSStringRubyTests.xcconfig"; path = "Pods/Pods-NSStringRubyTests.xcconfig"; sourceTree = SOURCE_ROOT; }; 55 | /* End PBXFileReference section */ 56 | 57 | /* Begin PBXFrameworksBuildPhase section */ 58 | 873D10F21804A51700BCAC49 /* Frameworks */ = { 59 | isa = PBXFrameworksBuildPhase; 60 | buildActionMask = 2147483647; 61 | files = ( 62 | 873D10F61804A51700BCAC49 /* XCTest.framework in Frameworks */, 63 | 873D10F81804A51800BCAC49 /* UIKit.framework in Frameworks */, 64 | 873D10F71804A51800BCAC49 /* Foundation.framework in Frameworks */, 65 | E047A00C4F564FA3BE77CAA5 /* libPods-NSStringRubyTests.a in Frameworks */, 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | B1DB17BD16DE6A6F005DF97A /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | B1DB17C416DE6A6F005DF97A /* Foundation.framework in Frameworks */, 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | /* End PBXFrameworksBuildPhase section */ 78 | 79 | /* Begin PBXGroup section */ 80 | 873D10F91804A51800BCAC49 /* NSStringRubyTests */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 873D10FF1804A51800BCAC49 /* NSStringRubyTests.m */, 84 | 879051231806E8840016DA9E /* NSMutableStringRubyTests.m */, 85 | 873D10FA1804A51800BCAC49 /* Supporting Files */, 86 | ); 87 | path = NSStringRubyTests; 88 | sourceTree = ""; 89 | }; 90 | 873D10FA1804A51800BCAC49 /* Supporting Files */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 873D10FB1804A51800BCAC49 /* NSStringRubyTests-Info.plist */, 94 | 873D10FC1804A51800BCAC49 /* InfoPlist.strings */, 95 | 873D11011804A51800BCAC49 /* NSStringRubyTests-Prefix.pch */, 96 | ); 97 | name = "Supporting Files"; 98 | sourceTree = ""; 99 | }; 100 | B1DB17B516DE6A6F005DF97A = { 101 | isa = PBXGroup; 102 | children = ( 103 | B1DB17C516DE6A6F005DF97A /* NSString+Ruby */, 104 | 873D10F91804A51800BCAC49 /* NSStringRubyTests */, 105 | B1DB17C216DE6A6F005DF97A /* Frameworks */, 106 | B1DB17C116DE6A6F005DF97A /* Products */, 107 | E5FA76D7C8CC44E2B5F8F775 /* Pods-NSStringRubyTests.xcconfig */, 108 | ); 109 | sourceTree = ""; 110 | }; 111 | B1DB17C116DE6A6F005DF97A /* Products */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | B1DB17C016DE6A6F005DF97A /* libNSStringRuby.a */, 115 | 873D10F51804A51700BCAC49 /* NSStringRubyTests.xctest */, 116 | ); 117 | name = Products; 118 | sourceTree = ""; 119 | }; 120 | B1DB17C216DE6A6F005DF97A /* Frameworks */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | 873D10D81804A33900BCAC49 /* XCTest.framework */, 124 | B1DB17C316DE6A6F005DF97A /* Foundation.framework */, 125 | B1DB17D216DE6A6F005DF97A /* SenTestingKit.framework */, 126 | B1DB17D416DE6A6F005DF97A /* UIKit.framework */, 127 | 5B9EF9EDC4BA4DE2B789CC05 /* libPods-NSStringRubyTests.a */, 128 | ); 129 | name = Frameworks; 130 | sourceTree = ""; 131 | }; 132 | B1DB17C516DE6A6F005DF97A /* NSString+Ruby */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | B1DB17EB16DE6AB8005DF97A /* NSString+Ruby.h */, 136 | B1DB17EC16DE6AB8005DF97A /* NSString+Ruby.m */, 137 | B1D4F38A177C4DAF001CFD4E /* NSMutableString+Ruby.h */, 138 | B1D4F38B177C4DAF001CFD4E /* NSMutableString+Ruby.m */, 139 | B1DB17C616DE6A6F005DF97A /* Supporting Files */, 140 | ); 141 | path = "NSString+Ruby"; 142 | sourceTree = ""; 143 | }; 144 | B1DB17C616DE6A6F005DF97A /* Supporting Files */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | B1DB17C716DE6A6F005DF97A /* NSString+Ruby-Prefix.pch */, 148 | ); 149 | name = "Supporting Files"; 150 | sourceTree = ""; 151 | }; 152 | /* End PBXGroup section */ 153 | 154 | /* Begin PBXNativeTarget section */ 155 | 873D10F41804A51700BCAC49 /* NSStringRubyTests */ = { 156 | isa = PBXNativeTarget; 157 | buildConfigurationList = 873D11041804A51800BCAC49 /* Build configuration list for PBXNativeTarget "NSStringRubyTests" */; 158 | buildPhases = ( 159 | D53E2BAAA55B47D9ADE7F7D4 /* Check Pods Manifest.lock */, 160 | 873D10F11804A51700BCAC49 /* Sources */, 161 | 873D10F21804A51700BCAC49 /* Frameworks */, 162 | 873D10F31804A51700BCAC49 /* Resources */, 163 | 27BF2CF3FF0F4F7E8BDDCDC9 /* Copy Pods Resources */, 164 | ); 165 | buildRules = ( 166 | ); 167 | dependencies = ( 168 | ); 169 | name = NSStringRubyTests; 170 | productName = NSStringRubyTests; 171 | productReference = 873D10F51804A51700BCAC49 /* NSStringRubyTests.xctest */; 172 | productType = "com.apple.product-type.bundle.unit-test"; 173 | }; 174 | B1DB17BF16DE6A6F005DF97A /* NSStringRuby */ = { 175 | isa = PBXNativeTarget; 176 | buildConfigurationList = B1DB17E516DE6A6F005DF97A /* Build configuration list for PBXNativeTarget "NSStringRuby" */; 177 | buildPhases = ( 178 | B1DB17BC16DE6A6F005DF97A /* Sources */, 179 | B1DB17BD16DE6A6F005DF97A /* Frameworks */, 180 | B1DB17BE16DE6A6F005DF97A /* CopyFiles */, 181 | ); 182 | buildRules = ( 183 | ); 184 | dependencies = ( 185 | ); 186 | name = NSStringRuby; 187 | productName = "NSString+Ruby"; 188 | productReference = B1DB17C016DE6A6F005DF97A /* libNSStringRuby.a */; 189 | productType = "com.apple.product-type.library.static"; 190 | }; 191 | /* End PBXNativeTarget section */ 192 | 193 | /* Begin PBXProject section */ 194 | B1DB17B716DE6A6F005DF97A /* Project object */ = { 195 | isa = PBXProject; 196 | attributes = { 197 | LastUpgradeCheck = 0500; 198 | ORGANIZATIONNAME = ZD; 199 | }; 200 | buildConfigurationList = B1DB17BA16DE6A6F005DF97A /* Build configuration list for PBXProject "NSString+Ruby" */; 201 | compatibilityVersion = "Xcode 3.2"; 202 | developmentRegion = English; 203 | hasScannedForEncodings = 0; 204 | knownRegions = ( 205 | en, 206 | ); 207 | mainGroup = B1DB17B516DE6A6F005DF97A; 208 | productRefGroup = B1DB17C116DE6A6F005DF97A /* Products */; 209 | projectDirPath = ""; 210 | projectRoot = ""; 211 | targets = ( 212 | B1DB17BF16DE6A6F005DF97A /* NSStringRuby */, 213 | 873D10F41804A51700BCAC49 /* NSStringRubyTests */, 214 | ); 215 | }; 216 | /* End PBXProject section */ 217 | 218 | /* Begin PBXResourcesBuildPhase section */ 219 | 873D10F31804A51700BCAC49 /* Resources */ = { 220 | isa = PBXResourcesBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | 873D10FE1804A51800BCAC49 /* InfoPlist.strings in Resources */, 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | /* End PBXResourcesBuildPhase section */ 228 | 229 | /* Begin PBXShellScriptBuildPhase section */ 230 | 27BF2CF3FF0F4F7E8BDDCDC9 /* Copy Pods Resources */ = { 231 | isa = PBXShellScriptBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | ); 235 | inputPaths = ( 236 | ); 237 | name = "Copy Pods Resources"; 238 | outputPaths = ( 239 | ); 240 | runOnlyForDeploymentPostprocessing = 0; 241 | shellPath = /bin/sh; 242 | shellScript = "\"${SRCROOT}/Pods/Pods-NSStringRubyTests-resources.sh\"\n"; 243 | showEnvVarsInLog = 0; 244 | }; 245 | D53E2BAAA55B47D9ADE7F7D4 /* Check Pods Manifest.lock */ = { 246 | isa = PBXShellScriptBuildPhase; 247 | buildActionMask = 2147483647; 248 | files = ( 249 | ); 250 | inputPaths = ( 251 | ); 252 | name = "Check Pods Manifest.lock"; 253 | outputPaths = ( 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | shellPath = /bin/sh; 257 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 258 | showEnvVarsInLog = 0; 259 | }; 260 | /* End PBXShellScriptBuildPhase section */ 261 | 262 | /* Begin PBXSourcesBuildPhase section */ 263 | 873D10F11804A51700BCAC49 /* Sources */ = { 264 | isa = PBXSourcesBuildPhase; 265 | buildActionMask = 2147483647; 266 | files = ( 267 | 879051241806E8840016DA9E /* NSMutableStringRubyTests.m in Sources */, 268 | 87600EA31804A63B0095E6CC /* NSString+Ruby.m in Sources */, 269 | 87600EA41804A63B0095E6CC /* NSMutableString+Ruby.m in Sources */, 270 | 873D11001804A51800BCAC49 /* NSStringRubyTests.m in Sources */, 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | }; 274 | B1DB17BC16DE6A6F005DF97A /* Sources */ = { 275 | isa = PBXSourcesBuildPhase; 276 | buildActionMask = 2147483647; 277 | files = ( 278 | B1DB17ED16DE6AB8005DF97A /* NSString+Ruby.m in Sources */, 279 | B1D4F38C177C4DAF001CFD4E /* NSMutableString+Ruby.m in Sources */, 280 | ); 281 | runOnlyForDeploymentPostprocessing = 0; 282 | }; 283 | /* End PBXSourcesBuildPhase section */ 284 | 285 | /* Begin PBXVariantGroup section */ 286 | 873D10FC1804A51800BCAC49 /* InfoPlist.strings */ = { 287 | isa = PBXVariantGroup; 288 | children = ( 289 | 873D10FD1804A51800BCAC49 /* en */, 290 | ); 291 | name = InfoPlist.strings; 292 | sourceTree = ""; 293 | }; 294 | /* End PBXVariantGroup section */ 295 | 296 | /* Begin XCBuildConfiguration section */ 297 | 873D11051804A51800BCAC49 /* Debug */ = { 298 | isa = XCBuildConfiguration; 299 | baseConfigurationReference = E5FA76D7C8CC44E2B5F8F775 /* Pods-NSStringRubyTests.xcconfig */; 300 | buildSettings = { 301 | CLANG_ENABLE_MODULES = YES; 302 | CLANG_WARN_BOOL_CONVERSION = YES; 303 | CLANG_WARN_CONSTANT_CONVERSION = YES; 304 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 305 | CLANG_WARN_ENUM_CONVERSION = YES; 306 | CLANG_WARN_INT_CONVERSION = YES; 307 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 308 | FRAMEWORK_SEARCH_PATHS = ( 309 | "$(SDKROOT)/Developer/Library/Frameworks", 310 | "$(inherited)", 311 | "$(DEVELOPER_FRAMEWORKS_DIR)", 312 | ); 313 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 314 | GCC_PREFIX_HEADER = "NSStringRubyTests/NSStringRubyTests-Prefix.pch"; 315 | GCC_PREPROCESSOR_DEFINITIONS = ( 316 | "DEBUG=1", 317 | "$(inherited)", 318 | ); 319 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 320 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 321 | GCC_WARN_UNDECLARED_SELECTOR = YES; 322 | GCC_WARN_UNUSED_FUNCTION = YES; 323 | INFOPLIST_FILE = "NSStringRubyTests/NSStringRubyTests-Info.plist"; 324 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 325 | ONLY_ACTIVE_ARCH = YES; 326 | PRODUCT_NAME = "$(TARGET_NAME)"; 327 | VALID_ARCHS = "armv7 armv7s"; 328 | WRAPPER_EXTENSION = xctest; 329 | }; 330 | name = Debug; 331 | }; 332 | 873D11061804A51800BCAC49 /* Release */ = { 333 | isa = XCBuildConfiguration; 334 | baseConfigurationReference = E5FA76D7C8CC44E2B5F8F775 /* Pods-NSStringRubyTests.xcconfig */; 335 | buildSettings = { 336 | CLANG_ENABLE_MODULES = YES; 337 | CLANG_WARN_BOOL_CONVERSION = YES; 338 | CLANG_WARN_CONSTANT_CONVERSION = YES; 339 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 340 | CLANG_WARN_ENUM_CONVERSION = YES; 341 | CLANG_WARN_INT_CONVERSION = YES; 342 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 343 | ENABLE_NS_ASSERTIONS = NO; 344 | FRAMEWORK_SEARCH_PATHS = ( 345 | "$(SDKROOT)/Developer/Library/Frameworks", 346 | "$(inherited)", 347 | "$(DEVELOPER_FRAMEWORKS_DIR)", 348 | ); 349 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 350 | GCC_PREFIX_HEADER = "NSStringRubyTests/NSStringRubyTests-Prefix.pch"; 351 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 352 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 353 | GCC_WARN_UNDECLARED_SELECTOR = YES; 354 | GCC_WARN_UNUSED_FUNCTION = YES; 355 | INFOPLIST_FILE = "NSStringRubyTests/NSStringRubyTests-Info.plist"; 356 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 357 | PRODUCT_NAME = "$(TARGET_NAME)"; 358 | VALID_ARCHS = "armv7 armv7s"; 359 | WRAPPER_EXTENSION = xctest; 360 | }; 361 | name = Release; 362 | }; 363 | B1DB17E316DE6A6F005DF97A /* Debug */ = { 364 | isa = XCBuildConfiguration; 365 | buildSettings = { 366 | ALWAYS_SEARCH_USER_PATHS = NO; 367 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 368 | CLANG_CXX_LIBRARY = "libc++"; 369 | CLANG_ENABLE_OBJC_ARC = YES; 370 | CLANG_WARN_EMPTY_BODY = YES; 371 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 372 | COPY_PHASE_STRIP = NO; 373 | GCC_C_LANGUAGE_STANDARD = gnu99; 374 | GCC_DYNAMIC_NO_PIC = NO; 375 | GCC_OPTIMIZATION_LEVEL = 0; 376 | GCC_PREPROCESSOR_DEFINITIONS = ( 377 | "DEBUG=1", 378 | "$(inherited)", 379 | ); 380 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 381 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 382 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 383 | GCC_WARN_UNUSED_VARIABLE = YES; 384 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 385 | ONLY_ACTIVE_ARCH = YES; 386 | SDKROOT = iphoneos; 387 | }; 388 | name = Debug; 389 | }; 390 | B1DB17E416DE6A6F005DF97A /* Release */ = { 391 | isa = XCBuildConfiguration; 392 | buildSettings = { 393 | ALWAYS_SEARCH_USER_PATHS = NO; 394 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 395 | CLANG_CXX_LIBRARY = "libc++"; 396 | CLANG_ENABLE_OBJC_ARC = YES; 397 | CLANG_WARN_EMPTY_BODY = YES; 398 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 399 | COPY_PHASE_STRIP = YES; 400 | GCC_C_LANGUAGE_STANDARD = gnu99; 401 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 402 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 403 | GCC_WARN_UNUSED_VARIABLE = YES; 404 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 405 | SDKROOT = iphoneos; 406 | VALIDATE_PRODUCT = YES; 407 | }; 408 | name = Release; 409 | }; 410 | B1DB17E616DE6A6F005DF97A /* Debug */ = { 411 | isa = XCBuildConfiguration; 412 | buildSettings = { 413 | DSTROOT = /tmp/NSString_Ruby.dst; 414 | FRAMEWORK_SEARCH_PATHS = ( 415 | "$(inherited)", 416 | "$(DEVELOPER_FRAMEWORKS_DIR)", 417 | ); 418 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 419 | GCC_PREFIX_HEADER = "NSString+Ruby/NSString+Ruby-Prefix.pch"; 420 | GCC_TREAT_WARNINGS_AS_ERRORS = YES; 421 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 422 | ONLY_ACTIVE_ARCH = YES; 423 | OTHER_LDFLAGS = "-ObjC"; 424 | PRODUCT_NAME = "$(TARGET_NAME)"; 425 | SKIP_INSTALL = YES; 426 | VALID_ARCHS = "armv7 armv7s"; 427 | }; 428 | name = Debug; 429 | }; 430 | B1DB17E716DE6A6F005DF97A /* Release */ = { 431 | isa = XCBuildConfiguration; 432 | buildSettings = { 433 | DSTROOT = /tmp/NSString_Ruby.dst; 434 | FRAMEWORK_SEARCH_PATHS = ( 435 | "$(inherited)", 436 | "$(DEVELOPER_FRAMEWORKS_DIR)", 437 | ); 438 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 439 | GCC_PREFIX_HEADER = "NSString+Ruby/NSString+Ruby-Prefix.pch"; 440 | GCC_TREAT_WARNINGS_AS_ERRORS = YES; 441 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 442 | OTHER_LDFLAGS = "-ObjC"; 443 | PRODUCT_NAME = "$(TARGET_NAME)"; 444 | SKIP_INSTALL = YES; 445 | VALID_ARCHS = "armv7 armv7s"; 446 | }; 447 | name = Release; 448 | }; 449 | /* End XCBuildConfiguration section */ 450 | 451 | /* Begin XCConfigurationList section */ 452 | 873D11041804A51800BCAC49 /* Build configuration list for PBXNativeTarget "NSStringRubyTests" */ = { 453 | isa = XCConfigurationList; 454 | buildConfigurations = ( 455 | 873D11051804A51800BCAC49 /* Debug */, 456 | 873D11061804A51800BCAC49 /* Release */, 457 | ); 458 | defaultConfigurationIsVisible = 0; 459 | defaultConfigurationName = Release; 460 | }; 461 | B1DB17BA16DE6A6F005DF97A /* Build configuration list for PBXProject "NSString+Ruby" */ = { 462 | isa = XCConfigurationList; 463 | buildConfigurations = ( 464 | B1DB17E316DE6A6F005DF97A /* Debug */, 465 | B1DB17E416DE6A6F005DF97A /* Release */, 466 | ); 467 | defaultConfigurationIsVisible = 0; 468 | defaultConfigurationName = Release; 469 | }; 470 | B1DB17E516DE6A6F005DF97A /* Build configuration list for PBXNativeTarget "NSStringRuby" */ = { 471 | isa = XCConfigurationList; 472 | buildConfigurations = ( 473 | B1DB17E616DE6A6F005DF97A /* Debug */, 474 | B1DB17E716DE6A6F005DF97A /* Release */, 475 | ); 476 | defaultConfigurationIsVisible = 0; 477 | defaultConfigurationName = Release; 478 | }; 479 | /* End XCConfigurationList section */ 480 | }; 481 | rootObject = B1DB17B716DE6A6F005DF97A /* Project object */; 482 | } 483 | -------------------------------------------------------------------------------- /NSString+Ruby.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /NSString+Ruby.xcodeproj/project.xcworkspace/xcuserdata/zair.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zdavison/NSString-Ruby/a9089287f5b4b986c3c14ca71337c3cfea55ff48/NSString+Ruby.xcodeproj/project.xcworkspace/xcuserdata/zair.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /NSString+Ruby.xcodeproj/xcshareddata/xcschemes/NSStringRubyTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 36 | 37 | 38 | 39 | 45 | 46 | 48 | 49 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /NSString+Ruby.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /NSString+Ruby.xcworkspace/xcshareddata/NSString+Ruby.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 53C086CD-B158-4446-B8E4-F3472F151A58 9 | IDESourceControlProjectName 10 | NSString+Ruby 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 9D1F2581-2411-4B2D-BE54-10CB58848502 14 | ssh://github.com/zdavison/NSString-Ruby.git 15 | 16 | IDESourceControlProjectPath 17 | NSString+Ruby.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 9D1F2581-2411-4B2D-BE54-10CB58848502 21 | .. 22 | 23 | IDESourceControlProjectURL 24 | ssh://github.com/zdavison/NSString-Ruby.git 25 | IDESourceControlProjectVersion 26 | 110 27 | IDESourceControlProjectWCCIdentifier 28 | 9D1F2581-2411-4B2D-BE54-10CB58848502 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 9D1F2581-2411-4B2D-BE54-10CB58848502 36 | IDESourceControlWCCName 37 | NSString-Ruby 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /NSString+Ruby/NSMutableString+Ruby.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableString+Ruby.h 3 | // NSString+Ruby 4 | // 5 | // Created by @thingsdoer on 27/06/2013. 6 | // Copyright (c) 2013 ZD. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSString+Ruby.h" 11 | 12 | @interface NSMutableString (Ruby) 13 | 14 | //Ruby Methods 15 | -(NSString*)capitalizeInPlace; 16 | -(NSString*)chompInPlace; 17 | -(NSString*)chompInPlace:(NSString*)string; 18 | -(NSString*)chopInPlace; 19 | -(NSString*)deleteInPlace:(NSString*)first, ...; 20 | -(NSString*)lowercaseInPlace; 21 | -(NSString*)substituteAllInPlace:(NSDictionary *)subDictionary; 22 | -(NSString*)substituteAllInPlace:(NSString *)pattern with:(NSString *)sub; 23 | -(NSString*)leftStripInPlace; 24 | -(NSString*)reverseInPlace; 25 | -(NSString*)rightStripInPlace; 26 | -(NSString*)squeezeInPlace; 27 | -(NSString*)squeezeInPlace:(NSString *)pattern; 28 | -(NSString*)stripInPlace; 29 | -(NSString*)substituteFirstInPlace:(NSString *)pattern with:(NSString *)sub; 30 | -(NSString*)substituteLastInPlace:(NSString *)pattern with:(NSString *)sub; 31 | -(NSString*)swapcaseInPlace; 32 | -(NSString*)uppercaseInPlace; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /NSString+Ruby/NSMutableString+Ruby.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableString+Ruby.m 3 | // NSString+Ruby 4 | // 5 | // Created by @thingsdoer on 27/06/2013. 6 | // Copyright (c) 2013 ZD. All rights reserved. 7 | // 8 | 9 | /* Ruby -> Obj-C Equivalents 10 | 11 | #capitalize! capitalizeInPlace 12 | #chomp! chompInPlace 13 | chompInPlace: 14 | #chop! chopInPlace 15 | #delete! deleteInPlace: 16 | #downcase! lowercaseStringInPlace 17 | #gsub! substituteAllInPlace: 18 | substituteAllInPlace:pattern 19 | #lstrip! leftStripInPlace 20 | #reverse! reverseInPlace 21 | #rstrip! rightStripInPlace 22 | #squeeze! squeezeInPlace 23 | squeezeInPlace: 24 | #strip! stripInPlace 25 | #sub! substituteFirstInPlace: 26 | substituteLastInPlace: 27 | #swapcase! swapcaseInPlace 28 | #upcase! uppercaseInPlace 29 | 30 | */ 31 | 32 | #import "NSMutableString+Ruby.h" 33 | 34 | @interface NSString(RubyPrivate) 35 | 36 | NSString* _stringRepresentationOf(id object); 37 | -(NSString*)_delete:(NSString*)first remaining:(va_list)args; 38 | 39 | @end 40 | 41 | @implementation NSMutableString (Ruby) 42 | 43 | -(NSString*)capitalizeInPlace{ 44 | NSString *oldString = [NSString stringWithString:self]; 45 | [self setString:[self capitalizedString]]; 46 | if([oldString isEqualToString:self]){ 47 | return nil; 48 | }else{ 49 | return self; 50 | } 51 | } 52 | 53 | -(NSString*)chompInPlace{ 54 | NSString *oldString = [NSString stringWithString:self]; 55 | [self setString:[self chomp]]; 56 | if([oldString isEqualToString:self]){ 57 | return nil; 58 | }else{ 59 | return self; 60 | } 61 | } 62 | 63 | -(NSString*)chompInPlace:(NSString*)string{ 64 | NSString *oldString = [NSString stringWithString:self]; 65 | [self setString:[self chomp:string]]; 66 | if([oldString isEqualToString:self]){ 67 | return nil; 68 | }else{ 69 | return self; 70 | } 71 | } 72 | 73 | -(NSString*)chopInPlace{ 74 | [self setString:[self chop]]; 75 | return self; 76 | } 77 | 78 | -(NSString*)deleteInPlace:(NSString*)first, ...{ 79 | NSString *oldString = [NSString stringWithString:self]; 80 | va_list args; 81 | va_start(args, first); 82 | [self setString:[self _delete:first remaining:args]]; 83 | va_end(args); 84 | if([oldString isEqualToString:self]){ 85 | return nil; 86 | }else{ 87 | return self; 88 | } 89 | } 90 | 91 | -(NSString*)lowercaseInPlace{ 92 | NSString *oldString = [NSString stringWithString:self]; 93 | [self setString:[self lowercaseString]]; 94 | if([oldString isEqualToString:self]){ 95 | return nil; 96 | }else{ 97 | return self; 98 | } 99 | } 100 | 101 | -(NSString*)substituteAllInPlace:(NSDictionary *)subDictionary{ 102 | NSString *oldString = [NSString stringWithString:self]; 103 | [self setString:[self substituteAll:subDictionary]]; 104 | if([oldString isEqualToString:self]){ 105 | return nil; 106 | }else{ 107 | return self; 108 | } 109 | } 110 | 111 | -(NSString*)substituteAllInPlace:(NSString *)pattern with:(NSString *)sub{ 112 | NSString *oldString = [NSString stringWithString:self]; 113 | [self setString:[self substituteAll:pattern with:sub]]; 114 | if([oldString isEqualToString:self]){ 115 | return nil; 116 | }else{ 117 | return self; 118 | } 119 | } 120 | 121 | -(NSString*)leftStripInPlace{ 122 | NSString *oldString = [NSString stringWithString:self]; 123 | [self setString:[self leftStrip]]; 124 | if([oldString isEqualToString:self]){ 125 | return nil; 126 | }else{ 127 | return self; 128 | } 129 | } 130 | 131 | -(NSString*)reverseInPlace{ 132 | NSString *oldString = [NSString stringWithString:self]; 133 | [self setString:[self reverse]]; 134 | if([oldString isEqualToString:self]){ 135 | return nil; 136 | }else{ 137 | return self; 138 | } 139 | } 140 | 141 | -(NSString*)rightStripInPlace{ 142 | NSString *oldString = [NSString stringWithString:self]; 143 | [self setString:[self rightStrip]]; 144 | if([oldString isEqualToString:self]){ 145 | return nil; 146 | }else{ 147 | return self; 148 | } 149 | } 150 | 151 | -(NSString*)squeezeInPlace{ 152 | NSString *oldString = [NSString stringWithString:self]; 153 | [self setString:[self squeeze]]; 154 | if([oldString isEqualToString:self]){ 155 | return nil; 156 | }else{ 157 | return self; 158 | } 159 | } 160 | 161 | -(NSString*)squeezeInPlace:(NSString *)pattern{ 162 | NSString *oldString = [NSString stringWithString:self]; 163 | [self setString:[self squeeze:pattern]]; 164 | if([oldString isEqualToString:self]){ 165 | return nil; 166 | }else{ 167 | return self; 168 | } 169 | } 170 | 171 | -(NSString*)stripInPlace{ 172 | NSString *oldString = [NSString stringWithString:self]; 173 | [self setString:[self strip]]; 174 | if([oldString isEqualToString:self]){ 175 | return nil; 176 | }else{ 177 | return self; 178 | } 179 | } 180 | 181 | -(NSString*)substituteFirstInPlace:(NSString *)pattern with:(NSString *)sub{ 182 | NSString *oldString = [NSString stringWithString:self]; 183 | [self setString:[self substituteFirst:pattern with:sub]]; 184 | if([oldString isEqualToString:self]){ 185 | return nil; 186 | }else{ 187 | return self; 188 | } 189 | } 190 | 191 | -(NSString*)substituteLastInPlace:(NSString *)pattern with:(NSString *)sub{ 192 | NSString *oldString = [NSString stringWithString:self]; 193 | [self setString:[self substituteLast:pattern with:sub]]; 194 | if([oldString isEqualToString:self]){ 195 | return nil; 196 | }else{ 197 | return self; 198 | } 199 | } 200 | 201 | -(NSString*)swapcaseInPlace{ 202 | NSString *oldString = [NSString stringWithString:self]; 203 | [self setString:[self swapcase]]; 204 | if([oldString isEqualToString:self]){ 205 | return nil; 206 | }else{ 207 | return self; 208 | } 209 | } 210 | 211 | -(NSString*)uppercaseInPlace{ 212 | NSString *oldString = [NSString stringWithString:self]; 213 | [self setString:[self uppercaseString]]; 214 | if([oldString isEqualToString:self]){ 215 | return nil; 216 | }else{ 217 | return self; 218 | } 219 | } 220 | 221 | @end 222 | -------------------------------------------------------------------------------- /NSString+Ruby/NSString+Ruby-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'NSString+Ruby' target in the 'NSString+Ruby' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /NSString+Ruby/NSString+Ruby.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Ruby.h 3 | // 4 | // Created by Zachary Davison on 30/10/2012. 5 | // Copyright (c) 2012 ZD. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | #pragma mark - Categories 11 | 12 | @protocol Concatenatable 13 | @end 14 | 15 | @interface NSNumber(Ruby) 16 | @end 17 | 18 | @interface NSString(Ruby) 19 | 20 | //Operator-likes 21 | -(NSString*):(NSObject*)concat, ...; 22 | -(NSString*)x:(NSInteger )mult; 23 | 24 | //Shorthand Accessors 25 | -(NSString*):(NSInteger )loc :(NSInteger )len; 26 | -(NSString*):(NSInteger )start :(char*)shorthand :(NSInteger )end; 27 | 28 | //Ruby Methods 29 | -(void)bytes:(void(^)(unichar))block; 30 | - (NSString*)center:(NSInteger )amount; 31 | - (NSString*)center:(NSInteger )amount with:(NSString*)padString; 32 | -(void)chars:(void(^)(unichar))block; 33 | -(NSString*)chomp; 34 | -(NSString*)chomp:(NSString*)string; 35 | -(NSString*)chop; 36 | -(NSString*)chr; 37 | -(void)codePoints:(void(^)(NSInteger ))block; 38 | - (NSString*)concat:(id)concat; 39 | -(NSInteger)count:(NSString*)setString, ...; 40 | -(NSString*)delete:(NSString*)first, ...; 41 | -(BOOL)endsWith:(NSString*)first,...; 42 | -(long)hex; 43 | -(BOOL)includes:(NSString*)include; 44 | -(NSInteger)index:(NSString*)pattern; 45 | -(NSInteger)index:(NSString*)pattern offset:(NSInteger )offset; 46 | -(NSString*)insert:(NSInteger)index string:(NSString*)string; 47 | -(NSString*)inspect; 48 | -(BOOL)isASCII; 49 | -(BOOL)isEmpty; 50 | -(NSInteger)lastIndex:(NSString*)pattern; 51 | -(NSInteger)lastIndex:(NSString*)pattern offset:(NSInteger )offset; 52 | -(NSString*)leftJustify:(NSInteger )amount; 53 | -(NSString*)leftJustify:(NSInteger )amount with:(NSString*)padString; 54 | -(NSString*)leftStrip; 55 | -(void)lines:(void(^)(NSString*))block; 56 | -(void)lines:(void(^)(NSString*))block separator:(NSString*)separator; 57 | -(NSArray*)match:(NSString*)pattern; 58 | -(NSArray*)match:(NSString*)pattern offset:(NSInteger )offset; 59 | -(NSInteger)occurencesOf:(NSString*)subString; 60 | -(long)octal; 61 | -(NSInteger )ordinal; 62 | -(NSArray*)partition:(NSString*)pattern; 63 | -(NSString*)prepend:(NSString*)prefix; 64 | -(NSRange)range; 65 | -(NSString*)reverse; 66 | -(NSInteger)rightIndex:(NSString*)pattern; 67 | -(NSInteger)rightIndex:(NSString*)pattern offset:(NSInteger )offset; 68 | -(NSString*)rightJustify:(NSInteger )amount; 69 | -(NSString*)rightJustify:(NSInteger )amount with:(NSString*)padString; 70 | -(NSArray*)rightPartition:(NSString*)pattern; 71 | -(NSString*)rightStrip; 72 | - (NSArray*)scan:(NSString*)pattern; 73 | - (BOOL)startsWith:(NSString*)first,...; 74 | - (NSString*)strip; 75 | - (NSArray*)split; 76 | - (NSArray*)split:(NSString*)pattern; 77 | - (NSArray*)split:(NSString*)pattern limit:(NSInteger )limit; 78 | - (NSString*)squeeze; 79 | - (NSString*)squeeze:(NSString*)pattern; 80 | - (NSString*)substituteFirst:(NSString*)pattern with:(NSString*)sub; 81 | - (NSString*)substituteLast:(NSString*)pattern with:(NSString*)sub; 82 | -(NSString*)substituteAll:(NSDictionary*)subDictionary; 83 | -(NSString*)substituteAll:(NSString*)pattern with:(NSString*)sub; 84 | -(NSInteger )sum; 85 | -(NSInteger )sum:(NSInteger )bit; 86 | -(NSString*)swapcase; 87 | 88 | //Subscript Protocol 89 | -(id)objectAtIndexedSubscript:(NSUInteger)index; 90 | -(id)objectForKeyedSubscript:(id)key; 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /NSString+Ruby/NSString+Ruby.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Ruby.m 3 | // 4 | // Created by Zachary Davison on 30/10/2012. 5 | // Copyright (c) 2012 ZD. All rights reserved. 6 | // 7 | 8 | /* Ruby -> Obj-C Equivalents 9 | 10 | ::try_convert 11 | #% (no sensible way to implement this) 12 | #* x: 13 | #+ : 14 | #<< : 15 | #<=> compare: 16 | #== isEqualToString: 17 | #=== == 18 | #=~ index: 19 | #[] start:shorthand:end |> [@"string" :1:@"..":3] 20 | @"string"[1] 21 | @"string"{@"regex"} 22 | @"string"{@[1,3]} 23 | #[]= (no mutating methods) 24 | #ascii_only? isASCII: 25 | #bytes bytes: 26 | #bytesize 27 | #byteslice 28 | #capitalize capitalizedString 29 | #casecmp caseInsensitiveCompare: 30 | #center center: 31 | center:with: 32 | #chars chars: 33 | #chomp chomp 34 | chomp: 35 | #chop chop 36 | #chr chr 37 | #clear (unnecessary in obj-c) 38 | #codepoints codePoints: 39 | #concat concat: 40 | #count count: 41 | #crypt (unsure as of yet of which method to use for this, wary of providing easily misused insecure method) 42 | #delete delete: 43 | #downcase lowercaseString 44 | #dump (implementation very close to |inspect|, |inspect| might suffice?) 45 | #each_byte bytes: 46 | #each_char chars: 47 | #each_codepointcodepoints: 48 | #each_line lines: 49 | #empty? isEmpty 50 | #encode 51 | #encoding 52 | #end_with? endsWith: 53 | #eql? isEqualToString: 54 | #force_encoding 55 | #getbyte 56 | #gsub substituteAll: 57 | substituteAll:pattern 58 | #hash hash 59 | #hex hex 60 | #include? includes: 61 | #index match: 62 | match:offset: 63 | #insert insert:string: 64 | #inspect inspect 65 | #intern (not viable in obj-c, Ruby specific) 66 | #length length 67 | #lines lines: 68 | #ljust leftJustify: 69 | leftJustify:with: 70 | #lstrip leftStrip 71 | #match index: 72 | index:offset: 73 | #next 74 | #oct octal 75 | #ord ordinal 76 | #partition partition: 77 | #prepend prepend: 78 | #replace (unnecessary in obj-c) 79 | #reverse reverse 80 | #rindex lastIndex: 81 | lastIndex:offset: 82 | #rjust rightJustify: 83 | rightJustify:with: 84 | #rpartition rightPartition: 85 | #rstrip rightStrip 86 | #scan scan: 87 | #setbyte 88 | #size length 89 | #slice start:shorthand:end |> [@"string" :1:@"..":3] 90 | @"string"[1] 91 | @"string"{@"regex"} 92 | @"string"{@[1,3]} 93 | #split split 94 | split: 95 | split:limit: 96 | #squeeze squeeze 97 | squeeze: 98 | #start_with? startsWith: 99 | #strip strip 100 | #sub substituteFirst: 101 | substituteLast: 102 | #succ 103 | #sum sum 104 | sum: 105 | #swapcase swapcase 106 | #to_c 107 | #to_f floatValue 108 | #to_i intValue 109 | #to_r 110 | #to_s (just use self) 111 | #to_str (just use self) 112 | #to_sym (not viable in obj-c, Ruby specific, NS____FromString methods might do what you want) 113 | #tr (functionality is very similar to gsub for us, suggest using that instead) 114 | #tr_s 115 | #unpack 116 | #upcase uppercaseString 117 | #upto 118 | #valid_encoding? 119 | 120 | */ 121 | 122 | #import "NSString+Ruby.h" 123 | 124 | @implementation NSString (Ruby) 125 | 126 | #pragma mark - Private 127 | 128 | NSString* _stringRepresentationOf(id object){ 129 | if([object isKindOfClass:[NSString class]]){ 130 | return (NSString*)object; 131 | }else if([object isKindOfClass:[NSNumber class]]){ 132 | unichar c = [(NSNumber*)object charValue]; 133 | return [NSString stringWithCharacters:&c length:1]; 134 | }else if([object respondsToSelector:@selector(description)]){ 135 | return [object description]; 136 | }else{ 137 | return @""; 138 | } 139 | } 140 | 141 | - (NSString*)_delete:(NSString*)first remaining:(va_list)args{ 142 | NSSet *comparisonSet = [self unionOfCharactersInStrings:first remaining:args]; 143 | NSString *finalString = self; 144 | for(NSString *charString in comparisonSet) { 145 | finalString = [finalString stringByReplacingOccurrencesOfString:charString withString:@""]; 146 | } 147 | return finalString; 148 | } 149 | 150 | 151 | #pragma mark - Public Operator-likes 152 | 153 | - (NSString*):(id)concat, ... { 154 | NSMutableString *newString = [NSMutableString stringWithString:self]; 155 | va_list args; 156 | va_start(args, concat); 157 | for (id arg = concat ; arg != nil ; arg = va_arg(args, id)){ 158 | [newString appendString:_stringRepresentationOf(arg)]; 159 | } 160 | va_end(args); 161 | 162 | return newString; 163 | } 164 | 165 | - (NSString*)x:(NSInteger )mult { 166 | NSMutableString *result = [NSMutableString string]; 167 | for(NSInteger i = 0; i= 0) ? loc:self.length - labs(loc), 176 | len)]; 177 | } 178 | 179 | - (NSString*):(NSInteger )start :(char*)shorthand :(NSInteger )end { 180 | NSUInteger rstart = (start >= 0) ? start : self.length - labs(start); 181 | NSUInteger rend = (end >= 0) ? end : self.length - labs(end); 182 | if(rstart > rend) 183 | return nil; 184 | 185 | NSRange range = NSMakeRange(rstart,rend-rstart); 186 | if(strcmp(shorthand, "...") == 0) { 187 | return [self substringWithRange:range]; 188 | } else if(strcmp(shorthand, "..") == 0) { 189 | range.length += 1; 190 | return [self substringWithRange:range]; 191 | } 192 | return nil; 193 | } 194 | 195 | #pragma mark - Public Ruby String Methods 196 | - (void)bytes:(void (^)(unichar))block { 197 | unichar *characters = calloc(self.length, sizeof(unichar)); 198 | [self getCharacters:characters]; 199 | for(NSInteger i = 0; i= padString.length) 218 | c = 0; 219 | } 220 | NSString *result = [NSString stringWithFormat:@"%@%@%@",pad,self,pad]; 221 | return (result.length == amount) ? result : [NSString stringWithFormat:@"%@%c",result,[padString characterAtIndex:c]]; 222 | } 223 | 224 | - (void)chars:(void (^)(unichar))block { 225 | unichar *characters = calloc(self.length, sizeof(unichar)); 226 | [self getCharacters:characters]; 227 | for(NSInteger i = 0; i0) ? 1:0))]; 251 | } 252 | 253 | - (NSString*)chr { 254 | return [self substringWithRange:NSMakeRange(0, (self.length > 0) ? 1:0)]; 255 | } 256 | 257 | - (void)codePoints:(void (^)(NSInteger ))block{ 258 | unichar *characters = calloc(self.length, sizeof(unichar)); 259 | [self getCharacters:characters]; 260 | for(NSInteger i = 0; i= 0) ? offset : self.length-labs(offset); 325 | NSUInteger len = self.length - loc; 326 | NSRange range = NSMakeRange(loc,len); 327 | NSTextCheckingResult *result = [regex firstMatchInString:self options:0 range:range]; 328 | return (result.range.length > 0) ? result.range.location : NSNotFound; 329 | } 330 | return NSNotFound; 331 | } 332 | 333 | - (NSString*)insert:(NSInteger)index string:(NSString*)string{ 334 | if(index < 0) 335 | index = self.length - labs(index) + 1; 336 | else if(index >= self.length) 337 | index = self.length; 338 | return [NSString stringWithFormat:@"%@%@%@",[self substringToIndex:index],string,[self substringFromIndex:index]]; 339 | } 340 | 341 | - (NSString *)inspect; 342 | { 343 | NSMutableString *result = [self mutableCopy]; 344 | NSRange stringRange = NSMakeRange(0, [self length]); 345 | 346 | [@{ 347 | @"\0" : @"\\0", 348 | @"\a" : @"\\a", 349 | @"\b" : @"\\b", 350 | @"\t" : @"\\t", 351 | @"\n" : @"\\n", 352 | @"\f" : @"\\f", 353 | @"\r" : @"\\r", 354 | @"\e" : @"\\e", 355 | } enumerateKeysAndObjectsUsingBlock:^(NSString *string, NSString *replacement, BOOL *stop) { 356 | [result replaceOccurrencesOfString:string withString:replacement options:0 range:stringRange]; 357 | }]; 358 | 359 | return [NSString stringWithFormat:@"\"%@\"",result]; 360 | } 361 | 362 | -(BOOL)isASCII{ 363 | unichar *characters = calloc(self.length, sizeof(unichar)); 364 | [self getCharacters:characters]; 365 | for(NSInteger i = 0; i 127){ 367 | free(characters); 368 | return NO; 369 | } 370 | } 371 | free(characters); 372 | return YES; 373 | } 374 | 375 | -(BOOL)isEmpty{ 376 | return self.length == 0; 377 | } 378 | 379 | -(NSInteger)lastIndex:(NSString*)pattern{ 380 | return [self lastIndex:pattern offset:0]; 381 | } 382 | 383 | -(NSInteger)lastIndex:(NSString*)pattern offset:(NSInteger )offset{ 384 | offset = labs(offset); //lets allow for negative and positive inputs 385 | NSError *error = nil; 386 | NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern 387 | options:0 388 | error:&error]; 389 | if(!error){ 390 | NSTextCheckingResult *result = [regex matchesInString:self options:0 range:NSMakeRange(0, self.length-offset)].lastObject; 391 | return (result.range.length > 0) ? result.range.location : NSNotFound; 392 | } 393 | return NSNotFound; 394 | } 395 | 396 | -(NSString*)leftJustify:(NSInteger )amount{ 397 | return [self leftJustify:amount with:@" "]; 398 | } 399 | 400 | -(NSString*)leftJustify:(NSInteger )amount with:(NSString*)padString{ 401 | if (amount <= self.length) 402 | return self; 403 | NSString *pad = @""; 404 | NSInteger c = 0; 405 | for(NSInteger i = 0;i= padString.length) 408 | c = 0; 409 | } 410 | NSString *result = [NSString stringWithFormat:@"%@%@",self,pad]; 411 | return result; 412 | } 413 | 414 | -(NSString*)leftStrip{ 415 | NSInteger i; 416 | for(i=0;i 1){ 452 | for(NSInteger i=1;i=0;i--) 517 | [reversedStr appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:i]]]; 518 | 519 | return reversedStr; 520 | } 521 | 522 | -(NSInteger)rightIndex:(NSString*)pattern{ 523 | return [self index:pattern offset:0]; 524 | } 525 | 526 | -(NSInteger)rightIndex:(NSString*)pattern offset:(NSInteger )offset{ 527 | NSError *error = nil; 528 | NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern 529 | options:0 530 | error:&error]; 531 | if(!error){ 532 | NSInteger loc = (offset >= 0) ? offset : self.length-labs(offset); 533 | NSInteger len = self.length - loc; 534 | NSRange range = NSMakeRange(0,len); 535 | NSTextCheckingResult *result = [regex matchesInString:self options:0 range:range].lastObject; 536 | return (result.range.length > 0) ? result.range.location : NSNotFound; 537 | } 538 | return NSNotFound; 539 | } 540 | 541 | -(NSString*)rightJustify:(NSInteger )amount{ 542 | return [self rightJustify:amount with:@" "]; 543 | } 544 | 545 | -(NSString*)rightJustify:(NSInteger )amount with:(NSString*)padString{ 546 | if(amount <= self.length) 547 | return self; 548 | NSString *pad = [@"" stringByPaddingToLength:amount-self.length withString:padString startingAtIndex:0]; 549 | return [pad:self,nil]; 550 | } 551 | 552 | -(NSArray*)rightPartition:(NSString*)pattern{ 553 | NSError *error = nil; 554 | NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern 555 | options:0 556 | error:&error]; 557 | if(error) 558 | return @[]; 559 | 560 | NSTextCheckingResult *result = [regex matchesInString:self options:0 range:self.range].lastObject; 561 | if(!result) 562 | return @[@"",@"",self]; 563 | 564 | NSString *first = [self substringWithRange:NSMakeRange(0, result.range.location)]; 565 | NSString *middle = [self substringWithRange:result.range]; 566 | NSString *last = [self substringWithRange:NSMakeRange(result.range.location+result.range.length, 567 | self.length-(result.range.location+result.range.length))]; 568 | return @[first,middle,last]; 569 | } 570 | 571 | -(NSString*)rightStrip{ 572 | NSInteger i; 573 | for(i=self.length-1;i>0;i--){ 574 | if(![[NSCharacterSet whitespaceAndNewlineCharacterSet] characterIsMember:[self characterAtIndex:i]]) 575 | break; 576 | } 577 | return [self stringByReplacingCharactersInRange:NSMakeRange(i+1, self.length-1-i) withString:@""]; 578 | } 579 | 580 | - (NSArray*)scan:(NSString*)pattern{ 581 | NSMutableArray *strings = [NSMutableArray array]; 582 | NSError *error = nil; 583 | NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern 584 | options:0 585 | error:&error]; 586 | if(error) 587 | return @[]; 588 | 589 | NSArray *results = [regex matchesInString:self options:0 range:self.range]; 590 | for(NSTextCheckingResult *result in results){ 591 | [strings addObject:[self substringWithRange:result.range]]; 592 | } 593 | return [NSArray arrayWithArray:strings]; 594 | } 595 | 596 | - (BOOL)startsWith:(NSString*)first,...{ 597 | va_list args; 598 | va_start(args, first); 599 | for(NSString *arg = first; arg!=nil; arg = va_arg(args, NSString*)) { 600 | if([self rangeOfString:arg].location == 0) 601 | return true; 602 | } 603 | va_end(args); 604 | return false; 605 | } 606 | 607 | - (NSString*)strip{ 608 | return [[self leftStrip] rightStrip]; 609 | } 610 | 611 | - (NSArray*)split{ 612 | return [self split:@" "]; 613 | } 614 | 615 | - (NSArray*)split:(NSString*)pattern{ 616 | return [self split:pattern limit:INT_MAX]; 617 | } 618 | 619 | - (NSArray*)split:(NSString*)pattern limit:(NSInteger )limit{ 620 | NSString *str = self; 621 | 622 | //if limit is negative, dont suppress fields and return all fields 623 | if(limit < 0) 624 | limit = INT_MAX - 1; 625 | 626 | NSMutableArray *strings = [NSMutableArray array]; 627 | //if splitting on nothing, just split every character 628 | if(pattern.length == 0){ 629 | for(NSInteger i=0;i 0 || s.length > 0) 653 | [strings addObject:s]; 654 | loc = result.range.location + result.range.length; 655 | if(strings.count >= limit-1) 656 | break; 657 | } 658 | NSString *s = [str substringWithRange:NSMakeRange(loc, str.length-loc)]; 659 | if(s.length > 0 || limit == INT_MAX - 1) 660 | [strings addObject:s]; 661 | 662 | //if limit isn't specified, suppress trailing nulls 663 | if(limit == INT_MAX && [[strings lastObject] length] == 0) 664 | [strings removeLastObject]; 665 | return strings; 666 | } 667 | 668 | - (NSString*)squeeze{ 669 | return [self squeeze:@"."]; 670 | } 671 | 672 | - (NSString*)squeeze:(NSString*)pattern{ 673 | NSMutableString *s = [NSMutableString string]; 674 | NSString *wrapped = [NSString stringWithFormat:@"(%@)\\1+",pattern]; 675 | NSError *error = nil; 676 | NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:wrapped 677 | options:0 678 | error:&error]; 679 | if(error) 680 | return nil; 681 | NSArray *matches = [regex matchesInString:self options:0 range:self.range]; 682 | NSInteger loc = 0; 683 | for(NSTextCheckingResult *result in matches){ 684 | [s appendString:[self substringWithRange:NSMakeRange(loc, result.range.location-loc)]]; 685 | loc = result.range.location + result.range.length; 686 | [s appendFormat:@"%c",[self characterAtIndex:result.range.location]]; 687 | } 688 | [s appendString:[self substringWithRange:NSMakeRange(loc, self.length-loc)]]; 689 | return s; 690 | } 691 | 692 | - (NSString*)substituteFirst:(NSString*)pattern with:(NSString*)sub { 693 | NSString *result = self; 694 | NSError *error = nil; 695 | NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern 696 | options:0 697 | error:&error]; 698 | if(!error) { 699 | NSTextCheckingResult *match = [regex firstMatchInString:self options:0 range:self.range]; 700 | result = [result stringByReplacingCharactersInRange:match.range withString:sub]; 701 | } 702 | return result; 703 | } 704 | 705 | - (NSString*)substituteLast:(NSString*)pattern with:(NSString*)sub { 706 | NSString *result = self; 707 | NSError *error = nil; 708 | NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern 709 | options:0 710 | error:&error]; 711 | if(!error) { 712 | NSTextCheckingResult *match = [regex matchesInString:self options:0 range:self.range].lastObject; 713 | result = [result stringByReplacingCharactersInRange:match.range withString:sub]; 714 | } 715 | return result; 716 | } 717 | 718 | - (NSString*)substituteAll:(NSDictionary*)subDictionary { 719 | NSString *result = self; 720 | for(NSString *key in [subDictionary allKeys]) { 721 | NSRange range = [self rangeOfString:key]; 722 | if(range.location != NSNotFound) 723 | result = [result stringByReplacingOccurrencesOfString:key withString:[subDictionary objectForKey:key]]; 724 | } 725 | return result; 726 | } 727 | 728 | - (NSString*)substituteAll:(NSString*)pattern with:(NSString*)sub { 729 | NSString *result = self; 730 | NSError *error = nil; 731 | NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern 732 | options:0 733 | error:&error]; 734 | if(!error) { 735 | NSArray *matches = [regex matchesInString:self options:0 range:self.range]; 736 | for(NSTextCheckingResult *match in matches) { 737 | result = [result stringByReplacingCharactersInRange:match.range withString:sub]; 738 | } 739 | } 740 | return result; 741 | } 742 | 743 | - (NSInteger )sum{ 744 | return [self sum:16]; 745 | } 746 | 747 | - (NSInteger )sum:(NSInteger )bit{ 748 | __block NSInteger total = 0; 749 | [self chars:^(unichar c) { 750 | total += (NSInteger )c; 751 | }]; 752 | return (total % (NSInteger )pow(2, bit-1)); 753 | } 754 | 755 | - (NSString*)swapcase{ 756 | unichar *s = calloc(self.length, sizeof(unichar)); 757 | [self getCharacters:s]; 758 | for(NSInteger i=0;i= 64 && s[i] <= 90) 760 | s[i] = s[i] + 32; 761 | else if(s[i] >= 97 && s[i] <= 122) 762 | s[i] = s[i] - 32; 763 | } 764 | return [NSString stringWithCharacters:s length:self.length]; 765 | } 766 | 767 | #pragma mark - Subscript Protocol Methods 768 | 769 | - (id)objectAtIndexedSubscript:(NSUInteger)index { 770 | if(index > self.length-1) 771 | return nil; 772 | unichar character = [self characterAtIndex:index]; 773 | return [NSString stringWithCharacters:&character length:1]; 774 | } 775 | 776 | - (id)objectForKeyedSubscript:(id)key { 777 | if([key isKindOfClass:[NSString class]]) { //if it's a string, assume a regex. 778 | NSError *error = nil; 779 | NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:key 780 | options:0 781 | error:&error]; 782 | if(error) 783 | return nil; 784 | NSTextCheckingResult *result = [regex firstMatchInString:self options:0 range:self.range]; 785 | if(result) 786 | return [self substringWithRange:result.range]; 787 | } else if([key isKindOfClass:[NSArray class]]) { 788 | NSInteger loc = [key[0] intValue]; 789 | NSInteger len = [key[1] intValue]; 790 | return [self substringWithRange:NSMakeRange((loc > 0) ? loc:self.length - labs(loc), 791 | len)]; 792 | } 793 | return nil; 794 | } 795 | 796 | #pragma mark - Helper Methods 797 | - (NSSet*)unionOfCharactersInStrings:(NSString*)first remaining:(va_list)va_list { 798 | NSMutableArray *sets = [NSMutableArray array]; 799 | NSMutableSet *negateSet = [NSMutableSet set]; 800 | for(NSString *arg = first; arg!=nil; arg = va_arg(va_list, NSString*)) { 801 | NSMutableSet *argSet = [NSMutableSet set]; 802 | NSString *cleanedArg = [arg stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 803 | unichar *characters = calloc(cleanedArg.length, sizeof(unichar)); 804 | [cleanedArg getCharacters:characters]; 805 | if(characters[0] == '^') { 806 | for(NSInteger i = 1; i 2 | #import "NSMutableString+Ruby.h" 3 | 4 | #pragma mark - Support 5 | 6 | #pragma mark - Tests 7 | 8 | /* 9 | -(NSString*)upperCaseStringM; 10 | */ 11 | 12 | SPEC_BEGIN(NSMutableStringRubySpec) 13 | 14 | /* 15 | "hello".chomp! #=> "hello" 16 | "hello\n".chomp! #=> "hello" 17 | "hello\r\n".chomp! #=> "hello" FAIL (\r\n is not recognized as a single carriage return character in obj-c) 18 | "hello\n\r".chomp! #=> "hello\n" 19 | "hello\r".chomp! #=> "hello" 20 | "hello \n there".chomp! #=> "hello \n there" 21 | "hello".chomp!("llo") #=> "he" 22 | */ 23 | describe(@"NSMutableString chompM", ^{ 24 | it(@"\"hello\".chomp #=> \"hello\"", ^{ 25 | NSMutableString *string = [NSMutableString stringWithString:@"hello"]; 26 | [string chompInPlace]; 27 | [[string should] equal:@"hello"]; 28 | }); 29 | it(@"\"hello\n\".chomp #=> \"hello\"", ^{ 30 | NSMutableString *string = [NSMutableString stringWithString:@"hello\n"]; 31 | [string chompInPlace]; 32 | [[string should] equal:@"hello"]; 33 | }); 34 | it(@"\"hello\r\n\".chomp #=> \"hello\r\"", ^{ 35 | NSMutableString *string = [NSMutableString stringWithString:@"hello\r\n"]; 36 | [string chompInPlace]; 37 | [[string should] equal:@"hello\r"]; 38 | }); 39 | it(@"\"hello\n\r\".chomp #=> \"hello\n\"", ^{ 40 | NSMutableString *string = [NSMutableString stringWithString:@"hello\n\r"]; 41 | [string chompInPlace]; 42 | [[string should] equal:@"hello\n"]; 43 | }); 44 | it(@"\"hello \n there\".chomp #=> \"hello \n there\"", ^{ 45 | NSMutableString *string = [NSMutableString stringWithString:@"hello \n there"]; 46 | [string chompInPlace]; 47 | [[string should] equal:@"hello \n there"]; 48 | }); 49 | it(@"\"hello\".chomp(\"llo\") #=> \"he\"", ^{ 50 | NSMutableString *string = [NSMutableString stringWithString:@"hello"]; 51 | [string chompInPlace:@"llo"]; 52 | [[string should] equal:@"he"]; 53 | }); 54 | }); 55 | 56 | /* 57 | "hello".delete!("l","lo") #=> "heo" 58 | "hello".delete!("lo") #=> "he" 59 | "hello".delete!("aeiou", "^e") #=> "hell" 60 | "hello".delete!("ej-m") #=> "ho" 61 | */ 62 | describe(@"NSMutableString deleteM", ^{ 63 | 64 | __block NSMutableString *a = nil; 65 | beforeEach(^{ 66 | a = [NSMutableString stringWithString:@"hello"]; 67 | }); 68 | 69 | it(@"a.delete(\"l\",\"lo\") #=> \"heo\"", ^{ 70 | [a deleteInPlace:@"l",@"lo",nil]; 71 | [[a should] equal:@"heo"]; 72 | }); 73 | it(@"a.delete(\"l\") #=> \"he\"", ^{ 74 | [a deleteInPlace:@"lo",nil]; 75 | [[a should] equal:@"he"]; 76 | }); 77 | it(@"a.delete(\"aeiou\",\"^e\") #=> \"hell\"", ^{ 78 | [a deleteInPlace:@"aeiou",@"^e",nil]; 79 | [[a should] equal:@"hell"]; 80 | }); 81 | it(@"a.delete(\"ej-m\") #=> \"ho\"", ^{ 82 | [a deleteInPlace:@"ej-m",nil]; 83 | [[a should] equal:@"ho"]; 84 | }); 85 | }); 86 | 87 | /* 88 | "hEllO".downcase! #=> "hello" 89 | */ 90 | describe(@"NSMutableString lowercaseM", ^{ 91 | it(@"a.downcase! #=> \"hello\"", ^{ 92 | NSMutableString *a = [NSMutableString stringWithString:@"hEllO"]; 93 | [a lowercaseInPlace]; 94 | [[a should] equal:@"hello"]; 95 | }); 96 | }); 97 | 98 | /* 99 | "hello".gsub!(%r[aeiou]/, '*') #=> "h*ll*" 100 | 'hello'.gsub!(%r[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*" 101 | */ 102 | describe(@"NSMutableString substituteAllM", ^{ 103 | 104 | __block NSMutableString *a = nil; 105 | beforeEach(^{ 106 | a = [NSMutableString stringWithString:@"hello"]; 107 | }); 108 | 109 | it(@"\"hello\".gsub!(%r[aeiou]/, '*') #=> \"h*ll*\"", ^{ 110 | [a substituteAllInPlace:@"[aeiou]" with:@"*"]; 111 | [[a should] equal:@"h*ll*"]; 112 | }); 113 | it(@"\"hello\".gsub!(%r[eo]/, 'e' => 3, 'o' => '*') #=> \"h3ll*\"", ^{ 114 | [a substituteAllInPlace:@{@"e" : @"3", 115 | @"o" : @"*"}]; 116 | [[a should] equal:@"h3ll*"]; 117 | }); 118 | }); 119 | 120 | /* 121 | " hello ".lstrip! #=> "hello " 122 | "hello".lstrip! #=> "hello" 123 | */ 124 | describe(@"NSMutableString leftStripM", ^{ 125 | it(@"\" hello \".lstrip! #=> \"hello \"", ^{ 126 | NSMutableString *a = [NSMutableString stringWithString:@" hello "]; 127 | [a leftStripInPlace]; 128 | [[a should] equal:@"hello "]; 129 | }); 130 | it(@"\" hello \".lstrip! #=> \"hello \"", ^{ 131 | NSMutableString *a = [NSMutableString stringWithString:@"hello"]; 132 | [a leftStripInPlace]; 133 | [[a should] equal:@"hello"]; 134 | }); 135 | }); 136 | 137 | /* 138 | "stressed".reverse! #=> "desserts" 139 | */ 140 | describe(@"NSMutableString reverseM", ^{ 141 | it(@"\"stressed\".reverse! #=> \"desserts\"", ^{ 142 | NSMutableString *a = [NSMutableString stringWithString:@"stressed"]; 143 | [a reverseInPlace]; 144 | [[a should] equal:@"desserts"]; 145 | }); 146 | }); 147 | 148 | /* 149 | " hello ".lstrip! #=> "hello " 150 | "hello".lstrip! #=> "hello" 151 | */ 152 | describe(@"NSMutableString rightStripM", ^{ 153 | it(@"\" hello \".rstrip! #=> \"hello \"", ^{ 154 | NSMutableString *a = [NSMutableString stringWithString:@" hello "]; 155 | [a rightStripInPlace]; 156 | [[a should] equal:@" hello"]; 157 | }); 158 | it(@"\" hello \".rstrip! #=> \"hello \"", ^{ 159 | NSMutableString *a = [NSMutableString stringWithString:@"hello"]; 160 | [a rightStripInPlace]; 161 | [[a should] equal:@"hello"]; 162 | }); 163 | }); 164 | 165 | /* 166 | "yellow moon".squeeze! #=> "yelow mon" 167 | " now is the".squeeze!(" ") #=> " now is the" 168 | "putters shoot balls".squeeze!("[m-z]") #=> "puters shot balls" 169 | */ 170 | describe(@"NSMutableString squeezeM", ^{ 171 | it(@"\"yellow moon\".squeeze!/, '*') #=> \"yelow mon\"", ^{ 172 | NSMutableString *a = [NSMutableString stringWithString:@"yellow moon"]; 173 | [a squeezeInPlace]; 174 | [[a should] equal:@"yelow mon"]; 175 | }); 176 | it(@"\" now is the\".squeeze!(\" \")/, '*') #=> \" now is the\"", ^{ 177 | NSMutableString *a = [NSMutableString stringWithString:@" now is the"]; 178 | [a squeezeInPlace:@" "]; 179 | [[a should] equal:@" now is the"]; 180 | }); 181 | it(@"\"putters shoot balls\".squeeze!(\"[m-z]\")/, '*') #=> \"puters shot balls\"", ^{ 182 | NSMutableString *a = [NSMutableString stringWithString:@"putters shoot balls"]; 183 | [a squeezeInPlace:@"[m-z]"]; 184 | [[a should] equal:@"puters shot balls"]; 185 | }); 186 | }); 187 | 188 | /* 189 | " hello ".strip! #=> "hello" 190 | "\tgoodbye\r\n".strip! #=> "goodbye" 191 | */ 192 | describe(@"NSMutableString stripM", ^{ 193 | it(@"\" hello \".strip! #=> \"hello\"", ^{ 194 | NSMutableString *a = [NSMutableString stringWithString:@" hello "]; 195 | [a stripInPlace]; 196 | [[a should] equal:@"hello"]; 197 | }); 198 | it(@"\"\\tgoodbye\\r\\n\".strip! #=> \"goodbye\"", ^{ 199 | NSMutableString *a = [NSMutableString stringWithString:@"\tgoodbye\r\n"]; 200 | [a stripInPlace]; 201 | [[a should] equal:@"goodbye"]; 202 | }); 203 | }); 204 | 205 | /* 206 | "hello".sub!(%r[aeiou]/, '*') #=> "h*llo" 207 | */ 208 | describe(@"NSString substituteFirst", ^{ 209 | it(@"\"hello\".sub!(%r[aeiou]/, '*') #=> \"h*llo\"", ^{ 210 | NSMutableString *a = [NSMutableString stringWithString:@"hello"]; 211 | [a substituteFirstInPlace:@"[aeiou]" with:@"*"]; 212 | [[a should] equal:@"h*llo"]; 213 | }); 214 | }); 215 | 216 | /* 217 | NB: This doesn't actually exist in Ruby. 218 | "hello".sublast!(%r[aeiou]/, '*') #=> "h*llo" 219 | */ 220 | describe(@"NSMutableString substituteLast", ^{ 221 | it(@"\"hello\".sublast!(%r[aeiou]/, '*') #=> \"hell*\"", ^{ 222 | NSMutableString *a = [NSMutableString stringWithString:@"hello"]; 223 | [a substituteLastInPlace:@"[aeiou]" with:@"*"]; 224 | [[a should] equal:@"hell*"]; 225 | }); 226 | }); 227 | 228 | /* 229 | "Hello".swapcase! #=> "hELLO" 230 | "cYbEr_PuNk11".swapcase! #=> "CyBeR_pUnK11" 231 | */ 232 | describe(@"NSMutableString swapCaseM", ^{ 233 | it(@"\"Hello\".swapcase! #=> \"hELLO\"", ^{ 234 | NSMutableString *a = [NSMutableString stringWithString:@"Hello"]; 235 | [a swapcaseInPlace]; 236 | [[a should] equal:@"hELLO"]; 237 | }); 238 | it(@"\"cYbEr_PuNk11\".swapcase! #=> \"CyBeR_pUnK11\"", ^{ 239 | NSMutableString *a = [NSMutableString stringWithString:@"cYbEr_PuNk11"]; 240 | [a swapcaseInPlace]; 241 | [[a should] equal:@"CyBeR_pUnK11"]; 242 | }); 243 | }); 244 | 245 | /* 246 | "hEllO".upcase! #=> "hello" 247 | */ 248 | describe(@"NSMutableString uppercaseM", ^{ 249 | it(@"a.upcase! #=> \"hello\"", ^{ 250 | NSMutableString *a = [NSMutableString stringWithString:@"hEllO"]; 251 | [a uppercaseInPlace]; 252 | [[a should] equal:@"HELLO"]; 253 | }); 254 | }); 255 | 256 | SPEC_END -------------------------------------------------------------------------------- /NSStringRubyTests/NSStringRubyTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | thingsdoer.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /NSStringRubyTests/NSStringRubyTests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #import 10 | #endif 11 | -------------------------------------------------------------------------------- /NSStringRubyTests/NSStringRubyTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import "NSString+Ruby.h" 3 | 4 | #pragma mark - Support 5 | 6 | @interface TestObject : NSObject 7 | @end 8 | 9 | @implementation TestObject 10 | 11 | -(NSString*)description{ 12 | return @"TestObjectDescription"; 13 | } 14 | 15 | @end 16 | 17 | #pragma mark - Tests 18 | 19 | SPEC_BEGIN(NSStringRubySpec) 20 | 21 | describe(@"NSString operator-likes, such as", ^{ 22 | /* 23 | "Ho! " * 3 #=> "Ho! Ho! Ho! " 24 | */ 25 | context(@"x aka(*)", ^{ 26 | it(@"\"Ho! \" * 3 #=> \"Ho! Ho! Ho! \"", ^{ 27 | [[[@"Ho! " x:3] should] equal:@"Ho! Ho! Ho! "]; 28 | }); 29 | it(@"should return empty strings the same", ^{ 30 | [[[@"" x:3] should] equal:@""]; 31 | }); 32 | }); 33 | /* 34 | "hello" + "world" #=> "hello world" 35 | "hello".concat(33) #=> "hello world!" 36 | */ 37 | context(@": aka(+)", ^{ 38 | it(@"\"hello\" + \"world\" #=> \"hello world\"", ^{ 39 | [[[@"hello ":@"world",nil] should] equal:@"hello world"]; 40 | }); 41 | it(@"\"hello \" + \"world\" + \"!\" #=> \"hello world\"", ^{ 42 | [[[@"hello ":@"world",@"!",nil] should] equal:@"hello world!"]; 43 | }); 44 | it(@"\"hello\".concat(33) #=> \"hello world!\"", ^{ 45 | [[[@"hello world":[NSNumber numberWithInt:33],nil] should] equal:@"hello world!"]; 46 | }); 47 | it(@"\"hello\" + TestObject #=> \"hello world!\"", ^{ 48 | TestObject *object = [[TestObject alloc] init]; 49 | [[[@"hello world ":object,nil] should] equal:@"hello world TestObjectDescription"]; 50 | }); 51 | }); 52 | }); 53 | 54 | /* 55 | a = "hello there" 56 | a[1] #=> "e" 57 | a[2, 3] #=> "llo" 58 | a[2..3] #=> "ll" 59 | a[-3, 2] #=> "er" 60 | a[7..-2] #=> "her" 61 | a[-4..-2] #=> "her" 62 | a[-2..-4] #=> nil 63 | a[12..-1] #=> nil 64 | a[%r[aeiou](.){2}] #=> "ell" 65 | a["lo"] #=> "lo" 66 | a["bye"] #=> nil 67 | */ 68 | describe(@"NSString []/{} accessors / ranges", ^{ 69 | NSString *a = @"hello there"; 70 | it(@"a[1] #=> \"e\"", ^{ 71 | [[a[1] should] equal:@"e"]; 72 | }); 73 | it(@"a[2, 3] #=> \"llo\"", ^{ 74 | [[[a:2:3] should] equal:@"llo"]; 75 | }); 76 | it(@"a[2..3] #=> \"ll\"", ^{ 77 | [[[a:2:"..":3] should] equal:@"ll"]; 78 | }); 79 | it(@"a[-3, 2] #=> \"er\"", ^{ 80 | [[[a:-3:2] should] equal:@"er"]; 81 | }); 82 | it(@"a[7..-2] #=> \"her\"", ^{ 83 | [[[a:7:"..":-2] should] equal:@"her"]; 84 | }); 85 | it(@"a[-2..-4] #=> nil", ^{ 86 | [[a:-2:"..":-4] shouldBeNil]; 87 | }); 88 | it(@"a[12..-1] #=> nil", ^{ 89 | [[a:12:"..":-1] shouldBeNil]; 90 | }); 91 | it(@"a[%r[aeiou](.){2}] #=> \"ell\"", ^{ 92 | [[a[@"[aeiou](.){2}"] should] equal:@"ell"]; 93 | }); 94 | it(@"a[\"lo\"] #=> \"lo\"", ^{ 95 | [[a[@"lo"] should] equal:@"lo"]; 96 | }); 97 | it(@"a[\"bye\"] #=> nil", ^{ 98 | [a[@"bye"] shouldBeNil]; 99 | }); 100 | }); 101 | 102 | //Methods 103 | 104 | describe(@"NSString bytes", ^{ 105 | it(@"should execute a block for each byte", ^{ 106 | NSMutableArray *bytes = [NSMutableArray array]; 107 | [@"hello world" bytes:^(unichar byte) { 108 | [bytes addObject:[NSNumber numberWithChar:byte]]; 109 | }]; 110 | [[theValue(bytes.count) should] equal:theValue(@"hello world".length)]; 111 | unichar *characters = calloc(@"hello world".length, sizeof(unichar)); 112 | [@"hello world" getCharacters:characters]; 113 | for(NSInteger i=0;i<@"hello world".length;i++){ 114 | unichar character = [[bytes objectAtIndex:i] charValue]; 115 | [[theValue(character) should] equal:theValue(characters[i])]; 116 | } 117 | }); 118 | }); 119 | 120 | /* 121 | "hello".center(4) #=> "hello" 122 | "hello".center(20) #=> " hello " 123 | "hello".center(20, '123') #=> "1231231hello12312312" 124 | */ 125 | describe(@"NSString center", ^{ 126 | it(@"\"hello\".center(4) #=> \"hello\"", ^{ 127 | [[[@"hello" center:4] should] equal:@"hello"]; 128 | }); 129 | it(@"\"hello\".center(20) #=> \" hello \"", ^{ 130 | [[[@"hello" center:20] should] equal:@" hello "]; 131 | }); 132 | it(@"\"hello\".center(20, '123') #=> \"1231231hello12312312\"", ^{ 133 | [[[@"hello" center:20 with:@"123"] should] equal:@"1231231hello12312312"]; 134 | }); 135 | }); 136 | 137 | describe(@"NSString chars", ^{ 138 | it(@"should execute a block for each char", ^{ 139 | NSMutableArray *chars = [NSMutableArray array]; 140 | [@"hello world" bytes:^(unichar chr) { 141 | [chars addObject:[NSNumber numberWithChar:chr]]; 142 | }]; 143 | [[theValue(chars.count) should] equal:theValue(@"hello world".length)]; 144 | unichar *characters = calloc(@"hello world".length, sizeof(unichar)); 145 | [@"hello world" getCharacters:characters]; 146 | for(NSInteger i=0;i<@"hello world".length;i++){ 147 | unichar character = [[chars objectAtIndex:i] charValue]; 148 | [[theValue(character) should] equal:theValue(characters[i])]; 149 | } 150 | free(characters); 151 | }); 152 | }); 153 | 154 | /* 155 | "hello".chomp #=> "hello" 156 | "hello\n".chomp #=> "hello" 157 | "hello\r\n".chomp #=> "hello" FAIL (\r\n is not recognized as a single carriage return character in obj-c) 158 | "hello\n\r".chomp #=> "hello\n" 159 | "hello\r".chomp #=> "hello" 160 | "hello \n there".chomp #=> "hello \n there" 161 | "hello".chomp("llo") #=> "he" 162 | */ 163 | describe(@"NSString chomp", ^{ 164 | it(@"\"hello\".chomp #=> \"hello\"", ^{ 165 | [[@"hello".chomp should] equal:@"hello"]; 166 | }); 167 | it(@"\"hello\n\".chomp #=> \"hello\"", ^{ 168 | [[@"hello\n".chomp should] equal:@"hello"]; 169 | }); 170 | it(@"\"hello\r\n\".chomp #=> \"hello\r\"", ^{ 171 | [[@"hello\r\n".chomp should] equal:@"hello\r"]; 172 | }); 173 | it(@"\"hello\n\r\".chomp #=> \"hello\n\"", ^{ 174 | [[@"hello\n\r".chomp should] equal:@"hello\n"]; 175 | }); 176 | it(@"\"hello \n there\".chomp #=> \"hello \n there\"", ^{ 177 | [[@"hello \n there".chomp should] equal:@"hello \n there"]; 178 | }); 179 | it(@"\"hello\".chomp(\"llo\") #=> \"he\"", ^{ 180 | [[[@"hello" chomp:@"llo"] should] equal:@"he"]; 181 | }); 182 | }); 183 | 184 | /* 185 | "string\r\n".chop #=> "string" FAIL (\r\n is not recognized as a single carriage return character in obj-c) 186 | "string\n\r".chop #=> "string\n" 187 | "string\n".chop #=> "string" 188 | "string".chop #=> "strin" 189 | "x".chop.chop #=> "" 190 | */ 191 | describe(@"NSString chop", ^{ 192 | it(@"\"string\r\n\".chop #=> \"string\r\"", ^{ 193 | [[@"string\r\n".chop should] equal:@"string\r"]; 194 | }); 195 | it(@"\"string\n\r\".chop #=> \"string\n\"", ^{ 196 | [[@"string\n\r".chop should] equal:@"string\n"]; 197 | }); 198 | it(@"\"string\n\".chop #=> \"string\"", ^{ 199 | [[@"string\n".chop should] equal:@"string"]; 200 | }); 201 | it(@"\"string\".chop #=> \"strin\"", ^{ 202 | [[@"string".chop should] equal:@"strin"]; 203 | }); 204 | it(@"\"x\".chop.chop #=> \"\"", ^{ 205 | [[@"x".chop.chop should] equal:@""]; 206 | }); 207 | }); 208 | 209 | /* 210 | "abcde".chr #=> "a" 211 | */ 212 | describe(@"NSString chr", ^{ 213 | it(@"\"abcde\".chr #=> \"a\"", ^{ 214 | [[@"abcde".chr should] equal:@"a"]; 215 | }); 216 | it(@"should fail gracefully on empty strings.", ^{ 217 | [[@"".chr should] equal:@""]; 218 | }); 219 | }); 220 | 221 | describe(@"NSString codepoints", ^{ 222 | it(@"should execute a block for each char", ^{ 223 | NSMutableArray *chars = [NSMutableArray array]; 224 | [@"hello world" codePoints:^(NSInteger i) { 225 | [chars addObject:[NSNumber numberWithLong:i]]; 226 | }]; 227 | [[theValue(chars.count) should] equal:theValue(@"hello world".length)]; 228 | unichar *characters = calloc(@"hello world".length, sizeof(unichar)); 229 | [@"hello world" getCharacters:characters]; 230 | for(NSInteger i=0;i<@"hello world".length;i++){ 231 | unichar character = [[chars objectAtIndex:i] charValue]; 232 | [[theValue(character) should] equal:theValue(characters[i])]; 233 | } 234 | free(characters); 235 | }); 236 | }); 237 | 238 | /* 239 | a = "hello world" 240 | a.count("lo") #=> 5 241 | a.count("lo", "o") #=> 2 242 | a.count("hello", "^l") #=> 4 243 | a.count("ej-m") #=> 4 244 | */ 245 | describe(@"NSString count", ^{ 246 | NSString *a = @"hello world"; 247 | it(@"a.count(\"lo\") #=> 5", ^{ 248 | NSInteger count = [a count:@"lo",nil]; 249 | [[theValue(count) should] equal:theValue(5)]; 250 | }); 251 | it(@"a.count(\"lo,\"o\"\") #=> 2", ^{ 252 | NSInteger count = [a count:@"lo",@"o",nil]; 253 | [[theValue(count) should] equal:theValue(2)]; 254 | }); 255 | it(@"a.count(\"hello\",\"^l\") #=> 4", ^{ 256 | NSInteger count = [a count:@"hello",@"^l",nil]; 257 | [[theValue(count) should] equal:theValue(4)]; 258 | }); 259 | it(@"a.count(\"ej-m\") #=> 4", ^{ 260 | NSInteger count = [a count:@"ej-m",nil]; 261 | [[theValue(count) should] equal:theValue(4)]; 262 | }); 263 | }); 264 | 265 | /* 266 | "hello".delete("l","lo") #=> "heo" 267 | "hello".delete("lo") #=> "he" 268 | "hello".delete("aeiou", "^e") #=> "hell" 269 | "hello".delete("ej-m") #=> "ho" 270 | */ 271 | describe(@"NSString delete", ^{ 272 | NSString *a = @"hello"; 273 | it(@"a.delete(\"l\",\"lo\") #=> \"heo\"", ^{ 274 | NSString *s = [a delete:@"l",@"lo",nil]; 275 | [[s should] equal:@"heo"]; 276 | }); 277 | it(@"a.delete(\"l\") #=> \"he\"", ^{ 278 | NSString *s = [a delete:@"lo",nil]; 279 | [[s should] equal:@"he"]; 280 | }); 281 | it(@"a.delete(\"aeiou\",\"^e\") #=> \"hell\"", ^{ 282 | NSString *s = [a delete:@"aeiou",@"^e",nil]; 283 | [[s should] equal:@"hell"]; 284 | }); 285 | it(@"a.delete(\"ej-m\") #=> \"ho\"", ^{ 286 | NSString *s = [a delete:@"ej-m",nil]; 287 | [[s should] equal:@"ho"]; 288 | }); 289 | }); 290 | 291 | describe(@"NSString endsWith", ^{ 292 | it(@"should return true if the string ends with any of the provided strings.", ^{ 293 | BOOL result = [@"hello world" endsWith:@"hello",@"wrold",@"orld",nil]; 294 | [[theValue(result) should] equal:theValue(YES)]; 295 | }); 296 | }); 297 | 298 | /* 299 | "0x0a".hex #=> 10 300 | "-1234".hex #=> -4660 301 | "0".hex #=> 0 302 | "wombat".hex #=> 0 303 | */ 304 | describe(@"NSString hex", ^{ 305 | it(@"'0x0a'.hex #=> 10", ^{ 306 | [[theValue(@"0x0a".hex) should] equal:theValue(10)]; 307 | }); 308 | it(@"'-1234'.hex #=> -4660", ^{ 309 | [[theValue(@"0x0a".hex) should] equal:theValue(10)]; 310 | }); 311 | it(@"'0'.hex #=> 0", ^{ 312 | [[theValue(@"0x0a".hex) should] equal:theValue(10)]; 313 | }); 314 | it(@"'wombat'.hex #=> 0", ^{ 315 | [[theValue(@"0x0a".hex) should] equal:theValue(10)]; 316 | }); 317 | }); 318 | 319 | /* 320 | "hello".include? "lo" #=> true 321 | "hello".include? "ol" #=> false 322 | "hello".include? h #=> true 323 | */ 324 | describe(@"NSString include", ^{ 325 | it(@"'hello'.include? 'lo' #=> true", ^{ 326 | [[theValue([@"hello" includes:@"lo"]) should] equal:theValue(YES)]; 327 | }); 328 | it(@"'hello'.include? 'ol' #=> false", ^{ 329 | [[theValue([@"hello" includes:@"ol"]) should] equal:theValue(NO)]; 330 | }); 331 | it(@"'hello'.include? 'h' #=> true", ^{ 332 | [[theValue([@"hello" includes:@"h"]) should] equal:theValue(YES)]; 333 | }); 334 | }); 335 | 336 | /* 337 | "cat o' 9 tails" =~ %r\d/ #=> 7 338 | "cat o' 9 tails" =~ "nope" #=> nil 339 | "hello".index('e') #=> 1 340 | "hello".index('lo') #=> 3 341 | "hello".index('a') #=> nil 342 | "hello".index(%r[aeiou]/, -3) #=> 4 343 | */ 344 | describe(@"NSString index", ^{ 345 | it(@"\"cat o' 9 tails\" =~ %r\\d/ #=> 7", ^{ 346 | [[theValue([@"cat o' 9 tails" index:@"\\d"]) should] equal:theValue(7)]; 347 | }); 348 | it(@"\"cat o' 9 tails\" =~ \"nope\" #=> nil", ^{ 349 | [[theValue([@"cat o' 9 tails" index:@"nope"]) should] equal:theValue(NSNotFound)]; 350 | }); 351 | it(@"\"hello\".index('e') #=> 1", ^{ 352 | [[theValue([@"hello" index:@"e"]) should] equal:theValue(1)]; 353 | }); 354 | it(@"\"hello\".index('lo') #=> 3", ^{ 355 | [[theValue([@"hello" index:@"lo"]) should] equal:theValue(3)]; 356 | }); 357 | it(@"\"hello\".index('a') #=> nil", ^{ 358 | [[theValue([@"hello" index:@"a"]) should] equal:theValue(NSNotFound)]; 359 | }); 360 | it(@"\"hello\".index(%r[aeiou]/, -3) #=> 4", ^{ 361 | [[theValue([@"hello" index:@"[aeiou]" offset:-3]) should] equal:theValue(4)]; 362 | }); 363 | }); 364 | 365 | /* 366 | "abcd".insert(0, 'X') #=> "Xabcd" 367 | "abcd".insert(3, 'X') #=> "abcXd" 368 | "abcd".insert(4, 'X') #=> "abcdX" 369 | "abcd".insert(-3, 'X') #=> "abXcd" 370 | "abcd".insert(-1, 'X') #=> "abcdX" 371 | */ 372 | describe(@"NSString insert", ^{ 373 | it(@"'abcd'.insert(0, 'X') #=> 'Xabcd'", ^{ 374 | [[[@"abcd" insert:0 string:@"X"] should] equal:@"Xabcd"]; 375 | }); 376 | it(@"'abcd'.insert(3, 'X') #=> 'abcXd'", ^{ 377 | [[[@"abcd" insert:3 string:@"X"] should] equal:@"abcXd"]; 378 | }); 379 | it(@"'abcd'.insert(4, 'X') #=> 'abcdX'", ^{ 380 | [[[@"abcd" insert:4 string:@"X"] should] equal:@"abcdX"]; 381 | }); 382 | it(@"'abcd'.insert(-3, 'X') #=> 'abXcd'", ^{ 383 | [[[@"abcd" insert:-3 string:@"X"] should] equal:@"abXcd"]; 384 | }); 385 | it(@"'abcd'.insert(-1, 'X') #=> 'abXcd'", ^{ 386 | [[[@"abcd" insert:-1 string:@"X"] should] equal:@"abcdX"]; 387 | }); 388 | }); 389 | 390 | /* 391 | "hel\blo".inspect #=> "\"hel\\blo\"" 392 | */ 393 | describe(@"NSString inspect", ^{ 394 | it(@"\"hel\blo\".inspect #=> \"\"hel\\blo\"\"", ^{ 395 | [[[@"hel\blo" inspect] should] equal:@"\"hel\\blo\""]; 396 | }); 397 | }); 398 | 399 | /* 400 | "abc".ascii_only? #=> true 401 | "abc\u{6666}".ascii_only? #=> false 402 | */ 403 | describe(@"NSString isASCII", ^{ 404 | it(@"\"abc\".ascii_only? #=> true.", ^{ 405 | [[theValue(@"abc".isASCII) should] equal:theValue(YES)]; 406 | }); 407 | it(@"\"abc\\u{6666}\".ascii_only? #=> false.", ^{ 408 | [[theValue(@"abc\u6666".isASCII) should] equal:theValue(NO)]; 409 | }); 410 | }); 411 | 412 | /* 413 | "hello".empty? #=> false 414 | "".empty? #=> true 415 | */ 416 | describe(@"NSString isEmpty", ^{ 417 | it(@"\"hello\".empty? #=> false.", ^{ 418 | [[theValue(@"hello".isEmpty) should] equal:theValue(NO)]; 419 | }); 420 | it(@"\"\".empty? #=> true.", ^{ 421 | [[theValue(@"".isEmpty) should] equal:theValue(YES)]; 422 | }); 423 | }); 424 | 425 | /* 426 | "hello".ljust(4) #=> "hello" 427 | "hello".ljust(20) #=> "hello " 428 | "hello".ljust(20, '1234') #=> "hello123412341234123" 429 | */ 430 | describe(@"NSString leftJustify", ^{ 431 | it(@"\"hello\".ljust(4) #=> \"hello\"", ^{ 432 | [[[@"hello" leftJustify:4] should] equal:@"hello"]; 433 | }); 434 | it(@"\"hello\".ljust(20) #=> \"hello \"", ^{ 435 | [[[@"hello" leftJustify:20] should] equal:@"hello "]; 436 | }); 437 | it(@"\"hello\".ljust(20, '1234') #=> \"hello123412341234123\"", ^{ 438 | [[[@"hello" leftJustify:20 with:@"1234"] should] equal:@"hello123412341234123"]; 439 | }); 440 | }); 441 | 442 | /* 443 | " hello ".lstrip #=> "hello " 444 | "hello".lstrip #=> "hello" 445 | */ 446 | describe(@"NSString leftStrip", ^{ 447 | it(@"\" hello \".lstrip #=> \"hello \"", ^{ 448 | [[[@" hello " leftStrip] should] equal:@"hello "]; 449 | }); 450 | it(@"\" hello \".lstrip #=> \"hello \"", ^{ 451 | [[[@"hello" leftStrip] should] equal:@"hello"]; 452 | }); 453 | }); 454 | 455 | describe(@"NSString lines", ^{ 456 | it(@"should execute a block on each line by default", ^{ 457 | NSMutableArray *lines = [NSMutableArray array]; 458 | [@"hello\nworld" lines:^(NSString *line) { 459 | [lines addObject:line]; 460 | }]; 461 | [[theValue(lines.count) should] equal:theValue(2)]; 462 | [[[lines objectAtIndex:0] should] equal:@"hello"]; 463 | [[[lines objectAtIndex:1] should] equal:@"world"]; 464 | }); 465 | it(@"should execute a block on each chunk seperated by a provided separator", ^{ 466 | NSMutableArray *lines = [NSMutableArray array]; 467 | [@"hello!world" lines:^(NSString *line) { 468 | [lines addObject:line]; 469 | } separator:@"!"]; 470 | [[theValue(lines.count) should] equal:theValue(2)]; 471 | [[[lines objectAtIndex:0] should] equal:@"hello"]; 472 | [[[lines objectAtIndex:1] should] equal:@"world"]; 473 | }); 474 | }); 475 | 476 | /* 477 | 'hello'.match('(.){1}') #=> ["h","e","l","l","o"] 478 | 'hello'.match('(.){1}')[0] #=> "h" 479 | 'hello'.match(%r[aeiou](.){2})[0]#=> "ell" 480 | 'hello'.match('xx') #=> [] 481 | */ 482 | describe(@"NSString match", ^{ 483 | it(@"'hello'.match('(.){1}') #=> [\"l\"]", ^{ 484 | [[[@"hello" match:@"(.){1}"] should] equal:@[@"h",@"e",@"l",@"l",@"o"]]; 485 | }); 486 | it(@"'hello'.match('(.){1}') #=> [\"l\"]", ^{ 487 | [[[@"hello" match:@"(.){1}"][0] should] equal:@"h"]; 488 | }); 489 | it(@"'hello'.match('([aeiou](.){2})') #=> [\"ell\"]", ^{ 490 | [[[@"hello" match:@"([aeiou](.){2})"][0] should] equal:@"ell"]; 491 | }); 492 | it(@"'hello'.match('xx') #=> nil", ^{ 493 | [[[@"hello" match:@"xx"] should] equal:@[]]; 494 | }); 495 | }); 496 | 497 | /* 498 | "123".oct #=> 83 499 | "-377".oct #=> -255 500 | "bad".oct #=> 0 501 | "0377bad".oct #=> 255 502 | */ 503 | describe(@"NSString octal", ^{ 504 | it(@"'123'.oct #=> 83", ^{ 505 | [[theValue(@"123".octal) should] equal:theValue(83)]; 506 | }); 507 | it(@"'-377'.oct #=> -255", ^{ 508 | [[theValue(@"-377".octal) should] equal:theValue(-255)]; 509 | }); 510 | it(@"'bad'.oct #=> 0", ^{ 511 | [[theValue(@"bad".octal) should] equal:theValue(0)]; 512 | }); 513 | it(@"'0377bad'.hex #=> 255", ^{ 514 | [[theValue(@"0377bad".octal) should] equal:theValue(255)]; 515 | }); 516 | }); 517 | 518 | /* 519 | "a".ord #=> 97 520 | */ 521 | describe(@"NSString ordinal", ^{ 522 | it(@"'a'.ord #=> 97", ^{ 523 | [[theValue(@"a".ordinal) should] equal:theValue(97)]; 524 | }); 525 | }); 526 | 527 | /* 528 | "hello".partition("l") #=> ["he", "l", "lo"] 529 | "hello".partition("x") #=> ["hello", "", ""] 530 | "hello".partition(%r.l/) #=> ["h", "el", "lo"] 531 | */ 532 | describe(@"NSString partition", ^{ 533 | it(@"\"hello\".partition(\"l\") #=> [\"he\", \"l\", \"lo\"]", ^{ 534 | NSArray *result = [@"hello" partition:@"l"]; 535 | [[result should] equal:@[@"he",@"l",@"lo"]]; 536 | }); 537 | it(@"\"hello\".partition(\"x\") #=> [\"hello\", \"\", \"\"]", ^{ 538 | NSArray *result = [@"hello" partition:@"x"]; 539 | [[result should] equal:@[@"hello",@"",@""]]; 540 | }); 541 | it(@"\"hello\".partition(\"%r.l\") #=> [\"h\", \"el\", \"lo\"]", ^{ 542 | NSArray *result = [@"hello" partition:@".l"]; 543 | [[result should] equal:@[@"h",@"el",@"lo"]]; 544 | }); 545 | }); 546 | 547 | /* 548 | "world".prepend(“hello ”) #=> “hello world” 549 | */ 550 | describe(@"NSString prepend", ^{ 551 | it(@"\"world\".prepend(“hello ”) #=> \"hello world\"", ^{ 552 | [[[@"world" prepend:@"hello " ] should] equal:@"hello world"]; 553 | }); 554 | }); 555 | 556 | /* 557 | "stressed".reverse #=> "desserts" 558 | */ 559 | describe(@"NSString reverse", ^{ 560 | it(@"\"stressed\".reverse #=> \"desserts\"", ^{ 561 | [[@"stressed".reverse should] equal:@"desserts"]; 562 | }); 563 | }); 564 | 565 | /* 566 | "hello".rindex('e') #=> 1 567 | "hello".rindex('lo') #=> 3 568 | "hello".rindex('a') #=> nil 569 | "hello".rindex(%r[aeiou]/, -2) #=> 1 570 | */ 571 | describe(@"NSString rightIndex", ^{ 572 | it(@"\"hello\".rindex('e') #=> 1", ^{ 573 | [[theValue([@"hello" rightIndex:@"e"]) should] equal:theValue(1)]; 574 | }); 575 | it(@"\"hello\".rindex('lo') #=> 3", ^{ 576 | [[theValue([@"hello" rightIndex:@"lo"]) should] equal:theValue(3)]; 577 | }); 578 | it(@"\"hello\".rindex('a') #=> nil", ^{ 579 | [[theValue([@"hello" rightIndex:@"a"]) should] equal:theValue(NSNotFound)]; 580 | }); 581 | it(@"\"hello\".rindex(%r[aeiou]/, -2) #=> 1", ^{ 582 | [[theValue([@"hello" rightIndex:@"[aeiou]" offset:-2]) should] equal:theValue(1)]; 583 | }); 584 | }); 585 | 586 | /* 587 | "hello".rjust(4) #=> "hello" 588 | "hello".rjust(20) #=> " hello" 589 | "hello".rjust(20, '1234') #=> "123412341234123hello" 590 | */ 591 | describe(@"NSString rightJustify", ^{ 592 | it(@"\"hello\".rjust(4) #=> \"hello\"", ^{ 593 | [[[@"hello" rightJustify:4] should] equal:@"hello"]; 594 | }); 595 | it(@"\"hello\".rjust(20) #=> \" hello\"", ^{ 596 | [[[@"hello" rightJustify:20] should] equal:@" hello"]; 597 | }); 598 | it(@"\"hello\".rjust(20, '1234') #=> \"123412341234123hello\"", ^{ 599 | [[[@"hello" rightJustify:20 with:@"1234"] should] equal:@"123412341234123hello"]; 600 | }); 601 | }); 602 | 603 | /* 604 | " hello ".lstrip #=> "hello " 605 | "hello".lstrip #=> "hello" 606 | */ 607 | describe(@"NSString rightStrip", ^{ 608 | it(@"\" hello \".rstrip #=> \"hello \"", ^{ 609 | [[[@" hello " rightStrip] should] equal:@" hello"]; 610 | }); 611 | it(@"\" hello \".rstrip #=> \"hello \"", ^{ 612 | [[[@"hello" rightStrip] should] equal:@"hello"]; 613 | }); 614 | }); 615 | 616 | /* 617 | "hello".rpartition("l") #=> ["hel", "l", "o"] 618 | "hello".rpartition("x") #=> ["", "", "hello"] 619 | "hello".rpartition(%r.l/) #=> ["he", "ll", "o"] 620 | */ 621 | describe(@"NSString rpartition", ^{ 622 | it(@"\"hello\".rpartition(\"l\") #=> [\"hel\", \"l\", \"o\"]", ^{ 623 | NSArray *result = [@"hello" rightPartition:@"l"]; 624 | [[result should] equal:@[@"hel",@"l",@"o"]]; 625 | }); 626 | it(@"\"hello\".rpartition(\"x\") #=> [\"\", \"\", \"hello\"]", ^{ 627 | NSArray *result = [@"hello" rightPartition:@"x"]; 628 | [[result should] equal:@[@"",@"",@"hello"]]; 629 | }); 630 | it(@"\"hello\".rpartition(\"%rl.\") #=> [\"he\", \"ll\", \"o\"]", ^{ 631 | NSArray *result = [@"hello" rightPartition:@"l."]; 632 | [[result should] equal:@[@"he",@"ll",@"o"]]; 633 | }); 634 | }); 635 | 636 | /* 637 | a = "cruel world" 638 | a.scan(%r\w+/) #=> ["cruel", "world"] 639 | a.scan(%r.../) #=> ["cru", "el ", "wor"] 640 | */ 641 | describe(@"NSString scan", ^{ 642 | NSString *a = @"cruel world"; 643 | it(@"a.scan(%r\\w+/) #=> [\"cruel\", \"world\"]", ^{ 644 | NSArray *result = [a scan:@"\\w+"]; 645 | [[result should] equal:@[@"cruel",@"world"]]; 646 | }); 647 | it(@"a.scan(%r.../) #=> [\"cruel\", \"world\"]", ^{ 648 | NSArray *result = [a scan:@"..."]; 649 | [[result should] equal:@[@"cru",@"el ",@"wor"]]; 650 | }); 651 | }); 652 | 653 | /* 654 | " now's the time".split #=> ["now's", "the", "time"] 655 | " now's the time".split(' ') #=> ["now's", "the", "time"] 656 | " now's the time".split(%r /) #=> ["", "now's", "", "the", "time"] 657 | "1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"] 658 | "hello".split(%r/) #=> ["h", "e", "l", "l", "o"] 659 | "hello".split(%r/, 3) #=> ["h", "e", "llo"] 660 | "hi mom".split(%r{\s*}) #=> ["h", "i", "m", "o", "m"] 661 | 662 | "mellow yellow".split("ello") #=> ["m", "w y", "w"] 663 | "1,2,,3,4,,".split(',') #=> ["1", "2", "", "3", "4"] 664 | "1,2,,3,4,,".split(',', 4) #=> ["1", "2", "", "3,4,,"] 665 | "1,2,,3,4,,".split(',', -4) #=> ["1", "2", "", "3", "4", "", ""] 666 | */ 667 | describe(@"NSString split", ^{ 668 | it(@"\" now's the time\".split #=> [\"now's\", \"the\", \"time\"]", ^{ 669 | NSArray *result = [@" now's the time" split]; 670 | [[result should] equal:@[@"now's",@"the",@"time"]]; 671 | }); 672 | it(@"\" now's the time\".split(' ') #=> [\"now's\", \"the\", \"time\"]", ^{ 673 | NSArray *result = [@" now's the time" split:@" "]; 674 | [[result should] equal:@[@"now's",@"the",@"time"]]; 675 | }); 676 | it(@"\" now's the time\".split('%r /') #=> [\"now's\", \"the\", \"time\"]", ^{ 677 | NSArray *result = [@" now's the time" split:@"( )"]; 678 | [[result should] equal:@[@"",@"now's",@"",@"the",@"time"]]; 679 | }); 680 | it(@"\"1, 2.34,56, 7\".split('%r{,\\s*}') #=> [\"1\", \"2.34\", \"56\", \"7\"]", ^{ 681 | NSArray *result = [@"1, 2.34,56, 7" split:@",\\s*"]; 682 | [[result should] equal:@[@"1",@"2.34",@"56",@"7"]]; 683 | }); 684 | it(@"\"hello\".split('%r/') #=> [\"h\", \"e\", \"l\", \"l\", \"o\"]", ^{ 685 | NSArray *result = [@"hello" split:@""]; 686 | [[result should] equal:@[@"h",@"e",@"l",@"l",@"o"]]; 687 | }); 688 | it(@"\"hello\".split('%r/',3) #=> [\"h\", \"e\", \"llo\"]", ^{ 689 | NSArray *result = [@"hello" split:@"" limit:3]; 690 | [[result should] equal:@[@"h",@"e",@"llo"]]; 691 | }); 692 | it(@"\"hi mom\".split('%r{\\s*}') #=> [\"h\", \"i\", \"m\", \"o\", \"m\"]", ^{ 693 | NSArray *result = [@"hi mom" split:@"\\s*"]; 694 | [[result should] equal:@[@"h",@"i",@"m",@"o",@"m"]]; 695 | }); 696 | it(@"\"mellow yellow\".split('ello') #=> [\"m\", \"w y\", \"w\"]", ^{ 697 | NSArray *result = [@"mellow yellow" split:@"ello"]; 698 | [[result should] equal:@[@"m",@"w y",@"w"]]; 699 | }); 700 | it(@"\"1,2,,3,4,,\".split(',') #=> [\"1\", \"2\", \"\", \"3\", \"4\"]", ^{ 701 | NSArray *result = [@"1,2,,3,4,," split:@","]; 702 | [[result should] equal:@[@"1",@"2",@"",@"3",@"4"]]; 703 | }); 704 | it(@"\"1,2,,3,4,,\".split(',',4) #=> [\"1\", \"2\", \"\", \"3,4,,\"]", ^{ 705 | NSArray *result = [@"1,2,,3,4,," split:@"," limit:4]; 706 | [[result should] equal:@[@"1",@"2",@"",@"3,4,,"]]; 707 | }); 708 | it(@"\"1,2,,3,4,,\".split(',',-4) #=> [\"1\", \"2\", \"\", \"3\", \"4\", \"\", \"\"]", ^{ 709 | NSArray *result = [@"1,2,,3,4,," split:@"," limit:-4]; 710 | [[result should] equal:@[@"1",@"2",@"",@"3",@"4",@"",@""]]; 711 | }); 712 | }); 713 | 714 | describe(@"NSString split (additional)", ^{ 715 | it(@"\"gesges 7774b14 abcdef\".split(' ') #=> [\"gesges\", \"7774b14\", \"abcdef\"]", ^{ 716 | NSArray *result = [@"gesges 7774b14 abcdef" split:@" "]; 717 | [[result should] equal:@[@"gesges",@"7774b14",@"abcdef"]]; 718 | }); 719 | }); 720 | 721 | /* 722 | "yellow moon".squeeze #=> "yelow mon" 723 | " now is the".squeeze(" ") #=> " now is the" 724 | "putters shoot balls".squeeze("[m-z]") #=> "puters shot balls" 725 | */ 726 | describe(@"NSString squeeze", ^{ 727 | it(@"\"yellow moon\".squeeze/, '*') #=> \"yelow mon\"", ^{ 728 | [[[@"yellow moon" squeeze] should] equal:@"yelow mon"]; 729 | }); 730 | it(@"\" now is the\".squeeze(\" \")/, '*') #=> \" now is the\"", ^{ 731 | [[[@" now is the" squeeze:@" "] should] equal:@" now is the"]; 732 | }); 733 | it(@"\"putters shoot balls\".squeeze(\"[m-z]\")/, '*') #=> \"puters shot balls\"", ^{ 734 | [[[@"putters shoot balls" squeeze:@"[m-z]"] should] equal:@"puters shot balls"]; 735 | }); 736 | }); 737 | 738 | /* 739 | "hello".start_with?("hell") #=> true 740 | "hello".start_with?("heaven", "hell") #=> true 741 | "hello".start_with?("heaven", "paradise") #=> false 742 | */ 743 | describe(@"NSString startsWith", ^{ 744 | it(@"\"hello\".starts_with?(\"hell\") #=> true.", ^{ 745 | [[theValue([@"hello" startsWith:@"hell"]) should] equal:theValue(YES)]; 746 | }); 747 | it(@"\"hello\".starts_with?(\"heaven\",\"hell\") #=> true.", ^{ 748 | BOOL result = [@"hello" startsWith:@"heaven",@"hell",nil]; 749 | [[theValue(result) should] equal:theValue(YES)]; 750 | }); 751 | it(@"\"hello\".starts_with?(\"heaven\",\"paradise\") #=> false.", ^{ 752 | BOOL result = [@"hello" startsWith:@"heaven",@"paradise",nil]; 753 | [[theValue(result) should] equal:theValue(NO)]; 754 | }); 755 | }); 756 | 757 | /* 758 | " hello ".strip #=> "hello" 759 | "\tgoodbye\r\n".strip #=> "goodbye" 760 | */ 761 | describe(@"NSString strip", ^{ 762 | it(@"\" hello \".strip #=> \"hello\"", ^{ 763 | [[[@" hello " strip] should] equal:@"hello"]; 764 | }); 765 | it(@"\"\\tgoodbye\\r\\n\".strip #=> \"goodbye\"", ^{ 766 | [[[@"\tgoodbye\r\n" strip] should] equal:@"goodbye"]; 767 | }); 768 | }); 769 | 770 | /* 771 | "hello".gsub(%r[aeiou]/, '*') #=> "h*ll*" 772 | 'hello'.gsub(%r[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*" 773 | */ 774 | describe(@"NSString substituteAll", ^{ 775 | it(@"\"hello\".gsub(%r[aeiou]/, '*') #=> \"h*ll*\"", ^{ 776 | [[[@"hello" substituteAll:@"[aeiou]" with:@"*"] should] equal:@"h*ll*"]; 777 | }); 778 | it(@"\"hello\".gsub(%r[eo]/, 'e' => 3, 'o' => '*') #=> \"h3ll*\"", ^{ 779 | [[[@"hello" substituteAll:@{@"e" : @"3", 780 | @"o" : @"*"}] should] equal:@"h3ll*"]; 781 | }); 782 | }); 783 | 784 | /* 785 | "hello".sub(%r[aeiou]/, '*') #=> "h*llo" 786 | */ 787 | describe(@"NSString substituteFirst", ^{ 788 | it(@"\"hello\".sub(%r[aeiou]/, '*') #=> \"h*llo\"", ^{ 789 | [[[@"hello" substituteFirst:@"[aeiou]" with:@"*"] should] equal:@"h*llo"]; 790 | }); 791 | }); 792 | 793 | /* 794 | NB: This doesn't actually exist in Ruby. 795 | "hello".sublast(%r[aeiou]/, '*') #=> "h*llo" 796 | */ 797 | describe(@"NSString substituteLast", ^{ 798 | it(@"\"hello\".sublast(%r[aeiou]/, '*') #=> \"hell*\"", ^{ 799 | [[[@"hello" substituteLast:@"[aeiou]" with:@"*"] should] equal:@"hell*"]; 800 | }); 801 | }); 802 | 803 | /* 804 | "hello".sum #=> 532 805 | "hello".sum(8) #=> 20 806 | */ 807 | describe(@"NSString sum", ^{ 808 | it(@"\"hello\".sum #=> 532", ^{ 809 | [[theValue([@"hello" sum]) should] equal:theValue(532)]; 810 | }); 811 | it(@"\"hello\".sum(8) #=> 20", ^{ 812 | [[theValue([@"hello" sum:8]) should] equal:theValue(20)]; 813 | }); 814 | }); 815 | 816 | /* 817 | "Hello".swapcase #=> "hELLO" 818 | "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11" 819 | */ 820 | describe(@"NSString swapCase", ^{ 821 | it(@"\"Hello\".swapcase #=> \"hELLO\"", ^{ 822 | [[[@"Hello" swapcase] should] equal:@"hELLO"]; 823 | }); 824 | it(@"\"cYbEr_PuNk11\".swapcase #=> \"CyBeR_pUnK11\"", ^{ 825 | [[[@"cYbEr_PuNk11" swapcase] should] equal:@"CyBeR_pUnK11"]; 826 | }); 827 | }); 828 | 829 | SPEC_END -------------------------------------------------------------------------------- /NSStringRubyTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | target :NSStringRubyTests, :exclusive => true do 2 | pod 'Kiwi/XCTest' 3 | end 4 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Kiwi/ARC (2.2.2) 3 | - Kiwi/NonARC (2.2.2) 4 | - Kiwi/XCTest (2.2.2): 5 | - Kiwi/ARC 6 | - Kiwi/NonARC 7 | 8 | DEPENDENCIES: 9 | - Kiwi/XCTest 10 | 11 | SPEC CHECKSUMS: 12 | Kiwi: 03539aeb004ccd42bdbc31253617b26364315df4 13 | 14 | COCOAPODS: 0.29.0 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NSString+Ruby [![Build Status](https://travis-ci.org/zdavison/NSString-Ruby.png?branch=master)](https://travis-ci.org/zdavison/NSString-Ruby) 2 | ==================== 3 | 4 | Intro 5 | --------------------- 6 | NSString+Ruby is an attempt to improve NSString by porting Ruby String methods onto a category on NSString. 7 | This means you can use the majority of Ruby String methods in obj-c, with the exception of a few unnecessary, and 8 | unimplimented (as of yet). 9 | 10 | Next Improvements 11 | --------------------- 12 | Even better format/concat options 13 | Ruby style block execution 14 | 15 | Differences / Important notes 16 | --------------------- 17 | Changes have been made to method names, mostly to line up with traditional objective-c naming conventions, the rule 18 | generally being that all shorthand words have been extended to their full equivalent (eg: rStrip is rightStrip). 19 | 20 | Original methods provided by objective-c are not aliased to Ruby equivalents. 21 | 22 | Blocks are available for some methods, and not others, mostly for language paradigm reasons. 23 | 24 | Operator overloading has been mimicked to the best of our ability, using clever shorthand and unnamed methods, 25 | the equivalent of the concatenation operator (+), would be (:) in NSString+Ruby, as follows: 26 | 27 | ```ruby 28 | "hello " + "world" #=>"hello world" 29 | ``` 30 | 31 | ```objective-c 32 | [@"hello ":@"world",nil]; //"hello world" 33 | ``` 34 | 35 | This is still a little ugly, but is the least amount of code you'd need to write in obj-c to do concatenation now. 36 | 37 | Array/index style accessors are provided through: 38 | 39 | ```objective-c 40 | -(id)objectAtIndexedSubscript:(NSUInteger)index; 41 | -(id)objectForKeyedSubscript:(id)key; 42 | ``` 43 | 44 | ...and provide for the majority of Ruby style functionality, the following Ruby methods, for example, are all implemented: 45 | 46 | ```ruby 47 | (Ruby) 48 | a = "hello there" 49 | a[1] #=> "e" 50 | a[2, 3] #=> "llo" 51 | a[-3, 2] #=> "er" 52 | a[2..3] #=> "ll" 53 | a[7..-2] #=> "her" 54 | a[-4..-2] #=> "her" 55 | a[-2..-4] #=> nil 56 | a[12..-1] #=> nil 57 | a[%r[aeiou](.){2}] #=> "ell" 58 | a["lo"] #=> "lo" 59 | a["bye"] #=> nil 60 | ``` 61 | 62 | ```objective-c 63 | NSString *a = @"hello there"; 64 | a[1]; // "e" 65 | [a:2:3]; // "llo" 66 | [a:-3:2]; // "er" 67 | ``` 68 | 69 | Ranges are provided through C-string shorthand and nameless methods, allowing you to write the following: 70 | 71 | ```objective-c 72 | NSString *a = @"hello there"; 73 | [a:2:"..":3]; // "ll" 74 | [a:7:"..":-2]; // "her" 75 | [a:-4:"..":-2] // "her" 76 | [a:-2:"..":-4] // nil 77 | [a:12:"..":-1] // nil 78 | ``` 79 | 80 | Regex matching also works, and is provided as the primary means of matching, almost anything that takes a string 81 | can take a regex pattern. 82 | 83 | ```objective-c 84 | NSString *a = @"hello there"; 85 | a[@"[aeiou](.){2}"] // ell 86 | a["lo"] // lo 87 | a["bye"] // nil 88 | ``` 89 | 90 | iOS Requirements / ARC Status 91 | --------------------- 92 | NSString+Ruby requires iOS 5.0+, and is ARC enabled. 93 | 94 | Installation 95 | --------------------- 96 | Installation can be done using [CocoaPods](http://cocoapods.org): 97 | add `pod 'NSString+Ruby'` to your `Podfile`, then run `pod install`. 98 | 99 | Tests 100 | --------------------- 101 | Tests are provided through Kiwi ( https://github.com/allending/Kiwi ), and are largely reproduced from the Ruby String 102 | Reference page ( http://www.ruby-doc.org/core-1.9.3/String.html ), some methods may be changed slightly 103 | in how they function, but for the most part the goal is to ape Ruby behaviour. 104 | 105 | NSMutableString 106 | --------------------- 107 | NSMutableString has mutating versions of all the usual destructive methods. The modifier `InPlace` 108 | is used to signify a mutating/destructive method, vs the Ruby `!` bang modifier. 109 | 110 | 111 | 112 | 113 | 114 | # Method List 115 | 116 | Here is a full equivalence list of methods provided (Notes are provided in brackets for when things are purposefully 117 | not implemented, blank lines will be implemented in future versions). 118 | 119 | Please consult the Ruby String Reference page ( http://www.ruby-doc.org/core-1.9.3/String.html ) for method behaviour 120 | documentation. 121 | 122 | ## NSString 123 | ``` 124 | ::try_convert 125 | #% (no sensible way to implement this) 126 | #* x: 127 | #+ : 128 | #<< : 129 | #<=> compare: 130 | #== isEqualToString: 131 | #=== == 132 | #=~ index: 133 | #[] start:shorthand:end |> [@"string" :1:@"..":3] 134 | @"string"[1] 135 | @"string"{@"regex"} 136 | @"string"{@[1,3]} 137 | #[]= (no mutating methods) 138 | #ascii_only? isASCII: 139 | #bytes bytes: 140 | #bytesize 141 | #byteslice 142 | #capitalize capitalizedString 143 | #casecmp caseInsensitiveCompare: 144 | #center center: 145 | center:with: 146 | #chars chars: 147 | #chomp chomp 148 | chomp: 149 | #chop chop 150 | #chr chr 151 | #clear (unnecessary in obj-c) 152 | #codepoints codePoints: 153 | #concat concat: 154 | #count count: 155 | #crypt (unsure as of yet of which method to use for this, wary of providing easily misused insecure method) 156 | #delete delete: 157 | #downcase lowercaseString 158 | #dump (implementation very close to |inspect|, |inspect| might suffice?) 159 | #each_byte bytes: 160 | #each_char chars: 161 | #each_codepointcodepoints: 162 | #each_line lines: 163 | #empty? isEmpty 164 | #encode 165 | #encoding 166 | #end_with? endsWith: 167 | #eql? isEqualToString: 168 | #force_encoding 169 | #getbyte 170 | #gsub substituteAll: 171 | substituteAll:pattern 172 | #hash hash 173 | #hex hex 174 | #include? includes: 175 | #index match: 176 | match:offset: 177 | #insert insert:string: 178 | #inspect inspect 179 | #intern (not viable in obj-c, Ruby specific) 180 | #length length 181 | #lines lines: 182 | #ljust leftJustify: 183 | leftJustify:with: 184 | #lstrip leftStrip 185 | #match index: 186 | index:offset: 187 | #next 188 | #oct octal 189 | #ord ordinal 190 | #partition partition: 191 | #prepend prepend: 192 | #replace (unnecessary in obj-c) 193 | #reverse reverse 194 | #rindex lastIndex: 195 | lastIndex:offset: 196 | #rjust rightJustify: 197 | rightJustify:with: 198 | #rpartition rightPartition: 199 | #rstrip rightStrip 200 | #scan scan: 201 | #setbyte 202 | #size length 203 | #slice start:shorthand:end |> [@"string" :1:@"..":3] 204 | @"string"[1] 205 | @"string"{@"regex"} 206 | @"string"{@[1,3]} 207 | #split split 208 | split: 209 | split:limit: 210 | #squeeze squeeze 211 | squeeze: 212 | #start_with? startsWith: 213 | #strip strip 214 | #sub substituteFirst: 215 | substituteLast: 216 | #succ 217 | #sum sum 218 | sum: 219 | #swapcase swapcase 220 | #to_c 221 | #to_f floatValue 222 | #to_i intValue 223 | #to_r 224 | #to_s (just use self) 225 | #to_str (just use self) 226 | #to_sym (not viable in obj-c, Ruby specific) 227 | #tr (functionality is very similar to gsub for us, suggest using that instead) 228 | #tr_s 229 | #unpack 230 | #upcase uppercaseString 231 | #upto 232 | #valid_encoding? 233 | 234 | ``` 235 | 236 | ## NSMutableString 237 | ``` 238 | 239 | #capitalize! capitalizeInPlace 240 | #chomp! chompInPlace 241 | chompInPlace: 242 | #chop! chopInPlace 243 | #delete! deleteInPlace: 244 | #downcase! lowercaseStringInPlace 245 | #gsub! substituteAllInPlace: 246 | substituteAllInPlace:pattern 247 | #lstrip! leftStripInPlace 248 | #reverse! reverseInPlace 249 | #rstrip! rightStripInPlace 250 | #squeeze! squeezeInPlace 251 | squeezeInPlace: 252 | #strip! stripInPlace 253 | #sub! substituteFirstInPlace: 254 | substituteLastInPlace: 255 | #swapcase! swapcaseInPlace 256 | #upcase! uppercaseInPlace 257 | 258 | ``` 259 | --------------------------------------------------------------------------------