Class: Cri::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/SANStore/cri/base.rb

Overview

Cri::Base is the central class representing a commandline tool. It has a list of commands.

Direct Known Subclasses

SANStore::CLI::Base

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tool_name) ⇒ Base

Creates a new instance of the commandline tool.



14
15
16
17
18
# File 'lib/SANStore/cri/base.rb', line 14

def initialize(tool_name)
  @tool_name = tool_name

  @commands = []
end

Instance Attribute Details

#commandsObject (readonly)

The CLI’s list of commands (should also contain the help command)



8
9
10
# File 'lib/SANStore/cri/base.rb', line 8

def commands
  @commands
end

#help_commandObject

The CLI’s help command (required)



11
12
13
# File 'lib/SANStore/cri/base.rb', line 11

def help_command
  @help_command
end

Instance Method Details

#add_command(command) ⇒ Object

Adds the given command to the list of commands. Adding a command will also cause the command’s base to be set to this instance.



133
134
135
136
# File 'lib/SANStore/cri/base.rb', line 133

def add_command(command)
  @commands << command
  command.base = self
end

#command_named(name) ⇒ Object

Returns the command with the given name.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/SANStore/cri/base.rb', line 96

def command_named(name)
  # Find by exact name or alias
  command = @commands.find { |c| c.name == name or c.aliases.include?(name) }
  return command unless command.nil?

  # Find by approximation
  commands = @commands.select { |c| c.name[0, name.length] == name }
  if commands.length > 1
    $stderr.puts "#{@tool_name}: '#{name}' is ambiguous:"
    $stderr.puts "  #{commands.map { |c| c.name }.join(' ') }"
    exit 1
  elsif commands.length == 0
    $stderr.puts "#{@tool_name}: unknown command '#{name}'\n"
    show_help
    exit 1
  else
    return commands[0]
  end
end

#global_option_definitionsObject

Returns the list of global option definitionss.



127
128
129
# File 'lib/SANStore/cri/base.rb', line 127

def global_option_definitions
  []
end

#handle_option(option) ⇒ Object

Handles the given optio



139
140
141
# File 'lib/SANStore/cri/base.rb', line 139

def handle_option(option)
  false
end

#run(args) ⇒ Object

Parses the given commandline arguments and executes the requested command.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/SANStore/cri/base.rb', line 22

def run(args)
  # Check arguments
  if args.length == 0
    @help_command.run([], [])
    exit 1
  end

  # Partition options
  opts_before_command         = []
  command_name                = nil
  opts_and_args_after_command = []
  stage = 0
  args.each do |arg|
    # Update stage if necessary
    stage = 1 if stage == 0 && !is_option?(arg)

    # Add
    opts_before_command << arg         if stage == 0
    command_name = arg                 if stage == 1
    opts_and_args_after_command << arg if stage == 2

    # Update stage if necessary
    stage = 2 if stage == 1
  end

  # Handle options before command
  begin
    parsed_arguments = Cri::OptionParser.parse(opts_before_command, global_option_definitions)
  rescue Cri::OptionParser::IllegalOptionError => e
    $stderr.puts "illegal option -- #{e}"
    exit 1
  end
  parsed_arguments[:options].keys.each do |option|
    handle_option(option)
  end

  # Get command
  if command_name.nil?
    $stderr.puts "no command given"
    exit 1
  end
  command = command_named(command_name)
  if command.nil?
    $stderr.puts "no such command: #{command_name}"
    exit 1
  end

  # Parse arguments
  option_definitions = command.option_definitions + global_option_definitions
  begin
    parsed_arguments = Cri::OptionParser.parse(opts_and_args_after_command, option_definitions)
  rescue Cri::OptionParser::IllegalOptionError => e
    $stderr.puts "illegal option -- #{e}"
    exit 1
  rescue Cri::OptionParser::OptionRequiresAnArgumentError => e
    $stderr.puts "option requires an argument -- #{e}"
    exit 1
  end

  # Handle global options
  global_options = global_option_definitions.map { |o| o[:long] }
  global_options.delete_if { |o| !parsed_arguments[:options].keys.include?(o.to_sym) }
  global_options.each { |o| handle_option(o.to_sym) }

  if parsed_arguments[:options].has_key?(:help)
    # Show help for this command
    show_help(command)
  else
    # Run command
    command.run(parsed_arguments[:options], parsed_arguments[:arguments])
  end
end

#show_help(command = nil) ⇒ Object

Shows the help text for the given command, or shows the general help text if no command is given.



118
119
120
121
122
123
124
# File 'lib/SANStore/cri/base.rb', line 118

def show_help(command=nil)
  if command.nil?
    @help_command.run([], [])
  else
    @help_command.run([], [ command.name ])
  end
end