1
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
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
module Slop
class MissingCommand < Error
end
class UnknownCommand < Error
attr_reader :name
def initialize(msg, name)
super(msg)
@name = name
end
end
end
module Groonga
class CommandLineParser
def initialize(program_name=nil)
$0 ||= nil
@program_name = program_name || $0
@commands = []
@action_runner = ActionRunner.new
@options = Slop::Options.new
setup_options
end
def options
yield(@options) if block_given?
@options
end
def add_command(name)
command = Command.new(@program_name, name)
setup_common_options(command.options)
yield(command)
@commands << command
end
def add_action(&action)
@action_runner.add(&action)
end
def parse(command_line)
if @commands.empty?
result = @options.parse(command_line)
apply_actions(result)
return result
end
if command_line.empty?
message = "Command is missing"
raise Slop::MissingCommand.new(message)
end
first_argument = command_line.first
if first_argument.start_with?("-")
result = @options.parse(command_line)
apply_actions(result)
return result
end
command_name = first_argument
command = find_command(command_name)
if command.nil?
message = "Unknown command: <#{command_name}>"
raise Slop::UnknownCommand.new(message, command_name)
end
command.parse(command_line[1..-1])
end
def help_message
message = @options.to_s
@commands.each do |command|
message << "\n"
indent = " " * 4
message << "#{command.description}:\n" if command.description
message << "#{indent}#{command.options.banner}\n"
end
message
end
private
def setup_options
@options.banner = "Usage: #{@program_name} [OPTIONS]"
setup_common_options(@options)
@options.on("-h", "--help", "Display this help message.",
:tail => true) do
$stdout.puts(help_message)
end
end
def setup_common_options(options)
options.string("--log-path",
"Change log path (#{Logger.default_path})",
default: Logger.default_path)
default_log_level = Logger.default_level
options.string("--log-level",
"Change log level (#{default_log_level.name})",
default: default_log_level)
end
def find_command(name)
@commands.find do |command|
command.name == name
end
end
def apply_actions(result)
@action_runner.run(result) unless result.help?
end
class ActionRunner
def initialize
@actions = []
end
def add(&action)
@actions << action
end
def run(*args)
@actions.each do |action|
action.call(*args)
end
end
end
class Command
attr_reader :name
attr_reader :options
attr_accessor :description
def initialize(program_name, name)
@program_name = program_name
@name = name
@options = Slop::Options.new
setup_options
@description = nil
@action_runner = ActionRunner.new
end
def add_action(&action)
@action_runner.add(&action)
end
def parse(command_line)
result = @options.parse(command_line)
@action_runner.run(result) unless result.help?
result
end
def help_message
message = ""
message << "Description: #{@description}\n" if @description
message << @options.to_s
message
end
private
def setup_options
@options.banner = "Usage: #{@program_name} #{@name} [OPTIONS]"
@options.on("-h", "--help", "Display this help message.",
:tail => true) do
$stdout.puts(help_message)
end
end
end
end
end
|