├── .gitignore ├── BCurrency.xcodeproj └── project.pbxproj └── BCurrency └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | 20 | -------------------------------------------------------------------------------- /BCurrency.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 46AD11D820864B9600FCCCB6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 46AD11D720864B9600FCCCB6 /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 46AD11D220864B9600FCCCB6 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 46AD11D420864B9600FCCCB6 /* BCurrency */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = BCurrency; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 46AD11D720864B9600FCCCB6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 46AD11D120864B9600FCCCB6 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 46AD11CB20864B9500FCCCB6 = { 42 | isa = PBXGroup; 43 | children = ( 44 | 46AD11D620864B9600FCCCB6 /* BCurrency */, 45 | 46AD11D520864B9600FCCCB6 /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | 46AD11D520864B9600FCCCB6 /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 46AD11D420864B9600FCCCB6 /* BCurrency */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | 46AD11D620864B9600FCCCB6 /* BCurrency */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 46AD11D720864B9600FCCCB6 /* main.m */, 61 | ); 62 | path = BCurrency; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | 46AD11D320864B9600FCCCB6 /* BCurrency */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = 46AD11DB20864B9600FCCCB6 /* Build configuration list for PBXNativeTarget "BCurrency" */; 71 | buildPhases = ( 72 | 46AD11D020864B9600FCCCB6 /* Sources */, 73 | 46AD11D120864B9600FCCCB6 /* Frameworks */, 74 | 46AD11D220864B9600FCCCB6 /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = BCurrency; 81 | productName = BCurrency; 82 | productReference = 46AD11D420864B9600FCCCB6 /* BCurrency */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | 46AD11CC20864B9500FCCCB6 /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0930; 92 | ORGANIZATIONNAME = Yach; 93 | TargetAttributes = { 94 | 46AD11D320864B9600FCCCB6 = { 95 | CreatedOnToolsVersion = 9.3; 96 | }; 97 | }; 98 | }; 99 | buildConfigurationList = 46AD11CF20864B9500FCCCB6 /* Build configuration list for PBXProject "BCurrency" */; 100 | compatibilityVersion = "Xcode 9.3"; 101 | developmentRegion = en; 102 | hasScannedForEncodings = 0; 103 | knownRegions = ( 104 | en, 105 | ); 106 | mainGroup = 46AD11CB20864B9500FCCCB6; 107 | productRefGroup = 46AD11D520864B9600FCCCB6 /* Products */; 108 | projectDirPath = ""; 109 | projectRoot = ""; 110 | targets = ( 111 | 46AD11D320864B9600FCCCB6 /* BCurrency */, 112 | ); 113 | }; 114 | /* End PBXProject section */ 115 | 116 | /* Begin PBXSourcesBuildPhase section */ 117 | 46AD11D020864B9600FCCCB6 /* Sources */ = { 118 | isa = PBXSourcesBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | 46AD11D820864B9600FCCCB6 /* main.m in Sources */, 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | 46AD11D920864B9600FCCCB6 /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | CLANG_ANALYZER_NONNULL = YES; 133 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 134 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 135 | CLANG_CXX_LIBRARY = "libc++"; 136 | CLANG_ENABLE_MODULES = YES; 137 | CLANG_ENABLE_OBJC_ARC = YES; 138 | CLANG_ENABLE_OBJC_WEAK = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 144 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 145 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 146 | CLANG_WARN_EMPTY_BODY = YES; 147 | CLANG_WARN_ENUM_CONVERSION = YES; 148 | CLANG_WARN_INFINITE_RECURSION = YES; 149 | CLANG_WARN_INT_CONVERSION = YES; 150 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 152 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 153 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 154 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 155 | CLANG_WARN_STRICT_PROTOTYPES = YES; 156 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 157 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 158 | CLANG_WARN_UNREACHABLE_CODE = YES; 159 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 160 | CODE_SIGN_IDENTITY = "-"; 161 | COPY_PHASE_STRIP = NO; 162 | DEBUG_INFORMATION_FORMAT = dwarf; 163 | ENABLE_STRICT_OBJC_MSGSEND = YES; 164 | ENABLE_TESTABILITY = YES; 165 | GCC_C_LANGUAGE_STANDARD = gnu11; 166 | GCC_DYNAMIC_NO_PIC = NO; 167 | GCC_NO_COMMON_BLOCKS = YES; 168 | GCC_OPTIMIZATION_LEVEL = 0; 169 | GCC_PREPROCESSOR_DEFINITIONS = ( 170 | "DEBUG=1", 171 | "$(inherited)", 172 | ); 173 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 174 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 175 | GCC_WARN_UNDECLARED_SELECTOR = YES; 176 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 177 | GCC_WARN_UNUSED_FUNCTION = YES; 178 | GCC_WARN_UNUSED_VARIABLE = YES; 179 | MACOSX_DEPLOYMENT_TARGET = 10.13; 180 | MTL_ENABLE_DEBUG_INFO = YES; 181 | ONLY_ACTIVE_ARCH = YES; 182 | SDKROOT = macosx; 183 | }; 184 | name = Debug; 185 | }; 186 | 46AD11DA20864B9600FCCCB6 /* Release */ = { 187 | isa = XCBuildConfiguration; 188 | buildSettings = { 189 | ALWAYS_SEARCH_USER_PATHS = NO; 190 | CLANG_ANALYZER_NONNULL = YES; 191 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 192 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 193 | CLANG_CXX_LIBRARY = "libc++"; 194 | CLANG_ENABLE_MODULES = YES; 195 | CLANG_ENABLE_OBJC_ARC = YES; 196 | CLANG_ENABLE_OBJC_WEAK = YES; 197 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 198 | CLANG_WARN_BOOL_CONVERSION = YES; 199 | CLANG_WARN_COMMA = YES; 200 | CLANG_WARN_CONSTANT_CONVERSION = YES; 201 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 202 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 203 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 204 | CLANG_WARN_EMPTY_BODY = YES; 205 | CLANG_WARN_ENUM_CONVERSION = YES; 206 | CLANG_WARN_INFINITE_RECURSION = YES; 207 | CLANG_WARN_INT_CONVERSION = YES; 208 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 209 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 210 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 211 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 212 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 213 | CLANG_WARN_STRICT_PROTOTYPES = YES; 214 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 215 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 216 | CLANG_WARN_UNREACHABLE_CODE = YES; 217 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 218 | CODE_SIGN_IDENTITY = "-"; 219 | COPY_PHASE_STRIP = NO; 220 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 221 | ENABLE_NS_ASSERTIONS = NO; 222 | ENABLE_STRICT_OBJC_MSGSEND = YES; 223 | GCC_C_LANGUAGE_STANDARD = gnu11; 224 | GCC_NO_COMMON_BLOCKS = YES; 225 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 226 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 227 | GCC_WARN_UNDECLARED_SELECTOR = YES; 228 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 229 | GCC_WARN_UNUSED_FUNCTION = YES; 230 | GCC_WARN_UNUSED_VARIABLE = YES; 231 | MACOSX_DEPLOYMENT_TARGET = 10.13; 232 | MTL_ENABLE_DEBUG_INFO = NO; 233 | SDKROOT = macosx; 234 | }; 235 | name = Release; 236 | }; 237 | 46AD11DC20864B9600FCCCB6 /* Debug */ = { 238 | isa = XCBuildConfiguration; 239 | buildSettings = { 240 | CODE_SIGN_STYLE = Manual; 241 | DEVELOPMENT_TEAM = ""; 242 | PRODUCT_NAME = "$(TARGET_NAME)"; 243 | PROVISIONING_PROFILE_SPECIFIER = ""; 244 | }; 245 | name = Debug; 246 | }; 247 | 46AD11DD20864B9600FCCCB6 /* Release */ = { 248 | isa = XCBuildConfiguration; 249 | buildSettings = { 250 | CODE_SIGN_STYLE = Manual; 251 | DEVELOPMENT_TEAM = ""; 252 | PRODUCT_NAME = "$(TARGET_NAME)"; 253 | PROVISIONING_PROFILE_SPECIFIER = ""; 254 | }; 255 | name = Release; 256 | }; 257 | /* End XCBuildConfiguration section */ 258 | 259 | /* Begin XCConfigurationList section */ 260 | 46AD11CF20864B9500FCCCB6 /* Build configuration list for PBXProject "BCurrency" */ = { 261 | isa = XCConfigurationList; 262 | buildConfigurations = ( 263 | 46AD11D920864B9600FCCCB6 /* Debug */, 264 | 46AD11DA20864B9600FCCCB6 /* Release */, 265 | ); 266 | defaultConfigurationIsVisible = 0; 267 | defaultConfigurationName = Release; 268 | }; 269 | 46AD11DB20864B9600FCCCB6 /* Build configuration list for PBXNativeTarget "BCurrency" */ = { 270 | isa = XCConfigurationList; 271 | buildConfigurations = ( 272 | 46AD11DC20864B9600FCCCB6 /* Debug */, 273 | 46AD11DD20864B9600FCCCB6 /* Release */, 274 | ); 275 | defaultConfigurationIsVisible = 0; 276 | defaultConfigurationName = Release; 277 | }; 278 | /* End XCConfigurationList section */ 279 | }; 280 | rootObject = 46AD11CC20864B9500FCCCB6 /* Project object */; 281 | } 282 | -------------------------------------------------------------------------------- /BCurrency/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // BCurrency 4 | // 5 | // Created by Blankwonder on 2018/4/17. 6 | // Copyright © 2018 Yach. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | @autoreleasepool { 13 | NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:argc]; 14 | for (int i = 0; i < argc; i++) { 15 | [array addObject:[NSString stringWithUTF8String:argv[i]]]; 16 | } 17 | 18 | NSString *execName = [(NSString *)array.firstObject lastPathComponent]; 19 | NSArray *comps = [execName componentsSeparatedByString:@"-"]; 20 | 21 | NSString *from = comps.count == 2 ? comps.lastObject : @"USD"; 22 | NSString *to = @"CNY"; 23 | 24 | NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://free.currencyconverterapi.com/api/v5/convert?q=%@_%@&compact=ultra", from, to]]; 25 | 26 | NSString *cachedResultPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"BCurrency_%@%@", from, to]]; 27 | 28 | NSData *data; 29 | if ([[NSFileManager defaultManager] fileExistsAtPath:cachedResultPath] && -[[NSFileManager defaultManager] attributesOfItemAtPath:cachedResultPath error:nil].fileModificationDate.timeIntervalSinceNow < 12 * 3600) { 30 | data = [NSData dataWithContentsOfFile:cachedResultPath]; 31 | } else { 32 | NSURLResponse *response = nil; 33 | NSError *error = nil; 34 | data = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url] returningResponse:&response error:&error]; 35 | 36 | if (data.length == 0 || error) { 37 | NSDictionary *output = @{@"items": @[@{@"title": [NSString stringWithFormat:@"Error: %@", error.localizedDescription]}]}; 38 | 39 | NSData *outputData = [NSJSONSerialization dataWithJSONObject:output options:0 error:nil]; 40 | 41 | NSFileHandle *sout = [NSFileHandle fileHandleWithStandardOutput]; 42 | [sout writeData:outputData]; 43 | return 0; 44 | } 45 | 46 | [data writeToFile:cachedResultPath atomically:YES]; 47 | } 48 | 49 | NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 50 | 51 | double value = [(NSString *)json.allValues.firstObject doubleValue]; 52 | double source = [array.lastObject doubleValue]; 53 | 54 | // {"items": [ 55 | // { 56 | // "uid": "desktop", 57 | // "type": "file", 58 | // "title": "Desktop", 59 | // "subtitle": "~/Desktop", 60 | // "arg": "~/Desktop", 61 | // "autocomplete": "Desktop", 62 | // "icon": { 63 | // "type": "fileicon", 64 | // "path": "~/Desktop" 65 | // } 66 | // } 67 | // ]} 68 | 69 | NSString *result = [@(value * source) stringValue]; 70 | 71 | NSDictionary *output = @{@"items": @[@{@"subtitle": [NSString stringWithFormat:@"%@/%@ %g", from, to, value], 72 | @"title": result, 73 | @"arg": result 74 | }]}; 75 | 76 | NSData *outputData = [NSJSONSerialization dataWithJSONObject:output options:0 error:nil]; 77 | 78 | NSFileHandle *sout = [NSFileHandle fileHandleWithStandardOutput]; 79 | [sout writeData:outputData]; 80 | } 81 | return 0; 82 | } 83 | --------------------------------------------------------------------------------