mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
Inject _pry_ into Pry::Editor
This commit is contained in:
parent
2202ab775c
commit
d220af1061
4 changed files with 142 additions and 149 deletions
|
@ -60,7 +60,7 @@ class Pry
|
|||
end
|
||||
|
||||
def repl_edit
|
||||
content = Pry::Editor.edit_tempfile_with_content(initial_temp_file_content,
|
||||
content = Pry::Editor.new(_pry_).edit_tempfile_with_content(initial_temp_file_content,
|
||||
initial_temp_file_content.lines.count)
|
||||
silence_warnings do
|
||||
eval_string.replace content
|
||||
|
@ -80,7 +80,7 @@ class Pry
|
|||
ExceptionPatcher.new(_pry_, state, file_and_line_for_current_exception).perform_patch
|
||||
else
|
||||
if code_object.is_a?(Pry::Method)
|
||||
code_object.redefine Pry::Editor.edit_tempfile_with_content(code_object.source)
|
||||
code_object.redefine Pry::Editor.new(_pry_).edit_tempfile_with_content(code_object.source)
|
||||
else
|
||||
raise NotImplementedError, "Cannot yet patch #{code_object} objects!"
|
||||
end
|
||||
|
@ -116,7 +116,7 @@ class Pry
|
|||
|
||||
ensure_file_name_is_valid(file_name)
|
||||
|
||||
Pry::Editor.invoke_editor(file_name, line, reload?(file_name))
|
||||
Pry::Editor.new(_pry_).invoke_editor(file_name, line, reload?(file_name))
|
||||
set_file_and_dir_locals(file_name)
|
||||
|
||||
if reload?(file_name)
|
||||
|
|
|
@ -16,7 +16,7 @@ class Pry
|
|||
file_name, _ = file_and_line
|
||||
lines = state.dynamical_ex_file || File.read(file_name)
|
||||
|
||||
source = Pry::Editor.edit_tempfile_with_content(lines)
|
||||
source = Pry::Editor.new(_pry_).edit_tempfile_with_content(lines)
|
||||
_pry_.evaluate_ruby source
|
||||
state.dynamical_ex_file = source.split("\n")
|
||||
end
|
||||
|
|
|
@ -1,129 +1,133 @@
|
|||
class Pry
|
||||
class Editor
|
||||
extend Pry::Helpers::BaseHelpers
|
||||
extend Pry::Helpers::CommandHelpers
|
||||
include Pry::Helpers::BaseHelpers
|
||||
include Pry::Helpers::CommandHelpers
|
||||
|
||||
class << self
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
# 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.
|
||||
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
|
||||
|
||||
# Start the editor running, using the calculated invocation string
|
||||
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 :/
|
||||
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
|
||||
|
||||
# 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.
|
||||
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/
|
||||
'-w' if blocking
|
||||
end
|
||||
end
|
||||
|
||||
# Return the syntax for a given editor for starting the editor
|
||||
# and moving to a particular line within that file
|
||||
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}"
|
||||
else
|
||||
if windows?
|
||||
"#{file_name}"
|
||||
else
|
||||
"+#{line_number} #{file_name}"
|
||||
end
|
||||
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
|
||||
#
|
||||
def editor_name
|
||||
File.basename(Pry.config.editor).split(" ").first
|
||||
end
|
||||
attr_reader :_pry_
|
||||
|
||||
def initialize(_pry_)
|
||||
@_pry_ = _pry_
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
# 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.
|
||||
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
|
||||
|
||||
# Start the editor running, using the calculated invocation string
|
||||
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 :/
|
||||
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
|
||||
|
||||
# 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.
|
||||
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/
|
||||
'-w' if blocking
|
||||
end
|
||||
end
|
||||
|
||||
# Return the syntax for a given editor for starting the editor
|
||||
# and moving to a particular line within that file
|
||||
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}"
|
||||
else
|
||||
if windows?
|
||||
"#{file_name}"
|
||||
else
|
||||
"+#{line_number} #{file_name}"
|
||||
end
|
||||
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
|
||||
#
|
||||
def editor_name
|
||||
File.basename(_pry_.config.editor).split(" ").first
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@ require 'pathname'
|
|||
require_relative 'helper'
|
||||
|
||||
describe Pry::Editor do
|
||||
class << Pry::Editor
|
||||
class Pry::Editor
|
||||
public :build_editor_invocation_string
|
||||
end
|
||||
|
||||
|
@ -17,18 +17,14 @@ describe Pry::Editor do
|
|||
end
|
||||
|
||||
@tf_path = File.join(@tf_dir.to_s, 'hello world.rb')
|
||||
|
||||
@editor = Pry::Editor.new(Pry.new)
|
||||
end
|
||||
|
||||
unless Pry::Helpers::BaseHelpers.windows?
|
||||
describe "build_editor_invocation_string" do
|
||||
before do
|
||||
class << Pry::Editor
|
||||
public :build_editor_invocation_string
|
||||
end
|
||||
end
|
||||
|
||||
it 'should shell-escape files' do
|
||||
invocation_str = Pry::Editor.build_editor_invocation_string(@tf_path, 5, true)
|
||||
invocation_str = @editor.build_editor_invocation_string(@tf_path, 5, true)
|
||||
invocation_str.should =~ /#@tf_dir.+hello\\ world\.rb/
|
||||
end
|
||||
end
|
||||
|
@ -36,43 +32,36 @@ describe Pry::Editor do
|
|||
|
||||
describe "build_editor_invocation_string on windows" do
|
||||
before do
|
||||
class << Pry::Editor
|
||||
class Pry::Editor
|
||||
def windows?; true; end
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
class << Pry::Editor
|
||||
class Pry::Editor
|
||||
undef windows?
|
||||
end
|
||||
end
|
||||
|
||||
it "should replace / by \\" do
|
||||
invocation_str = Pry::Editor.build_editor_invocation_string(@tf_path, 5, true)
|
||||
invocation_str = @editor.build_editor_invocation_string(@tf_path, 5, true)
|
||||
invocation_str.should =~ %r(\\#{@tf_dir.basename}\\)
|
||||
end
|
||||
|
||||
it "should not shell-escape files" do
|
||||
invocation_str = Pry::Editor.build_editor_invocation_string(@tf_path, 5, true)
|
||||
invocation_str = @editor.build_editor_invocation_string(@tf_path, 5, true)
|
||||
invocation_str.should =~ /hello world\.rb/
|
||||
end
|
||||
end
|
||||
|
||||
describe 'invoke_editor with a proc' do
|
||||
before do
|
||||
@old_editor = Pry.config.editor
|
||||
Pry.config.editor = proc{ |file, line, blocking|
|
||||
it 'should not shell-escape files' do
|
||||
editor = Pry::Editor.new(Pry.new(editor: proc{ |file, line, blocking|
|
||||
@file = file
|
||||
nil
|
||||
}
|
||||
end
|
||||
}))
|
||||
|
||||
after do
|
||||
Pry.config.editor = @old_editor
|
||||
end
|
||||
|
||||
it 'should not shell-escape files' do
|
||||
Pry::Editor.invoke_editor(@tf_path, 10, true)
|
||||
editor.invoke_editor(@tf_path, 10, true)
|
||||
@file.should == @tf_path
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue