Module: Pry::Helpers::CommandHelpers
Class Method Summary collapse
- .absolute_index_number(line_number, array_length) ⇒ Object
- .absolute_index_range(range_or_number, array_length) ⇒ Object
-
.blocking_flag_for_editor(block) ⇒ Object
Some editors that run outside the terminal allow you to control whether or not to block the process from which they were launched (in this case, Pry).
- .command_error(message, omit_help, klass = CommandError) ⇒ Object
-
.editor_name ⇒ Object
Get the name of the binary that Pry.config.editor points to.
-
.file_and_line_from_binding(target) ⇒ Array
Return the file and line for a Binding.
- .get_method_or_raise(name, target, opts = {}, omit_help = false) ⇒ Object
- .internal_binding?(target) ⇒ Boolean
- .invoke_editor(file, line, reloading) ⇒ Object
- .make_header(meth, content = meth.source) ⇒ Object
- .one_index_number(line_number) ⇒ Object
-
.one_index_range(range) ⇒ Object
convert a 1-index range to a 0-indexed one.
- .one_index_range_or_number(range_or_number) ⇒ Object
- .render_output(str, opts = {}) ⇒ Object
-
.restrict_to_lines(content, lines) ⇒ String
Restrict a string to the given range of lines (1-indexed).
-
.start_line_syntax_for_editor(file_name, line_number) ⇒ Object
Return the syntax for a given editor for starting the editor and moving to a particular line within that file.
-
.temp_file(ext = '.rb') ⇒ String
Open a temp file and yield it to the block, closing it after.
-
.unindent(text) ⇒ String
Remove any common leading whitespace from every line in
text.
Instance Method Summary collapse
- #absolute_index_number(line_number, array_length) ⇒ Object private
- #absolute_index_range(range_or_number, array_length) ⇒ Object private
-
#blocking_flag_for_editor(block) ⇒ Object
private
Some editors that run outside the terminal allow you to control whether or not to block the process from which they were launched (in this case, Pry).
- #command_error(message, omit_help, klass = CommandError) ⇒ Object private
-
#editor_name ⇒ Object
private
Get the name of the binary that Pry.config.editor points to.
-
#file_and_line_from_binding(target) ⇒ Array
private
Return the file and line for a Binding.
- #get_method_or_raise(name, target, opts = {}, omit_help = false) ⇒ Object private
- #internal_binding?(target) ⇒ Object private
- #invoke_editor(file, line, reloading) ⇒ Object private
- #make_header(meth, content = meth.source) ⇒ Object private
- #one_index_number(line_number) ⇒ Object private
-
#one_index_range(range) ⇒ Object
private
convert a 1-index range to a 0-indexed one.
- #one_index_range_or_number(range_or_number) ⇒ Object private
- #render_output(str, opts = {}) ⇒ Object private
-
#restrict_to_lines(content, lines) ⇒ String
private
Restrict a string to the given range of lines (1-indexed).
-
#start_line_syntax_for_editor(file_name, line_number) ⇒ Object
private
Return the syntax for a given editor for starting the editor and moving to a particular line within that file.
-
#temp_file(ext = '.rb') ⇒ String
private
Open a temp file and yield it to the block, closing it after.
-
#unindent(text) ⇒ String
private
Remove any common leading whitespace from every line in
text.
Methods included from OptionsHelpers
#method_object, method_object, method_options, #method_options
Class Method Details
.absolute_index_number(line_number, array_length) ⇒ Object
245 246 247 248 249 250 251 |
# File 'lib/pry/helpers/command_helpers.rb', line 245 def absolute_index_number(line_number, array_length) if line_number >= 0 line_number else [array_length + line_number, 0].max end end |
.absolute_index_range(range_or_number, array_length) ⇒ Object
253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/pry/helpers/command_helpers.rb', line 253 def absolute_index_range(range_or_number, array_length) case range_or_number when Range a = absolute_index_number(range_or_number.begin, array_length) b = absolute_index_number(range_or_number.end, array_length) else a = b = absolute_index_number(range_or_number, array_length) end Range.new(a, b) end |
.blocking_flag_for_editor(block) ⇒ Object
Some editors that run outside the terminal allow you to control whether or not to block the process from which they were launched (in this case, Pry). For those editors, return the flag that produces the desired behavior.
117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/pry/helpers/command_helpers.rb', line 117 def blocking_flag_for_editor(block) case editor_name when /^emacsclient/ '--no-wait' unless block when /^[gm]vim/ '--nofork' if block when /^jedit/ '-wait' if block when /^mate/, /^subl/ '-w' if block end end |
.command_error(message, omit_help, klass = CommandError) ⇒ Object
71 72 73 74 |
# File 'lib/pry/helpers/command_helpers.rb', line 71 def command_error(, omit_help, klass=CommandError) += " Type `#{command_name} --help` for help." unless omit_help raise klass, end |
.editor_name ⇒ Object
Get the name of the binary that Pry.config.editor points to.
This is useful for deciding which flags we pass to the editor as we can just use the program's name and ignore any absolute paths.
170 171 172 |
# File 'lib/pry/helpers/command_helpers.rb', line 170 def editor_name File.basename(Pry.config.editor).split(" ").first end |
.file_and_line_from_binding(target) ⇒ Array
Return the file and line for a Binding.
29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/pry/helpers/command_helpers.rb', line 29 def file_and_line_from_binding(target) file = target.eval('__FILE__') line_num = target.eval('__LINE__') if rbx? if !target.instance_variable_defined?(:@__actual_file__) target.instance_variable_set(:@__actual_file__, RbxPath.convert_path_to_full(target.variables.method.file.to_s)) end file = target.instance_variable_get(:@__actual_file__).to_s end [file, line_num] end |
.get_method_or_raise(name, target, opts = {}, omit_help = false) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/pry/helpers/command_helpers.rb', line 48 def get_method_or_raise(name, target, opts={}, omit_help=false) meth = Pry::Method.from_str(name, target, opts) if name && !meth command_error("The method '#{name}' could not be found.", omit_help) end (opts[:super] || 0).times do if meth.super meth = meth.super else command_error("'#{meth.name_with_owner}' has no super method.", omit_help) end end if !meth || (!name && internal_binding?(target)) command_error("No method name given, and context is not a method.", omit_help, NonMethodContextError) end set_file_and_dir_locals(meth.source_file) meth end |
.internal_binding?(target) ⇒ Boolean
42 43 44 45 46 |
# File 'lib/pry/helpers/command_helpers.rb', line 42 def internal_binding?(target) m = target.eval("__method__").to_s # class_eval is here because of http://jira.codehaus.org/browse/JRUBY-6753 ["__binding__", "__pry__", "class_eval"].include?(m) end |
.invoke_editor(file, line, reloading) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/pry/helpers/command_helpers.rb', line 88 def invoke_editor(file, line, reloading) raise CommandError, "Please set Pry.config.editor or export $VISUAL or $EDITOR" unless Pry.config.editor if Pry.config.editor.respond_to?(:call) args = [file, line, reloading][0...(Pry.config.editor.arity)] editor_invocation = Pry.config.editor.call(*args) else editor_invocation = "#{Pry.config.editor} #{blocking_flag_for_editor(reloading)} #{start_line_syntax_for_editor(file, line)}" end return nil unless editor_invocation if jruby? begin require 'spoon' pid = Spoon.spawnp(*editor_invocation.split) Process.waitpid(pid) rescue FFI::NotFoundError system(editor_invocation) end else # Note we dont want to use Pry.config.system here as that # may be invoked non-interactively (i.e via Open4), whereas we want to # ensure the editor is always interactive system(editor_invocation) or raise CommandError, "`#{editor_invocation}` gave exit status: #{$?.exitstatus}" end end |
.make_header(meth, content = meth.source) ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/pry/helpers/command_helpers.rb', line 76 def make_header(meth, content=meth.source) header = "\n#{Pry::Helpers::Text.bold('From:')} #{meth.source_file} " if meth.source_type == :c header << "(C Method):\n" else header << "@ line #{meth.source_line}:\n" end header << "#{Pry::Helpers::Text.bold("Number of lines:")} #{content.each_line.count.to_s}\n" end |
.one_index_number(line_number) ⇒ Object
223 224 225 226 227 228 229 |
# File 'lib/pry/helpers/command_helpers.rb', line 223 def one_index_number(line_number) if line_number > 0 line_number - 1 else line_number end end |
.one_index_range(range) ⇒ Object
convert a 1-index range to a 0-indexed one
232 233 234 |
# File 'lib/pry/helpers/command_helpers.rb', line 232 def one_index_range(range) Range.new(one_index_number(range.begin), one_index_number(range.end)) end |
.one_index_range_or_number(range_or_number) ⇒ Object
236 237 238 239 240 241 242 243 |
# File 'lib/pry/helpers/command_helpers.rb', line 236 def one_index_range_or_number(range_or_number) case range_or_number when Range one_index_range(range_or_number) else one_index_number(range_or_number) end end |
.render_output(str, opts = {}) ⇒ Object
18 19 20 21 22 23 24 |
# File 'lib/pry/helpers/command_helpers.rb', line 18 def render_output(str, opts={}) if opts[:flood] output.puts str else stagger_output str end end |
.restrict_to_lines(content, lines) ⇒ String
Restrict a string to the given range of lines (1-indexed)
218 219 220 221 |
# File 'lib/pry/helpers/command_helpers.rb', line 218 def restrict_to_lines(content, lines) line_range = one_index_range_or_number(lines) Array(content.lines.to_a[line_range]).join end |
.start_line_syntax_for_editor(file_name, line_number) ⇒ Object
Return the syntax for a given editor for starting the editor and moving to a particular line within that file
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/pry/helpers/command_helpers.rb', line 132 def start_line_syntax_for_editor(file_name, line_number) if windows? file_name = file_name.gsub(/\//, '\\') end # special case for 1st line return file_name if line_number <= 1 case editor_name when /^[gm]?vi/, /^emacs/, /^nano/, /^pico/, /^gedit/, /^kate/ "+#{line_number} #{file_name}" when /^mate/, /^geany/ "-l #{line_number} #{file_name}" when /^subl/ "#{file_name}:#{line_number}" when /^uedit32/ "#{file_name}/#{line_number}" when /^jedit/ "#{file_name} +line:#{line_number}" else if windows? "#{file_name}" else "+#{line_number} #{file_name}" end end end |
.temp_file(ext = '.rb') ⇒ String
Open a temp file and yield it to the block, closing it after
11 12 13 14 15 16 |
# File 'lib/pry/helpers/command_helpers.rb', line 11 def temp_file(ext='.rb') file = Tempfile.new(['pry', ext]) yield file ensure file.close(true) if file end |
.unindent(text) ⇒ String
Remove any common leading whitespace from every line in text.
This can be used to make a HEREDOC line up with the left margin, without sacrificing the indentation level of the source code.
e.g. opt.banner unindent <<-USAGE Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "Ut enim ad minim veniam." USAGE
Heavily based on textwrap.dedent from Python, which is: Copyright (C) 1999-2001 Gregory P. Ward. Copyright (C) 2002, 2003 Python Software Foundation. Written by Greg Ward [email protected]
Licensed under http://docs.python.org/license.html From http://hg.python.org/cpython/file/6b9f0a6efaeb/Lib/textwrap.py
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/pry/helpers/command_helpers.rb', line 196 def unindent(text) # Empty blank lines text = text.sub(/^[ \t]+$/, '') # Find the longest common whitespace to all indented lines margin = text.scan(/^[ \t]*(?=[^ \t\n])/).inject do |current_margin, next_indent| if next_indent.start_with?(current_margin) current_margin elsif current_margin.start_with?(next_indent) next_indent else "" end end text.gsub(/^#{margin}/, '') end |
Instance Method Details
#absolute_index_number(line_number, array_length) ⇒ Object (private)
245 246 247 248 249 250 251 |
# File 'lib/pry/helpers/command_helpers.rb', line 245 def absolute_index_number(line_number, array_length) if line_number >= 0 line_number else [array_length + line_number, 0].max end end |
#absolute_index_range(range_or_number, array_length) ⇒ Object (private)
253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/pry/helpers/command_helpers.rb', line 253 def absolute_index_range(range_or_number, array_length) case range_or_number when Range a = absolute_index_number(range_or_number.begin, array_length) b = absolute_index_number(range_or_number.end, array_length) else a = b = absolute_index_number(range_or_number, array_length) end Range.new(a, b) end |
#blocking_flag_for_editor(block) ⇒ Object (private)
Some editors that run outside the terminal allow you to control whether or not to block the process from which they were launched (in this case, Pry). For those editors, return the flag that produces the desired behavior.
117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/pry/helpers/command_helpers.rb', line 117 def blocking_flag_for_editor(block) case editor_name when /^emacsclient/ '--no-wait' unless block when /^[gm]vim/ '--nofork' if block when /^jedit/ '-wait' if block when /^mate/, /^subl/ '-w' if block end end |
#command_error(message, omit_help, klass = CommandError) ⇒ Object (private)
71 72 73 74 |
# File 'lib/pry/helpers/command_helpers.rb', line 71 def command_error(, omit_help, klass=CommandError) += " Type `#{command_name} --help` for help." unless omit_help raise klass, end |
#editor_name ⇒ Object (private)
Get the name of the binary that Pry.config.editor points to.
This is useful for deciding which flags we pass to the editor as we can just use the program's name and ignore any absolute paths.
170 171 172 |
# File 'lib/pry/helpers/command_helpers.rb', line 170 def editor_name File.basename(Pry.config.editor).split(" ").first end |
#file_and_line_from_binding(target) ⇒ Array (private)
Return the file and line for a Binding.
29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/pry/helpers/command_helpers.rb', line 29 def file_and_line_from_binding(target) file = target.eval('__FILE__') line_num = target.eval('__LINE__') if rbx? if !target.instance_variable_defined?(:@__actual_file__) target.instance_variable_set(:@__actual_file__, RbxPath.convert_path_to_full(target.variables.method.file.to_s)) end file = target.instance_variable_get(:@__actual_file__).to_s end [file, line_num] end |
#get_method_or_raise(name, target, opts = {}, omit_help = false) ⇒ Object (private)
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/pry/helpers/command_helpers.rb', line 48 def get_method_or_raise(name, target, opts={}, omit_help=false) meth = Pry::Method.from_str(name, target, opts) if name && !meth command_error("The method '#{name}' could not be found.", omit_help) end (opts[:super] || 0).times do if meth.super meth = meth.super else command_error("'#{meth.name_with_owner}' has no super method.", omit_help) end end if !meth || (!name && internal_binding?(target)) command_error("No method name given, and context is not a method.", omit_help, NonMethodContextError) end set_file_and_dir_locals(meth.source_file) meth end |
#internal_binding?(target) ⇒ Object (private)
42 43 44 45 46 |
# File 'lib/pry/helpers/command_helpers.rb', line 42 def internal_binding?(target) m = target.eval("__method__").to_s # class_eval is here because of http://jira.codehaus.org/browse/JRUBY-6753 ["__binding__", "__pry__", "class_eval"].include?(m) end |
#invoke_editor(file, line, reloading) ⇒ Object (private)
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/pry/helpers/command_helpers.rb', line 88 def invoke_editor(file, line, reloading) raise CommandError, "Please set Pry.config.editor or export $VISUAL or $EDITOR" unless Pry.config.editor if Pry.config.editor.respond_to?(:call) args = [file, line, reloading][0...(Pry.config.editor.arity)] editor_invocation = Pry.config.editor.call(*args) else editor_invocation = "#{Pry.config.editor} #{blocking_flag_for_editor(reloading)} #{start_line_syntax_for_editor(file, line)}" end return nil unless editor_invocation if jruby? begin require 'spoon' pid = Spoon.spawnp(*editor_invocation.split) Process.waitpid(pid) rescue FFI::NotFoundError system(editor_invocation) end else # Note we dont want to use Pry.config.system here as that # may be invoked non-interactively (i.e via Open4), whereas we want to # ensure the editor is always interactive system(editor_invocation) or raise CommandError, "`#{editor_invocation}` gave exit status: #{$?.exitstatus}" end end |
#make_header(meth, content = meth.source) ⇒ Object (private)
76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/pry/helpers/command_helpers.rb', line 76 def make_header(meth, content=meth.source) header = "\n#{Pry::Helpers::Text.bold('From:')} #{meth.source_file} " if meth.source_type == :c header << "(C Method):\n" else header << "@ line #{meth.source_line}:\n" end header << "#{Pry::Helpers::Text.bold("Number of lines:")} #{content.each_line.count.to_s}\n" end |
#one_index_number(line_number) ⇒ Object (private)
223 224 225 226 227 228 229 |
# File 'lib/pry/helpers/command_helpers.rb', line 223 def one_index_number(line_number) if line_number > 0 line_number - 1 else line_number end end |
#one_index_range(range) ⇒ Object (private)
convert a 1-index range to a 0-indexed one
232 233 234 |
# File 'lib/pry/helpers/command_helpers.rb', line 232 def one_index_range(range) Range.new(one_index_number(range.begin), one_index_number(range.end)) end |
#one_index_range_or_number(range_or_number) ⇒ Object (private)
236 237 238 239 240 241 242 243 |
# File 'lib/pry/helpers/command_helpers.rb', line 236 def one_index_range_or_number(range_or_number) case range_or_number when Range one_index_range(range_or_number) else one_index_number(range_or_number) end end |
#render_output(str, opts = {}) ⇒ Object (private)
18 19 20 21 22 23 24 |
# File 'lib/pry/helpers/command_helpers.rb', line 18 def render_output(str, opts={}) if opts[:flood] output.puts str else stagger_output str end end |
#restrict_to_lines(content, lines) ⇒ String (private)
Restrict a string to the given range of lines (1-indexed)
218 219 220 221 |
# File 'lib/pry/helpers/command_helpers.rb', line 218 def restrict_to_lines(content, lines) line_range = one_index_range_or_number(lines) Array(content.lines.to_a[line_range]).join end |
#start_line_syntax_for_editor(file_name, line_number) ⇒ Object (private)
Return the syntax for a given editor for starting the editor and moving to a particular line within that file
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/pry/helpers/command_helpers.rb', line 132 def start_line_syntax_for_editor(file_name, line_number) if windows? file_name = file_name.gsub(/\//, '\\') end # special case for 1st line return file_name if line_number <= 1 case editor_name when /^[gm]?vi/, /^emacs/, /^nano/, /^pico/, /^gedit/, /^kate/ "+#{line_number} #{file_name}" when /^mate/, /^geany/ "-l #{line_number} #{file_name}" when /^subl/ "#{file_name}:#{line_number}" when /^uedit32/ "#{file_name}/#{line_number}" when /^jedit/ "#{file_name} +line:#{line_number}" else if windows? "#{file_name}" else "+#{line_number} #{file_name}" end end end |
#temp_file(ext = '.rb') ⇒ String (private)
Open a temp file and yield it to the block, closing it after
11 12 13 14 15 16 |
# File 'lib/pry/helpers/command_helpers.rb', line 11 def temp_file(ext='.rb') file = Tempfile.new(['pry', ext]) yield file ensure file.close(true) if file end |
#unindent(text) ⇒ String (private)
Remove any common leading whitespace from every line in text.
This can be used to make a HEREDOC line up with the left margin, without sacrificing the indentation level of the source code.
e.g. opt.banner unindent <<-USAGE Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "Ut enim ad minim veniam." USAGE
Heavily based on textwrap.dedent from Python, which is: Copyright (C) 1999-2001 Gregory P. Ward. Copyright (C) 2002, 2003 Python Software Foundation. Written by Greg Ward [email protected]
Licensed under http://docs.python.org/license.html From http://hg.python.org/cpython/file/6b9f0a6efaeb/Lib/textwrap.py
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/pry/helpers/command_helpers.rb', line 196 def unindent(text) # Empty blank lines text = text.sub(/^[ \t]+$/, '') # Find the longest common whitespace to all indented lines margin = text.scan(/^[ \t]*(?=[^ \t\n])/).inject do |current_margin, next_indent| if next_indent.start_with?(current_margin) current_margin elsif current_margin.start_with?(next_indent) next_indent else "" end end text.gsub(/^#{margin}/, '') end |