Class: Pry::Editor

Inherits:
Object show all
Includes:
Helpers::BaseHelpers, Helpers::CommandHelpers
Defined in:
lib/pry/editor.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helpers::CommandHelpers

#absolute_index_number, absolute_index_number, #absolute_index_range, absolute_index_range, #command_error, command_error, #get_method_or_raise, get_method_or_raise, #internal_binding?, internal_binding?, #one_index_number, one_index_number, #one_index_range, one_index_range, #one_index_range_or_number, one_index_range_or_number, #restrict_to_lines, restrict_to_lines, #set_file_and_dir_locals, set_file_and_dir_locals, #temp_file, temp_file, #unindent, unindent

Methods included from Helpers::OptionsHelpers

#method_object, method_object, #method_options, method_options

Methods included from Helpers::BaseHelpers

#colorize_code, colorize_code, #command_dependencies_met?, command_dependencies_met?, #find_command, find_command, #heading, heading, #highlight, highlight, #jruby?, jruby?, #jruby_19?, jruby_19?, #mri?, mri?, #mri_19?, mri_19?, #mri_20?, mri_20?, #mri_21?, mri_21?, #mri_2?, mri_2?, #not_a_real_file?, not_a_real_file?, #rbx?, rbx?, #safe_send, safe_send, #silence_warnings, silence_warnings, #stagger_output, stagger_output, #use_ansi_codes?, use_ansi_codes?, #windows?, windows?, #windows_ansi?, windows_ansi?

Constructor Details

#initialize(_pry_) ⇒ Editor

Returns a new instance of Editor



8
9
10
# File 'lib/pry/editor.rb', line 8

def initialize(_pry_)
  @_pry_ = _pry_
end

Instance Attribute Details

#_pry_Object (readonly)

Returns the value of attribute pry



6
7
8
# File 'lib/pry/editor.rb', line 6

def _pry_
  @_pry_
end

Instance Method Details

#blocking_flag_for_editor(blocking) ⇒ 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.



79
80
81
82
83
84
85
86
87
88
89
90
# 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

#build_editor_invocation_string(file, line, blocking) ⇒ Object (private)

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.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 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

#edit_tempfile_with_content(initial_content, line = 1) ⇒ Object



12
13
14
15
16
17
18
19
20
# 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

#editor_nameObject (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.

Examples:

Pry.config.editor="/home/conrad/bin/textmate -w"
editor_name
# => textmate


130
131
132
# File 'lib/pry/editor.rb', line 130

def editor_name
  File.basename(_pry_.config.editor).split(" ").first
end

#invoke_editor(file, line, blocking = true) ⇒ Object

Raises:



22
23
24
25
26
27
28
29
30
31
32
33
# 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

#open_editor(editor_invocation) ⇒ Object (private)

Start the editor running, using the calculated invocation string



57
58
59
60
61
62
# 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

#open_editor_on_jruby(editor_invocation) ⇒ Object (private)

We need JRuby specific code here cos just shelling out using system() appears to be pretty broken :/



66
67
68
69
70
71
72
73
74
# 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

#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



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# 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