Module: SOPT

Defined in:
lib/scout/simple_opt/doc.rb,
lib/scout/simple_opt/get.rb,
lib/scout/simple_opt/parse.rb,
lib/scout/simple_opt/setup.rb,
lib/scout/simple_opt/accessor.rb

Constant Summary collapse

GOT_OPTIONS =
IndiferentHash.setup({})

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.commandObject



8
9
10
# File 'lib/scout/simple_opt/doc.rb', line 8

def self.command
  @command ||= File.basename($0)
end

.descriptionObject



25
26
27
# File 'lib/scout/simple_opt/doc.rb', line 25

def self.description
  @description ||= "Missing"
end

.input_defaultsObject



30
31
32
# File 'lib/scout/simple_opt/accessor.rb', line 30

def self.input_defaults 
  @input_defaults ||= {}
end

.input_descriptionsObject



26
27
28
# File 'lib/scout/simple_opt/accessor.rb', line 26

def self.input_descriptions 
  @input_descriptions ||= {}
end

.input_shortcutsObject



18
19
20
# File 'lib/scout/simple_opt/accessor.rb', line 18

def self.input_shortcuts 
  @input_shortcuts ||= {}
end

.input_typesObject



22
23
24
# File 'lib/scout/simple_opt/accessor.rb', line 22

def self.input_types 
  @input_types ||= {}
end

.inputsObject



14
15
16
# File 'lib/scout/simple_opt/accessor.rb', line 14

def self.inputs 
  @inputs ||= []
end

.summaryObject



12
13
14
# File 'lib/scout/simple_opt/doc.rb', line 12

def self.summary
  @summary ||= ""
end

.synopsysObject



16
17
18
19
20
21
22
23
# File 'lib/scout/simple_opt/doc.rb', line 16

def self.synopsys
  @synopsys ||= begin
                  "#{command} " <<
                  inputs.collect{|name|
                    "[" << input_format(name, input_types[name] || :string, input_defaults[name], input_shortcuts[name]).sub(/:$/,'') << "]"
                  } * " "
                end
end

Class Method Details

.allObject



6
7
8
# File 'lib/scout/simple_opt/accessor.rb', line 6

def self.all
  @all ||= {}
end

.consume(args = ARGV) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/scout/simple_opt/get.rb', line 6

def self.consume(args = ARGV)
  i = 0
  @@current_options ||= {}
  while i < args.length do
    current = args[i]
    break if current == "--"
    if m = current.match(/--?(.+?)(?:=(.+))?$/)
      key = $1
      value = $2

      input = inputs.include?(key)? key : shortcuts[key]

      if input.nil?
        i += 1
        next
      else
        args.delete_at i
      end
    else
      i += 1
      next
    end

    if input_types[input] == :string
      value = args.delete_at(i) if value.nil?
      @@current_options[input] = value
    else
      if value.nil? and %w(F false FALSE no).include?(args[i])
        Log.warn "Boolean values are best specified as #{current}=[true|false], not #{ current } [true|false]. Token '#{args[i]}' following '#{current}' automatically assigned as value" 
        value = args.delete_at(i)
      end
      @@current_options[input] = %w(F false FALSE no).include?(value)? false : true
    end
  end

  IndiferentHash.setup @@current_options
  GOT_OPTIONS.merge! @@current_options

  @@current_options
end

.current_options=(options) ⇒ Object



3
4
5
# File 'lib/scout/simple_opt/get.rb', line 3

def self.current_options=(options)
  @@current_options = options
end

.delete_inputs(inputs) ⇒ Object



39
40
41
42
43
44
45
46
47
48
# File 'lib/scout/simple_opt/accessor.rb', line 39

def self.delete_inputs(inputs)
  inputs.each do |input|
    input = input.to_s
    self.shortcuts.delete self.input_shortcuts.delete(input)
    self.inputs.delete input
    self.input_types.delete input
    self.input_defaults.delete input
    self.input_descriptions.delete input
  end
end

.docObject



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/scout/simple_opt/doc.rb', line 104

def self.doc
  doc =<<-EOF
#{Log.color :magenta}#{command}(1) -- #{summary}
#{"=" * (command.length + summary.length + 7)}#{Log.color :reset}

  EOF

  if synopsys and not synopsys.empty?
    doc << Log.color(:magenta, "## SYNOPSYS") << "\n\n"
    doc << Log.color(:blue, synopsys) << "\n\n"
  end

  if description and not description.empty?
    doc << Log.color(:magenta, "## DESCRIPTION") << "\n\n"
    doc << Misc.format_paragraph(description) << "\n\n"
  end

  doc << Log.color(:magenta, "## OPTIONS") << "\n\n"
  doc << input_doc(inputs, input_types, input_descriptions, input_defaults, input_shortcuts)

  doc
end

.fix_shortcut(short, long) ⇒ Object



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/scout/simple_opt/parse.rb', line 2

def self.fix_shortcut(short, long)
  return short unless short and shortcuts.include?(short)

  current = shortcuts.select{|s,l| l == long}.collect{|s,l| s }.first
  return current if current

  chars = long.chars.to_a
  current = [chars.shift]
  short = current * ""

  if (shortcuts.include?(short) and not shortcuts[short] == long) 
    if long.index "-" or long.index "_"
      parts = long.split(/[_-]/)
      acc = parts.collect{|s| s[0] } * ""
      return acc unless shortcuts.include? acc
    elsif m = long.match(/(\d+)/)
      n = m[0]
      acc = long[0] + n
      return acc unless shortcuts.include? acc
    end
  end

  while shortcuts.include?(short) && shortcuts[short] != long 
    next_letter = chars.shift
    next_letter = chars.shift while %w(. - _).include?(next_letter)
    return nil if next_letter.nil?
    current << next_letter
    short = current * ""
  end

  return nil if shortcuts.include? short

  short
end

.get(opt_str) ⇒ Object



47
48
49
50
# File 'lib/scout/simple_opt/get.rb', line 47

def self.get(opt_str)
  SOPT.parse(opt_str)
  SOPT.consume(ARGV)
end

.input_array_doc(input_array) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/scout/simple_opt/doc.rb', line 49

def self.input_array_doc(input_array)
  input_array.collect do |name,type,description,default,options|
    type = :string if type.nil?

    name = name.to_s
    shortcut, options = options, nil if String === options || Symbol === options

    case options && options[:shortcut]
    when FalseClass
      shortcut = nil
    when TrueClass, nil
      shortcut = fix_shortcut(name[0], name)
    else
      shortcut = options[:shortcut]
    end unless shortcut

    shortcut = fix_shortcut(shortcut, name)
    register(shortcut, name, type, description) unless self.inputs.include? name
    name  = SOPT.input_format(name, type.to_sym, default, shortcut ) 
    Misc.format_definition_list_item(name, description)
  end * "\n"
end

.input_doc(inputs, input_types = nil, input_descriptions = nil, input_defaults = nil, input_shortcuts = nil) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/scout/simple_opt/doc.rb', line 72

def self.input_doc(inputs, input_types = nil, input_descriptions = nil, input_defaults = nil, input_shortcuts = nil)
  type = description = default = nil
  shortcut = ""
  seen = []
  inputs.collect do |name|
    next if seen.include? name
    seen << name

    type = input_types[name] unless input_types.nil?
    description = input_descriptions[name] unless input_descriptions.nil?
    default = input_defaults[name] unless input_defaults.nil?

    name = name.to_s

    case input_shortcuts
    when nil, FalseClass
      shortcut = nil
    when Hash
      shortcut = input_shortcuts[name] 
    when TrueClass
      shortcut = fix_shortcut(name[0], name)
    end

    type = :string if type.nil?
    register(shortcut, name, type, description) unless self.inputs.include? name

    name  = SOPT.input_format(name, type.to_sym, default, shortcut) 
    Misc.format_definition_list_item(name, description)
  end * "\n"
end

.input_format(name, type = nil, default = nil, short = nil) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/scout/simple_opt/doc.rb', line 29

def self.input_format(name, type = nil, default = nil, short = nil)
  input_str = (short.nil? or short.empty?) ? "--#{name}" : "-#{short},--#{name}"
  input_str = Log.color(:blue, input_str)
  extra = case type
  when nil
    ""
  when :boolean
    "[=false]" 
  when :tsv, :text
    "=<file|->"
  when :array
    "=<list|file|->"
  else
    "=<#{ type }>"
  end
  #extra << " (default: #{Array === default ? (default.length > 3 ? default[0..2]*", " + ', ...' : default*", " ): default})" if default != nil
  extra << " (default: #{Log.fingerprint(default)})" if default != nil
  input_str << Log.color(:green, extra)
end

.parse(opt_str) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/scout/simple_opt/parse.rb', line 46

def self.parse(opt_str)
  inputs = []

  if opt_str.include? "\n"
    re = /\n+/
  else
    re = /:/
  end

  opt_str.split(re).each do |entry|
    entry.strip!
    next if entry.empty?
    names, _sep, description = entry.partition(/\s+/)
    short, long, asterisk = names.match(/\s*(?:-(.+))?(?:--(.+?))([*])?$/).values_at 1,2,3 

    inputs << long
    register short, long, asterisk, description
  end

  inputs
end

.register(short, long, asterisk, description) ⇒ Object



37
38
39
40
41
42
43
44
# File 'lib/scout/simple_opt/parse.rb', line 37

def self.register(short, long, asterisk, description)
  short = fix_shortcut(short, long)
  shortcuts[short] = long if short
  inputs << long
  input_shortcuts[long] = short
  input_descriptions[long] = description
  input_types[long] = asterisk ? :string : :boolean
end

.require(options, *parameters) ⇒ Object



52
53
54
55
56
# File 'lib/scout/simple_opt/get.rb', line 52

def self.require(options, *parameters)
  parameters.flatten.each do |parameter|
    raise ParameterException, "Parameter '#{ Log.color :blue, parameter }' not given" if options[parameter].nil?
  end
end

.resetObject



34
35
36
37
# File 'lib/scout/simple_opt/accessor.rb', line 34

def self.reset
  @shortcuts = {}
  @all = {}
end

.setup(str) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/scout/simple_opt/setup.rb', line 3

def self.setup(str)
  parts = str.split(/\n\n+/)

  summary = parts.shift unless parts.first =~ /^\s*\$-/
  synopsys = parts.shift if parts.first =~ /^\s*\$/

  description = []
  while parts.first and parts.first !~ /^\s*-/
    description << parts.shift
  end
  description = description * "\n\n"

  options = parts.collect{|part| part.split("\n").select{|l| l=~ /^\s*-/ }  }.flatten.compact * "\n"

  synopsys.sub!(/^\$\s+/,'') if synopsys

  SOPT.summary = summary.strip if summary
  SOPT.synopsys = synopsys.strip if synopsys
  SOPT.description = description.strip if description
  SOPT.parse options  if options

  SOPT.consume
end

.shortcutsObject



10
11
12
# File 'lib/scout/simple_opt/accessor.rb', line 10

def self.shortcuts
  @shortcuts ||= {}
end

.usageObject



50
51
52
53
# File 'lib/scout/simple_opt/accessor.rb', line 50

def self.usage
  puts SOPT.doc
  exit 0
end