pry 0.9.10pre1-i386-mswin32 → 0.9.11-i386-mswin32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +3 -1
- data/CHANGELOG +63 -2
- data/CONTRIBUTORS +43 -25
- data/Gemfile +7 -0
- data/Guardfile +62 -0
- data/README.markdown +4 -4
- data/Rakefile +34 -35
- data/lib/pry.rb +107 -54
- data/lib/pry/cli.rb +34 -11
- data/lib/pry/code.rb +165 -182
- data/lib/pry/code/code_range.rb +70 -0
- data/lib/pry/code/loc.rb +92 -0
- data/lib/pry/code_object.rb +153 -0
- data/lib/pry/command.rb +160 -22
- data/lib/pry/command_set.rb +37 -26
- data/lib/pry/commands.rb +4 -27
- data/lib/pry/commands/amend_line.rb +99 -0
- data/lib/pry/commands/bang.rb +20 -0
- data/lib/pry/commands/bang_pry.rb +17 -0
- data/lib/pry/commands/cat.rb +53 -0
- data/lib/pry/commands/cat/abstract_formatter.rb +27 -0
- data/lib/pry/commands/cat/exception_formatter.rb +78 -0
- data/lib/pry/commands/cat/file_formatter.rb +84 -0
- data/lib/pry/commands/cat/input_expression_formatter.rb +43 -0
- data/lib/pry/commands/cd.rb +30 -0
- data/lib/pry/commands/code_collector.rb +165 -0
- data/lib/pry/commands/deprecated_commands.rb +2 -0
- data/lib/pry/commands/disable_pry.rb +27 -0
- data/lib/pry/commands/easter_eggs.rb +112 -0
- data/lib/pry/commands/edit.rb +206 -0
- data/lib/pry/commands/edit/exception_patcher.rb +25 -0
- data/lib/pry/commands/edit/file_and_line_locator.rb +38 -0
- data/lib/pry/commands/edit/method_patcher.rb +122 -0
- data/lib/pry/commands/exit.rb +42 -0
- data/lib/pry/commands/exit_all.rb +29 -0
- data/lib/pry/commands/exit_program.rb +24 -0
- data/lib/pry/commands/find_method.rb +199 -0
- data/lib/pry/commands/fix_indent.rb +19 -0
- data/lib/pry/commands/gem_cd.rb +26 -0
- data/lib/pry/commands/gem_install.rb +29 -0
- data/lib/pry/commands/gem_list.rb +33 -0
- data/lib/pry/commands/gem_open.rb +29 -0
- data/lib/pry/commands/gist.rb +95 -0
- data/lib/pry/commands/help.rb +164 -0
- data/lib/pry/commands/hist.rb +161 -0
- data/lib/pry/commands/import_set.rb +22 -0
- data/lib/pry/commands/install_command.rb +51 -0
- data/lib/pry/commands/jump_to.rb +29 -0
- data/lib/pry/commands/ls.rb +339 -0
- data/lib/pry/commands/nesting.rb +25 -0
- data/lib/pry/commands/play.rb +69 -0
- data/lib/pry/commands/pry_backtrace.rb +26 -0
- data/lib/pry/commands/pry_version.rb +17 -0
- data/lib/pry/commands/raise_up.rb +32 -0
- data/lib/pry/commands/reload_code.rb +39 -0
- data/lib/pry/commands/reset.rb +18 -0
- data/lib/pry/commands/ri.rb +56 -0
- data/lib/pry/commands/save_file.rb +61 -0
- data/lib/pry/commands/shell_command.rb +43 -0
- data/lib/pry/commands/shell_mode.rb +27 -0
- data/lib/pry/commands/show_doc.rb +78 -0
- data/lib/pry/commands/show_info.rb +139 -0
- data/lib/pry/commands/show_input.rb +17 -0
- data/lib/pry/commands/show_source.rb +37 -0
- data/lib/pry/commands/simple_prompt.rb +22 -0
- data/lib/pry/commands/stat.rb +40 -0
- data/lib/pry/commands/switch_to.rb +23 -0
- data/lib/pry/commands/toggle_color.rb +20 -0
- data/lib/pry/commands/whereami.rb +114 -0
- data/lib/pry/commands/wtf.rb +57 -0
- data/lib/pry/completion.rb +120 -46
- data/lib/pry/config.rb +11 -0
- data/lib/pry/core_extensions.rb +30 -19
- data/lib/pry/editor.rb +129 -0
- data/lib/pry/helpers.rb +1 -0
- data/lib/pry/helpers/base_helpers.rb +89 -119
- data/lib/pry/helpers/command_helpers.rb +7 -122
- data/lib/pry/helpers/table.rb +100 -0
- data/lib/pry/helpers/text.rb +4 -4
- data/lib/pry/history_array.rb +5 -0
- data/lib/pry/hooks.rb +1 -3
- data/lib/pry/indent.rb +104 -30
- data/lib/pry/method.rb +66 -22
- data/lib/pry/module_candidate.rb +26 -15
- data/lib/pry/pager.rb +70 -0
- data/lib/pry/plugins.rb +1 -2
- data/lib/pry/pry_class.rb +63 -22
- data/lib/pry/pry_instance.rb +58 -37
- data/lib/pry/rubygem.rb +74 -0
- data/lib/pry/terminal_info.rb +43 -0
- data/lib/pry/test/helper.rb +185 -0
- data/lib/pry/version.rb +1 -1
- data/lib/pry/wrapped_module.rb +58 -24
- data/pry.gemspec +21 -37
- data/{test/test_cli.rb → spec/cli_spec.rb} +0 -0
- data/spec/code_object_spec.rb +277 -0
- data/{test/test_code.rb → spec/code_spec.rb} +19 -1
- data/{test/test_command_helpers.rb → spec/command_helpers_spec.rb} +0 -0
- data/{test/test_command_integration.rb → spec/command_integration_spec.rb} +38 -46
- data/{test/test_command_set.rb → spec/command_set_spec.rb} +18 -1
- data/{test/test_command.rb → spec/command_spec.rb} +250 -149
- data/spec/commands/amend_line_spec.rb +247 -0
- data/spec/commands/bang_spec.rb +19 -0
- data/spec/commands/cat_spec.rb +164 -0
- data/spec/commands/cd_spec.rb +250 -0
- data/spec/commands/disable_pry_spec.rb +25 -0
- data/spec/commands/edit_spec.rb +727 -0
- data/spec/commands/exit_all_spec.rb +34 -0
- data/spec/commands/exit_program_spec.rb +19 -0
- data/spec/commands/exit_spec.rb +34 -0
- data/{test/test_default_commands/test_find_method.rb → spec/commands/find_method_spec.rb} +27 -7
- data/spec/commands/gem_list_spec.rb +26 -0
- data/spec/commands/gist_spec.rb +75 -0
- data/{test/test_default_commands/test_help.rb → spec/commands/help_spec.rb} +8 -9
- data/spec/commands/hist_spec.rb +181 -0
- data/spec/commands/jump_to_spec.rb +15 -0
- data/spec/commands/ls_spec.rb +177 -0
- data/spec/commands/play_spec.rb +140 -0
- data/spec/commands/raise_up_spec.rb +56 -0
- data/spec/commands/save_file_spec.rb +177 -0
- data/spec/commands/show_doc_spec.rb +378 -0
- data/spec/commands/show_input_spec.rb +17 -0
- data/spec/commands/show_source_spec.rb +597 -0
- data/spec/commands/whereami_spec.rb +154 -0
- data/spec/completion_spec.rb +233 -0
- data/spec/control_d_handler_spec.rb +58 -0
- data/spec/editor_spec.rb +79 -0
- data/{test/test_exception_whitelist.rb → spec/exception_whitelist_spec.rb} +0 -0
- data/{test → spec/fixtures}/candidate_helper1.rb +0 -0
- data/{test → spec/fixtures}/candidate_helper2.rb +0 -0
- data/{test/test_default_commands → spec/fixtures}/example.erb +0 -0
- data/spec/fixtures/example_nesting.rb +33 -0
- data/spec/fixtures/show_source_doc_examples.rb +15 -0
- data/{test → spec/fixtures}/testrc +0 -0
- data/{test → spec/fixtures}/testrcbad +0 -0
- data/spec/helper.rb +34 -0
- data/spec/helpers/bacon.rb +86 -0
- data/spec/helpers/mock_pry.rb +43 -0
- data/spec/helpers/table_spec.rb +83 -0
- data/{test/test_history_array.rb → spec/history_array_spec.rb} +21 -19
- data/{test/test_hooks.rb → spec/hooks_spec.rb} +0 -0
- data/{test/test_indent.rb → spec/indent_spec.rb} +24 -0
- data/{test/test_input_stack.rb → spec/input_stack_spec.rb} +4 -0
- data/{test/test_method.rb → spec/method_spec.rb} +65 -1
- data/{test/test_prompt.rb → spec/prompt_spec.rb} +0 -0
- data/{test/test_pry_defaults.rb → spec/pry_defaults_spec.rb} +14 -14
- data/{test/test_pry_history.rb → spec/pry_history_spec.rb} +15 -0
- data/spec/pry_output_spec.rb +95 -0
- data/{test/test_pry.rb → spec/pry_spec.rb} +74 -32
- data/{test/test_sticky_locals.rb → spec/sticky_locals_spec.rb} +27 -25
- data/{test/test_syntax_checking.rb → spec/syntax_checking_spec.rb} +17 -1
- data/{test/test_wrapped_module.rb → spec/wrapped_module_spec.rb} +92 -5
- metadata +239 -115
- data/examples/example_basic.rb +0 -15
- data/examples/example_command_override.rb +0 -32
- data/examples/example_commands.rb +0 -36
- data/examples/example_hooks.rb +0 -9
- data/examples/example_image_edit.rb +0 -67
- data/examples/example_input.rb +0 -7
- data/examples/example_input2.rb +0 -29
- data/examples/example_output.rb +0 -11
- data/examples/example_print.rb +0 -6
- data/examples/example_prompt.rb +0 -9
- data/examples/helper.rb +0 -6
- data/lib/pry/default_commands/cd.rb +0 -81
- data/lib/pry/default_commands/commands.rb +0 -62
- data/lib/pry/default_commands/context.rb +0 -98
- data/lib/pry/default_commands/easter_eggs.rb +0 -95
- data/lib/pry/default_commands/editing.rb +0 -420
- data/lib/pry/default_commands/find_method.rb +0 -169
- data/lib/pry/default_commands/gems.rb +0 -84
- data/lib/pry/default_commands/gist.rb +0 -187
- data/lib/pry/default_commands/help.rb +0 -127
- data/lib/pry/default_commands/hist.rb +0 -120
- data/lib/pry/default_commands/input_and_output.rb +0 -306
- data/lib/pry/default_commands/introspection.rb +0 -410
- data/lib/pry/default_commands/ls.rb +0 -272
- data/lib/pry/default_commands/misc.rb +0 -38
- data/lib/pry/default_commands/navigating_pry.rb +0 -110
- data/lib/pry/default_commands/whereami.rb +0 -92
- data/lib/pry/extended_commands/experimental.rb +0 -7
- data/test/helper.rb +0 -223
- data/test/test_completion.rb +0 -62
- data/test/test_control_d_handler.rb +0 -45
- data/test/test_default_commands/test_cd.rb +0 -321
- data/test/test_default_commands/test_context.rb +0 -288
- data/test/test_default_commands/test_documentation.rb +0 -315
- data/test/test_default_commands/test_gems.rb +0 -18
- data/test/test_default_commands/test_input.rb +0 -428
- data/test/test_default_commands/test_introspection.rb +0 -511
- data/test/test_default_commands/test_ls.rb +0 -151
- data/test/test_default_commands/test_shell.rb +0 -343
- data/test/test_default_commands/test_show_source.rb +0 -432
- data/test/test_pry_output.rb +0 -41
@@ -0,0 +1,164 @@
|
|
1
|
+
class Pry
|
2
|
+
class Command::Help < Pry::ClassCommand
|
3
|
+
match 'help'
|
4
|
+
group 'Help'
|
5
|
+
description 'Show a list of commands or information about a specific command'
|
6
|
+
|
7
|
+
banner <<-'BANNER'
|
8
|
+
Usage: help [COMMAND]
|
9
|
+
|
10
|
+
With no arguments, help lists all the available commands in the current
|
11
|
+
command-set along with their description. When given a command name as an
|
12
|
+
argument, shows the help for that command.
|
13
|
+
BANNER
|
14
|
+
|
15
|
+
# We only want to show commands that have descriptions, so that the
|
16
|
+
# easter eggs don't show up.
|
17
|
+
def visible_commands
|
18
|
+
visible = {}
|
19
|
+
commands.each do |key, command|
|
20
|
+
visible[key] = command if command.description && !command.description.empty?
|
21
|
+
end
|
22
|
+
visible
|
23
|
+
end
|
24
|
+
|
25
|
+
# Get a hash of available commands grouped by the "group" name.
|
26
|
+
def command_groups
|
27
|
+
visible_commands.values.group_by(&:group)
|
28
|
+
end
|
29
|
+
|
30
|
+
def process
|
31
|
+
if args.empty?
|
32
|
+
display_index(command_groups)
|
33
|
+
else
|
34
|
+
display_search(args.first)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Display the index view, with headings and short descriptions per command.
|
39
|
+
#
|
40
|
+
# @param Hash[String => Array[Commands]]
|
41
|
+
def display_index(groups)
|
42
|
+
help_text = []
|
43
|
+
|
44
|
+
sorted_group_names(groups).each do |group_name|
|
45
|
+
commands = sorted_commands(groups[group_name])
|
46
|
+
|
47
|
+
if commands.any?
|
48
|
+
help_text << help_text_for_commands(group_name, commands)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
stagger_output(help_text.join("\n\n"))
|
53
|
+
end
|
54
|
+
|
55
|
+
# Given a group name and an array of commands,
|
56
|
+
# return the help string for those commands.
|
57
|
+
#
|
58
|
+
# @param [String] name The group name.
|
59
|
+
# @param [Array<Pry::Command>]] commands
|
60
|
+
# @return [String] The generated help string.
|
61
|
+
def help_text_for_commands(name, commands)
|
62
|
+
"#{text.bold(name)}\n" + commands.map do |command|
|
63
|
+
" #{command.options[:listing].to_s.ljust(18)} #{command.description}"
|
64
|
+
end.join("\n")
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param [Hash] groups
|
68
|
+
# @return [Array<String>] An array of sorted group names.
|
69
|
+
def sorted_group_names(groups)
|
70
|
+
groups.keys.sort_by(&method(:group_sort_key))
|
71
|
+
end
|
72
|
+
|
73
|
+
# Sort an array of commands by their `listing` name.
|
74
|
+
#
|
75
|
+
# @param [Array<Pry::Command>] commands The commands to sort
|
76
|
+
# @return [Array<Pry::Command>] commands sorted by listing name.
|
77
|
+
def sorted_commands(commands)
|
78
|
+
commands.sort_by{ |command| command.options[:listing].to_s }
|
79
|
+
end
|
80
|
+
|
81
|
+
# Display help for an individual command or group.
|
82
|
+
#
|
83
|
+
# @param [String] search The string to search for.
|
84
|
+
def display_search(search)
|
85
|
+
if command = command_set.find_command_for_help(search)
|
86
|
+
display_command(command)
|
87
|
+
else
|
88
|
+
display_filtered_search_results(search)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Display help for a searched item, filtered first by group
|
93
|
+
# and if that fails, filtered by command name.
|
94
|
+
#
|
95
|
+
# @param [String] search The string to search for.
|
96
|
+
def display_filtered_search_results(search)
|
97
|
+
groups = search_hash(search, command_groups)
|
98
|
+
|
99
|
+
if groups.size > 0
|
100
|
+
display_index(groups)
|
101
|
+
else
|
102
|
+
display_filtered_commands(search)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Display help for a searched item, filtered by group
|
107
|
+
#
|
108
|
+
# @param [String] search The string to search for.
|
109
|
+
def display_filtered_commands(search)
|
110
|
+
filtered = search_hash(search, visible_commands)
|
111
|
+
raise CommandError, "No help found for '#{args.first}'" if filtered.empty?
|
112
|
+
|
113
|
+
if filtered.size == 1
|
114
|
+
display_command(filtered.values.first)
|
115
|
+
else
|
116
|
+
display_index({"'#{search}' commands" => filtered.values})
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Display help for an individual command.
|
121
|
+
#
|
122
|
+
# @param [Pry::Command] command
|
123
|
+
def display_command(command)
|
124
|
+
stagger_output command.new.help
|
125
|
+
end
|
126
|
+
|
127
|
+
# Find a subset of a hash that matches the user's search term.
|
128
|
+
#
|
129
|
+
# If there's an exact match a Hash of one element will be returned,
|
130
|
+
# otherwise a sub-Hash with every key that matches the search will
|
131
|
+
# be returned.
|
132
|
+
#
|
133
|
+
# @param [String] the search term
|
134
|
+
# @param [Hash] the hash to search
|
135
|
+
def search_hash(search, hash)
|
136
|
+
matching = {}
|
137
|
+
|
138
|
+
hash.each_pair do |key, value|
|
139
|
+
next unless key.is_a?(String)
|
140
|
+
if normalize(key) == normalize(search)
|
141
|
+
return {key => value}
|
142
|
+
elsif normalize(key).start_with?(normalize(search))
|
143
|
+
matching[key] = value
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
matching
|
148
|
+
end
|
149
|
+
|
150
|
+
# Clean search terms to make it easier to search group names
|
151
|
+
#
|
152
|
+
# @param String
|
153
|
+
# @return String
|
154
|
+
def normalize(key)
|
155
|
+
key.downcase.gsub(/pry\W+/, '')
|
156
|
+
end
|
157
|
+
|
158
|
+
def group_sort_key(group_name)
|
159
|
+
[%w(Help Context Editing Introspection Input_and_output Navigating_pry Gems Basic Commands).index(group_name.gsub(' ', '_')) || 99, group_name]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
Pry::Commands.add_command(Pry::Command::Help)
|
164
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
class Pry
|
2
|
+
class Command::Hist < Pry::ClassCommand
|
3
|
+
match 'hist'
|
4
|
+
group 'Editing'
|
5
|
+
description 'Show and replay Readline history.'
|
6
|
+
|
7
|
+
banner <<-'BANNER'
|
8
|
+
Usage: hist [--head|--tail]
|
9
|
+
hist --head N
|
10
|
+
hist --tail N
|
11
|
+
hist --show START..END
|
12
|
+
hist --grep PATTERN
|
13
|
+
hist --clear
|
14
|
+
hist --replay START..END
|
15
|
+
hist --save [START..END] FILE
|
16
|
+
Aliases: history
|
17
|
+
|
18
|
+
Show and replay Readline history.
|
19
|
+
BANNER
|
20
|
+
|
21
|
+
def options(opt)
|
22
|
+
opt.on :H, :head, "Display the first N items", :optional_argument => true, :as => Integer
|
23
|
+
opt.on :T, :tail, "Display the last N items", :optional_argument => true, :as => Integer
|
24
|
+
opt.on :s, :show, "Show the given range of lines", :optional_argument => true, :as => Range
|
25
|
+
opt.on :G, :grep, "Show lines matching the given pattern", :argument => true, :as => String
|
26
|
+
opt.on :c, :clear , "Clear the current session's history"
|
27
|
+
opt.on :r, :replay, "Replay a line or range of lines", :argument => true, :as => Range
|
28
|
+
opt.on :save, "Save history to a file", :argument => true, :as => Range
|
29
|
+
opt.on :e, :'exclude-pry', "Exclude Pry commands from the history"
|
30
|
+
opt.on :n, :'no-numbers', "Omit line numbers"
|
31
|
+
opt.on :f, :flood, "Do not use a pager to view text longer than one screen"
|
32
|
+
end
|
33
|
+
|
34
|
+
def process
|
35
|
+
@history = Pry::Code(Pry.history.to_a)
|
36
|
+
|
37
|
+
if opts.present?(:show)
|
38
|
+
@history = @history.between(opts[:show])
|
39
|
+
end
|
40
|
+
|
41
|
+
if opts.present?(:grep)
|
42
|
+
@history = @history.grep(opts[:grep])
|
43
|
+
end
|
44
|
+
|
45
|
+
@history = case
|
46
|
+
when opts.present?(:head)
|
47
|
+
@history.take_lines(1, opts[:head] || 10)
|
48
|
+
when opts.present?(:tail)
|
49
|
+
@history.take_lines(-(opts[:tail] || 10), opts[:tail] || 10)
|
50
|
+
when opts.present?(:show)
|
51
|
+
@history.between(opts[:show])
|
52
|
+
else
|
53
|
+
@history
|
54
|
+
end
|
55
|
+
|
56
|
+
if opts.present?(:'exclude-pry')
|
57
|
+
@history = @history.select { |l, ln| !command_set.valid_command?(l) }
|
58
|
+
end
|
59
|
+
|
60
|
+
if opts.present?(:save)
|
61
|
+
process_save
|
62
|
+
elsif opts.present?(:clear)
|
63
|
+
process_clear
|
64
|
+
elsif opts.present?(:replay)
|
65
|
+
process_replay
|
66
|
+
else
|
67
|
+
process_display
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def process_display
|
74
|
+
unless opts.present?(:'no-numbers')
|
75
|
+
@history = @history.with_line_numbers
|
76
|
+
end
|
77
|
+
|
78
|
+
render_output(@history, opts)
|
79
|
+
end
|
80
|
+
|
81
|
+
def process_save
|
82
|
+
case opts[:save]
|
83
|
+
when Range
|
84
|
+
@history = @history.between(opts[:save])
|
85
|
+
|
86
|
+
unless args.first
|
87
|
+
raise CommandError, "Must provide a file name."
|
88
|
+
end
|
89
|
+
|
90
|
+
file_name = File.expand_path(args.first)
|
91
|
+
when String
|
92
|
+
file_name = File.expand_path(opts[:save])
|
93
|
+
end
|
94
|
+
|
95
|
+
output.puts "Saving history in #{file_name}..."
|
96
|
+
|
97
|
+
File.open(file_name, 'w') { |f| f.write(@history.raw) }
|
98
|
+
|
99
|
+
output.puts "History saved."
|
100
|
+
end
|
101
|
+
|
102
|
+
def process_clear
|
103
|
+
Pry.history.clear
|
104
|
+
output.puts "History cleared."
|
105
|
+
end
|
106
|
+
|
107
|
+
def process_replay
|
108
|
+
@history = @history.between(opts[:r])
|
109
|
+
replay_sequence = @history.raw
|
110
|
+
|
111
|
+
# If we met follow-up "hist" call, check for the "--replay" option
|
112
|
+
# presence. If "hist" command is called with other options, proceed
|
113
|
+
# further.
|
114
|
+
check_for_juxtaposed_replay(replay_sequence)
|
115
|
+
|
116
|
+
_pry_.input_stack.push _pry_.input
|
117
|
+
_pry_.input = StringIO.new(replay_sequence)
|
118
|
+
# eval_string << "#{@history.raw}\n"
|
119
|
+
# run "show-input" unless _pry_.complete_expression?(eval_string)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Checks +replay_sequence+ for the presence of neighboring replay calls.
|
123
|
+
# @example
|
124
|
+
# [1] pry(main)> hist --show 46894
|
125
|
+
# 46894: hist --replay 46675..46677
|
126
|
+
# [2] pry(main)> hist --show 46675..46677
|
127
|
+
# 46675: 1+1
|
128
|
+
# 46676: a = 100
|
129
|
+
# 46677: hist --tail
|
130
|
+
# [3] pry(main)> hist --replay 46894
|
131
|
+
# Error: Replay index 46894 points out to another replay call: `hist -r 46675..46677`
|
132
|
+
# [4] pry(main)>
|
133
|
+
#
|
134
|
+
# @raise [Pry::CommandError] If +replay_sequence+ contains another
|
135
|
+
# "hist --replay" call
|
136
|
+
# @param [String] replay_sequence The sequence of commands to be replayed
|
137
|
+
# (per saltum)
|
138
|
+
# @return [Boolean] `false` if +replay_sequence+ does not contain another
|
139
|
+
# "hist --replay" call
|
140
|
+
def check_for_juxtaposed_replay(replay_sequence)
|
141
|
+
if replay_sequence =~ /\Ahist(?:ory)?\b/
|
142
|
+
# Create *fresh* instance of Options for parsing of "hist" command.
|
143
|
+
_slop = self.slop
|
144
|
+
_slop.parse replay_sequence.split(' ')[1..-1]
|
145
|
+
|
146
|
+
if _slop.present?(:r)
|
147
|
+
replay_sequence = replay_sequence.split("\n").join('; ')
|
148
|
+
index = opts[:r]
|
149
|
+
index = index.min if index.min == index.max || index.max.nil?
|
150
|
+
|
151
|
+
raise CommandError, "Replay index #{ index } points out to another replay call: `#{ replay_sequence }`"
|
152
|
+
end
|
153
|
+
else
|
154
|
+
false
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
Pry::Commands.add_command(Pry::Command::Hist)
|
160
|
+
Pry::Commands.alias_command 'history', 'hist'
|
161
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Pry
|
2
|
+
class Command::ImportSet < Pry::ClassCommand
|
3
|
+
match 'import-set'
|
4
|
+
group 'Commands'
|
5
|
+
# TODO: Provide a better description with examples and a general conception
|
6
|
+
# of this command.
|
7
|
+
description 'Import a Pry command set.'
|
8
|
+
|
9
|
+
banner <<-'BANNER'
|
10
|
+
Import a Pry command set.
|
11
|
+
BANNER
|
12
|
+
|
13
|
+
def process(command_set_name)
|
14
|
+
raise CommandError, "Provide a command set name" if command_set.nil?
|
15
|
+
|
16
|
+
set = target.eval(arg_string)
|
17
|
+
_pry_.commands.import set
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Pry::Commands.add_command(Pry::Command::ImportSet)
|
22
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Pry
|
2
|
+
class Command::InstallCommand < Pry::ClassCommand
|
3
|
+
match 'install-command'
|
4
|
+
group 'Commands'
|
5
|
+
description 'Install a disabled command.'
|
6
|
+
|
7
|
+
banner <<-'BANNER'
|
8
|
+
Usage: install-command COMMAND
|
9
|
+
|
10
|
+
Installs the gems necessary to run the given COMMAND. You will generally not
|
11
|
+
need to run this unless told to by an error message.
|
12
|
+
BANNER
|
13
|
+
|
14
|
+
def process(name)
|
15
|
+
require 'rubygems/dependency_installer' unless defined? Gem::DependencyInstaller
|
16
|
+
command = find_command(name)
|
17
|
+
|
18
|
+
if command_dependencies_met?(command.options)
|
19
|
+
output.puts "Dependencies for #{command.name} are met. Nothing to do."
|
20
|
+
return
|
21
|
+
end
|
22
|
+
|
23
|
+
output.puts "Attempting to install `#{name}` command..."
|
24
|
+
gems_to_install = Array(command.options[:requires_gem])
|
25
|
+
|
26
|
+
gems_to_install.each do |g|
|
27
|
+
next if Rubygem.installed?(g)
|
28
|
+
output.puts "Installing `#{g}` gem..."
|
29
|
+
|
30
|
+
begin
|
31
|
+
Gem::DependencyInstaller.new.install(g)
|
32
|
+
rescue Gem::GemNotFoundException
|
33
|
+
raise CommandError, "Required Gem: `#{g}` not found. Aborting command installation."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Gem.refresh
|
38
|
+
gems_to_install.each do |g|
|
39
|
+
begin
|
40
|
+
require g
|
41
|
+
rescue LoadError
|
42
|
+
raise CommandError, "Required Gem: `#{g}` installed but not found?!. Aborting command installation."
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
output.puts "Installation of `#{name}` successful! Type `help #{name}` for information"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Pry::Commands.add_command(Pry::Command::InstallCommand)
|
51
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Pry
|
2
|
+
class Command::JumpTo < Pry::ClassCommand
|
3
|
+
match 'jump-to'
|
4
|
+
group 'Navigating Pry'
|
5
|
+
description 'Jump to a binding further up the stack.'
|
6
|
+
|
7
|
+
banner <<-'BANNER'
|
8
|
+
Jump to a binding further up the stack, popping all bindings below.
|
9
|
+
BANNER
|
10
|
+
|
11
|
+
def process(break_level)
|
12
|
+
break_level = break_level.to_i
|
13
|
+
nesting_level = _pry_.binding_stack.size - 1
|
14
|
+
|
15
|
+
case break_level
|
16
|
+
when nesting_level
|
17
|
+
output.puts "Already at nesting level #{nesting_level}"
|
18
|
+
when (0...nesting_level)
|
19
|
+
_pry_.binding_stack.slice!(break_level + 1, _pry_.binding_stack.size)
|
20
|
+
|
21
|
+
else
|
22
|
+
max_nest_level = nesting_level - 1
|
23
|
+
output.puts "Invalid nest level. Must be between 0 and #{max_nest_level}. Got #{break_level}."
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Pry::Commands.add_command(Pry::Command::JumpTo)
|
29
|
+
end
|
@@ -0,0 +1,339 @@
|
|
1
|
+
class Pry
|
2
|
+
class Command::Ls < Pry::ClassCommand
|
3
|
+
match 'ls'
|
4
|
+
group 'Context'
|
5
|
+
description 'Show the list of vars and methods in the current scope.'
|
6
|
+
command_options :shellwords => false, :interpolate => false
|
7
|
+
|
8
|
+
def options(opt)
|
9
|
+
opt.banner unindent <<-'BANNER'
|
10
|
+
Usage: ls [-m|-M|-p|-pM] [-q|-v] [-c|-i] [Object]
|
11
|
+
ls [-g] [-l]
|
12
|
+
|
13
|
+
ls shows you which methods, constants and variables are accessible to Pry. By
|
14
|
+
default it shows you the local variables defined in the current shell, and any
|
15
|
+
public methods or instance variables defined on the current object.
|
16
|
+
|
17
|
+
The colours used are configurable using Pry.config.ls.*_color, and the separator
|
18
|
+
is Pry.config.ls.separator.
|
19
|
+
|
20
|
+
Pry.config.ls.ceiling is used to hide methods defined higher up in the
|
21
|
+
inheritance chain, this is by default set to [Object, Module, Class] so that
|
22
|
+
methods defined on all Objects are omitted. The -v flag can be used to ignore
|
23
|
+
this setting and show all methods, while the -q can be used to set the ceiling
|
24
|
+
much lower and show only methods defined on the object or its direct class.
|
25
|
+
BANNER
|
26
|
+
|
27
|
+
opt.on :m, :methods, "Show public methods defined on the Object (default)"
|
28
|
+
opt.on :M, "instance-methods", "Show methods defined in a Module or Class"
|
29
|
+
opt.on :p, :ppp, "Show public, protected (in yellow) and private (in green) methods"
|
30
|
+
opt.on :q, :quiet, "Show only methods defined on object.singleton_class and object.class"
|
31
|
+
opt.on :v, :verbose, "Show methods and constants on all super-classes (ignores Pry.config.ls.ceiling)"
|
32
|
+
opt.on :g, :globals, "Show global variables, including those builtin to Ruby (in cyan)"
|
33
|
+
opt.on :l, :locals, "Show hash of local vars, sorted by descending size"
|
34
|
+
opt.on :c, :constants, "Show constants, highlighting classes (in blue), and exceptions (in purple).\n" +
|
35
|
+
" " * 32 + "Constants that are pending autoload? are also shown (in yellow)"
|
36
|
+
opt.on :i, :ivars, "Show instance variables (in blue) and class variables (in bright blue)"
|
37
|
+
opt.on :G, :grep, "Filter output by regular expression", :argument => true
|
38
|
+
|
39
|
+
if jruby?
|
40
|
+
opt.on :J, "all-java", "Show all the aliases for methods from java (default is to show only prettiest)"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
attr_reader :object_to_interrogate, :has_user_specified_any_options, :grep, :grep_regex
|
45
|
+
|
46
|
+
def process
|
47
|
+
@object_to_interrogate = args.empty? ? target_self : target.eval(args.join(" "))
|
48
|
+
|
49
|
+
# exclude -q, -v and --grep because they don't specify what the user wants to see.
|
50
|
+
@has_user_specified_any_options = (opts.present?(:methods) || opts.present?(:'instance-methods') || opts.present?(:ppp) ||
|
51
|
+
opts.present?(:globals) || opts.present?(:locals) || opts.present?(:constants) ||
|
52
|
+
opts.present?(:ivars))
|
53
|
+
|
54
|
+
@grep_regex, @grep = [Regexp.new(opts[:G] || "."), lambda{ |x| x.grep(@grep_regex) }]
|
55
|
+
|
56
|
+
raise_errors_if_arguments_are_weird
|
57
|
+
|
58
|
+
all_output = [
|
59
|
+
write_out_globals,
|
60
|
+
write_out_constants,
|
61
|
+
write_out_methods,
|
62
|
+
write_out_self_methods,
|
63
|
+
write_out_ivars,
|
64
|
+
write_out_local_names,
|
65
|
+
write_out_locals,
|
66
|
+
].compact.join("")
|
67
|
+
|
68
|
+
stagger_output(all_output)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# http://ruby.runpaint.org/globals, and running "puts global_variables.inspect".
|
74
|
+
BUILTIN_GLOBALS = %w($" $$ $* $, $-0 $-F $-I $-K $-W $-a $-d $-i $-l $-p $-v $-w $. $/ $\\
|
75
|
+
$: $; $< $= $> $0 $ARGV $CONSOLE $DEBUG $DEFAULT_INPUT $DEFAULT_OUTPUT
|
76
|
+
$FIELD_SEPARATOR $FILENAME $FS $IGNORECASE $INPUT_LINE_NUMBER
|
77
|
+
$INPUT_RECORD_SEPARATOR $KCODE $LOADED_FEATURES $LOAD_PATH $NR $OFS
|
78
|
+
$ORS $OUTPUT_FIELD_SEPARATOR $OUTPUT_RECORD_SEPARATOR $PID $PROCESS_ID
|
79
|
+
$PROGRAM_NAME $RS $VERBOSE $deferr $defout $stderr $stdin $stdout)
|
80
|
+
|
81
|
+
# $SAFE and $? are thread-local, the exception stuff only works in a rescue clause,
|
82
|
+
# everything else is basically a local variable with a $ in its name.
|
83
|
+
PSEUDO_GLOBALS = %w($! $' $& $` $@ $? $+ $_ $~ $1 $2 $3 $4 $5 $6 $7 $8 $9
|
84
|
+
$CHILD_STATUS $SAFE $ERROR_INFO $ERROR_POSITION $LAST_MATCH_INFO
|
85
|
+
$LAST_PAREN_MATCH $LAST_READ_LINE $MATCH $POSTMATCH $PREMATCH)
|
86
|
+
|
87
|
+
# Get all the methods that we'll want to output
|
88
|
+
def all_methods(obj, instance_methods=false)
|
89
|
+
methods = if instance_methods || opts.present?(:'instance-methods')
|
90
|
+
Pry::Method.all_from_class(obj)
|
91
|
+
else
|
92
|
+
Pry::Method.all_from_obj(obj)
|
93
|
+
end
|
94
|
+
|
95
|
+
if jruby? && !opts.present?(:J)
|
96
|
+
methods = trim_jruby_aliases(methods)
|
97
|
+
end
|
98
|
+
|
99
|
+
methods.select{ |method| opts.present?(:ppp) || method.visibility == :public }
|
100
|
+
end
|
101
|
+
|
102
|
+
# JRuby creates lots of aliases for methods imported from java in an attempt to
|
103
|
+
# make life easier for ruby programmers.
|
104
|
+
# (e.g. getFooBar becomes get_foo_bar and foo_bar, and maybe foo_bar? if it
|
105
|
+
# returns a Boolean).
|
106
|
+
# The full transformations are in the assignAliases method of:
|
107
|
+
# https://github.com/jruby/jruby/blob/master/src/org/jruby/javasupport/JavaClass.java
|
108
|
+
#
|
109
|
+
# This has the unfortunate side-effect of making the output of ls even more
|
110
|
+
# incredibly verbose than it normally would be for these objects; and so we filter
|
111
|
+
# out all but the nicest of these aliases here.
|
112
|
+
#
|
113
|
+
# TODO: This is a little bit vague, better heuristics could be used.
|
114
|
+
# JRuby also has a lot of scala-specific logic, which we don't copy.
|
115
|
+
#
|
116
|
+
def trim_jruby_aliases(methods)
|
117
|
+
grouped = methods.group_by do |m|
|
118
|
+
m.name.sub(/\A(is|get|set)(?=[A-Z_])/, '').gsub(/[_?=]/, '').downcase
|
119
|
+
end
|
120
|
+
|
121
|
+
grouped.map do |key, values|
|
122
|
+
values = values.sort_by do |m|
|
123
|
+
rubbishness(m.name)
|
124
|
+
end
|
125
|
+
|
126
|
+
found = []
|
127
|
+
values.select do |x|
|
128
|
+
(!found.any?{ |y| x == y }) && found << x
|
129
|
+
end
|
130
|
+
end.flatten(1)
|
131
|
+
end
|
132
|
+
|
133
|
+
# When removing jruby aliases, we want to keep the alias that is "least rubbish"
|
134
|
+
# according to this metric.
|
135
|
+
def rubbishness(name)
|
136
|
+
name.each_char.map{ |x|
|
137
|
+
case x
|
138
|
+
when /[A-Z]/
|
139
|
+
1
|
140
|
+
when '?', '=', '!'
|
141
|
+
-2
|
142
|
+
else
|
143
|
+
0
|
144
|
+
end
|
145
|
+
}.inject(&:+) + (name.size / 100.0)
|
146
|
+
end
|
147
|
+
|
148
|
+
def resolution_order(obj)
|
149
|
+
opts.present?(:'instance-methods') ? Pry::Method.instance_resolution_order(obj) : Pry::Method.resolution_order(obj)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Get a lambda that can be used with .take_while to prevent over-eager
|
153
|
+
# traversal of the Object's ancestry graph.
|
154
|
+
def below_ceiling(obj)
|
155
|
+
ceiling = if opts.present?(:quiet)
|
156
|
+
[opts.present?(:'instance-methods') ? obj.ancestors[1] : obj.class.ancestors[1]] + Pry.config.ls.ceiling
|
157
|
+
elsif opts.present?(:verbose)
|
158
|
+
[]
|
159
|
+
else
|
160
|
+
Pry.config.ls.ceiling.dup
|
161
|
+
end
|
162
|
+
|
163
|
+
lambda { |klass| !ceiling.include?(klass) }
|
164
|
+
end
|
165
|
+
|
166
|
+
def raise_errors_if_arguments_are_weird
|
167
|
+
[
|
168
|
+
["-l does not make sense with a specified Object", :locals, !args.empty?],
|
169
|
+
["-g does not make sense with a specified Object", :globals, !args.empty?],
|
170
|
+
["-q does not make sense with -v", :quiet, opts.present?(:verbose)],
|
171
|
+
["-M only makes sense with a Module or a Class", :'instance-methods', !interrogating_a_module?],
|
172
|
+
["-c only makes sense with a Module or a Class", :constants, !args.empty? && !interrogating_a_module?],
|
173
|
+
].each do |message, option, expression|
|
174
|
+
raise Pry::CommandError, message if opts.present?(option) && expression
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def interrogating_a_module?
|
179
|
+
(Module === object_to_interrogate)
|
180
|
+
end
|
181
|
+
|
182
|
+
def write_out_globals
|
183
|
+
return unless opts.present?(:globals)
|
184
|
+
|
185
|
+
output_section("global variables", grep[format_globals(target.eval("global_variables"))])
|
186
|
+
end
|
187
|
+
|
188
|
+
def write_out_constants
|
189
|
+
return unless opts.present?(:constants) || (!has_user_specified_any_options && interrogating_a_module?)
|
190
|
+
|
191
|
+
mod = interrogating_a_module? ? object_to_interrogate : Object
|
192
|
+
constants = mod.constants
|
193
|
+
constants -= (mod.ancestors - [mod]).map(&:constants).flatten unless opts.present?(:verbose)
|
194
|
+
output_section("constants", grep[format_constants(mod, constants)])
|
195
|
+
end
|
196
|
+
|
197
|
+
def write_out_methods
|
198
|
+
return unless opts.present?(:methods) || opts.present?(:'instance-methods') || opts.present?(:ppp) || !has_user_specified_any_options
|
199
|
+
|
200
|
+
# methods is a hash {Module/Class => [Pry::Methods]}
|
201
|
+
methods = all_methods(object_to_interrogate).group_by(&:owner)
|
202
|
+
|
203
|
+
output = ""
|
204
|
+
# reverse the resolution order so that the most useful information appears right by the prompt
|
205
|
+
resolution_order(object_to_interrogate).take_while(&below_ceiling(object_to_interrogate)).reverse.each do |klass|
|
206
|
+
methods_here = format_methods((methods[klass] || []).select{ |m| m.name =~ grep_regex })
|
207
|
+
output << output_section("#{Pry::WrappedModule.new(klass).method_prefix}methods", methods_here)
|
208
|
+
end
|
209
|
+
output
|
210
|
+
end
|
211
|
+
|
212
|
+
def write_out_self_methods
|
213
|
+
return unless (!has_user_specified_any_options && interrogating_a_module?)
|
214
|
+
|
215
|
+
methods = all_methods(object_to_interrogate, true).select{ |m| m.owner == object_to_interrogate && m.name =~ grep_regex }
|
216
|
+
output_section("#{Pry::WrappedModule.new(object_to_interrogate).method_prefix}methods", format_methods(methods))
|
217
|
+
end
|
218
|
+
|
219
|
+
def write_out_ivars
|
220
|
+
return unless opts.present?(:ivars) || !has_user_specified_any_options
|
221
|
+
|
222
|
+
klass = (interrogating_a_module? ? object_to_interrogate : object_to_interrogate.class)
|
223
|
+
ivars = Pry::Method.safe_send(object_to_interrogate, :instance_variables)
|
224
|
+
kvars = Pry::Method.safe_send(klass, :class_variables)
|
225
|
+
output_section("instance variables", format_variables(:instance_var, ivars)) +
|
226
|
+
output_section("class variables", format_variables(:class_var, kvars))
|
227
|
+
end
|
228
|
+
|
229
|
+
def write_out_local_names
|
230
|
+
return unless !has_user_specified_any_options && args.empty?
|
231
|
+
|
232
|
+
output_section("locals", format_local_names(grep[target.eval("local_variables")]))
|
233
|
+
end
|
234
|
+
|
235
|
+
def write_out_locals
|
236
|
+
return unless opts.present?(:locals)
|
237
|
+
|
238
|
+
loc_names = target.eval('local_variables').reject do |e|
|
239
|
+
_pry_.sticky_locals.keys.include? e.to_sym
|
240
|
+
end
|
241
|
+
name_value_pairs = loc_names.map do |name|
|
242
|
+
[name, (target.eval name.to_s)]
|
243
|
+
end
|
244
|
+
format_locals(name_value_pairs).join("")
|
245
|
+
end
|
246
|
+
|
247
|
+
# Format and colourise a list of methods.
|
248
|
+
def format_methods(methods)
|
249
|
+
methods.sort_by(&:name).map do |method|
|
250
|
+
if method.name == 'method_missing'
|
251
|
+
color(:method_missing, 'method_missing')
|
252
|
+
elsif method.visibility == :private
|
253
|
+
color(:private_method, method.name)
|
254
|
+
elsif method.visibility == :protected
|
255
|
+
color(:protected_method, method.name)
|
256
|
+
else
|
257
|
+
color(:public_method, method.name)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def format_variables(type, vars)
|
263
|
+
vars.sort_by(&:downcase).map{ |var| color(type, var) }
|
264
|
+
end
|
265
|
+
|
266
|
+
def format_constants(mod, constants)
|
267
|
+
constants.sort_by(&:downcase).map do |name|
|
268
|
+
if const = (!mod.autoload?(name) && (mod.const_get(name) || true) rescue nil)
|
269
|
+
if (const < Exception rescue false)
|
270
|
+
color(:exception_constant, name)
|
271
|
+
elsif (Module === mod.const_get(name) rescue false)
|
272
|
+
color(:class_constant, name)
|
273
|
+
else
|
274
|
+
color(:constant, name)
|
275
|
+
end
|
276
|
+
else
|
277
|
+
color(:unloaded_constant, name)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def format_globals(globals)
|
283
|
+
globals.sort_by(&:downcase).map do |name|
|
284
|
+
if PSEUDO_GLOBALS.include?(name)
|
285
|
+
color(:pseudo_global, name)
|
286
|
+
elsif BUILTIN_GLOBALS.include?(name)
|
287
|
+
color(:builtin_global, name)
|
288
|
+
else
|
289
|
+
color(:global_var, name)
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def format_local_names(locals)
|
295
|
+
locals.sort_by(&:downcase).map do |name|
|
296
|
+
if _pry_.sticky_locals.include?(name.to_sym)
|
297
|
+
color(:pry_var, name)
|
298
|
+
else
|
299
|
+
color(:local_var, name)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def format_locals(name_value_pairs)
|
305
|
+
name_value_pairs.sort_by do |name, value|
|
306
|
+
value.to_s.size
|
307
|
+
end.reverse.map do |name, value|
|
308
|
+
colorized_assignment_style(name, format_value(value))
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
def colorized_assignment_style(lhs, rhs, desired_width = 7)
|
313
|
+
colorized_lhs = color(:local_var, lhs)
|
314
|
+
color_escape_padding = colorized_lhs.size - lhs.size
|
315
|
+
pad = desired_width + color_escape_padding
|
316
|
+
"%-#{pad}s = %s" % [color(:local_var, colorized_lhs), rhs]
|
317
|
+
end
|
318
|
+
|
319
|
+
def format_value(value)
|
320
|
+
accumulator = StringIO.new
|
321
|
+
Pry.output_with_default_format(accumulator, value, :hashrocket => false)
|
322
|
+
accumulator.string
|
323
|
+
end
|
324
|
+
|
325
|
+
# Add a new section to the output. Outputs nothing if the section would be empty.
|
326
|
+
def output_section(heading, body)
|
327
|
+
return "" if body.compact.empty?
|
328
|
+
table = Pry::Helpers.tablify_to_screen_width(body)
|
329
|
+
"#{text.bold(color(:heading, heading))}: \n#{table}\n"
|
330
|
+
end
|
331
|
+
|
332
|
+
# Color output based on config.ls.*_color
|
333
|
+
def color(type, str)
|
334
|
+
text.send(Pry.config.ls.send(:"#{type}_color"), str)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
Pry::Commands.add_command(Pry::Command::Ls)
|
339
|
+
end
|