nsstringgen / README.rst


nsstringfromenumgen generates Objective-C functions for converting enums to NSStrings. It uses libclang for parsing.


The NSStringFromEnumGenerator.py module and nsstringfromenumgen script are distributed under the terms of the MIT License. See LICENSE.TXT for details. The repository also includes and installs libclang Python bindings. See clang/LICENSE.TXT for details on them.


Assuming you're on a Mac, you need Xcode and the command line tools installed. On other platforms you probably need libclang somewhere where Python finds it.

This software includes a copy of the libclang Python bindings because they aren't installed by Xcode. They require LLVM 3.1 which is included at least in Xcode 4.5.2.


To install, use setup.py:

$ sudo python ./setup.py install


Call nsstringfromenumgen with one or more Objective-C source files. It parses them and outputs NSStringFromEnum functions for each enumeration found. It tries to be smart with typedefs and enum names and if it finds both names, it produces two functions. It also outputs an extern declaration for each function:

$ nsstringfromenumgen Foo.h
extern NSString* NSStringFromAnEnum(AnEnum v);
NSString* NSStringFromAnEnum(AnEnum v) {
  switch (v) {
    case AnEnumFirstValue: return @"AnEnumFirstValue";
    case AnEnumSecondValue: return @"AnEnumSecondValue";

If your enums have values defined, they will be included too:

extern NSString* NSStringFromValuesEnum(ValuesEnum v);
NSString* NSStringFromValuesEnum(ValuesEnum v) {
  switch (v) {
    case ValuesEnumFirstValue: return [NSString stringWithFormat:@"ValuesEnumFirstValue (%d)", 1];
    case ValuesEnumSecondValue: return [NSString stringWithFormat:@"ValuesEnumSecondValue (%d)", 2];

You can use - as the file name, in which case nsstringfromenumgen expects to receive the file contents from standard input. You can use this to feed a single enum definition nsstringfromenumgen, instead of a whole source file.

If your code relies on a prefix header, like for NS_ENUM or NS_OPTIONS, you need to include it on the command line with the --include flag. You can specify more than one of them if necessary. You probably want NSObjCRuntime.h or another header that includes it, such as Foundation.h.

Another option for including partial code is --text which allows you to supply the code as a string parameter, eg nsstringfromenumgen --text "typedef enum { TestEnumFirst, TestEnumSecond } TestEnum;". And as above you use the --include flag for headers. This option is useful at least with AppCode which doesn't support Services but has the External Tools section in Preferences.

You can also instruct nsstringfromenumgen to treat your enums as options for a bitmask by including the --mask flag:

$ nsstringfromenumgen Foo.h --mask
extern NSString* NSStringFromMaskEnum(enum MaskEnum v);
NSString* NSStringFromMaskEnum(enum MaskEnum v) {
  NSMutableArray *bits = [NSMutableArray array];
  if (v & MaskEnumFirstValue) [bits addObject:@"MaskEnumFirstValue"];
  if (v & MaskEnumSecondValue) [bits addObject:@"MaskEnumSecondValue"];
  return [bits componentsJoinedByString:@" | "];


If you want to use nsstringfromenumgen as an OS X Service, there's an Automator workflow in service.workflow. It's not installed by setup.py, but you can use Automator to modify it as necessary and install it as a service. It assumes the following:

  1. You'll install the nsstringfromenumgen script in /usr/local/bin,
  2. Have /System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h which it includes automatically,
  3. You want to read stdin and copy the results to clipboard.

If that sounds right and you install it as a service, you can feed it code blocks like:

typedef NS_ENUM(NSInteger, AnEnum) {

and get the right thing on your clipboard.


Because libclang is a real C parser, your file needs to make sense. If libclang produces errors, nsstringfromenumgen gives up because the syntax tree tends to be unpredictable in the presence of errors.

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.