rzo 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,123 @@
1
+ module Rzo
2
+ ##
3
+ # Mix-in module to handle all option parsing. Options will be accessible from
4
+ # the `opts` method. This module is meant to be included in an App class.
5
+ module OptionParsing
6
+ attr_reader :argv, :env, :opts
7
+
8
+ ##
9
+ # Reset the @opts instance variable by parsing @argv and @env. Operates
10
+ # against duplicate copies of the argument vector avoid side effects.
11
+ #
12
+ # @return [Hash<Symbol, String>] Options hash
13
+ def reset_options!
14
+ @opts = parse_options(argv, env)
15
+ end
16
+
17
+ ##
18
+ # Parse options using the argument vector and the environment hash as
19
+ # input. Option parsing occurs in two phases, first the global options are
20
+ # parsed. These are the options specified before the subcommand. The
21
+ # subcommand, if any, is matched, and subcommand specific options are then
22
+ # parsed from the remainder of the argument vector.
23
+ #
24
+ # @param [Array] argv The argument vector, passed to the option parser.
25
+ #
26
+ # @param [Hash] env The environment hash, passed to the option parser to
27
+ # supply defaults not specified on the command line argument vector.
28
+ #
29
+ # @return [Hash<Symbol, String>] options hash
30
+ def parse_options(argv, env)
31
+ argv_copy = argv.dup
32
+ opts = parse_global_options!(argv_copy, env)
33
+ if subcommand = parse_subcommand!(argv_copy)
34
+ opts[:subcommand] = subcommand
35
+ sub_opts = parse_subcommand_options!(subcommand, argv_copy, env)
36
+ opts.merge!(sub_opts)
37
+ end
38
+ opts
39
+ end
40
+
41
+ ##
42
+ # Parse out the global options, the ones specified between the main
43
+ # executable and the subcommand argument.
44
+ #
45
+ # Modifies argv as a side effect, shifting elements from the array until
46
+ # the first unknown option is found, which is assumed to be the subcommand
47
+ # name.
48
+ #
49
+ # @return [Hash<Symbol, String>] Global options
50
+ # rubocop:disable Metrics/MethodLength
51
+ def parse_global_options!(argv, env)
52
+ semver = Rzo::VERSION
53
+ prog_name = NAME
54
+ Rzo::Trollop.options(argv) do
55
+ stop_on_unknown
56
+ version "#{prog_name} #{semver} (c) 2017 Garrett Honeycutt"
57
+ banner BANNER
58
+ log_msg = 'Log file to write to or keywords '\
59
+ 'STDOUT, STDERR {RZO_LOGTO}'
60
+ opt :logto, log_msg, default: env['RZO_LOGTO'] || 'STDERR'
61
+ opt :syslog, 'Log to syslog', default: false, conflicts: :logto
62
+ opt :verbose, 'Set log level to INFO'
63
+ opt :debug, 'Set log level to DEBUG'
64
+ opt :config, 'Rizzo config file {RZO_CONFIG}',
65
+ default: env['RZO_CONFIG'] || '~/.rizzo.json'
66
+ end
67
+ end
68
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
69
+
70
+ ##
71
+ # Extract the subcommand, if any, from the arguments provided. Modifies
72
+ # argv as a side effect, shifting the subcommand name if it is present.
73
+ #
74
+ # @return [String] The subcommand name, e.g. 'backup' or 'restore', or
75
+ # false if no arguments remain in the argument vector.
76
+ def parse_subcommand!(argv)
77
+ argv.shift || false
78
+ end
79
+
80
+ ##
81
+ # Parse the subcommand options. This method branches out because each
82
+ # subcommand can have quite different options, unlike global options which
83
+ # are consistent across all invocations of the application.
84
+ #
85
+ # Modifies argv as a side effect, shifting all options as things are
86
+ # parsed.
87
+ #
88
+ # @return [Hash<Symbol, String>] Subcommand specific options hash
89
+ # rubocop:disable Metrics/MethodLength
90
+ def parse_subcommand_options!(subcommand, argv, env)
91
+ prog_name = NAME
92
+ case subcommand
93
+ when 'config'
94
+ Rzo::Trollop.options(argv) do
95
+ banner "#{prog_name} #{subcommand} options:"
96
+ opt :output, 'Config output', short: 'o', default: env['RZO_OUTPUT'] || 'STDOUT'
97
+ end
98
+ when 'generate'
99
+ Rzo::Trollop.options(argv) do
100
+ banner "#{prog_name} #{subcommand} options:"
101
+ opt :vagrantfile, 'Output Vagrantfile', short: 'o', default: env['RZO_VAGRANTFILE'] || 'Vagrantfile'
102
+ end
103
+ else
104
+ Rzo::Trollop.die "Unknown subcommand: #{subcommand.inspect}"
105
+ end
106
+ end
107
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
108
+
109
+ # The name of the executable, could be `rizzo` or `rzo`
110
+ NAME = File.basename($PROGRAM_NAME).freeze
111
+
112
+ # rubocop:disable Layout/IndentHeredoc
113
+ BANNER = <<-"EOBANNER".freeze
114
+ usage: #{NAME} [GLOBAL OPTIONS] SUBCOMMAND [ARGS]
115
+ Sub Commands:
116
+
117
+ config Print out the combined rizzo json config
118
+ generate Initialize Vagrantfile in top control repo
119
+
120
+ Global options: (Note, command line arguments supersede ENV vars in {}'s)
121
+ EOBANNER
122
+ end
123
+ end