Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Added ability to used stored options with nib2cib #1230

Closed
wants to merge 1 commit into from

1 participant

@aparajita
Owner

This is especially important with xcodeapp, because it provides no way of passing options to nib2cib. Even if it did, it's great to have a way to provide app-specific or nib-specific options.

Full documentation of stored options is in the man page.

@aparajita
Owner

Gentlemen,

With the increasing use of xcodecapp, and now XCodeCapp-Cocoa, this enhancement becomes increasingly important. Please take a look at it.

@aparajita
Owner

This is being merged separately.

@aparajita aparajita closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 16, 2011
  1. Added ability to used store options.

    Aparajita Fishman authored
This page is out of date. Refresh to see the latest.
Showing with 199 additions and 37 deletions.
  1. +148 −35 Tools/nib2cib/main.j
  2. +51 −2 Tools/nib2cib/nib2cib.1
View
183 Tools/nib2cib/main.j
@@ -37,18 +37,23 @@ var FILE = require("file"),
stream = require("narwhal/term").stream,
StaticResource = require("objective-j").StaticResource,
- DefaultTheme = "Aristo",
- BuildTypes = ["Debug", "Release"],
- DefaultFile = "MainMenu";
-
-var parser = new (require("narwhal/args").Parser)(),
+ Parser = require("narwhal/args").Parser,
nibInfo = {},
appDirectory = "",
- resourcesDirectory = "";
+ resourcesDirectory = "",
+ logLevel = -1,
+
+ DefaultTheme = "Aristo",
+ BuildTypes = ["Debug", "Release"],
+ DefaultFile = "MainMenu",
+ AllowedStoredOptionsRe = new RegExp("^(defaultTheme|extraThemes|verbosity|quiet|frameworks|format)$");
+ ArgsRe = /"[^\"]+"|'[^\']+'|\S+/g;
function main(args)
{
+ setLogLevel(0);
+
try
{
var options = parseOptions(args);
@@ -73,6 +78,14 @@ function convert(options, inputFile)
getAppAndResourceDirectoriesFromInputFile(inputFile, options);
+ if (options.readStoredOptions)
+ options = mergeOptionsWithStoredOptions(options, inputFile);
+
+ setLogLevel(options.quiet ? -1 : options.verbosity);
+
+ if (!options.quiet && options.verbosity > 0)
+ printVersion();
+
var outputFile = getOutputFile(inputFile, options.args),
configInfo = readConfigFile(options.configFile || "", inputFile),
defaultTheme = null;
@@ -110,7 +123,7 @@ function convert(options, inputFile)
CPLog.info("-------------------------------------------------------------\n");
var converter = [[Converter alloc] initWithInputPath:inputFile
- format:options.format
+ format:options.format || NibFormatUndetermined
themes:themes];
[converter setOutputPath:outputFile];
@@ -132,9 +145,11 @@ function convert(options, inputFile)
function watch(options)
{
- var verbosity = options.quiet ? -1 : options.verbosity,
+ var level = options.quiet ? -1 : options.verbosity,
watchDir = options.args[0];
+ setLogLevel(level);
+
if (!watchDir)
watchDir = FILE.canonical(FILE.isDirectory("Resources") ? "Resources" : ".");
else
@@ -195,16 +210,18 @@ function watch(options)
continue;
}
- // Let the converter log however the user configured it
- setLogLevel(verbosity);
+ // Let the converter log however the user configured it.
+ // Since convert() may change the log level, capture it after convert().
+ setLogLevel(level);
- var success = convert(options, nib);
+ var success = convert(options, nib),
+ level = logLevel;
setLogLevel(1);
if (success)
{
- if (verbosity > 0)
+ if (level > 0)
stream.print();
else
CPLog.warn("Conversion successful");
@@ -217,6 +234,8 @@ function watch(options)
function parseOptions(args)
{
+ var parser = new Parser();
+
parser.usage("[--watch DIRECTORY] [INPUT_FILE [OUTPUT_FILE]]");
parser.option("--watch", "watch")
@@ -255,13 +274,17 @@ function parseOptions(args)
.set(true)
.help("No output");
- parser.option("-F", "framework", "frameworks")
+ parser.option("-F", "--framework", "frameworks")
.push()
.help("Add a framework to load");
+ parser.option("--no-stored-options", "readStoredOptions")
+ .set(false)
+ .def(true)
+ .help("Do not read stored options");
+
parser.option("--mac", "format")
.set(NibFormatMac)
- .def(NibFormatUndetermined)
.help("Set format to Mac");
parser.option("--version", "showVersion")
@@ -278,16 +301,106 @@ function parseOptions(args)
OS.exit(0);
}
- setLogLevel(options.quiet ? -1 : options.verbosity);
+ return options;
+}
+
+function mergeOptionsWithStoredOptions(options, inputFile)
+{
+ // We have to clone options
+ var userOptions = readStoredOptions(FILE.join(SYS.env["HOME"], ".nib2cibconfig")),
+ appOptions = readStoredOptions(FILE.join(appDirectory, "nib2cib.conf")),
+ filename = FILE.basename(inputFile, FILE.extension(inputFile)) + ".conf",
+ fileOptions = readStoredOptions(FILE.join(FILE.dirname(inputFile), filename));
+
+ // At this point we have an array of args without the initial command in args[0],
+ // add the command and parse the options.
+ userOptions = parseOptions([options.command].concat(userOptions), null, null, true);
+ appOptions = parseOptions([options.command].concat(appOptions), null, null, true);
+ fileOptions = parseOptions([options.command].concat(fileOptions), null, null, true);
+
+ // The increasing order of precedence is: user -> app -> file -> command line
+ var mergedOptions = userOptions;
+
+ mergeOptions(appOptions, mergedOptions);
+ mergeOptions(fileOptions, mergedOptions);
+ mergeOptions(options, mergedOptions);
+ mergedOptions.args = options.args;
+
+ return mergedOptions;
+}
+
+function readStoredOptions(path)
+{
+ path = FILE.canonical(path);
- if (!options.quiet && options.verbosity > 0)
- printVersion();
+ if (!FILE.isReadable(path))
+ return [];
- return options;
+ var file = FILE.open(path, "r"),
+ line = file.readLine(),
+ matches = line.match(ArgsRe) || [];
+
+ file.close();
+
+ if (matches)
+ {
+ for (var i = 0; i < matches.length; ++i)
+ {
+ var str = matches[i];
+
+ if ((str.charAt(0) === '"' && str.substr(-1) === '"') || (str.charAt(0) === "'" && str.substr(-1) === "'"))
+ matches[i] = str.substr(1, str.length - 2);
+ }
+
+ return matches;
+ }
+ else
+ return [];
+}
+
+function printOptions(options)
+{
+ for (option in options)
+ {
+ var value = options[option];
+
+ if (value)
+ {
+ var show = value.length !== undefined ? value.length > 0 : !!value;
+
+ if (show)
+ print(option + ": " + value);
+ }
+ }
+}
+
+// Merges properties in sourceOptions into targetOptions, overriding properties in targetOptions
+function mergeOptions(sourceOptions, targetOptions)
+{
+ for (option in sourceOptions)
+ {
+ // Make sure only a supported option is given
+ if (!AllowedStoredOptionsRe.test(option))
+ continue;
+
+ if (sourceOptions.hasOwnProperty(option))
+ {
+ var value = sourceOptions[option];
+
+ if (value)
+ {
+ var copy = value.length !== undefined ? value.length > 0 : !!value;
+
+ if (copy)
+ targetOptions[option] = value;
+ }
+ }
+ }
}
function setLogLevel(level)
{
+ logLevel = level;
CPLogUnregister(CPLogPrint);
if (level === 0)
@@ -635,15 +748,10 @@ function readConfigFile(configFile, inputFile)
if (configPath)
{
- var plist = FILE.read(configPath);
+ plist = readPlist(configPath);
if (!plist)
fail("Could not read the Info.plist at: " + configPath);
-
- plist = CFPropertyList.propertyListFromString(plist);
-
- if (!plist)
- fail("Could not parse the Info.plist at: " + configPath);
}
return {path: configPath, plist: plist};
@@ -684,6 +792,19 @@ function getModifiedNibs(path)
return modifiedNibs;
}
+function readPlist(path)
+{
+ if (!FILE.isReadable(path))
+ return null;
+
+ var plist = FILE.read(path);
+
+ if (!plist)
+ return null;
+
+ return CFPropertyList.propertyListFromString(plist);
+}
+
function printVersionAndExit()
{
printVersion();
@@ -709,18 +830,10 @@ function printVersion()
path = FILE.join(path, "lib", "nib2cib", "Info.plist");
- if (FILE.isReadable(path))
- {
- var plist = FILE.read(path);
-
- if (!plist)
- return;
-
- plist = CFPropertyList.propertyListFromString(plist);
-
- if (!plist)
- return;
+ var plist = readPlist(path);
+ if (plist)
+ {
version = plist.valueForKey("CPBundleVersion");
if (version)
View
53 Tools/nib2cib/nib2cib.1
@@ -1,6 +1,7 @@
.Dd April 3, 2011
.Os "Cappuccino"
.Dt NIB2CIB 1 "PRM"
+.nh
.\"-----------------------------------------------------------------------------------------
.Sh NAME
.\"-----------------------------------------------------------------------------------------
@@ -155,7 +156,7 @@ options, one for each theme that you load.
Themes are searched for in the Resources, $CAPP_BUILD/Debug and
$CAPP_BUILD/Release directories.
.\"-----------------------------------------------------------------------------------------
-.Sh "COMMON OPTIONS"
+.Sh "OPTIONS"
.\"-----------------------------------------------------------------------------------------
The following options are available in watch mode or single mode:
.Bl -tag -width 4n
@@ -208,7 +209,16 @@ Tells
.Nm
to output nothing. This is useful if you are using
.Nm
-in a shell script and are only interested in the return value.
+in a shell script and are only interested in the return value. Note that this
+option overrides the
+.Fl v
+option.
+.It Fl \-no-stored-options
+Tells
+.Nm
+not to read stored options. See
+.Sy Stored Options
+below for more information.
.It Fl \-version
Prints the current version of
.Nm
@@ -221,6 +231,45 @@ Displays
usage and options.
.El
.\"-----------------------------------------------------------------------------------------
+.Ss "Stored Options"
+.\"-----------------------------------------------------------------------------------------
+To make it easier to use nib2cib in an automated way, you can store command line options
+that will apply to converted xibs/nibs. To store command line options, you enter the
+options on a single line into a text file. For example, if you always want to set
+"MyTheme" as the default theme, you would create a text file with this line:
+.Pp
+.D1 --default-theme MyTheme
+.Pp
+If an option takes a parameter and the parameter contains spaces, it must be enclosed in
+single or double quotes. You may store options in the following three places, in increasing
+order of precedence:
+.Bl -ohang -offset 4n
+.It Em ~/.nib2cibconfig
+nib2cib options that apply to all nibs converted under your user account.
+.It Em <app>/nib2cib.conf
+nib2cib options that apply to all nibs in <app>/Resources.
+.It Em <app>/Resources/<xib-or-nib-basename>.conf
+nib2cib options that apply to a specific xib or nib. For example, if the xib
+is called MainMenu.xib, the stored options file would be MainMenu.conf.
+.El
+.Pp
+Each of these files is read in the order listed above, and if it exists, its options
+are merged with the previous file's options. Options in later files (more specific)
+override options in earlier files (more generic). After all of the stored options
+are merged, the command line options are merged in. Thus command line options always
+override stored options.
+.Pp
+Using stored options is especially useful if your xibs/nibs use custom themes or
+frameworks. By using stored options, you can avoid remembering (or forgetting!) to
+specify the theme or framework every time you invoke
+.Nm .
+.Pp
+To prevent
+.Nm
+from reading stored options, and thus only use command line options, use the
+.Fl \-no-stored-options
+option on the command line.
+.\"-----------------------------------------------------------------------------------------
.Sh "RETURN VALUES"
.\"-----------------------------------------------------------------------------------------
.Nm
Something went wrong with that request. Please try again.