/
command.cr
112 lines (98 loc) · 3.02 KB
/
command.cr
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
require "./argument_list"
require "./command/*"
abstract class Admiral::Command
@program_name : String
@argv : ArgumentList = Admiral.new_arglist(::ARGV)
@input_io : IO::FileDescriptor = STDIN
@output_io : IO::FileDescriptor = STDOUT
@error_io : IO::FileDescriptor = STDERR
@parent : ::Admiral::Command?
# Returns the commands program name.
getter program_name : String = PROGRAM_NAME
def self.expand_short_flags(argv : Admiral::ArgumentList)
Admiral::ArgumentList.new.tap do |args|
argv.each do |arg|
if arg =~ /^-\w+/
flags_with_value = arg.split("=", 2)
flags = flags_with_value[0][1..-1].chars.map(&.to_s)
if value = flags_with_value[1]?
flags[-1] = flags[-1] + "=" + value
end
flags.each do |flag|
args << StringValue.new("-" + flag)
end
else
args << arg
end
end
end
end
# Initializes a command with a `String`, which will be split into arguments.
def initialize(string : String, program_name = PROGRAM_NAME, input = STDIN, output = STDOUT, error = STDERR, parent : ::Admiral::Command? = nil)
initialize(string.split(" "), program_name, input, output, error, parent)
end
# Initializes a command with an `Array(String)` of arguments.
def initialize(argv : Array(String) = ::ARGV.clone, program_name = PROGRAM_NAME, input = STDIN, output = STDOUT, error = STDERR, parent : ::Admiral::Command? = nil)
initialize(Admiral.new_arglist(argv), program_name, input, output, error, parent)
end
# Initializes a command with an `Admiral::ArgumentList`.
def initialize(argv, program_name, input = nil, output = nil, error = nil, parent = nil)
@argv = self.class.expand_short_flags argv
@program_name = parent ? "#{parent.program_name} #{program_name}" : program_name
@parent = parent
@input_io = !input.nil? ? input : !parent.nil? ? parent.@input_io : STDIN
@output_io = !output.nil? ? output : !parent.nil? ? parent.@output_io : STDOUT
@error_io = !error.nil? ? error : !parent.nil? ? parent.@error_io : STDERR
end
# The run command.
abstract def run
# Returns the parent command if one is specified, or returns an error.
def parent
@parent.not_nil!
end
# Prints to the command's output `IO`.
def print(*args)
case (io = @output_io)
when IO
io.print(*args)
io.flush
end
end
# Puts to the command's output `IO`.
def puts(*args)
io = @output_io
case io
when IO
io.puts(*args)
end
end
# Puts to the command's error `IO`.
def error(*args)
io = @error_io
case io
when IO
io.puts(*args)
end
end
def panic(*args)
error *args
exit 1
end
# Prints to the command's error `IO`.
def print_error(*args)
case (io = @error_io)
when IO
io.print(*args)
io.flush
end
end
# Gets from the command's input `IO`.
def gets(*args)
case (io = @input_io)
when IO
io.gets(*args)
else
raise "Input is not allocated"
end
end
end