pry 0.9.7.4-i386-mswin32 → 0.9.8-i386-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/.gitignore +2 -3
  2. data/CHANGELOG +43 -0
  3. data/README.markdown +3 -1
  4. data/Rakefile +51 -32
  5. data/bin/pry +2 -80
  6. data/lib/pry.rb +33 -26
  7. data/lib/pry/cli.rb +152 -0
  8. data/lib/pry/code.rb +351 -0
  9. data/lib/pry/command.rb +422 -0
  10. data/lib/pry/command_set.rb +259 -129
  11. data/lib/pry/commands.rb +0 -1
  12. data/lib/pry/config.rb +43 -9
  13. data/lib/pry/default_commands/context.rb +109 -92
  14. data/lib/pry/default_commands/documentation.rb +174 -63
  15. data/lib/pry/default_commands/easter_eggs.rb +26 -2
  16. data/lib/pry/default_commands/gems.rb +65 -37
  17. data/lib/pry/default_commands/input.rb +175 -243
  18. data/lib/pry/default_commands/introspection.rb +173 -112
  19. data/lib/pry/default_commands/ls.rb +96 -114
  20. data/lib/pry/default_commands/shell.rb +175 -70
  21. data/lib/pry/helpers/base_helpers.rb +7 -2
  22. data/lib/pry/helpers/command_helpers.rb +71 -77
  23. data/lib/pry/helpers/options_helpers.rb +10 -41
  24. data/lib/pry/helpers/text.rb +24 -4
  25. data/lib/pry/history.rb +55 -17
  26. data/lib/pry/history_array.rb +2 -0
  27. data/lib/pry/hooks.rb +252 -0
  28. data/lib/pry/indent.rb +9 -5
  29. data/lib/pry/method.rb +149 -50
  30. data/lib/pry/plugins.rb +12 -4
  31. data/lib/pry/pry_class.rb +69 -26
  32. data/lib/pry/pry_instance.rb +187 -115
  33. data/lib/pry/version.rb +1 -1
  34. data/lib/pry/wrapped_module.rb +73 -0
  35. data/man/pry.1 +195 -0
  36. data/man/pry.1.html +204 -0
  37. data/man/pry.1.ronn +141 -0
  38. data/pry.gemspec +29 -32
  39. data/test/helper.rb +32 -36
  40. data/test/test_cli.rb +78 -0
  41. data/test/test_code.rb +201 -0
  42. data/test/test_command.rb +327 -0
  43. data/test/test_command_integration.rb +512 -0
  44. data/test/test_command_set.rb +338 -12
  45. data/test/test_completion.rb +1 -1
  46. data/test/test_default_commands.rb +1 -2
  47. data/test/test_default_commands/test_context.rb +27 -5
  48. data/test/test_default_commands/test_documentation.rb +20 -8
  49. data/test/test_default_commands/test_input.rb +84 -45
  50. data/test/test_default_commands/test_introspection.rb +74 -17
  51. data/test/test_default_commands/test_ls.rb +9 -36
  52. data/test/test_default_commands/test_shell.rb +240 -13
  53. data/test/test_hooks.rb +490 -0
  54. data/test/test_indent.rb +2 -0
  55. data/test/test_method.rb +60 -0
  56. data/test/test_pry.rb +29 -904
  57. data/test/test_pry_defaults.rb +380 -0
  58. data/test/test_pry_history.rb +24 -24
  59. data/test/test_syntax_checking.rb +63 -0
  60. data/test/test_wrapped_module.rb +71 -0
  61. metadata +50 -39
  62. data/lib/pry/command_context.rb +0 -53
  63. data/lib/pry/command_processor.rb +0 -181
  64. data/lib/pry/extended_commands/user_command_api.rb +0 -65
  65. data/test/test_command_processor.rb +0 -176
@@ -8,7 +8,7 @@ class Pry
8
8
  run "show-input"
9
9
  end
10
10
 
11
- command "get-naked" "" do
11
+ command "get-naked", "" do
12
12
  text = %{
13
13
  --
14
14
  We dont have to take our clothes off to have a good time.
@@ -60,8 +60,32 @@ they are lost for hours.
60
60
  text
61
61
  end
62
62
 
63
+ command "test-ansi", "" do
64
+ prev_color = Pry.color
65
+ Pry.color = true
63
66
 
64
- end
67
+ picture = unindent <<-'EOS'.gsub(/[[:alpha:]!]/) { |s| text.red(s) }
68
+ ____ _______________________
69
+ / \ | A W G |
70
+ / O O \ | N I O N ! |
71
+ | | | S S R I ! |
72
+ \ \__/ / __| I K ! |
73
+ \____/ \________________________|
74
+ EOS
75
+
76
+ if defined?(Win32::Console)
77
+ move_up = proc { |n| "\e[#{n}F" }
78
+ else
79
+ move_up = proc { |n| "\e[#{n}A\e[0G" }
80
+ end
81
+
82
+ output.puts "\n" * 6
83
+ output.puts picture.lines.map(&:chomp).reverse.join(move_up[1])
84
+ output.puts "\n" * 6
85
+ output.puts "** ENV['TERM'] is #{ENV['TERM']} **\n\n"
65
86
 
87
+ Pry.color = prev_color
88
+ end
89
+ end
66
90
  end
67
91
  end
@@ -3,53 +3,81 @@ class Pry
3
3
 
4
4
  Gems = Pry::CommandSet.new do
5
5
 
6
- command "gem-install", "Install a gem and refresh the gem cache.", :argument_required => true do |gem|
7
- require 'rubygems/dependency_installer' unless defined? Gem::DependencyInstaller
8
- begin
9
- destination = File.writable?(Gem.dir) ? Gem.dir : Gem.user_dir
10
- installer = Gem::DependencyInstaller.new :install_dir => destination
11
- installer.install gem
12
- rescue Errno::EACCES
13
- raise CommandError, "Insufficient permissions to install `#{text.green gem}`."
14
- rescue Gem::GemNotFoundException
15
- raise CommandError, "Gem `#{text.green gem}` not found."
16
- else
17
- Gem.refresh
18
- output.puts "Gem `#{text.green gem}` installed."
6
+ create_command "gem-install", "Install a gem and refresh the gem cache.", :argument_required => true do |gem|
7
+
8
+ banner <<-BANNER
9
+ Usage: gem-install GEM_NAME
10
+
11
+ Installs the given gem and refreshes the gem cache so that you can immediately 'require GEM_FILE'
12
+ BANNER
13
+
14
+ def setup
15
+ require 'rubygems/dependency_installer' unless defined? Gem::DependencyInstaller
19
16
  end
20
- end
21
17
 
22
- command "gem-cd", "Change working directory to specified gem's directory.", :argument_required => true do |gem|
23
- specs = Gem::Specification.respond_to?(:each) ? Gem::Specification.find_all_by_name(gem) : Gem.source_index.find_name(gem)
24
- spec = specs.sort { |a,b| Gem::Version.new(b.version) <=> Gem::Version.new(a.version) }.first
25
- if spec
26
- Dir.chdir(spec.full_gem_path)
27
- else
28
- raise CommandError, "Gem `#{gem}` not found."
18
+ def process(gem)
19
+ begin
20
+ destination = File.writable?(Gem.dir) ? Gem.dir : Gem.user_dir
21
+ installer = Gem::DependencyInstaller.new :install_dir => destination
22
+ installer.install gem
23
+ rescue Errno::EACCES
24
+ raise CommandError, "Insufficient permissions to install `#{text.green gem}`."
25
+ rescue Gem::GemNotFoundException
26
+ raise CommandError, "Gem `#{text.green gem}` not found."
27
+ else
28
+ Gem.refresh
29
+ output.puts "Gem `#{text.green gem}` installed."
30
+ end
29
31
  end
30
32
  end
31
33
 
32
- command "gem-list", "List/search installed gems. (Optional parameter: a regexp to limit the search)" do |pattern|
33
- pattern = Regexp.new pattern.to_s, Regexp::IGNORECASE
34
- gems = if Gem::Specification.respond_to?(:each)
35
- Gem::Specification.select{|spec| spec.name =~ pattern }.group_by(&:name)
36
- else
37
- Gem.source_index.gems.values.group_by(&:name).select { |gemname, specs| gemname =~ pattern }
38
- end
39
-
40
- gems.each do |gem, specs|
41
- specs.sort! do |a,b|
42
- Gem::Version.new(b.version) <=> Gem::Version.new(a.version)
43
- end
34
+ create_command "gem-cd", "Change working directory to specified gem's directory.", :argument_required => true do |gem|
35
+ banner <<-BANNER
36
+ Usage: gem-cd GEM_NAME
44
37
 
45
- versions = specs.each_with_index.map do |spec, index|
46
- index == 0 ? text.bright_green(spec.version.to_s) : text.green(spec.version.to_s)
47
- end
38
+ Change the current working directory to that in which the given gem is installed.
39
+ BANNER
48
40
 
49
- output.puts "#{text.default gem} (#{versions.join ', '})"
41
+ def process(gem)
42
+ specs = Gem::Specification.respond_to?(:each) ? Gem::Specification.find_all_by_name(gem) : Gem.source_index.find_name(gem)
43
+ spec = specs.sort { |a,b| Gem::Version.new(b.version) <=> Gem::Version.new(a.version) }.first
44
+ if spec
45
+ Dir.chdir(spec.full_gem_path)
46
+ output.puts(Dir.pwd)
47
+ else
48
+ raise CommandError, "Gem `#{gem}` not found."
49
+ end
50
50
  end
51
51
  end
52
52
 
53
+ create_command "gem-list", "List and search installed gems." do |pattern|
54
+ banner <<-BANNER
55
+ Usage: gem-list [REGEX]
56
+
57
+ List all installed gems, when a regex is provided, limit the output to those that
58
+ match the regex.
59
+ BANNER
60
+
61
+ def process(pattern=nil)
62
+ gems = if Gem::Specification.respond_to?(:each)
63
+ Gem::Specification.select{|spec| spec.name =~ pattern }.group_by(&:name)
64
+ else
65
+ Gem.source_index.gems.values.group_by(&:name).select { |gemname, specs| gemname =~ pattern }
66
+ end
67
+
68
+ gems.each do |gem, specs|
69
+ specs.sort! do |a,b|
70
+ Gem::Version.new(b.version) <=> Gem::Version.new(a.version)
71
+ end
72
+
73
+ versions = specs.each_with_index.map do |spec, index|
74
+ index == 0 ? text.bright_green(spec.version.to_s) : text.green(spec.version.to_s)
75
+ end
76
+
77
+ output.puts "#{text.default gem} (#{versions.join ', '})"
78
+ end
79
+ end
80
+ end
53
81
  end
54
82
  end
55
83
  end
@@ -3,313 +3,245 @@ class Pry
3
3
 
4
4
  Input = Pry::CommandSet.new do
5
5
 
6
- command "!", "Clear the input buffer. Useful if the parsing process goes wrong and you get stuck in the read loop.", :use_prefix => false do
7
- output.puts "Input buffer cleared!"
8
- eval_string.replace("")
9
- end
10
-
11
- command "show-input", "Show the contents of the input buffer for the current multi-line expression." do
12
- render_output(false, 1, Pry.color ? CodeRay.scan(eval_string, :ruby).term : eval_string)
13
- end
14
-
15
- command(/amend-line(?: (-?\d+)(?:\.\.(-?\d+))?)?/, "Amend a line of input in multi-line mode. Type `amend-line --help` for more information. Aliases %",
16
- :interpolate => false, :listing => "amend-line") do |*args|
17
- start_line_number, end_line_number, replacement_line = *args
18
-
19
- opts = Slop.parse!(args.compact) do |opt|
20
- opt.banner unindent <<-USAGE
21
- Amend a line of input in multi-line mode. `amend-line N`, where the N in `amend-line N` represents line to replace.
22
-
23
- Can also specify a range of lines using `amend-line N..M` syntax. Passing '!' as replacement content deletes the line(s) instead. Aliases: %N
24
- e.g amend-line 1 puts 'hello world! # replace line 1'
25
- e.g amend-line 1..4 ! # delete lines 1..4
26
- e.g amend-line 3 >puts 'goodbye' # insert before line 3
27
- e.g amend-line puts 'hello again' # no line number modifies immediately preceding line
28
- USAGE
29
-
30
- opt.on :h, :help, "This message." do
31
- output.puts opt
32
- end
6
+ create_command "!", "Clear the input buffer. Useful if the parsing process goes wrong and you get stuck in the read loop.", :use_prefix => false do
7
+ def process
8
+ output.puts "Input buffer cleared!"
9
+ eval_string.replace("")
33
10
  end
34
-
35
- next if opts.h?
36
-
37
- if eval_string.empty?
38
- raise CommandError, "No input to amend."
39
- end
40
-
41
- replacement_line = "" if !replacement_line
42
- input_array = eval_string.each_line.to_a
43
-
44
- end_line_number = start_line_number.to_i if !end_line_number
45
- line_range = start_line_number ? (one_index_number(start_line_number.to_i)..one_index_number(end_line_number.to_i)) : input_array.size - 1
46
-
47
- # delete selected lines if replacement line is '!'
48
- if arg_string == "!"
49
- input_array.slice!(line_range)
50
- elsif arg_string.start_with?(">")
51
- insert_slot = Array(line_range).first
52
- input_array.insert(insert_slot, arg_string[1..-1] + "\n")
53
- else
54
- input_array[line_range] = arg_string + "\n"
55
- end
56
- eval_string.replace input_array.join
57
- run "show-input"
58
11
  end
59
12
 
60
- alias_command(/%.?(-?\d+)?(?:\.\.(-?\d+))?/, /amend-line(?: (-?\d+)(?:\.\.(-?\d+))?)?/)
61
-
62
- command "play", "Play back a string variable or a method or a file as input. Type `play --help` for more information." do |*args|
63
- opts = Slop.parse!(args) do |opt|
64
- opt.banner unindent <<-USAGE
65
- Usage: play [OPTIONS] [--help]
66
- Default action (no options) is to play the provided string variable
67
- e.g `play _in_[20] --lines 1..3`
68
- e.g `play -m Pry#repl --lines 1..-1`
69
- e.g `play -f Rakefile --lines 5`
70
- USAGE
71
-
72
- opt.on :l, :lines, 'The line (or range of lines) to replay.', true, :as => Range
73
- opt.on :m, :method, 'Play a method.', true
74
- opt.on :f, "file", 'The file to replay in context.', true
75
- opt.on :o, "open", 'When used with the -m switch, it plays the entire method except the last line, leaving the method definition "open". `amend-line` can then be used to modify the method.'
76
- opt.on :h, :help, "This message." do
77
- output.puts opt
78
- end
13
+ create_command "show-input", "Show the contents of the input buffer for the current multi-line expression." do
14
+ def process
15
+ output.puts Code.new(eval_string).with_line_numbers
79
16
  end
17
+ end
80
18
 
81
- if opts.m?
82
- meth_name = opts[:m]
83
- meth = get_method_or_raise(meth_name, target, {}, :omit_help)
84
- next unless meth.source
85
-
86
- range = opts.l? ? one_index_range_or_number(opts[:l]) : (0..-1)
87
- range = (0..-2) if opts.o?
19
+ create_command(/amend-line(?: (-?\d+)(?:\.\.(-?\d+))?)?/) do
20
+ description "Amend a line of input in multi-line mode. Type `amend-line --help` for more information."
21
+ command_options :interpolate => false, :listing => "amend-line"
88
22
 
89
- eval_string << Array(meth.source.each_line.to_a[range]).join
90
- elsif opts.f?
91
- file_name = File.expand_path(opts[:f])
23
+ banner <<-'BANNER'
24
+ Amend a line of input in multi-line mode. `amend-line N`, where the N in `amend-line N` represents line to replace.
92
25
 
93
- if !File.exists?(file_name)
94
- raise CommandError, "No such file: #{opts[:f]}"
95
- end
26
+ Can also specify a range of lines using `amend-line N..M` syntax. Passing '!' as replacement content deletes the line(s) instead.
27
+ e.g amend-line 1 puts 'hello world! # replace line 1'
28
+ e.g amend-line 1..4 ! # delete lines 1..4
29
+ e.g amend-line 3 >puts 'goodbye' # insert before line 3
30
+ e.g amend-line puts 'hello again' # no line number modifies immediately preceding line
31
+ BANNER
96
32
 
97
- text_array = File.readlines(file_name)
98
- range = opts.l? ? one_index_range_or_number(opts[:l]) : (0..-1)
99
- range = (0..-2) if opts.o?
33
+ def process
34
+ start_line_number, end_line_number, replacement_line = *args
100
35
 
101
- _pry_.input_stack << _pry_.input
102
- _pry_.input = StringIO.new(Array(text_array[range]).join)
103
- else
104
- if !args.first
105
- raise CommandError, "No input to play command."
36
+ if eval_string.empty?
37
+ raise CommandError, "No input to amend."
106
38
  end
107
39
 
108
- code = target.eval(args.first)
40
+ replacement_line = "" if !replacement_line
41
+ input_array = eval_string.each_line.to_a
109
42
 
110
- range = opts.l? ? one_index_range_or_number(opts[:l]) : (0..-1)
111
- range = (0..-2) if opts.o?
43
+ end_line_number = start_line_number.to_i if !end_line_number
44
+ line_range = start_line_number ? (one_index_number(start_line_number.to_i)..one_index_number(end_line_number.to_i)) : input_array.size - 1
112
45
 
113
- eval_string << Array(code.each_line.to_a[range]).join
46
+ # delete selected lines if replacement line is '!'
47
+ if arg_string == "!"
48
+ input_array.slice!(line_range)
49
+ elsif arg_string.start_with?(">")
50
+ insert_slot = Array(line_range).first
51
+ input_array.insert(insert_slot, arg_string[1..-1] + "\n")
52
+ else
53
+ input_array[line_range] = arg_string + "\n"
54
+ end
55
+ eval_string.replace input_array.join
56
+ run "show-input"
114
57
  end
115
-
116
- run "show-input" if !_pry_.valid_expression?(eval_string)
117
58
  end
118
59
 
119
- command "hist", "Show and replay Readline history. Type `hist --help` for more info. Aliases: history" do |*args|
120
- # exclude the current command from history.
121
- history = Pry.history.to_a[0..-2]
122
-
123
- opts = Slop.parse!(args) do |opt|
124
- opt.banner "Usage: hist [--replay START..END] [--clear] [--grep PATTERN] [--head N] [--tail N] [--help] [--save [START..END] file.txt]\n"
125
-
126
- opt.on :n, 'no-numbers', 'Omit line numbers.'
127
-
128
- opt.on :g, :grep, 'A pattern to match against the history.', true
60
+ create_command "play" do
61
+ description "Play back a string variable or a method or a file as input. Type `play --help` for more information."
129
62
 
130
- opt.on :head, 'Display the first N items of history.',
131
- :optional => true,
132
- :as => Integer
63
+ banner <<-BANNER
64
+ Usage: play [OPTIONS] [--help]
133
65
 
134
- opt.on :t, :tail, 'Display the last N items of history.',
135
- :optional => true,
136
- :as => Integer
66
+ The play command enables you to replay code from files and methods as
67
+ if they were entered directly in the Pry REPL. Default action (no
68
+ options) is to play the provided string variable
137
69
 
138
- opt.on :s, :show, 'Show the history corresponding to the history line (or range of lines).',
139
- :optional => true,
140
- :as => Range
70
+ e.g: `play -i 20 --lines 1..3`
71
+ e.g: `play -m Pry#repl --lines 1..-1`
72
+ e.g: `play -f Rakefile --lines 5`
141
73
 
142
- opt.on :e, :exclude, 'Exclude pry commands from the history.'
74
+ https://github.com/pry/pry/wiki/User-Input#wiki-Play
75
+ BANNER
143
76
 
144
- opt.on :r, :replay, 'The line (or range of lines) to replay.', true,
145
- :as => Range
77
+ attr_accessor :content
146
78
 
147
- opt.on "save", "Save history to a file. --save [start..end] output.txt. Pry commands are excluded from saved history.", true,
148
- :as => Range
149
-
150
- opt.on :c, :clear, 'Clear the history.', :unless => :grep
79
+ def setup
80
+ self.content = ""
81
+ end
151
82
 
152
- opt.on :h, :help, 'Show this message.', :tail => true, :unless => :grep do
153
- output.puts opt.help
83
+ def options(opt)
84
+ opt.on :m, :method, "Play a method's source.", true do |meth_name|
85
+ meth = get_method_or_raise(meth_name, target, {})
86
+ self.content << meth.source
154
87
  end
155
- end
156
- next if opts.help?
157
-
158
- if opts.grep?
159
- pattern = Regexp.new(arg_string.strip.split(/ /, 2).last.strip)
160
- history.pop
161
-
162
- history.map!.with_index do |element, index|
163
- if element =~ pattern
164
- if opts.n?
165
- element
166
- else
167
- "#{text.blue index}: #{element}"
168
- end
88
+ opt.on :d, :doc, "Play a method's documentation.", true do |meth_name|
89
+ meth = get_method_or_raise(meth_name, target, {})
90
+ text.no_color do
91
+ self.content << process_comment_markup(meth.doc, :ruby)
169
92
  end
170
93
  end
94
+ opt.on :c, :command, "Play a command's source.", true do |command_name|
95
+ command = find_command(command_name)
96
+ block = Pry::Method.new(find_command(command_name).block)
97
+ self.content << block.source
98
+ end
99
+ opt.on :f, :file, "Play a file.", true do |file|
100
+ self.content << File.read(File.expand_path(file))
101
+ end
102
+ opt.on :l, :lines, "Only play a subset of lines.", :optional => true, :as => Range, :default => 1..-1
103
+ opt.on :i, :in, "Play entries from Pry's input expression history. Takes an index or range.", :optional => true,
104
+ :as => Range, :default => -5..-1 do |range|
105
+ input_expressions = _pry_.input_array[range] || []
106
+ Array(input_expressions).each { |v| self.content << v }
107
+ end
108
+ opt.on :o, "open", 'When used with the -m switch, it plays the entire method except the last line, leaving the method definition "open". `amend-line` can then be used to modify the method.'
109
+ end
171
110
 
172
- stagger_output history.compact.join "\n"
173
- next
111
+ def process
112
+ perform_play
113
+ run "show-input" unless _pry_.complete_expression?(eval_string)
174
114
  end
175
115
 
176
- if opts.head?
177
- limit = opts['head'] || 10
178
- list = history.first limit
179
- lines = list.join("\n")
180
- if opts.n?
181
- stagger_output lines
182
- else
183
- stagger_output text.with_line_numbers(lines, 0)
116
+ def process_non_opt
117
+ args.each do |arg|
118
+ begin
119
+ self.content << target.eval(arg)
120
+ rescue Pry::RescuableException
121
+ raise CommandError, "Prblem when evaling #{arg}."
122
+ end
184
123
  end
185
- next
186
124
  end
187
125
 
188
- if opts.tail?
189
- limit = opts['tail'] || 10
190
- offset = history.size - limit
191
- offset = offset < 0 ? 0 : offset
126
+ def perform_play
127
+ process_non_opt
192
128
 
193
- list = history.last limit
194
- lines = list.join("\n")
195
- if opts.n?
196
- stagger_output lines
197
- else
198
- stagger_output text.with_line_numbers(lines, offset)
129
+ if opts.present?(:lines)
130
+ self.content = restrict_to_lines(self.content, opts[:l])
199
131
  end
200
- next
201
- end
202
132
 
203
- if opts.show?
204
- range = opts['show']
205
- start_line = range.is_a?(Range) ? range.first : range
206
- lines = Array(history[range]).join("\n")
207
- if opts.n?
208
- stagger_output lines
209
- else
210
- stagger_output text.with_line_numbers(lines, start_line)
133
+ if opts.present?(:open)
134
+ self.content = restrict_to_lines(self.content, 1..-2)
211
135
  end
212
- next
136
+
137
+ eval_string << self.content
213
138
  end
139
+ end
214
140
 
215
- if opts.exclude?
216
- history.map!.with_index do |element, index|
217
- unless command_processor.valid_command? element
218
- if opts.n?
219
- element
220
- else
221
- "#{text.blue index}: #{element}"
222
- end
141
+ create_command "hist", "Show and replay Readline history. Aliases: history" do
142
+ banner <<-USAGE
143
+ Usage: hist
144
+ hist --head N
145
+ hist --tail N
146
+ hist --show START..END
147
+ hist --grep PATTERN
148
+ hist --clear
149
+ hist --replay START..END
150
+ hist --save [START..END] FILE
151
+ USAGE
152
+
153
+ def options(opt)
154
+ opt.on :H, :head, "Display the first N items.", :optional => true, :as => Integer
155
+ opt.on :T, :tail, "Display the last N items.", :optional => true, :as => Integer
156
+ opt.on :s, :show, "Show the given range of lines.", :optional => true, :as => Range
157
+ opt.on :G, :grep, "Show lines matching the given pattern.", true, :as => String
158
+ opt.on :c, :clear, "Clear the current session's history."
159
+ opt.on :r, :replay, "Replay a line or range of lines.", true, :as => Range
160
+ opt.on :save, "Save history to a file.", true, :as => Range
161
+
162
+ opt.on :e, :'exclude-pry', "Exclude Pry commands from the history."
163
+ opt.on :n, :'no-numbers', "Omit line numbers."
164
+ opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
165
+ end
166
+
167
+ def process
168
+ @history = Pry::Code(Pry.history.to_a)
169
+
170
+ @history = case
171
+ when opts.present?(:head)
172
+ @history.between(1, opts[:head] || 10)
173
+ when opts.present?(:tail)
174
+ @history.between(-(opts[:tail] || 10), -1)
175
+ when opts.present?(:show)
176
+ @history.between(opts[:show])
177
+ else
178
+ @history
223
179
  end
180
+
181
+ if opts.present?(:grep)
182
+ @history = @history.grep(opts[:grep])
224
183
  end
225
- stagger_output history.compact.join "\n"
226
- next
227
- end
228
184
 
229
- if opts.replay?
230
- range = opts['replay']
231
- actions = Array(history[range]).join("\n") + "\n"
232
- _pry_.input_stack << _pry_.input
233
- _pry_.input = StringIO.new(actions)
234
- next
235
- end
185
+ if opts.present?(:'exclude-pry')
186
+ @history = @history.select { |l, ln| !command_set.valid_command?(l) }
187
+ end
236
188
 
237
- if opts.clear?
238
- Pry.history.clear
239
- output.puts 'History cleared.'
240
- next
189
+ if opts.present?(:save)
190
+ process_save
191
+ elsif opts.present?(:clear)
192
+ process_clear
193
+ elsif opts.present?(:replay)
194
+ process_replay
195
+ else
196
+ process_display
197
+ end
241
198
  end
242
199
 
243
- # FIXME: hack to save history (this must be refactored)
244
- if opts["save"]
245
- file_name = nil
246
- hist_array = nil
200
+ def process_display
201
+ unless opts.present?(:'no-numbers')
202
+ @history = @history.with_line_numbers
203
+ end
204
+
205
+ render_output(@history, opts)
206
+ end
247
207
 
248
- case opts["save"]
208
+ def process_save
209
+ case opts[:save]
249
210
  when Range
250
- hist_array = Array(history[opts["save"]])
211
+ @history = @history.between(opts[:save])
251
212
 
252
- if !args.first
213
+ unless args.first
253
214
  raise CommandError, "Must provide a file name."
254
215
  end
255
216
 
256
217
  file_name = File.expand_path(args.first)
257
218
  when String
258
- hist_array = history
259
- file_name = File.expand_path(opts["save"])
219
+ file_name = File.expand_path(opts[:save])
260
220
  end
261
221
 
262
- output.puts "Saving history in #{file_name} ..."
263
- # exclude pry commands
264
- hist_array.reject! do |element|
265
- command_processor.valid_command?(element)
266
- end
222
+ output.puts "Saving history in #{file_name}..."
267
223
 
268
- File.open(file_name, 'w') do |f|
269
- f.write hist_array.join("\n")
270
- end
224
+ File.open(file_name, 'w') { |f| f.write(@history.to_s) }
271
225
 
272
- output.puts "... history saved."
273
- next
226
+ output.puts "History saved."
274
227
  end
275
228
 
276
- lines = history.join("\n")
277
- if opts.n?
278
- stagger_output lines
279
- else
280
- stagger_output text.with_line_numbers(lines, 0)
281
- end
282
- end
283
-
284
- alias_command "history", "hist"
285
-
286
- helpers do
287
- def one_index_number(line_number)
288
- if line_number > 0
289
- line_number - 1
290
- elsif line_number < 0
291
- line_number
292
- else
293
- line_number
294
- end
229
+ def process_clear
230
+ Pry.history.clear
231
+ output.puts "History cleared."
295
232
  end
296
233
 
297
- def one_index_range(range)
298
- Range.new(one_index_number(range.begin), one_index_number(range.end))
299
- end
234
+ def process_replay
235
+ @history = @history.between(opts[:r])
300
236
 
301
- def one_index_range_or_number(range_or_number)
302
- case range_or_number
303
- when Range
304
- one_index_range(range_or_number)
305
- else
306
- one_index_number(range_or_number)
307
- end
237
+ _pry_.input_stack.push _pry_.input
238
+ _pry_.input = StringIO.new(@history.raw)
239
+ # eval_string << "#{@history.raw}\n"
240
+ # run "show-input" unless _pry_.complete_expression?(eval_string)
308
241
  end
309
-
310
242
  end
311
243
 
244
+ alias_command "history", "hist"
312
245
  end
313
-
314
246
  end
315
247
  end