pry 0.12.2 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +110 -1
  3. data/LICENSE +1 -1
  4. data/README.md +331 -269
  5. data/bin/pry +5 -0
  6. data/lib/pry.rb +133 -119
  7. data/lib/pry/basic_object.rb +8 -4
  8. data/lib/pry/block_command.rb +22 -0
  9. data/lib/pry/class_command.rb +194 -0
  10. data/lib/pry/cli.rb +40 -31
  11. data/lib/pry/code.rb +39 -27
  12. data/lib/pry/code/code_file.rb +28 -24
  13. data/lib/pry/code/code_range.rb +4 -2
  14. data/lib/pry/code/loc.rb +15 -8
  15. data/lib/pry/code_object.rb +40 -38
  16. data/lib/pry/color_printer.rb +47 -46
  17. data/lib/pry/command.rb +166 -369
  18. data/lib/pry/command_set.rb +76 -73
  19. data/lib/pry/command_state.rb +31 -0
  20. data/lib/pry/commands/amend_line.rb +86 -81
  21. data/lib/pry/commands/bang.rb +18 -14
  22. data/lib/pry/commands/bang_pry.rb +15 -11
  23. data/lib/pry/commands/cat.rb +61 -54
  24. data/lib/pry/commands/cat/abstract_formatter.rb +23 -18
  25. data/lib/pry/commands/cat/exception_formatter.rb +71 -60
  26. data/lib/pry/commands/cat/file_formatter.rb +55 -49
  27. data/lib/pry/commands/cat/input_expression_formatter.rb +35 -30
  28. data/lib/pry/commands/cd.rb +40 -35
  29. data/lib/pry/commands/change_inspector.rb +29 -22
  30. data/lib/pry/commands/change_prompt.rb +44 -39
  31. data/lib/pry/commands/clear_screen.rb +16 -10
  32. data/lib/pry/commands/code_collector.rb +148 -133
  33. data/lib/pry/commands/disable_pry.rb +23 -19
  34. data/lib/pry/commands/easter_eggs.rb +19 -30
  35. data/lib/pry/commands/edit.rb +184 -161
  36. data/lib/pry/commands/edit/exception_patcher.rb +21 -17
  37. data/lib/pry/commands/edit/file_and_line_locator.rb +34 -23
  38. data/lib/pry/commands/exit.rb +39 -35
  39. data/lib/pry/commands/exit_all.rb +24 -20
  40. data/lib/pry/commands/exit_program.rb +20 -16
  41. data/lib/pry/commands/find_method.rb +168 -160
  42. data/lib/pry/commands/fix_indent.rb +16 -12
  43. data/lib/pry/commands/help.rb +140 -133
  44. data/lib/pry/commands/hist.rb +151 -150
  45. data/lib/pry/commands/import_set.rb +20 -16
  46. data/lib/pry/commands/jump_to.rb +25 -21
  47. data/lib/pry/commands/list_inspectors.rb +35 -28
  48. data/lib/pry/commands/ls.rb +124 -102
  49. data/lib/pry/commands/ls/constants.rb +59 -42
  50. data/lib/pry/commands/ls/formatter.rb +50 -46
  51. data/lib/pry/commands/ls/globals.rb +38 -34
  52. data/lib/pry/commands/ls/grep.rb +17 -13
  53. data/lib/pry/commands/ls/instance_vars.rb +29 -27
  54. data/lib/pry/commands/ls/interrogatable.rb +18 -12
  55. data/lib/pry/commands/ls/jruby_hacks.rb +47 -41
  56. data/lib/pry/commands/ls/local_names.rb +26 -22
  57. data/lib/pry/commands/ls/local_vars.rb +38 -28
  58. data/lib/pry/commands/ls/ls_entity.rb +47 -51
  59. data/lib/pry/commands/ls/methods.rb +44 -43
  60. data/lib/pry/commands/ls/methods_helper.rb +46 -42
  61. data/lib/pry/commands/ls/self_methods.rb +23 -22
  62. data/lib/pry/commands/nesting.rb +21 -17
  63. data/lib/pry/commands/play.rb +93 -82
  64. data/lib/pry/commands/pry_backtrace.rb +24 -17
  65. data/lib/pry/commands/pry_version.rb +15 -11
  66. data/lib/pry/commands/raise_up.rb +27 -22
  67. data/lib/pry/commands/reload_code.rb +60 -48
  68. data/lib/pry/commands/reset.rb +16 -12
  69. data/lib/pry/commands/ri.rb +55 -45
  70. data/lib/pry/commands/save_file.rb +45 -43
  71. data/lib/pry/commands/shell_command.rb +51 -51
  72. data/lib/pry/commands/shell_mode.rb +21 -17
  73. data/lib/pry/commands/show_doc.rb +81 -68
  74. data/lib/pry/commands/show_info.rb +189 -171
  75. data/lib/pry/commands/show_input.rb +16 -11
  76. data/lib/pry/commands/show_source.rb +109 -45
  77. data/lib/pry/commands/stat.rb +35 -31
  78. data/lib/pry/commands/switch_to.rb +21 -15
  79. data/lib/pry/commands/toggle_color.rb +20 -16
  80. data/lib/pry/commands/watch_expression.rb +89 -86
  81. data/lib/pry/commands/watch_expression/expression.rb +32 -27
  82. data/lib/pry/commands/whereami.rb +156 -148
  83. data/lib/pry/commands/wtf.rb +75 -50
  84. data/lib/pry/config.rb +311 -25
  85. data/lib/pry/config/attributable.rb +22 -0
  86. data/lib/pry/config/lazy_value.rb +29 -0
  87. data/lib/pry/config/memoized_value.rb +34 -0
  88. data/lib/pry/config/value.rb +24 -0
  89. data/lib/pry/control_d_handler.rb +28 -0
  90. data/lib/pry/core_extensions.rb +9 -7
  91. data/lib/pry/editor.rb +48 -21
  92. data/lib/pry/env.rb +18 -0
  93. data/lib/pry/exception_handler.rb +43 -0
  94. data/lib/pry/exceptions.rb +13 -16
  95. data/lib/pry/forwardable.rb +5 -1
  96. data/lib/pry/helpers.rb +2 -0
  97. data/lib/pry/helpers/base_helpers.rb +68 -197
  98. data/lib/pry/helpers/command_helpers.rb +50 -61
  99. data/lib/pry/helpers/documentation_helpers.rb +20 -13
  100. data/lib/pry/helpers/options_helpers.rb +14 -7
  101. data/lib/pry/helpers/platform.rb +7 -5
  102. data/lib/pry/helpers/table.rb +33 -26
  103. data/lib/pry/helpers/text.rb +17 -14
  104. data/lib/pry/history.rb +48 -56
  105. data/lib/pry/hooks.rb +21 -12
  106. data/lib/pry/indent.rb +54 -50
  107. data/lib/pry/input_completer.rb +248 -230
  108. data/lib/pry/input_lock.rb +8 -9
  109. data/lib/pry/inspector.rb +36 -24
  110. data/lib/pry/last_exception.rb +45 -45
  111. data/lib/pry/method.rb +141 -94
  112. data/lib/pry/method/disowned.rb +16 -4
  113. data/lib/pry/method/patcher.rb +12 -3
  114. data/lib/pry/method/weird_method_locator.rb +68 -44
  115. data/lib/pry/object_path.rb +33 -25
  116. data/lib/pry/output.rb +121 -35
  117. data/lib/pry/pager.rb +41 -42
  118. data/lib/pry/plugins.rb +25 -8
  119. data/lib/pry/prompt.rb +123 -54
  120. data/lib/pry/pry_class.rb +61 -98
  121. data/lib/pry/pry_instance.rb +217 -215
  122. data/lib/pry/repl.rb +18 -22
  123. data/lib/pry/repl_file_loader.rb +27 -21
  124. data/lib/pry/ring.rb +11 -6
  125. data/lib/pry/slop.rb +574 -563
  126. data/lib/pry/slop/commands.rb +164 -169
  127. data/lib/pry/slop/option.rb +172 -168
  128. data/lib/pry/syntax_highlighter.rb +26 -0
  129. data/lib/pry/system_command_handler.rb +17 -0
  130. data/lib/pry/testable.rb +59 -61
  131. data/lib/pry/testable/evalable.rb +21 -12
  132. data/lib/pry/testable/mockable.rb +18 -10
  133. data/lib/pry/testable/pry_tester.rb +71 -56
  134. data/lib/pry/testable/utility.rb +29 -21
  135. data/lib/pry/testable/variables.rb +49 -43
  136. data/lib/pry/version.rb +3 -1
  137. data/lib/pry/warning.rb +27 -0
  138. data/lib/pry/wrapped_module.rb +51 -42
  139. data/lib/pry/wrapped_module/candidate.rb +21 -14
  140. metadata +31 -30
  141. data/lib/pry/commands.rb +0 -6
  142. data/lib/pry/commands/disabled_commands.rb +0 -2
  143. data/lib/pry/commands/gem_cd.rb +0 -26
  144. data/lib/pry/commands/gem_install.rb +0 -32
  145. data/lib/pry/commands/gem_list.rb +0 -33
  146. data/lib/pry/commands/gem_open.rb +0 -29
  147. data/lib/pry/commands/gem_readme.rb +0 -25
  148. data/lib/pry/commands/gem_search.rb +0 -40
  149. data/lib/pry/commands/gem_stats.rb +0 -83
  150. data/lib/pry/commands/gist.rb +0 -102
  151. data/lib/pry/commands/install_command.rb +0 -54
  152. data/lib/pry/config/behavior.rb +0 -255
  153. data/lib/pry/config/convenience.rb +0 -28
  154. data/lib/pry/config/default.rb +0 -159
  155. data/lib/pry/config/memoization.rb +0 -48
  156. data/lib/pry/platform.rb +0 -91
  157. data/lib/pry/rubygem.rb +0 -84
  158. data/lib/pry/terminal.rb +0 -91
@@ -1,194 +1,189 @@
1
- class Pry::Slop
2
- class Commands
3
- include Enumerable
4
-
5
- attr_reader :config, :commands, :arguments
6
- attr_writer :banner
7
-
8
- # Create a new instance of Slop::Commands and optionally build
9
- # Slop instances via a block. Any configuration options used in
10
- # this method will be the default configuration options sent to
11
- # each Slop object created.
12
- #
13
- # config - An optional configuration Hash.
14
- # block - Optional block used to define commands.
15
- #
16
- # Examples:
17
- #
18
- # commands = Slop::Commands.new do
19
- # on :new do
20
- # on '-o', '--outdir=', 'The output directory'
21
- # on '-v', '--verbose', 'Enable verbose mode'
22
- # end
23
- #
24
- # on :generate do
25
- # on '--assets', 'Generate assets', :default => true
26
- # end
27
- #
28
- # global do
29
- # on '-D', '--debug', 'Enable debug mode', :default => false
30
- # end
31
- # end
32
- #
33
- # commands[:new].class #=> Slop
34
- # commands.parse
35
- #
36
- def initialize(config = {}, &block)
37
- @config = config
38
- @commands = {}
39
- @banner = nil
40
- @triggered_command = nil
41
-
42
- warn "[DEPRECATED] Slop::Commands is deprecated and will be removed in "\
43
- "Slop version 4. Check out http://injekt.github.com/slop/#commands for "\
44
- "a new implementation of commands."
45
-
46
- if block_given?
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ class Slop
5
+ class Commands
6
+ include Enumerable
7
+
8
+ attr_reader :config, :commands, :arguments
9
+ attr_writer :banner
10
+
11
+ # Create a new instance of Slop::Commands and optionally build
12
+ # Slop instances via a block. Any configuration options used in
13
+ # this method will be the default configuration options sent to
14
+ # each Slop object created.
15
+ #
16
+ # config - An optional configuration Hash.
17
+ # block - Optional block used to define commands.
18
+ #
19
+ # Examples:
20
+ #
21
+ # commands = Slop::Commands.new do
22
+ # on :new do
23
+ # on '-o', '--outdir=', 'The output directory'
24
+ # on '-v', '--verbose', 'Enable verbose mode'
25
+ # end
26
+ #
27
+ # on :generate do
28
+ # on '--assets', 'Generate assets', :default => true
29
+ # end
30
+ #
31
+ # global do
32
+ # on '-D', '--debug', 'Enable debug mode', :default => false
33
+ # end
34
+ # end
35
+ #
36
+ # commands[:new].class #=> Slop
37
+ # commands.parse
38
+ #
39
+ def initialize(config = {}, &block)
40
+ @config = config
41
+ @commands = {}
42
+ @banner = nil
43
+ @triggered_command = nil
44
+
45
+ warn "[DEPRECATED] Slop::Commands is deprecated and will be removed in "\
46
+ "Slop version 4. Check out http://injekt.github.com/slop/#commands for "\
47
+ "a new implementation of commands."
48
+
49
+ return unless block_given?
50
+
47
51
  block.arity == 1 ? yield(self) : instance_eval(&block)
48
52
  end
49
- end
50
53
 
51
- # Optionally set the banner for this command help output.
52
- #
53
- # banner - The String text to set the banner.
54
- #
55
- # Returns the String banner if one is set.
56
- def banner(banner = nil)
57
- @banner = banner if banner
58
- @banner
59
- end
54
+ # Optionally set the banner for this command help output.
55
+ #
56
+ # banner - The String text to set the banner.
57
+ #
58
+ # Returns the String banner if one is set.
59
+ def banner(banner = nil)
60
+ @banner = banner if banner
61
+ @banner
62
+ end
60
63
 
61
- # Add a Slop instance for a specific command.
62
- #
63
- # command - A String or Symbol key used to identify this command.
64
- # config - A Hash of configuration options to pass to Slop.
65
- # block - An optional block used to pass options to Slop.
66
- #
67
- # Returns the newly created Slop instance mapped to command.
68
- def on(command, config = {}, &block)
69
- commands[command.to_s] = Slop.new(@config.merge(config), &block)
70
- end
64
+ # Add a Slop instance for a specific command.
65
+ #
66
+ # command - A String or Symbol key used to identify this command.
67
+ # config - A Hash of configuration options to pass to Slop.
68
+ # block - An optional block used to pass options to Slop.
69
+ #
70
+ # Returns the newly created Slop instance mapped to command.
71
+ def on(command, config = {}, &block)
72
+ commands[command.to_s] = Slop.new(@config.merge(config), &block)
73
+ end
71
74
 
72
- # Add a Slop instance used when no other commands exist.
73
- #
74
- # config - A Hash of configuration options to pass to Slop.
75
- # block - An optional block used to pass options to Slop.
76
- #
77
- # Returns the newly created Slop instance mapped to default.
78
- def default(config = {}, &block)
79
- on('default', config, &block)
80
- end
75
+ # Add a Slop instance used when no other commands exist.
76
+ #
77
+ # config - A Hash of configuration options to pass to Slop.
78
+ # block - An optional block used to pass options to Slop.
79
+ #
80
+ # Returns the newly created Slop instance mapped to default.
81
+ def default(config = {}, &block)
82
+ on('default', config, &block)
83
+ end
81
84
 
82
- # Add a global Slop instance.
83
- #
84
- # config - A Hash of configuration options to pass to Slop.
85
- # block - An optional block used to pass options to Slop.
86
- #
87
- # Returns the newly created Slop instance mapped to global.
88
- def global(config = {}, &block)
89
- on('global', config, &block)
90
- end
85
+ # Add a global Slop instance.
86
+ #
87
+ # config - A Hash of configuration options to pass to Slop.
88
+ # block - An optional block used to pass options to Slop.
89
+ #
90
+ # Returns the newly created Slop instance mapped to global.
91
+ def global(config = {}, &block)
92
+ on('global', config, &block)
93
+ end
91
94
 
92
- # Fetch the instance of Slop tied to a command.
93
- #
94
- # key - The String or Symbol key used to locate this command.
95
- #
96
- # Returns the Slop instance if this key is found, nil otherwise.
97
- def [](key)
98
- commands[key.to_s]
99
- end
100
- alias get []
101
-
102
- # Check for a command presence.
103
- #
104
- # Examples:
105
- #
106
- # cmds.parse %w( foo )
107
- # cmds.present?(:foo) #=> true
108
- # cmds.present?(:bar) #=> false
109
- #
110
- # Returns true if the given key is present in the parsed arguments.
111
- def present?(key)
112
- key.to_s == @triggered_command
113
- end
95
+ # Fetch the instance of Slop tied to a command.
96
+ #
97
+ # key - The String or Symbol key used to locate this command.
98
+ #
99
+ # Returns the Slop instance if this key is found, nil otherwise.
100
+ def [](key)
101
+ commands[key.to_s]
102
+ end
103
+ alias get []
104
+
105
+ # Check for a command presence.
106
+ #
107
+ # Examples:
108
+ #
109
+ # cmds.parse %w( foo )
110
+ # cmds.present?(:foo) #=> true
111
+ # cmds.present?(:bar) #=> false
112
+ #
113
+ # Returns true if the given key is present in the parsed arguments.
114
+ def present?(key)
115
+ key.to_s == @triggered_command
116
+ end
114
117
 
115
- # Enumerable interface.
116
- def each(&block)
117
- @commands.each(&block)
118
- end
118
+ # Enumerable interface.
119
+ def each(&block)
120
+ @commands.each(&block)
121
+ end
119
122
 
120
- # Parse a list of items.
121
- #
122
- # items - The Array of items to parse.
123
- #
124
- # Returns the original Array of items.
125
- def parse(items = ARGV)
126
- parse! items.dup
127
- items
128
- end
123
+ # Parse a list of items.
124
+ #
125
+ # items - The Array of items to parse.
126
+ #
127
+ # Returns the original Array of items.
128
+ def parse(items = ARGV)
129
+ parse! items.dup
130
+ items
131
+ end
129
132
 
130
- # Parse a list of items, removing any options or option arguments found.
131
- #
132
- # items - The Array of items to parse.
133
- #
134
- # Returns the original Array of items with options removed.
135
- def parse!(items = ARGV)
136
- if (opts = commands[items[0].to_s])
137
- @triggered_command = items.shift
138
- execute_arguments! items
139
- opts.parse! items
140
- execute_global_opts! items
141
- else
142
- if (opts = commands['default'])
133
+ # Parse a list of items, removing any options or option arguments found.
134
+ #
135
+ # items - The Array of items to parse.
136
+ #
137
+ # Returns the original Array of items with options removed.
138
+ def parse!(items = ARGV)
139
+ if (opts = commands[items[0].to_s])
140
+ @triggered_command = items.shift
141
+ execute_arguments! items
142
+ opts.parse! items
143
+ elsif (opts = commands['default'])
143
144
  opts.parse! items
144
- else
145
- if config[:strict] && items[0]
146
- raise InvalidCommandError, "Unknown command `#{items[0]}`"
147
- end
145
+ elsif config[:strict] && items[0]
146
+ raise InvalidCommandError, "Unknown command `#{items[0]}`"
148
147
  end
149
148
  execute_global_opts! items
149
+ items
150
150
  end
151
- items
152
- end
153
151
 
154
- # Returns a nested Hash with Slop options and values. See Slop#to_hash.
155
- def to_hash
156
- Hash[commands.map { |k, v| [k.to_sym, v.to_hash] }]
157
- end
152
+ # Returns a nested Hash with Slop options and values. See Slop#to_hash.
153
+ def to_hash
154
+ Hash[commands.map { |k, v| [k.to_sym, v.to_hash] }]
155
+ end
158
156
 
159
- # Returns the help String.
160
- def to_s
161
- defaults = commands.delete('default')
162
- globals = commands.delete('global')
163
- helps = commands.reject { |_, v| v.options.none? }
164
- if globals && globals.options.any?
165
- helps.merge!('Global options' => globals.to_s)
157
+ # Returns the help String.
158
+ def to_s
159
+ defaults = commands.delete('default')
160
+ globals = commands.delete('global')
161
+ helps = commands.reject { |_, v| v.options.none? }
162
+ helps['Global options'] = globals.to_s if globals && globals.options.any?
163
+ helps['Other options'] = defaults.to_s if defaults && defaults.options.any?
164
+ banner = @banner ? "#{@banner}\n" : ""
165
+ banner + helps.map { |key, opts| " #{key}\n#{opts}" }.join("\n\n")
166
166
  end
167
- if defaults && defaults.options.any?
168
- helps.merge!('Other options' => defaults.to_s)
167
+ alias help to_s
168
+
169
+ # Returns the inspection String.
170
+ def inspect
171
+ "#<Slop::Commands #{config.inspect} #{commands.values.map(&:inspect)}>"
169
172
  end
170
- banner = @banner ? "#{@banner}\n" : ""
171
- banner + helps.map { |key, opts| " #{key}\n#{opts}" }.join("\n\n")
172
- end
173
- alias help to_s
174
173
 
175
- # Returns the inspection String.
176
- def inspect
177
- "#<Slop::Commands #{config.inspect} #{commands.values.map(&:inspect)}>"
178
- end
174
+ private
179
175
 
180
- private
176
+ # Returns nothing.
177
+ def execute_arguments!(items)
178
+ @arguments = items.take_while { |arg| !arg.start_with?('-') }
179
+ items.shift @arguments.size
180
+ end
181
181
 
182
- # Returns nothing.
183
- def execute_arguments!(items)
184
- @arguments = items.take_while { |arg| !arg.start_with?('-') }
185
- items.shift @arguments.size
186
- end
182
+ # Returns nothing.
183
+ def execute_global_opts!(items)
184
+ return unless (global_opts = commands['global'])
187
185
 
188
- # Returns nothing.
189
- def execute_global_opts!(items)
190
- if (global_opts = commands['global'])
191
- global_opts.parse! items
186
+ global_opts.parse!(items)
192
187
  end
193
188
  end
194
189
  end
@@ -1,203 +1,207 @@
1
- class Pry::Slop
2
- class Option
3
- # The default Hash of configuration options this class uses.
4
- DEFAULT_OPTIONS = {
5
- argument: false,
6
- optional_argument: false,
7
- tail: false,
8
- default: nil,
9
- callback: nil,
10
- delimiter: ',',
11
- limit: 0,
12
- match: nil,
13
- optional: true,
14
- required: false,
15
- as: String,
16
- autocreated: false
17
- }
18
-
19
- attr_reader :short, :long, :description, :config, :types
20
- attr_accessor :count, :argument_in_value
21
-
22
- # Incapsulate internal option information, mainly used to store
23
- # option specific configuration data, most of the meat of this
24
- # class is found in the #value method.
25
- #
26
- # slop - The instance of Slop tied to this Option.
27
- # short - The String or Symbol short flag.
28
- # long - The String or Symbol long flag.
29
- # description - The String description text.
30
- # config - A Hash of configuration options.
31
- # block - An optional block used as a callback.
32
- def initialize(slop, short, long, description, config = {}, &block)
33
- @slop = slop
34
- @short = short
35
- @long = long
36
- @description = description
37
- @config = DEFAULT_OPTIONS.merge(config)
38
- @count = 0
39
- @callback = block_given? ? block : config[:callback]
40
- @value = nil
41
-
42
- @types = {
43
- string: proc { |v| v.to_s },
44
- symbol: proc { |v| v.to_sym },
45
- integer: proc { |v| value_to_integer(v) },
46
- float: proc { |v| value_to_float(v) },
47
- range: proc { |v| value_to_range(v) },
48
- count: proc { |v| @count }
49
- }
50
-
51
- if long && long.size > @slop.config[:longest_flag]
52
- @slop.config[:longest_flag] = long.size
53
- end
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ class Slop
5
+ class Option
6
+ # The default Hash of configuration options this class uses.
7
+ DEFAULT_OPTIONS = {
8
+ argument: false,
9
+ optional_argument: false,
10
+ tail: false,
11
+ default: nil,
12
+ callback: nil,
13
+ delimiter: ',',
14
+ limit: 0,
15
+ match: nil,
16
+ optional: true,
17
+ required: false,
18
+ as: String,
19
+ autocreated: false
20
+ }.freeze
21
+
22
+ attr_reader :short, :long, :description, :config, :types
23
+ attr_accessor :count, :argument_in_value
24
+
25
+ # Incapsulate internal option information, mainly used to store
26
+ # option specific configuration data, most of the meat of this
27
+ # class is found in the #value method.
28
+ #
29
+ # slop - The instance of Slop tied to this Option.
30
+ # short - The String or Symbol short flag.
31
+ # long - The String or Symbol long flag.
32
+ # description - The String description text.
33
+ # config - A Hash of configuration options.
34
+ # block - An optional block used as a callback.
35
+ def initialize(slop, short, long, description, config = {}, &block)
36
+ @slop = slop
37
+ @short = short
38
+ @long = long
39
+ @description = description
40
+ @config = DEFAULT_OPTIONS.merge(config)
41
+ @count = 0
42
+ @callback = block_given? ? block : config[:callback]
43
+ @value = nil
44
+
45
+ @types = {
46
+ string: proc { |v| v.to_s },
47
+ symbol: proc { |v| v.to_sym },
48
+ integer: proc { |v| value_to_integer(v) },
49
+ float: proc { |v| value_to_float(v) },
50
+ range: proc { |v| value_to_range(v) },
51
+ count: proc { @count }
52
+ }
53
+
54
+ if long && long.size > @slop.config[:longest_flag]
55
+ @slop.config[:longest_flag] = long.size
56
+ end
54
57
 
55
- @config.each_key do |key|
56
- predicate = :"#{key}?"
57
- unless self.class.method_defined? predicate
58
- self.class.__send__(:define_method, predicate) { !!@config[key] }
58
+ @config.each_key do |key|
59
+ predicate = :"#{key}?"
60
+ unless self.class.method_defined?(predicate)
61
+ self.class.__send__(:define_method, predicate) { !@config.key?(key) }
62
+ end
59
63
  end
60
64
  end
61
- end
62
65
 
63
- # Returns true if this option expects an argument.
64
- def expects_argument?
65
- config[:argument] && config[:argument] != :optional
66
- end
66
+ # Returns true if this option expects an argument.
67
+ def expects_argument?
68
+ config[:argument] && config[:argument] != :optional
69
+ end
67
70
 
68
- # Returns true if this option accepts an optional argument.
69
- def accepts_optional_argument?
70
- config[:optional_argument] || config[:argument] == :optional
71
- end
71
+ # Returns true if this option accepts an optional argument.
72
+ def accepts_optional_argument?
73
+ config[:optional_argument] || config[:argument] == :optional
74
+ end
72
75
 
73
- # Returns the String flag of this option. Preferring the long flag.
74
- def key
75
- long || short
76
- end
76
+ # Returns the String flag of this option. Preferring the long flag.
77
+ def key
78
+ long || short
79
+ end
77
80
 
78
- # Call this options callback if one exists, and it responds to call().
79
- #
80
- # Returns nothing.
81
- def call(*objects)
82
- @callback.call(*objects) if @callback.respond_to?(:call)
83
- end
81
+ # Call this options callback if one exists, and it responds to call().
82
+ #
83
+ # Returns nothing.
84
+ def call(*objects)
85
+ @callback.call(*objects) if @callback.respond_to?(:call)
86
+ end
84
87
 
85
- # Set the new argument value for this option.
86
- #
87
- # We use this setter method to handle concatenating lists. That is,
88
- # when an array type is specified and used more than once, values from
89
- # both options will be grouped together and flattened into a single array.
90
- def value=(new_value)
91
- if config[:as].to_s.downcase == 'array'
92
- @value ||= []
93
-
94
- if new_value.respond_to?(:split)
95
- @value.concat new_value.split(config[:delimiter], config[:limit])
88
+ # Set the new argument value for this option.
89
+ #
90
+ # We use this setter method to handle concatenating lists. That is,
91
+ # when an array type is specified and used more than once, values from
92
+ # both options will be grouped together and flattened into a single array.
93
+ def value=(new_value)
94
+ if config[:as].to_s.casecmp('array') == 0
95
+ @value ||= []
96
+
97
+ if new_value.respond_to?(:split)
98
+ @value.concat new_value.split(config[:delimiter], config[:limit])
99
+ end
100
+ else
101
+ @value = new_value
96
102
  end
97
- else
98
- @value = new_value
99
103
  end
100
- end
101
104
 
102
- # Fetch the argument value for this option.
103
- #
104
- # Returns the Object once any type conversions have taken place.
105
- def value
106
- value = @value.nil? ? config[:default] : @value
105
+ # Fetch the argument value for this option.
106
+ #
107
+ # Returns the Object once any type conversions have taken place.
108
+ def value
109
+ value = @value.nil? ? config[:default] : @value
107
110
 
108
- if [true, false, nil].include?(value) && config[:as].to_s != 'count'
109
- return value
110
- end
111
+ return value if [true, false, nil].include?(value) && config[:as].to_s != 'count'
111
112
 
112
- type = config[:as]
113
- if type.respond_to?(:call)
114
- type.call(value)
115
- else
116
- if (callable = types[type.to_s.downcase.to_sym])
113
+ type = config[:as]
114
+ if type.respond_to?(:call)
115
+ type.call(value)
116
+ elsif (callable = types[type.to_s.downcase.to_sym])
117
117
  callable.call(value)
118
118
  else
119
119
  value
120
120
  end
121
121
  end
122
- end
123
122
 
124
- # Returns the help String for this option.
125
- def to_s
126
- return config[:help] if config[:help].respond_to?(:to_str)
123
+ # Returns the help String for this option.
124
+ def to_s
125
+ return config[:help] if config[:help].respond_to?(:to_str)
127
126
 
128
- out = " #{short ? "-#{short}, " : ' ' * 4}"
127
+ out = " #{short ? "-#{short}, " : ' ' * 4}"
129
128
 
130
- if long
131
- out << "--#{long}"
132
- size = long.size
133
- diff = @slop.config[:longest_flag] - size
134
- out << (' ' * (diff + 6))
135
- else
136
- out << (' ' * (@slop.config[:longest_flag] + 8))
129
+ if long
130
+ out += "--#{long}"
131
+ size = long.size
132
+ diff = @slop.config[:longest_flag] - size
133
+ out += (' ' * (diff + 6))
134
+ else
135
+ out += (' ' * (@slop.config[:longest_flag] + 8))
136
+ end
137
+
138
+ "#{out}#{description}"
137
139
  end
140
+ alias help to_s
138
141
 
139
- "#{out}#{description}"
140
- end
141
- alias help to_s
142
+ # Returns the String inspection text.
143
+ def inspect
144
+ "#<Slop::Option [-#{short} | --#{long}" \
145
+ "#{'=' if expects_argument?}#{'=?' if accepts_optional_argument?}]" \
146
+ " (#{description}) #{config.inspect}"
147
+ end
142
148
 
143
- # Returns the String inspection text.
144
- def inspect
145
- "#<Slop::Option [-#{short} | --#{long}" +
146
- "#{'=' if expects_argument?}#{'=?' if accepts_optional_argument?}]" +
147
- " (#{description}) #{config.inspect}"
148
- end
149
+ private
149
150
 
150
- private
151
-
152
- # Convert an object to an Integer if possible.
153
- #
154
- # value - The Object we want to convert to an integer.
155
- #
156
- # Returns the Integer value if possible to convert, else a zero.
157
- def value_to_integer(value)
158
- if @slop.strict?
159
- begin
160
- Integer(value.to_s, 10)
161
- rescue ArgumentError
162
- raise InvalidArgumentError, "#{value} could not be coerced into Integer"
151
+ # Convert an object to an Integer if possible.
152
+ #
153
+ # value - The Object we want to convert to an integer.
154
+ #
155
+ # Returns the Integer value if possible to convert, else a zero.
156
+ def value_to_integer(value)
157
+ if @slop.strict?
158
+ begin
159
+ Integer(value.to_s, 10)
160
+ rescue ArgumentError
161
+ raise InvalidArgumentError, "#{value} could not be coerced into Integer"
162
+ end
163
+ else
164
+ value.to_s.to_i
163
165
  end
164
- else
165
- value.to_s.to_i
166
166
  end
167
- end
168
167
 
169
- # Convert an object to a Float if possible.
170
- #
171
- # value - The Object we want to convert to a float.
172
- #
173
- # Returns the Float value if possible to convert, else a zero.
174
- def value_to_float(value)
175
- if @slop.strict?
176
- begin
177
- Float(value.to_s)
178
- rescue ArgumentError
179
- raise InvalidArgumentError, "#{value} could not be coerced into Float"
168
+ # Convert an object to a Float if possible.
169
+ #
170
+ # value - The Object we want to convert to a float.
171
+ #
172
+ # Returns the Float value if possible to convert, else a zero.
173
+ def value_to_float(value)
174
+ if @slop.strict?
175
+ begin
176
+ Float(value.to_s)
177
+ rescue ArgumentError
178
+ raise InvalidArgumentError, "#{value} could not be coerced into Float"
179
+ end
180
+ else
181
+ value.to_s.to_f
180
182
  end
181
- else
182
- value.to_s.to_f
183
183
  end
184
- end
185
184
 
186
- # Convert an object to a Range if possible.
187
- #
188
- # value - The Object we want to convert to a range.
189
- #
190
- # Returns the Range value if one could be found, else the original object.
191
- def value_to_range(value)
192
- case value.to_s
193
- when /\A(\-?\d+)\z/
194
- Range.new($1.to_i, $1.to_i)
195
- when /\A(-?\d+?)(\.\.\.?|-|,)(-?\d+)\z/
196
- Range.new($1.to_i, $3.to_i, $2 == '...')
197
- else
198
- if @slop.strict?
199
- raise InvalidArgumentError, "#{value} could not be coerced into Range"
185
+ # Convert an object to a Range if possible.
186
+ #
187
+ # value - The Object we want to convert to a range.
188
+ #
189
+ # Returns the Range value if one could be found, else the original object.
190
+ def value_to_range(value)
191
+ case value.to_s
192
+ when /\A(\-?\d+)\z/
193
+ Range.new(Regexp.last_match(1).to_i, Regexp.last_match(1).to_i)
194
+ when /\A(-?\d+?)(\.\.\.?|-|,)(-?\d+)\z/
195
+ Range.new(
196
+ Regexp.last_match(1).to_i,
197
+ Regexp.last_match(3).to_i,
198
+ Regexp.last_match(2) == '...'
199
+ )
200
200
  else
201
+ if @slop.strict?
202
+ raise InvalidArgumentError, "#{value} could not be coerced into Range"
203
+ end
204
+
201
205
  value
202
206
  end
203
207
  end