class Pry::Editor
Attributes
Public Class Methods
# File lib/pry/editor.rb, line 8 def initialize(_pry_) @_pry_ = _pry_ end
Public Instance Methods
# File lib/pry/editor.rb, line 12 def edit_tempfile_with_content(initial_content, line=1) temp_file do |f| f.puts(initial_content) f.flush f.close(false) invoke_editor(f.path, line, true) File.read(f.path) end end
# File lib/pry/editor.rb, line 22 def invoke_editor(file, line, blocking=true) raise CommandError, "Please set Pry.config.editor or export $VISUAL or $EDITOR" unless _pry_.config.editor editor_invocation = build_editor_invocation_string(file, line, blocking) return nil unless editor_invocation if jruby? open_editor_on_jruby(editor_invocation) else open_editor(editor_invocation) end end
Private Instance Methods
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.
# File lib/pry/editor.rb, line 79 def blocking_flag_for_editor(blocking) case editor_name when /^emacsclient/ '--no-wait' unless blocking when /^[gm]vim/ '--nofork' if blocking when /^jedit/ '-wait' if blocking when /^mate/, /^subl/, /^redcar/ '-w' if blocking end end
Generate the string that's used to start the editor. This includes all the flags we want as well as the file and line number we want to open at.
# File lib/pry/editor.rb, line 40 def build_editor_invocation_string(file, line, blocking) if _pry_.config.editor.respond_to?(:call) args = [file, line, blocking][0...(_pry_.config.editor.arity)] _pry_.config.editor.call(*args) else sanitized_file = if windows? file.gsub(/\//, '\') else Shellwords.escape(file) end "#{_pry_.config.editor} #{blocking_flag_for_editor(blocking)} #{start_line_syntax_for_editor(sanitized_file, line)}" end end
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.
@example
Pry.config.editor="/home/conrad/bin/textmate -w" editor_name # => textmate
# File lib/pry/editor.rb, line 130 def editor_name File.basename(_pry_.config.editor).split(" ").first end
Start the editor running, using the calculated invocation string
# File lib/pry/editor.rb, line 57 def open_editor(editor_invocation) # 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(*Shellwords.split(editor_invocation)) or raise CommandError, "`#{editor_invocation}` gave exit status: #{$?.exitstatus}" end
We need JRuby specific code here cos just shelling out using system() appears to be pretty broken :/
# File lib/pry/editor.rb, line 66 def open_editor_on_jruby(editor_invocation) begin require 'spoon' pid = Spoon.spawnp(*Shellwords.split(editor_invocation)) Process.waitpid(pid) rescue FFI::NotFoundError system(editor_invocation) end end
Return the syntax for a given editor for starting the editor and moving to a particular line within that file
# File lib/pry/editor.rb, line 94 def start_line_syntax_for_editor(file_name, line_number) # 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}" when /^redcar/ "-l#{line_number} #{file_name}" else if windows? "#{file_name}" else "+#{line_number} #{file_name}" end end end