class Getopt::Declare

Main Class

Constants

VERSION
nocase

Attributes

nocase[RW]
clump[R]
helppat[R]
mutex[R]
source[R]
strict[R]
unused[RW]
verspat[R]

Public Class Methods

new(*opts) click to toggle source

Constructor

# File lib/Getopt/Declare.rb, line 996
def initialize(*opts)
  @cache = nil

  Getopt::Declare::Arg::clear

  # HANDLE SHORT-CIRCUITS
  return if opts.size==2 && (!opts[1] || opts[1] == '-SKIP') 

  grammar, source = opts

  if grammar.nil?
    raise "Error: No grammar description provided."
  end

  ### REMOVED PREDEF GRAMMAR AS IT WAS NOT DOCUMENTED NOR
  ### WORKING IN PERL'S Declare.pm VERSION.

  # PRESERVE ESCAPED '['s
  grammar.gsub!(/\\\[/,"\255")

  # MAKE SURE GRAMMAR ENDS WITH A NEWLINE.
  grammar.sub!(/([^\n])\Z/,'\1'+"\n")

  @usage   = grammar.dup

  # SET-UP
  i = grammar
  _args = []
  _mutex = {}
  _strict = false
  _all_repeatable = false
  _lastdesc = nil
  arg = nil
  Getopt::Declare::nocase = false
  Getopt::Declare::ScalarArg::_reset_stdtype


  # CONSTRUCT GRAMMAR
  while i.length > 0

    # COMMENT:
    i.sub!(/\A[ \t]*#.*\n/,"") and next


    # TYPE DIRECTIVE:
    se  = DelimScanner::new( i )

    if i =~ /\A\s*\[\s*pvtype:/ 
      _action = se.extractBracketed("[")
      if _action
        i.sub!( Regexp::quote( _action ).to_re, "" )   ### @GGA: added
        i.sub!(/\A[ \t]*\n/,"")                        ### @GGA: added
        _action.sub!(/.*?\[\s*pvtype:\s*/,"")
        _typedef(_action)
        next
      end # if
    end

    # ACTION
    codeblockDelimiters = {
      '{'     => '}',
    }

    _action = se.extractCodeblock(codeblockDelimiters)
    if _action
      i.sub!( Regexp::quote(_action ).to_re, "" )
      i.sub!(/\A[ \t]*\n/,"")
      _action = _action[1..-2]

      if !valid_syntax?( _action )
        raise "Error: bad action in Getopt::Declare specification:" +
          "\n\n#{_action}\n\n\n"
      end

      if _args.length == 0
        raise "Error: unattached action in Getopt::Declare specification:\n#{_action}\n" +
              "\t(did you forget the tab after the preceding parameter specification?)\n"
      end

      _args.last.actions.push( _action )
      next
    elsif i =~ /\A(\s*[{].*)/
      raise "Error: incomplete action in Getopt::Declare specification:\n$1.....\n" +
            "\t(did you forget a closing '}'?)\n"
    end


    # ARG + DESC:
    if i.sub!(re_argument,"")
      spec = "#$1".strip
      desc = "#$2"
      _strict ||= desc =~ /\[\s*strict\s*\]/

      while i.sub!(re_more_desc,"")
        desc += "#$1"
      end
      
      ditto = nil
      if _lastdesc and desc.sub!(/\A\s*\[\s*ditto\s*\]/,_lastdesc)
        ditto = arg
      else
        _lastdesc = desc
      end

      # Check for GNU spec line like:  -d, --debug
      arg = nil
      if spec =~ /(-[\w]+),\s+(--?[\w]+)(\s+.*)?/
        specs = ["#$1#$3", "#$2#$3"]
        specs.each { |sp|
          arg = Arg.new(sp,desc,ditto)
          _args.push( arg )
          _infer(desc, arg, _mutex)
          ditto = arg
        }
      else
        arg = Arg.new(spec,desc,ditto)
        _args.push( arg )
        _infer(desc, arg, _mutex)
      end


      next
    end

    # OTHERWISE: DECORATION
    i.sub!(/((?:(?!\[\s*pvtype:).)*)(\n|(?=\[\s*pvtype:))/,"")
    decorator = "#$1"
    _strict ||= decorator =~ /\[\s*strict\s*\]/
    _infer(decorator, nil, _mutex)

    _all_repeatable = true if decorator =~ /\[\s*repeatable\s*\]/
    @@debug = true if decorator =~ /\[\s*debug\s*\]/

  end # while i.length



  _lastactions = nil
  for i in _args
    if _lastactions && i.ditto && i.actions.size == 0
      i.actions = _lastactions
    else
      _lastactions = i.actions
    end

    if _all_repeatable
      i.repeatable = 1
    end
  end

  # Sort flags based on criteria described in docs
  # Sadly, this cannot be reduced to sort_by
   _args = _args.sort() { |a,b|
    cond1 = ( b.flag.size <=> a.flag.size )
    cond2 = ( b.flag == a.flag and ( b.args.size <=> a.args.size ) )
    cond3 = ( a.id <=> b.id )
    cond1 = nil if cond1 == 0
    cond2 = nil if cond2 == 0
    cond1 or cond2 or cond3
  }

  # Handle clump
  clump = (@usage =~ /\[\s*cluster:\s*none\s*\]/i)     ? 0 :
    (@usage =~ /\[\s*cluster:\s*singles?\s*\]/i) ? 1 :
    (@usage =~ /\[\s*cluster:\s*flags?\s*\]/i)   ? 2 :
    (@usage =~ /\[\s*cluster:\s*any\s*\]/i)      ? 3 :
    (@usage =~ /\[\s*cluster:(.*)\s*\]/i)      ? "r" : 3
  raise "Error: unknown clustering mode: [cluster:#$1]\n" if clump == "r"

  # CONSTRUCT OBJECT ITSELF
  @args    = _args
  @mutex   = _mutex
  @helppat = Arg::helppat()
  @verspat = Arg::versionpat()

  @strict  = _strict
  @clump   = clump
  @source  = ''
  @tight   = @usage =~ /\[\s*tight\s*\]/i
  @caller  = caller()

  # VESTIGAL DEBUGGING CODE
  if @@debug
    f = File.new(".CODE.rb","w") and
      f.puts( code() ) and
      f.close() 
  end

  # DO THE PARSE (IF APPROPRIATE)
  if opts.size == 2
    return nil unless parse(source)
  else
    return nil unless parse()
  end

end

Public Instance Methods

[](name) click to toggle source

Operator to easily return cache of Getopt::Declare

# File lib/Getopt/Declare.rb, line 1716
def [](name)
  if @cache
    return @cache[name]
  else
    return nil
  end
end
[]=(name,val) click to toggle source

Operator to easily create new value in of Getopt::Declare

# File lib/Getopt/Declare.rb, line 1710
def []=(name,val)
  @cache = {} unless @cache
  @cache[name] = val
end
code(*t) click to toggle source

Main method to generate code to be evaluated for parsing.

# File lib/Getopt/Declare.rb, line 1464
  def code(*t)
    package = t[0] || ''
    code = %q%


@_deferred = []
@_errormsg = nil
@_finished = nil

begin

  begin
    undef :defer
    undef :reject
    undef :finish
  rescue
  end

  def defer(&i)
    @_deferred.push( i )
  end

  def reject(*i)
    if !i || i[0]
      @_errormsg = i[1] if i[1]
      throw :paramout
    end
  end

  def finish(*i)
    if i.size
      @_finished = i
    else
      @_finished = true
    end
  end

  @unused = []
  @cache  = {}
  _FOUND_ = {}
  _errors = 0
  _invalid = {}
  _lastprefix = nil

  _pos     = 0   # current position to match from
  _nextpos = 0   # next position to match from

  catch(:alldone) do 
    while !@_finished
      begin
        catch(:arg) do
          @_errormsg = nil

          # This is used for clustering of flags
          while _lastprefix
            substr = _args[_nextpos..-1]
            substr =~ /^(?!\s|\0|\Z)% +
                Getopt::Declare::Arg::negflagpat() + %q%/ or
              begin 
                _lastprefix=nil
                break
              end
            "#{_lastprefix}#{substr}" =~ /^(% +
                Getopt::Declare::Arg::posflagpat() + %q%)/ or
              begin 
                _lastprefix=nil
                break
              end
            _args = _args[0.._nextpos-1] + _lastprefix + _args[_nextpos..-1]
            break
          end #  while _lastprefix

          % + '' + %q%
          _pos = _nextpos if _args

          usage(0) if _args && gindex(_args,/\G(% + @helppat + %q%)(\s|\0|\Z)/,_pos)
          version(0) if _args && _args =~ /\G(% + @verspat + %q%)(\s|\0|\Z)/
      %

          for arg in @args
            code << arg.code(self,package)
          end

          code << %q%

        if _lastprefix
           _pos = _nextpos + _lastprefix.length()
           _lastprefix = nil
           next
        end

          _pos = _nextpos

          _args && _pos = gindex( _args, /\G[\s|\0]*(\S+)/, _pos ) or throw(:alldone)

          if @_errormsg
             $stderr.puts( "Error#{source}: #{@_errormsg}\n" )
          else
             @unused.push( @@m[0] )
          end

          _errors += 1 if @_errormsg

        end  # catch(:arg)

      ensure  # begin
        _pos = 0 if _pos.nil?
        _nextpos = _pos if _args
        if _args and _args.index( /\G(\s|\0)*\Z/, _pos )
          _args = _get_nextline.call(self) if !@_finished
          throw(:alldone) unless _args
          _pos = _nextpos = 0
          _lastprefix = ''
        end   # if
      end   # begin/ensure
    end   # while @_finished
  end   # catch(:alldone)
end  # begin

%


            ################################
            # Check for required arguments #
            ################################
          for arg in @args
            next unless arg.required

            code << %q%unless _FOUND_['% + arg.name + %q%'] %

              if @mutex[arg.name]
                for m in @mutex[arg.name]
                  code << %q# or _FOUND_['# + m + %q#']#
                end
              end

            code << %q%
   $stderr.puts "Error#{@source}: required parameter '% + arg.name + %q%' not found."
   _errors += 1
end
%

          end

            ########################################
            # Check for arguments requiring others #
            ########################################

          for arg in @args
            next unless arg.requires

            code << %q%
if _FOUND_['% + arg.name + %q%'] && !(% + arg.found_requires +
              %q%)
   $stderr.puts "Error#{@source}: parameter '% + arg.name + %q%' can only be specified with '% + arg.requires + %q%'"
   _FOUND_['% + arg.name + %q%'] = nil
   @args['% + arg.name + %q%'] = nil
   _errors += 1
end
            %
          end

          code << %q%
#################### Add unused arguments
if _args && _nextpos > 0 && _args.length() > 0
    @unused.replace( @unused + _args[_nextpos..-1].split(' ') )
end

for i in @unused
    i.tr!( "\0", " " )
end

%

          if @strict
            code << %q%
#################### Handle strict flag
unless _nextpos < ( _args ? _args.length : 0 )
  for i in @unused
    $stderr.puts "Error#{@source}: unrecognizable argument ('#{i}')"
    _errors += 1
  end
end
%
          end

          code << %q%
#################### Print help hint
if _errors > 0 && !@source.nil?
  $stderr.puts "\n(try '#$0 % + Getopt::Declare::Arg::besthelp + %q%' for more information)"
end

## cannot just assign unused to ARGV in ruby
unless @source != ''
  ARGV.clear
  @unused.map { |j| ARGV.push(j) }
end

unless _errors > 0
  for i in @_deferred
    begin
      i.call
    rescue => e
      STDERR.puts "Action in Getopt::Declare specification produced:\n#{e}"
      _errors += 1
    end
  end
end

!(_errors>0)  # return true or false (false for errors)

%
        return code
  end
each(&t) click to toggle source

Iterator for Getopt::Declare (travels thru all cache keys)

# File lib/Getopt/Declare.rb, line 1705
def each(&t)
  @cache.each(&t)
end
inspect() click to toggle source

Inspect cache (not the declare object)

# File lib/Getopt/Declare.rb, line 1681
def inspect
  return nil if !@cache 
  t = ''

  @cache.each { |a,b|
    t << a + " => "
    case b
    when Hash
      t << "{"
      i = []
      b.each { |c,d|
        i.push( " '#{c}' => " + d.inspect )
      }
      t << i.join(',')
      t << " }"
    else
      t << b.inspect
    end
    t << "\n"
  }
  t << "Unused: " + unused.join(', ')
end
parse(*opts) click to toggle source

Parse the parameter description and in some cases, optionally eval it, too.

# File lib/Getopt/Declare.rb, line 1196
def parse(*opts)
  source = opts[0]
  _args = nil
  _get_nextline = proc { nil }

  if source
    case source
    when Method
      _get_nextline = source
      _args = _get_nextline.call(self)
      source = '[METHOD]'
    when Proc
      _get_nextline = source
      _args = _get_nextline.call(self)
      source = '[PROC]'
    when IO
      if source.fileno > 0 && source.tty?
        _get_nextline = method(:_get_nextline)
        _args = $stdin.readline
        source = '<STDIN>'
      else
        _args = source.readlines.join(' ')
        _args.tr!('\t\n',' ')
      end
    when :build, :skip
      return 0
    when Array
      if source.length() == 1 && !source[0] ||
          source[0] == "-BUILD" ||
          source[0] == "-SKIP"
        return 0
      elsif source.length() == 2 && source[0] == "-ARGV"
        if !source[1] or !source[1] === Array
          raise 'Error: parse(["-ARGV"]) not passed an array as second parameter.'
        end
        _args  = source[1].map { |i| i.tr( " \t\n", "\0\0\0" ) }.join(' ')
        source = '<ARRAY>'
      elsif source.length() == 1 && source[0] == "-STDIN"
        _get_nextline = method(:_get_nextline)
        _args = $stdin.readline
        source = '<STDIN>'
      elsif source.length() == 1 && source[0] == '-CONFIG'
        progname = "#{$0}rc"
        progname.sub!(%r#.*/#,'')
        home = ENV['HOME'] || ''
        _args, source = _load_sources( _get_nextline,
                                      [ home+"/.#{progname}",
                                        ".#{progname}" ] )
      else
        # Bunch of files to load passed to parse()
        _args, source = _load_sources( _get_nextline, source )
      end
    when String  # else/case LITERAL STRING TO PARSE
      _args = source.dup
      source = source[0,7] + '...' if source && source.length() > 7
      source = "\"#{source[0..9]}\""
    else
      raise "Unknown source type for Getopt::Declare::parse"
    end  # case
    return 0 unless _args
    source = " (in #{source})"
  else
    _args  = ARGV.map { |i| i.tr( " \t\n", "\0\0\0" ) }.join(' ')
    source = ''
  end

  @source = source
  begin
    err = eval( code(@caller) )
    if $@
      # oops, something wrong... exit
      puts "#{$!}: #{$@.inspect}"
      exit(1)
    end
    if !err
      exit(1)
    end
  rescue
    raise
  end


  true
end
size() click to toggle source

Operator to return number of flags set

# File lib/Getopt/Declare.rb, line 1725
def size
  return 0 unless @cache
  return @cache.keys.size
end
type(*t) click to toggle source
# File lib/Getopt/Declare.rb, line 1281
def type(*t)
  Getopt::Declare::ScalarArg::addtype(t)
end
usage(*opt) click to toggle source

Print out usage information

# File lib/Getopt/Declare.rb, line 1310
def usage(*opt)

  t = @usage

  lastflag = nil
  lastdesc = nil
  usage = ''

  while !t.empty?

    # COMMENT:
    t.sub!(/\A[ \t]*#.*\n/,".") and next

    # TYPE DIRECTIVE:
    se  = DelimScanner::new( t )

    if t =~ /\A\s*\[\s*pvtype:/
      if action = se.extractBracketed("[")
        t.sub!(Regexp::quote( action ).to_re,'')
        t.sub!(/\A[ \t]*\n/,"")  
        next
      end
    end

    # ACTION
    codeblockDelimiters = {
      '{'     => '}'
    }
    se  = DelimScanner::new( t )
    if action = se.extractCodeblock(codeblockDelimiters)
      t.sub!(Regexp::quote( action ).to_re,'')
      t.sub!(/\A[ \t]*\n/,"")
      decfirst = 0 unless !decfirst.nil?
      next
    end


    # ARG + DESC:
    if t.sub!(re_argument,"")
      decfirst = 0 unless !decfirst.nil?
      spec = "#$1".expand_tabs!()
      desc = "#$2".expand_tabs!()

      while t.gsub!(re_more_desc, '')
        desc += "#$1".expand_tabs!
      end

      next if desc =~ /\[\s*undocumented\s*\]/i

      uoff = 0
      spec.gsub!(/(<[a-zA-Z]\w*):([^>]+)>/e) { |i|
        uoff += 1 + "#$2".length() and "#$1>"
      }
      spec.gsub!(/\t/,"=")

      ditto = desc =~ /\A\s*\[ditto\]/
      desc.gsub!(/^\s*\[.*?\]\s*\n/m,"")
      desc.gsub!(BracketDirectives,'')
      #desc.gsub!(/\[.*?\]/,"")

      
      if ditto
        desc = (lastdesc ? _ditto(lastflag,lastdesc,desc) : "" )
      elsif desc =~ /\A\s*\Z/
        next
      else
        lastdesc = desc
      end

      spec =~ /\A\s*(\S+)/ and lastflag = "#$1"
      
      desc.sub!(/\s+\Z/, "\n")
      usage += spec + ' ' * uoff + desc
      next
    end

    

    # OTHERWISE, DECORATION
    if t.sub!(/((?:(?!\[\s*pvtype:).)*)(\n|(?=\[\s*pvtype:))/,"")
      desc = "#$1"+("#$2"||'')
      #desc.gsub!(/^(\s*\[.*?\])+\s*\n/m,'')
      #desc.gsub!(/\[.*?\]/,'')  # eliminates anything in brackets
      if @tight || desc !~ /\A\s*\Z/
        desc.gsub!(BracketDirectives,'')
        next if desc =~ /\A\s*\Z/
      end
      decfirst = 1 unless !decfirst.nil? or desc =~ /\A\s*\Z/
      usage += desc
    end

  end  #while

  required = ''
  
  for arg in @args
    required += ' ' + arg.desc + ' '  if arg.required
  end
    
  usage.gsub!(/\255/,"[/") # REINSTATE ESCAPED '['s
    
  required.gsub!(/<([a-zA-Z]\w*):[^>]+>/,'<\1>')
  required.rstrip!
  
  helpcmd = Getopt::Declare::Arg::besthelp
  versioncmd = Getopt::Declare::Arg::bestversion
  
    
  header = ''
  unless @source.nil?
    header << version()
    prog = "#{$0}"
    prog.sub!(%r#.*/#,'')
    header <<  "Usage: #{prog} [options]#{required}\n"
    header <<  "       #{prog} #{helpcmd}\n" if helpcmd
    header <<  "       #{prog} #{versioncmd}\n" if versioncmd
    header <<  "\n" unless decfirst && decfirst == 1 && usage =~ /\A[ \t]*\n/
  end
  
  header << "Options:\n" unless decfirst && decfirst == 1
  
  usage.sub!(/[\s]+\Z/m, '')

  pager = $stdout

  #begin
  #  eval('require "IO/Pager";')
  #  pager = IO::Pager.new()
  #rescue
  #end

  if opt.empty?
    pager.puts "#{header}#{usage}"
    return 0
    ### usage
  end

  #usage.sub!(/\A[\s\n]+/m, '')
  pager.puts "#{header}#{usage}"
  exit(opt[0]) if opt[0]
end
used() click to toggle source

Return list of used parameters (after parsing)

# File lib/Getopt/Declare.rb, line 1456
def used
  used = @cache.keys
  return used.join(' ')
end
version(*t) click to toggle source

Print out version information and maybe exit

# File lib/Getopt/Declare.rb, line 1286
def version(*t)
  prog = "#{$0}"
  begin
    filedate = File.stat( prog ).mtime.localtime()
  rescue
    filedate = 'Unknown date'
  end
  prog.sub!(%r#.*/#,'')
  r = ''
  if defined?($VERSION)
    r << "\n#{prog}: version #{$VERSION}  (#{filedate})\n\n"
  else
    r << "\n#{prog}: version dated #{filedate}\n\n"
  end

  if t.empty?
    return r
  else
    puts r
    exit t[0]
  end 
end

Private Instance Methods

_ditto(originalflag, originaldesc, extra) click to toggle source

Handle quote replacements for [ditto] flag

# File lib/Getopt/Declare.rb, line 945
def _ditto(originalflag, originaldesc, extra)
  if originaldesc =~ /\n.*\n/
    originaldesc = "Same as #{originalflag} "
  else
    originaldesc.chomp
    originaldesc.gsub!(/\S/,'"')
    while originaldesc.gsub!(/"("+)"/,' \1 ')
    end
    originaldesc.gsub!(/""/,'" ')
  end

  "#{originaldesc}#{extra}\n"
end
_exclude(mref, excluded, mutexlist) click to toggle source

Check exclude conditions

# File lib/Getopt/Declare.rb, line 971
def _exclude(mref, excluded, mutexlist)
  for flag in mutexlist
    unless flag == excluded
      mref[flag]     = [] unless mref[flag]
      mref[excluded] = [] unless mref[excluded]
      mref[excluded].push( flag )
      mref[flag].push( excluded )
    end
  end
end
_get_nextline() click to toggle source

Read the next line from stdin

# File lib/Getopt/Declare.rb, line 833
def _get_nextline
  $stdin.readline
end
_infer(desc, arg, mutex) click to toggle source

Check parameter description for special options

# File lib/Getopt/Declare.rb, line 867
def _infer(desc, arg, mutex)
  while desc.sub!(/\[\s*mutex:\s*(.*?)\]/i,"")
    _mutex(mutex, "#$1".split(' '))
  end

  if desc =~ /\[\s*no\s*case\s*\]/i
    if arg
      arg.nocase = true
    end
  end

  if !arg.nil?
    if desc =~ /.*\[\s*excludes:\s*(.*?)\]/i
      _exclude(mutex, arg.name, ("#$1".split(' ')))
    end

    if desc =~ /.*\[\s*requires:\s*(.*?)\s*\]/i
      arg.requires = "#$1"
    end

    arg.required   = ( desc =~ /\[\s*required\s*\]/i )

    arg.repeatable = ( desc =~ /\[\s*repeatable\s*\]/i )
  end

  _typedef(desc) while desc.sub!(/.*?\[\s*pvtype:\s*/,"")

end
_load_sources( _get_nextline, files ) click to toggle source

For each file provided and found, read it in

# File lib/Getopt/Declare.rb, line 838
def _load_sources( _get_nextline, files )
  text  = ''
  found = []
  
  for i in files
    begin
      f = File.open(i,"r")
    rescue
      next
    end

    if f.tty?
      found.push( '<STDIN>' )
      _get_nextline = method(:_get_nextline)
    else
      found.push( i );
      t = f.readlines.join(' ')
      t.tr!('\t\n',' ')
      text += t
    end
  end

  return nil unless found.size > 0
  text = $stdin.readline if text.empty?
  return [text, found.join(' or ')]
end
_mutex(mref, mutexlist) click to toggle source

Check mutex conditions

# File lib/Getopt/Declare.rb, line 960
def _mutex(mref, mutexlist)
  for flag in mutexlist
    mref[flag] = [] unless mref[flag]
    for otherflag in mutexlist
      next if flag == otherflag
      mref[flag].push( otherflag )
    end
  end
end
_typedef(desc) click to toggle source

Extract a new type from the description and add it to the list of standard types

# File lib/Getopt/Declare.rb, line 900
def _typedef(desc)
  se  = DelimScanner::new( desc )
  tmp = se.scanQuotelike

  name = nil
  name, desc = tmp[:delimText], tmp[:suffix]  if tmp

  unless name
    desc.sub!(/\A\s*([^\] \t\n]+)/,"") and name = "#$1"
  end

  raise "Error: bad type directive (missing type name): [pvtype: " +
    desc[0,desc.index(']')||20] + "....\n" unless name

  se  = DelimScanner::new( desc )
  tmp = se.scanQuotelike('\s*:?\s*')

  # @TODO  What is element 2 of extract_quotelike?  :trail is a fake here
  # pat,desc,ind = (extract_quotelike(desc,'\s*:?\s*'))[5,1,2]
  pat = ind = nil
  pat, desc, ind = tmp[:match], tmp[:suffix], tmp[:prefix] if tmp
  pat = pat[1..-2] if pat

  unless pat
    desc.sub!(/\A\s*(:?)\s*([^\] \t\n]+)/,"") and pat = "#$2" and ind = "#$1"
  end

  pat = '' unless pat

  
  se  = DelimScanner::new( desc )
  action = se.extractCodeblock || ''

  desc.sub!( Regexp::quote(action).to_re, '' )
  action = action[1..-2]

  raise "Error: bad type directive (expected closing ']' but found " +
    "'#$1' instead): [pvtype: #{name} " + (pat ? "/#{pat}/" : '') +
    " action:#{action} #$1#$2....\n" if desc =~ /\A\s*([^\] \t\n])(\S*)/
  
  
  Getopt::Declare::ScalarArg::addtype(name,pat,action,ind=~/:/)
end
flatten(val, nested = nil) click to toggle source

Given an array or hash, flatten them to a string

# File lib/Getopt/Declare.rb, line 819
def flatten(val, nested = nil)
  case val
  when Array
    return val.map{ |i| flatten(i,1) }.join(" ")
  when Hash
    return val.keys.map{ |i| nested || 
        i =~ /^-/ ? [i, flatten(val[i],1)] : 
                    [flatten(val[i],1)] }.join(" ")
  else
    return val
  end
end
gindex(str, re, pos) click to toggle source

This is an additional function added to the class to simulate Perl’s pos() G behavior and m///g

It performs a regex match, and returns the last index position of the match or nil. On successive invocations, it allows doing regex matches NOT from the beginning of the string easily.

Class Array @@m stores the list of matches, as #$1 and similar variables have short lifespan in ruby, unlike perl.

# File lib/Getopt/Declare.rb, line 798
def gindex(str, re, pos)
  @@m.clear()
  if pos = str.index( re, pos )
    l = $&.size  # length of match
    if l > 0
      @@m[0] = "#$1"
      @@m[1] = "#$2"
      @@m[2] = "#$3"
      @@m[3] = "#$4"
      @@m[4] = "#$5"
      @@m[5] = "#$6"
      @@m[6] = "#$7"
      @@m[7] = "#$8"
      @@m[8] = "#$9"
      pos += l
    end
  end
  pos
end
re_argument() click to toggle source

Returns a regex to match a single argument line

# File lib/Getopt/Declare.rb, line 983
def re_argument
  /\A(.*?\S.*?#{@@separator})(.*?\n)/
end
re_more_desc() click to toggle source

Returns a regex to keep matching a multi-line description for an argument.

# File lib/Getopt/Declare.rb, line 989
def re_more_desc
  /\A((?![ \t]*(\{|\n)|.*?\S.*?#{@@separator}.*?\S).*?\S.*\n)/
end