• ジャンプ ... +
    browser.coffee cake.coffee coffeescript.coffee command.coffee grammar.coffee helpers.coffee index.coffee lexer.coffee nodes.coffee optparse.coffee register.coffee repl.coffee rewriter.coffee scope.litcoffee sourcemap.litcoffee
  • optparse.coffee

  • §
    {repeat} = require './helpers'
  • §

    コマンドラインからオプションフラグを解析するための単純なOptionParserクラス。次のように使用します。

    parser  = new OptionParser switches, helpBanner
    options = parser.parse process.argv
    

    最初の非オプションはファイル(およびファイルオプション)リストの開始と見なされ、それ以降のすべての引数は解析されないままになります。

    coffeeコマンドはsrc/command.coffeeでOptionParserのインスタンスを使用してコマンドライン引数を解析します。

    exports.OptionParser = class OptionParser
  • §

    使用可能なオプションのリストで初期化します。形式は次のとおりです。

    [short-flag, long-flag, description]
    

    使用法のヘルプのオプションのバナーを指定することもできます。

      constructor: (ruleDeclarations, @banner) ->
        @rules = buildRules ruleDeclarations
  • §

    引数リストを解析し、指定されたすべてのオプションを含むoptionsオブジェクトを取り込み、返します。最初の非オプション引数の後のオプションは引数として扱われます。options.argumentsは残りの引数を含む配列になります。これは、各フラグにコールバックアクションを添付できる多くのオプションパーサーよりも単純なAPIです。代わりに、オプションオブジェクトを解釈する必要があります。

      parse: (args) ->
  • §

    CoffeeScriptオプションパーサーは少し奇妙です;最初の非オプション引数の後のオプションは、非オプション引数自体として扱われます。オプション引数は、マージされたフラグを複数のフラグに展開することによって正規化されます。これにより、-wlを--watch --lintと同じにすることができます。shebang(#!)行を持つ実行可能スクリプトは、行#!/usr/bin/env coffeeまたは#!/absolute/path/to/coffeeを使用する必要があることに注意してください。これはLinuxでは失敗するため、その後ろに--引数を付けるべきではありません(#3946を参照)。

        {rules, positional} = normalizeArguments args, @rules.flagDict
        options = {}
  • §

    argumentフィールドはnormalizeArgumentsによって破壊的にルールインスタンスに追加されます。

        for {hasArgument, argument, isList, name} in rules
          if hasArgument
            if isList
              options[name] ?= []
              options[name].push argument
            else
              options[name] = argument
          else
            options[name] = true
    
        if positional[0] is '--'
          options.doubleDashed = yes
          positional = positional[1..]
    
        options.arguments = positional
        options
  • §

    このOptionParserのヘルプテキストを返し、--helpなどに使用可能なすべてのオプションを一覧表示して説明します。

      help: ->
        lines = []
        lines.unshift "#{@banner}\n" if @banner
        for rule in @rules.ruleList
          spaces  = 15 - rule.longFlag.length
          spaces  = if spaces > 0 then repeat ' ', spaces else ''
          letPart = if rule.shortFlag then rule.shortFlag + ', ' else '    '
          lines.push '  ' + letPart + rule.longFlag + spaces + rule.description
        "\n#{ lines.join('\n') }\n"
  • §

    ヘルパー

  • §
  • §

    コマンドラインとそれらのルールのオプションフラグの正規表現マッチャー。

    LONG_FLAG  = /^(--\w[\w\-]*)/
    SHORT_FLAG = /^(-\w)$/
    MULTI_FLAG = /^-(\w{2,})/
  • §

    引数を持つオプションのルールの長いフラグ部分に一致します。process.argvには適用されません。

    OPTIONAL   = /\[(\w+(\*?))\]/
  • §

    オプションルールのリストを作成して返します。オプションのショートフラグが指定されていない場合は、nullをパディングして除外します。

    buildRules = (ruleDeclarations) ->
      ruleList = for tuple in ruleDeclarations
        tuple.unshift null if tuple.length < 3
        buildRule tuple...
      flagDict = {}
      for rule in ruleList
  • §

    shortFlag は、ルールで指定されていない場合は null です。

        for flag in [rule.shortFlag, rule.longFlag] when flag?
          if flagDict[flag]?
            throw new Error "flag #{flag} for switch #{rule.name}
              was already declared for switch #{flagDict[flag].name}"
          flagDict[flag] = rule
    
      {ruleList, flagDict}
  • §

    短縮フラグ -o、長形式フラグ --output [DIR]、およびオプションの機能の記述からルールを作成します。

    buildRule = (shortFlag, longFlag, description) ->
      match     = longFlag.match(OPTIONAL)
      shortFlag = shortFlag?.match(SHORT_FLAG)[1]
      longFlag  = longFlag.match(LONG_FLAG)[1]
      {
        name:         longFlag.replace /^--/, ''
        shortFlag:    shortFlag
        longFlag:     longFlag
        description:  description
        hasArgument:  !!(match and match[1])
        isList:       !!(match and match[2])
      }
    
    normalizeArguments = (args, flagDict) ->
      rules = []
      positional = []
      needsArgOpt = null
      for arg, argIndex in args
  • §

    スクリプトに指定された前の引数が、その引数として次のコマンドライン引数を使用するオプションの場合は、argument フィールドを持つオプションのルールのコピーを作成します。

        if needsArgOpt?
          withArg = Object.assign {}, needsArgOpt.rule, {argument: arg}
          rules.push withArg
          needsArgOpt = null
          continue
    
        multiFlags = arg.match(MULTI_FLAG)?[1]
          .split('')
          .map (flagName) -> "-#{flagName}"
        if multiFlags?
          multiOpts = multiFlags.map (flag) ->
            rule = flagDict[flag]
            unless rule?
              throw new Error "unrecognized option #{flag} in multi-flag #{arg}"
            {rule, flag}
  • §

    複数フラグにある最後のフラグのみが引数を持つことができます。

          [innerOpts..., lastOpt] = multiOpts
          for {rule, flag} in innerOpts
            if rule.hasArgument
              throw new Error "cannot use option #{flag} in multi-flag #{arg} except
              as the last option, because it needs an argument"
            rules.push rule
          if lastOpt.rule.hasArgument
            needsArgOpt = lastOpt
          else
            rules.push lastOpt.rule
        else if ([LONG_FLAG, SHORT_FLAG].some (pat) -> arg.match(pat)?)
          singleRule = flagDict[arg]
          unless singleRule?
            throw new Error "unrecognized option #{arg}"
          if singleRule.hasArgument
            needsArgOpt = {rule: singleRule, flag: arg}
          else
            rules.push singleRule
        else
  • §

    これは位置引数です。

          positional = args[argIndex..]
          break
    
      if needsArgOpt?
        throw new Error "value required for #{needsArgOpt.flag}, but it was the last
        argument provided"
      {rules, positional}