Thursday, September 24, 2009

Cocoa: command line arguments

I found myself trying to write a "Foundation tool" that would process a command line argument. It's not really clear to me why I wouldn't use Python to do this, but that's another story. So I wrote the following code in a file "CL1.m" on my Desktop:


#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
if (argc > 1) {
printf("printf %s\n",argv[1]);
NSData *d = [NSData dataWithBytes:argv[1]
length:4];
NSLog(@"data: %@",[d description]);
NSString *s = [[NSString alloc]
initWithCString:argv[1]
encoding:NSASCIIStringEncoding];
NSLog(@"string description: %@",[s description]);
// this doesn't work!
NSLog(@"string: %s", s);
}
[pool drain];
return 0;
}


Compile like this:

gcc -o CL1 CL1.m -framework Foundation


and run from the command line:

.. $ ./CL1 xyz
printf xyz
.. data: <78797a00>
.. string description: xyz
.. string: †¥u†å


I looked at the data directly, because I was (wrongly) using NSLog as shown in the last call, and I wanted to look at the bytes directly. As expected, hex 78 is decimal 7*16 + 8 = 120, which is 'x' in ascii.

However, there is a better way to do this, as discussed in this post. NSUserDefaults will read command line arguments. It works like so:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSUserDefaults *args = [NSUserDefaults standardUserDefaults];
NSLog(@"arg = %@ ", [args stringForKey:@"input"]);
[pool drain];
return 0;
}


.. $ ./CL2 -input xyz
.. arg = xyz


As discussed in the post, this method is really versatile, it can parse for integers or floats or booleans. (If you try to copy and paste this code, be sure to fix the < symbol in the import statement).

You can get an idea what is in the dictionary by doing this from the command line:

defaults read > ~/Desktop/defaults.txt