pry 0.8.4pre1 → 0.9.0pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.gitignore +1 -0
  2. data/README.markdown +1 -1
  3. data/Rakefile +11 -5
  4. data/TODO +28 -2
  5. data/bin/pry +5 -9
  6. data/examples/example_basic.rb +2 -4
  7. data/examples/example_command_override.rb +2 -5
  8. data/examples/example_commands.rb +1 -4
  9. data/examples/example_hooks.rb +2 -5
  10. data/examples/example_image_edit.rb +4 -8
  11. data/examples/example_input.rb +1 -4
  12. data/examples/example_input2.rb +1 -4
  13. data/examples/example_output.rb +1 -4
  14. data/examples/example_print.rb +2 -5
  15. data/examples/example_prompt.rb +2 -5
  16. data/examples/helper.rb +6 -0
  17. data/lib/pry.rb +61 -4
  18. data/lib/pry/command_context.rb +10 -9
  19. data/lib/pry/command_processor.rb +29 -68
  20. data/lib/pry/command_set.rb +79 -28
  21. data/lib/pry/commands.rb +10 -121
  22. data/lib/pry/completion.rb +30 -29
  23. data/lib/pry/config.rb +93 -0
  24. data/lib/pry/default_commands/basic.rb +37 -0
  25. data/lib/pry/default_commands/context.rb +15 -15
  26. data/lib/pry/default_commands/documentation.rb +49 -48
  27. data/lib/pry/default_commands/easter_eggs.rb +1 -20
  28. data/lib/pry/default_commands/gems.rb +32 -41
  29. data/lib/pry/default_commands/input.rb +95 -19
  30. data/lib/pry/default_commands/introspection.rb +54 -60
  31. data/lib/pry/default_commands/ls.rb +2 -2
  32. data/lib/pry/default_commands/shell.rb +29 -39
  33. data/lib/pry/extended_commands/experimental.rb +48 -0
  34. data/lib/pry/extended_commands/user_command_api.rb +22 -0
  35. data/lib/pry/helpers.rb +1 -0
  36. data/lib/pry/helpers/base_helpers.rb +9 -106
  37. data/lib/pry/helpers/command_helpers.rb +96 -59
  38. data/lib/pry/helpers/text.rb +83 -0
  39. data/lib/pry/plugins.rb +79 -0
  40. data/lib/pry/pry_class.rb +96 -111
  41. data/lib/pry/pry_instance.rb +87 -55
  42. data/lib/pry/version.rb +1 -1
  43. data/test/helper.rb +56 -7
  44. data/test/test_command_processor.rb +99 -0
  45. data/test/{test_commandset.rb → test_command_set.rb} +18 -12
  46. data/test/test_default_commands.rb +59 -0
  47. data/test/test_default_commands/test_context.rb +64 -0
  48. data/test/test_default_commands/test_documentation.rb +31 -0
  49. data/test/test_default_commands/test_input.rb +157 -0
  50. data/test/test_default_commands/test_introspection.rb +146 -0
  51. data/test/test_pry.rb +430 -313
  52. metadata +25 -9
  53. data/lib/pry/hooks.rb +0 -17
  54. data/lib/pry/print.rb +0 -16
  55. data/lib/pry/prompts.rb +0 -31
@@ -0,0 +1,37 @@
1
+ class Pry
2
+ module DefaultCommands
3
+
4
+ Basic = Pry::CommandSet.new do
5
+ command "toggle-color", "Toggle syntax highlighting." do
6
+ Pry.color = !Pry.color
7
+ output.puts "Syntax highlighting #{Pry.color ? "on" : "off"}"
8
+ end
9
+
10
+ command "simple-prompt", "Toggle the simple prompt." do
11
+ case Pry.active_instance.prompt
12
+ when Pry::SIMPLE_PROMPT
13
+ Pry.active_instance.pop_prompt
14
+ else
15
+ Pry.active_instance.push_prompt Pry::SIMPLE_PROMPT
16
+ end
17
+ end
18
+
19
+ command "version", "Show Pry version." do
20
+ output.puts "Pry version: #{Pry::VERSION} on Ruby #{RUBY_VERSION}."
21
+ end
22
+
23
+ command "import", "Import a command set" do |command_set_name|
24
+ next output.puts "Provide a command set name" if command_set.nil?
25
+
26
+ set = target.eval(arg_string)
27
+ Pry.active_instance.commands.import set
28
+ end
29
+
30
+ command "reset", "Reset the REPL to a clean state." do
31
+ output.puts "Pry reset."
32
+ exec "pry"
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -3,23 +3,25 @@ require "pry/default_commands/ls"
3
3
  class Pry
4
4
  module DefaultCommands
5
5
 
6
- Context = Pry::CommandSet.new :context do
6
+ Context = Pry::CommandSet.new do
7
7
  import Ls
8
8
 
9
9
  command "cd", "Start a Pry session on VAR (use `cd ..` to go back and `cd /` to return to Pry top-level)", :keep_retval => true do |obj|
10
- if !obj
10
+ case obj
11
+ when nil
11
12
  output.puts "Must provide an object."
12
13
  next
13
- end
14
-
15
- throw(:breakout, opts[:nesting].level) if obj == ".."
16
-
17
- if obj == "/"
14
+ when ".."
15
+ throw(:breakout, opts[:nesting].level)
16
+ when "/"
18
17
  throw(:breakout, 1) if opts[:nesting].level > 0
19
18
  next
19
+ when "::"
20
+ TOPLEVEL_BINDING.pry
21
+ next
22
+ else
23
+ Pry.start target.eval(arg_string)
20
24
  end
21
-
22
- Pry.start target.eval("#{obj}")
23
25
  end
24
26
 
25
27
  command "nesting", "Show nesting information." do
@@ -52,16 +54,14 @@ class Pry
52
54
  end
53
55
 
54
56
  command "exit", "End the current Pry session. Accepts optional return value. Aliases: quit, back" do
55
- str = remove_first_word(opts[:val])
56
- throw(:breakout, [opts[:nesting].level, target.eval(str)])
57
+ throw(:breakout, [opts[:nesting].level, target.eval(arg_string)])
57
58
  end
58
59
 
59
60
  alias_command "quit", "exit", ""
60
61
  alias_command "back", "exit", ""
61
62
 
62
63
  command "exit-all", "End all nested Pry sessions. Accepts optional return value. Aliases: !!@" do
63
- str = remove_first_word(opts[:val])
64
- throw(:breakout, [0, target.eval(str)])
64
+ throw(:breakout, [0, target.eval(arg_string)])
65
65
  end
66
66
 
67
67
  alias_command "!!@", "exit-all", ""
@@ -74,7 +74,7 @@ class Pry
74
74
  alias_command "!!!", "exit-program", ""
75
75
 
76
76
  command "!pry", "Start a Pry session on current self; this even works mid-expression." do
77
- Pry.start(target)
77
+ target.pry
78
78
  end
79
79
 
80
80
  command "whereami", "Show the code context for the session. (whereami <n> shows <n> extra lines of code around the invocation line. Default: 5)" do |num|
@@ -97,7 +97,7 @@ class Pry
97
97
  end
98
98
 
99
99
  set_file_and_dir_locals(file)
100
- output.puts "\n#{bold('From:')} #{file} @ line #{line_num} in #{klass}##{meth_name}:\n\n"
100
+ output.puts "\n#{text.bold('From:')} #{file} @ line #{line_num} in #{klass}##{meth_name}:\n\n"
101
101
 
102
102
  # This method inspired by http://rubygems.org/gems/ir_b
103
103
  File.open(file).each_with_index do |line, index|
@@ -1,7 +1,7 @@
1
1
  class Pry
2
2
  module DefaultCommands
3
3
 
4
- Documentation = Pry::CommandSet.new :gems do
4
+ Documentation = Pry::CommandSet.new do
5
5
 
6
6
  command "ri", "View ri documentation. e.g `ri Array#each`" do |*args|
7
7
  run ".ri", *args
@@ -10,20 +10,19 @@ class Pry
10
10
  command "show-doc", "Show the comments above METH. Type `show-doc --help` for more info. Aliases: \?" do |*args|
11
11
  target = target()
12
12
 
13
- opts = Slop.parse!(args) do |opts|
14
- opts.banner %{Usage: show-doc [OPTIONS] [METH]
15
- Show the comments above method METH. Tries instance methods first and then methods by default.
16
- e.g show-doc hello_method
17
- --
18
- }
19
- opts.on :M, "instance-methods", "Operate on instance methods."
20
- opts.on :m, :methods, "Operate on methods."
21
- opts.on :c, :context, "Select object context to run under.", true do |context|
13
+ opts = Slop.parse!(args) do |opt|
14
+ opt.banner = "Usage: show-doc [OPTIONS] [METH]\n" \
15
+ "Show the comments above method METH. Tries instance methods first and then methods by default.\n" \
16
+ "e.g show-doc hello_method"
17
+
18
+ opt.on :M, "instance-methods", "Operate on instance methods."
19
+ opt.on :m, :methods, "Operate on methods."
20
+ opt.on :c, :context, "Select object context to run under.", true do |context|
22
21
  target = Pry.binding_for(target.eval(context))
23
22
  end
24
- opts.on :f, :flood, "Do not use a pager to view text longer than one screen."
25
- opts.on :h, :help, "This message." do
26
- output.puts opts
23
+ opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
24
+ opt.on :h, :help, "This message." do
25
+ output.puts opt
27
26
  end
28
27
  end
29
28
 
@@ -51,19 +50,18 @@ e.g show-doc hello_method
51
50
  command "stat", "View method information and set _file_ and _dir_ locals. Type `stat --help` for more info." do |*args|
52
51
  target = target()
53
52
 
54
- opts = Slop.parse!(args) do |opts|
55
- opts.banner %{Usage: stat [OPTIONS] [METH]
56
- Show method information for method METH and set _file_ and _dir_ locals.
57
- e.g: stat hello_method
58
- --
59
- }
60
- opts.on :M, "instance-methods", "Operate on instance methods."
61
- opts.on :m, :methods, "Operate on methods."
62
- opts.on :c, :context, "Select object context to run under.", true do |context|
53
+ opts = Slop.parse!(args) do |opt|
54
+ opt.banner "Usage: stat [OPTIONS] [METH]\n" \
55
+ "Show method information for method METH and set _file_ and _dir_ locals." \
56
+ "e.g: stat hello_method"
57
+
58
+ opt.on :M, "instance-methods", "Operate on instance methods."
59
+ opt.on :m, :methods, "Operate on methods."
60
+ opt.on :c, :context, "Select object context to run under.", true do |context|
63
61
  target = Pry.binding_for(target.eval(context))
64
62
  end
65
- opts.on :h, :help, "This message" do
66
- output.puts opts
63
+ opt.on :h, :help, "This message" do
64
+ output.puts opt
67
65
  end
68
66
  end
69
67
 
@@ -80,36 +78,37 @@ e.g: stat hello_method
80
78
  doc, code_type = doc_and_code_type_for(meth)
81
79
 
82
80
  output.puts make_header(meth, code_type, code)
83
- output.puts bold("Method Name: ") + meth_name
84
- output.puts bold("Method Owner: ") + (meth.owner.to_s ? meth.owner.to_s : "Unknown")
85
- output.puts bold("Method Language: ") + code_type.to_s.capitalize
86
- output.puts bold("Method Type: ") + (meth.is_a?(Method) ? "Bound" : "Unbound")
87
- output.puts bold("Method Arity: ") + meth.arity.to_s
81
+ output.puts text.bold("Method Name: ") + meth_name
82
+ output.puts text.bold("Method Owner: ") + (meth.owner.to_s ? meth.owner.to_s : "Unknown")
83
+ output.puts text.bold("Method Language: ") + code_type.to_s.capitalize
84
+ output.puts text.bold("Method Type: ") + (meth.is_a?(Method) ? "Bound" : "Unbound")
85
+ output.puts text.bold("Method Arity: ") + meth.arity.to_s
88
86
 
89
87
  name_map = { :req => "Required:", :opt => "Optional:", :rest => "Rest:" }
90
88
  if meth.respond_to?(:parameters)
91
- output.puts bold("Method Parameters: ") + meth.parameters.group_by(&:first).
89
+ output.puts text.bold("Method Parameters: ") + meth.parameters.group_by(&:first).
92
90
  map { |k, v| "#{name_map[k]} #{v.map { |kk, vv| vv ? vv.to_s : "noname" }.join(", ")}" }.join(". ")
93
91
  end
94
- output.puts bold("Comment length: ") + (doc.empty? ? 'No comment.' : (doc.lines.count.to_s + ' lines.'))
92
+ output.puts text.bold("Comment length: ") + (doc.empty? ? 'No comment.' : (doc.lines.count.to_s + ' lines.'))
95
93
  end
96
94
 
97
95
  command "gist-method", "Gist a method to github. Type `gist-method --help` for more info.", :requires_gem => "gist" do |*args|
96
+ require 'gist'
97
+
98
98
  target = target()
99
99
 
100
- opts = Slop.parse!(args) do |opts|
101
- opts.banner = %{Usage: gist-method [OPTIONS] [METH]
102
- Gist the method (doc or source) to github.
103
- Ensure the `gist` gem is properly working before use. http://github.com/defunkt/gist for instructions.
104
- e.g: gist -m my_method
105
- e.g: gist -d my_method
106
- --
107
- }
108
- opts.on :m, :method, "Gist a method's source."
109
- opts.on :d, :doc, "Gist a method's documentation."
110
- opts.on :p, :private, "Create a private gist (default: true)", :default => true
111
- opts.on :h, :help, "This message" do
112
- output.puts opts
100
+ opts = Slop.parse!(args) do |opt|
101
+ opt.banner "Usage: gist-method [OPTIONS] [METH]\n" \
102
+ "Gist the method (doc or source) to github.\n" \
103
+ "Ensure the `gist` gem is properly working before use. http://github.com/defunkt/gist for instructions.\n" \
104
+ "e.g: gist -m my_method\n" \
105
+ "e.g: gist -d my_method\n"
106
+
107
+ opt.on :m, :method, "Gist a method's source."
108
+ opt.on :d, :doc, "Gist a method's documentation."
109
+ opt.on :p, :private, "Create a private gist (default: true)", :default => true
110
+ opt.on :h, :help, "This message" do
111
+ output.puts opt
113
112
  end
114
113
  end
115
114
 
@@ -128,15 +127,17 @@ e.g: gist -d my_method
128
127
  content, code_type = code_and_code_type_for(meth)
129
128
  else
130
129
  content, code_type = doc_and_code_type_for(meth)
131
- no_color do
130
+ text.no_color do
132
131
  content = process_comment_markup(content, code_type)
133
132
  end
134
133
  code_type = :plain
135
134
  end
136
135
 
137
- IO.popen("gist#{' -p' if opts.p?} -t #{type_map[code_type]} -", "w") do |gist|
138
- gist.puts content
139
- end
136
+ link = Gist.write([:extension => ".#{type_map[code_type]}",
137
+ :input => content],
138
+ opts.p?)
139
+
140
+ output.puts "Gist created at #{link}"
140
141
  end
141
142
 
142
143
  end
@@ -1,26 +1,7 @@
1
1
  class Pry
2
2
  module DefaultCommands
3
3
 
4
- EasterEggs = Pry::CommandSet.new :easter_eggs do
5
-
6
- command "game", "" do |highest|
7
- highest = highest ? highest.to_i : 100
8
- num = rand(highest)
9
- output.puts "Guess the number between 0-#{highest}: ('.' to quit)"
10
- count = 0
11
- while(true)
12
- count += 1
13
- str = Readline.readline("game > ", true)
14
- break if str == "." || !str
15
- val = str.to_i
16
- output.puts "Too large!" if val > num
17
- output.puts "Too small!" if val < num
18
- if val == num
19
- output.puts "Well done! You guessed right! It took you #{count} guesses."
20
- break
21
- end
22
- end
23
- end
4
+ EasterEggs = Pry::CommandSet.new do
24
5
 
25
6
  command "east-coker", "" do
26
7
  text = %{
@@ -1,56 +1,47 @@
1
1
  class Pry
2
2
  module DefaultCommands
3
3
 
4
- Gems = Pry::CommandSet.new :gems do
5
-
6
- command "gem-install", "Install a gem and refresh the gem cache." do |gem_name|
7
- gem_home = Gem.instance_variable_get(:@gem_home)
8
- output.puts "Attempting to install gem: #{bold(gem_name)}"
4
+ Gems = Pry::CommandSet.new do
9
5
 
6
+ command "gem-install", "Install a gem and refresh the gem cache.", :argument_required => true do |gem|
10
7
  begin
11
- if File.writable?(gem_home)
12
- Gem::DependencyInstaller.new.install(gem_name)
13
- output.puts "Gem #{bold(gem_name)} successfully installed."
14
- else
15
- if system("sudo gem install #{gem_name}")
16
- output.puts "Gem #{bold(gem_name)} successfully installed."
17
- else
18
- output.puts "Gem #{bold(gem_name)} could not be installed."
19
- next
20
- end
21
- end
8
+ destination = File.writable?(Gem.dir) ? Gem.dir : Gem.user_dir
9
+ installer = Gem::DependencyInstaller.new :install_dir => destination
10
+ installer.install gem
11
+ rescue Errno::EACCES
12
+ output.puts "Insufficient permissions to install `#{text.green gem}`"
22
13
  rescue Gem::GemNotFoundException
23
- output.puts "Required Gem: #{bold(gem_name)} not found."
24
- next
14
+ output.puts "Gem `#{text.green gem}` not found."
15
+ else
16
+ Gem.refresh
17
+ output.puts "Gem `#{text.green gem}` installed."
25
18
  end
26
-
27
- Gem.refresh
28
- output.puts "Refreshed gem cache."
29
19
  end
30
20
 
31
- command "gem-cd", "Change working directory to specified gem's directory." do |gem_name|
32
- require 'rubygems'
33
- gem_spec = Gem.source_index.find_name(gem_name).first
34
- next output.puts("Gem `#{gem_name}` not found.") if !gem_spec
35
- Dir.chdir(File.expand_path(gem_spec.full_gem_path))
21
+ command "gem-cd", "Change working directory to specified gem's directory.", :argument_required => true do |gem|
22
+ specs = Gem::Specification.respond_to?(:each) ? Gem::Specification.find_all_by_name(gem) : Gem.source_index.find_name(gem)
23
+ spec = specs.sort { |a,b| Gem::Version.new(b.version) <=> Gem::Version.new(a.version) }.first
24
+ spec ? Dir.chdir(spec.full_gem_path) : output.puts("Gem `#{gem}` not found.")
36
25
  end
37
26
 
27
+ command "gem-list", "List/search installed gems. (Optional parameter: a regexp to limit the search)" do |pattern|
28
+ pattern = Regexp.new pattern.to_s, Regexp::IGNORECASE
29
+ gems = if Gem::Specification.respond_to?(:each)
30
+ Gem::Specification.select{|spec| spec.name =~ pattern }.group_by(&:name)
31
+ else
32
+ Gem.source_index.gems.values.group_by(&:name).select { |gemname, specs| gemname =~ pattern }
33
+ end
34
+
35
+ gems.each do |gem, specs|
36
+ specs.sort! do |a,b|
37
+ Gem::Version.new(b.version) <=> Gem::Version.new(a.version)
38
+ end
39
+
40
+ versions = specs.map.with_index do |spec, index|
41
+ index == 0 ? text.bright_green(spec.version.to_s) : text.green(spec.version.to_s)
42
+ end
38
43
 
39
- command "gem-list", "List/search installed gems. (Optional parameter: a regexp to limit the search)" do |arg|
40
- gems = Gem.source_index.gems.values.group_by(&:name)
41
- if arg
42
- query = Regexp.new(arg, Regexp::IGNORECASE)
43
- gems = gems.select { |gemname, specs| gemname =~ query }
44
- end
45
-
46
- gems.each do |gemname, specs|
47
- versions = specs.map(&:version).sort.reverse.map(&:to_s)
48
- versions = ["<bright_green>#{versions.first}</bright_green>"] +
49
- versions[1..-1].map{|v| "<green>#{v}</green>" }
50
-
51
- gemname = highlight(gemname, query) if query
52
- result = "<white>#{gemname} <grey>(#{versions.join ', '})</grey>"
53
- output.puts colorize(result)
44
+ output.puts "#{text.white gem} (#{versions.join ', '})"
54
45
  end
55
46
  end
56
47
 
@@ -1,36 +1,112 @@
1
1
  class Pry
2
2
  module DefaultCommands
3
3
 
4
- Input = Pry::CommandSet.new :input do
4
+ Input = Pry::CommandSet.new do
5
5
 
6
6
  command "!", "Clear the input buffer. Useful if the parsing process goes wrong and you get stuck in the read loop." do
7
7
  output.puts "Input buffer cleared!"
8
- opts[:eval_string].clear
8
+ eval_string.replace("")
9
9
  end
10
10
 
11
- command "hist", "Show and replay Readline history. When given no args history is displayed.\nType `hist --help` for more info." do |*args|
12
- hist_array = Readline::HISTORY.to_a
11
+ command "show-input", "Show the current eval_string" do
12
+ render_output(false, 0, Pry.color ? CodeRay.scan(eval_string, :ruby).term : eval_string)
13
+ end
13
14
 
14
- if args.empty?
15
- text = add_line_numbers(hist_array.join("\n"), 0)
16
- stagger_output(text)
17
- next
18
- end
15
+ command /amend-line-?(\d+)?/, "Experimental amend-line, where the N in amend-line-N represents line to replace. Aliases: %N",
16
+ :interpolate => false, :listing => "amend-line-N" do |line_number, replacement_line|
17
+ replacement_line = "" if !replacement_line
18
+ input_array = eval_string.each_line.to_a
19
+ line_num = line_number ? line_number.to_i : input_array.size - 1
20
+ input_array[line_num] = arg_string + "\n"
21
+ eval_string.replace input_array.join
22
+ end
19
23
 
20
- opts = Slop.parse(args) do |opt|
21
- opt.banner "Usage: hist [--replay START..END]\nView and replay history\nWhen given no args, history is displayed.\ne.g hist --replay 2..8"
22
- opt.on :r, :replay, 'The line (or range of lines) to replay.', true, :as => Range
23
- opt.on :h, :help, 'Show this message.', :tail => true do
24
- output.puts opt.help
24
+ alias_command /%(\d+)?/, /amend-line-?(\d+)?/, ""
25
+
26
+ command "hist", "Show and replay Readline history. Type `hist --help` for more info." do |*args|
27
+ Slop.parse(args) do |opt|
28
+ history = Readline::HISTORY.to_a
29
+ opt.banner "Usage: hist [--replay START..END] [--clear] [--grep PATTERN] [--head N] [--tail N] [--help]\n"
30
+
31
+ opt.on :g, :grep, 'A pattern to match against the history.', true do |pattern|
32
+ pattern = Regexp.new arg_string.split(/ /)[1]
33
+ history.pop
34
+
35
+ history.map!.with_index do |element, index|
36
+ if element =~ pattern
37
+ "#{text.blue index}: #{element}"
38
+ end
39
+ end
40
+
41
+ stagger_output history.compact.join "\n"
25
42
  end
26
- end
27
43
 
28
- next if opts.h?
44
+ opt.on :head, 'Display the first N items of history', :optional => true, :as => Integer do |limit|
45
+ unless opt.grep?
46
+ limit ||= 10
47
+ list = history.first limit
48
+ lines = text.with_line_numbers list.join("\n"), 0
49
+ stagger_output lines
50
+ end
51
+ end
29
52
 
30
- actions = Array(hist_array[opts[:replay]]).join("\n") + "\n"
31
- Pry.active_instance.input = StringIO.new(actions)
32
- end
53
+ opt.on :t, :tail, 'Display the last N items of history', :optional => true, :as => Integer do |limit|
54
+ unless opt.grep?
55
+ limit ||= 10
56
+ offset = history.size-limit
57
+ offset = offset < 0 ? 0 : offset
33
58
 
59
+ list = history.last limit
60
+ lines = text.with_line_numbers list.join("\n"), offset
61
+ stagger_output lines
62
+ end
63
+ end
64
+
65
+ opt.on :s, :show, 'Show the history corresponding to the history line (or range of lines).', true, :as => Range do |range|
66
+ unless opt.grep?
67
+ start_line = range.is_a?(Range) ? range.first : range
68
+ lines = text.with_line_numbers Array(history[range]).join("\n"), start_line
69
+ stagger_output lines
70
+ end
71
+ end
72
+
73
+ opt.on :e, :exclude, 'Exclude pry commands from the history.' do
74
+ unless opt.grep?
75
+ history.map!.with_index do |element, index|
76
+ unless command_processor.valid_command? element
77
+ "#{text.blue index}: #{element}"
78
+ end
79
+ end
80
+ stagger_output history.compact.join "\n"
81
+ end
82
+ end
83
+
84
+ opt.on :r, :replay, 'The line (or range of lines) to replay.', true, :as => Range do |range|
85
+ unless opt.grep?
86
+ actions = Array(history[range]).join("\n") + "\n"
87
+ Pry.active_instance.input = StringIO.new(actions)
88
+ end
89
+ end
90
+
91
+ opt.on :c, :clear, 'Clear the history' do
92
+ unless opt.grep?
93
+ Readline::HISTORY.shift until Readline::HISTORY.empty?
94
+ output.puts 'History cleared.'
95
+ end
96
+ end
97
+
98
+ opt.on :h, :help, 'Show this message.', :tail => true do
99
+ unless opt.grep?
100
+ output.puts opt.help
101
+ end
102
+ end
103
+
104
+ opt.on_empty do
105
+ lines = text.with_line_numbers history.join("\n"), 0
106
+ stagger_output lines
107
+ end
108
+ end
109
+ end
34
110
 
35
111
  end
36
112