Command Line Subcommands in Objective-C Here’s the translation of the Go code to Objective-C, with explanations in Markdown format suitable for Hugo:
Our first program demonstrates how to create command-line subcommands, each with its own set of flags. This is similar to how tools like git
have different subcommands (e.g., git commit
, git push
) with their own options.
#import <Foundation/Foundation.h>
@interface SubcommandParser : NSObject
@property ( nonatomic , strong ) NSString * subcommand ;
@property ( nonatomic , strong ) NSMutableDictionary * flags ;
- ( instancetype ) initWithSubcommand: ( NSString * ) subcommand ;
- ( void ) addFlagWithName: ( NSString * ) name defaultValue: ( id ) defaultValue description: ( NSString * ) description ;
- ( void ) parse: ( NSArray * ) arguments ;
- ( id ) valueForFlag: ( NSString * ) flagName ;
- ( NSArray * ) remainingArguments ;
@end
@implementation SubcommandParser
- ( instancetype ) initWithSubcommand: ( NSString * ) subcommand {
self = [ super init ];
if ( self ) {
_subcommand = subcommand ;
_flags = [ NSMutableDictionary dictionary ];
}
return self ;
}
- ( void ) addFlagWithName: ( NSString * ) name defaultValue: ( id ) defaultValue description: ( NSString * ) description {
self . flags [ name ] = @{ @"value" : defaultValue , @"description" : description } ;
}
- ( void ) parse: ( NSArray * ) arguments {
NSMutableArray * remaining = [ NSMutableArray array ];
for ( NSString * arg in arguments ) {
if ([ arg hasPrefix : @"--" ]) {
NSArray * components = [ arg componentsSeparatedByString : @"=" ];
NSString * flagName = [ components [ 0 ] substringFromIndex : 2 ];
id value = components . count > 1 ? components [ 1 ] : @YES ;
self . flags [ flagName ][ @"value" ] = value ;
} else {
[ remaining addObject : arg ];
}
}
self . flags [ @"remaining" ] = remaining ;
}
- ( id ) valueForFlag: ( NSString * ) flagName {
return self . flags [ flagName ][ @"value" ];
}
- ( NSArray * ) remainingArguments {
return self . flags [ @"remaining" ];
}
@end
int main ( int argc , const char * argv []) {
@autoreleasepool {
NSArray * args = [[ NSProcessInfo processInfo ] arguments ];
if ( args . count < 2 ) {
NSLog ( @"expected 'foo' or 'bar' subcommands" );
return 1 ;
}
NSString * subcommand = args [ 1 ];
if ([ subcommand isEqualToString : @"foo" ]) {
SubcommandParser * fooCmd = [[ SubcommandParser alloc ] initWithSubcommand : @"foo" ];
[ fooCmd addFlagWithName : @"enable" defaultValue : @NO description : @"enable" ];
[ fooCmd addFlagWithName : @"name" defaultValue : @"" description : @"name" ];
[ fooCmd parse :[ args subarrayWithRange : NSMakeRange ( 2 , args . count - 2 )]];
NSLog ( @"subcommand 'foo'" );
NSLog ( @" enable: %@" , [ fooCmd valueForFlag : @"enable" ]);
NSLog ( @" name: %@" , [ fooCmd valueForFlag : @"name" ]);
NSLog ( @" tail: %@" , [ fooCmd remainingArguments ]);
} else if ([ subcommand isEqualToString : @"bar" ]) {
SubcommandParser * barCmd = [[ SubcommandParser alloc ] initWithSubcommand : @"bar" ];
[ barCmd addFlagWithName : @"level" defaultValue : @0 description : @"level" ];
[ barCmd parse :[ args subarrayWithRange : NSMakeRange ( 2 , args . count - 2 )]];
NSLog ( @"subcommand 'bar'" );
NSLog ( @" level: %@" , [ barCmd valueForFlag : @"level" ]);
NSLog ( @" tail: %@" , [ barCmd remainingArguments ]);
} else {
NSLog ( @"expected 'foo' or 'bar' subcommands" );
return 1 ;
}
}
return 0 ;
}
To compile and run the program:
$ clang -framework Foundation command_line_subcommands.m -o command_line_subcommands
First, invoke the foo subcommand:
$ ./command_line_subcommands foo --enable --name= joe a1 a2
subcommand 'foo'
enable: 1
name: joe
tail: (
a1,
a2
)
Now try bar:
$ ./command_line_subcommands bar --level= 8 a1
subcommand 'bar'
level: 8
tail: (
a1
)
But bar won’t accept foo’s flags:
$ ./command_line_subcommands bar --enable a1
subcommand 'bar'
level: 0
tail: (
"--enable" ,
a1
)
This example demonstrates how to implement command-line subcommands in Objective-C. We’ve created a SubcommandParser
class to handle parsing of arguments for each subcommand. The main function checks which subcommand is invoked and processes the arguments accordingly.
Note that Objective-C doesn’t have built-in support for command-line argument parsing like Go’s flag
package. In a real-world application, you might want to use a third-party library for more robust command-line argument parsing.