<!DOCTYPE html> <html> <head> <title>optparse.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <ul id="jump_to"> <li> <a class="large" href="javascript:void(0);">Jump To …</a> <a class="small" href="javascript:void(0);">+</a> <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.litcoffee </a> <a class="source" href="sourcemap.html"> sourcemap.litcoffee </a> </div> </li> </ul> <ul class="sections"> <li id="title"> <div class="annotation"> <h1>optparse.coffee</h1> </div> </li> <li id="section-1"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-1">¶</a> </div> </div> <div class="content"><div class='highlight'><pre>{repeat} = require <span class="string">'./helpers'</span></pre></div></div> </li> <li id="section-2"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-2">¶</a> </div> <p>A simple <strong>OptionParser</strong> class to parse option flags from the command-line. Use it like so: </p> <pre><code>parser = new OptionParser switches, helpBanner options = parser.parse process.argv</code></pre> <p>The first non-option is considered to be the start of the file (and file option) list, and all subsequent arguments are left unparsed. </p> </div> <div class="content"><div class='highlight'><pre>exports.OptionParser = <span class="class"><span class="keyword">class</span> <span class="title">OptionParser</span></span></pre></div></div> </li> <li id="section-3"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Initialize with a list of valid options, in the form: </p> <pre><code>[short-flag, long-flag, description]</code></pre> <p>Along with an an optional banner for the usage help. </p> </div> <div class="content"><div class='highlight'><pre> constructor: (rules, <span class="property">@banner</span>) -> <span class="property">@rules</span> = buildRules rules</pre></div></div> </li> <li id="section-4"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Parse the list of arguments, populating an <code>options</code> object with all of the specified options, and return it. Options after the first non-option argument are treated as arguments. <code>options.arguments</code> will be an array containing the remaining arguments. This is a simpler API than many option parsers that allow you to attach callback actions for every flag. Instead, you're responsible for interpreting the options object. </p> </div> <div class="content"><div class='highlight'><pre> parse: (args) -> options = arguments: [] skippingArgument = <span class="literal">no</span> originalArgs = args args = normalizeArguments args <span class="keyword">for</span> arg, i <span class="keyword">in</span> args <span class="keyword">if</span> skippingArgument skippingArgument = <span class="literal">no</span> <span class="keyword">continue</span> <span class="keyword">if</span> arg <span class="keyword">is</span> <span class="string">'--'</span> pos = originalArgs.indexOf <span class="string">'--'</span> options.arguments = options.arguments.concat originalArgs[(pos + <span class="number">1</span>)..] <span class="keyword">break</span> isOption = !!(arg.match(LONG_FLAG) <span class="keyword">or</span> arg.match(SHORT_FLAG))</pre></div></div> </li> <li id="section-5"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-5">¶</a> </div> <p>the CS option parser is a little odd; options after the first non-option argument are treated as non-option arguments themselves </p> </div> <div class="content"><div class='highlight'><pre> seenNonOptionArg = options.arguments.length > <span class="number">0</span> <span class="keyword">unless</span> seenNonOptionArg matchedRule = <span class="literal">no</span> <span class="keyword">for</span> rule <span class="keyword">in</span> <span class="property">@rules</span> <span class="keyword">if</span> rule.shortFlag <span class="keyword">is</span> arg <span class="keyword">or</span> rule.longFlag <span class="keyword">is</span> arg value = <span class="literal">true</span> <span class="keyword">if</span> rule.hasArgument skippingArgument = <span class="literal">yes</span> value = args[i + <span class="number">1</span>] options[rule.name] = <span class="keyword">if</span> rule.isList <span class="keyword">then</span> (options[rule.name] <span class="keyword">or</span> []).concat value <span class="keyword">else</span> value matchedRule = <span class="literal">yes</span> <span class="keyword">break</span> <span class="keyword">throw</span> <span class="keyword">new</span> Error <span class="string">"unrecognized option: <span class="subst">#{arg}</span>"</span> <span class="keyword">if</span> isOption <span class="keyword">and</span> <span class="keyword">not</span> matchedRule <span class="keyword">if</span> seenNonOptionArg <span class="keyword">or</span> <span class="keyword">not</span> isOption options.arguments.push arg options</pre></div></div> </li> <li id="section-6"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Return the help text for this <strong>OptionParser</strong>, listing and describing all of the valid options, for <code>--help</code> and such. </p> </div> <div class="content"><div class='highlight'><pre> help: -> lines = [] lines.unshift <span class="string">"<span class="subst">#{@banner}</span>\n"</span> <span class="keyword">if</span> <span class="property">@banner</span> <span class="keyword">for</span> rule <span class="keyword">in</span> <span class="property">@rules</span> spaces = <span class="number">15</span> - rule.longFlag.length spaces = <span class="keyword">if</span> spaces > <span class="number">0</span> <span class="keyword">then</span> repeat <span class="string">' '</span>, spaces <span class="keyword">else</span> <span class="string">''</span> letPart = <span class="keyword">if</span> rule.shortFlag <span class="keyword">then</span> rule.shortFlag + <span class="string">', '</span> <span class="keyword">else</span> <span class="string">' '</span> lines.push <span class="string">' '</span> + letPart + rule.longFlag + spaces + rule.description <span class="string">"\n<span class="subst">#{ lines.join('\n') }</span>\n"</span></pre></div></div> </li> <li id="section-7"> <div class="annotation"> <div class="pilwrap for-h2"> <a class="pilcrow" href="#section-7">¶</a> </div> <h2>Helpers</h2> </div> </li> <li id="section-8"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-8">¶</a> </div> </div> </li> <li id="section-9"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Regex matchers for option flags. </p> </div> <div class="content"><div class='highlight'><pre>LONG_FLAG = <span class="regexp">/^(--\w[\w\-]*)/</span> SHORT_FLAG = <span class="regexp">/^(-\w)$/</span> MULTI_FLAG = <span class="regexp">/^-(\w{2,})/</span> OPTIONAL = <span class="regexp">/\[(\w+(\*?))\]/</span></pre></div></div> </li> <li id="section-10"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Build and return the list of option rules. If the optional <em>short-flag</em> is unspecified, leave it out by padding with <code>null</code>. </p> </div> <div class="content"><div class='highlight'><pre><span class="function"><span class="title">buildRules</span></span> = (rules) -> <span class="keyword">for</span> tuple <span class="keyword">in</span> rules tuple.unshift <span class="literal">null</span> <span class="keyword">if</span> tuple.length < <span class="number">3</span> buildRule tuple...</pre></div></div> </li> <li id="section-11"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Build a rule from a <code>-o</code> short flag, a <code>--output [DIR]</code> long flag, and the description of what the option does. </p> </div> <div class="content"><div class='highlight'><pre><span class="function"><span class="title">buildRule</span></span> = (shortFlag, longFlag, description, options = {}) -> match = longFlag.match(OPTIONAL) longFlag = longFlag.match(LONG_FLAG)[<span class="number">1</span>] { name: longFlag.substr <span class="number">2</span> shortFlag: shortFlag longFlag: longFlag description: description hasArgument: !!(match <span class="keyword">and</span> match[<span class="number">1</span>]) isList: !!(match <span class="keyword">and</span> match[<span class="number">2</span>]) }</pre></div></div> </li> <li id="section-12"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Normalize arguments by expanding merged flags into multiple flags. This allows you to have <code>-wl</code> be the same as <code>--watch --lint</code>. </p> </div> <div class="content"><div class='highlight'><pre><span class="function"><span class="title">normalizeArguments</span></span> = (args) -> args = args[..] result = [] <span class="keyword">for</span> arg <span class="keyword">in</span> args <span class="keyword">if</span> match = arg.match MULTI_FLAG result.push <span class="string">'-'</span> + l <span class="keyword">for</span> l <span class="keyword">in</span> match[<span class="number">1</span>].split <span class="string">''</span> <span class="keyword">else</span> result.push arg result</pre></div></div> </li> </ul> </div> </body> </html>