mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
Factor out gem-* commands to a separate plugin
This code doesn't really belong to Pry Core. It is all about RubyGems, but Pry is all about introspection and debugging. We used to have some gem-* commands in the past and it wasn't a big issue but now, since we have 7 commands, they really deserve their own place. These commands were moved to: https://github.com/pry/pry-gem
This commit is contained in:
parent
595ee86ac6
commit
d4c653f156
12 changed files with 3 additions and 405 deletions
|
@ -266,4 +266,3 @@ Style/PerlBackrefs:
|
||||||
- 'lib/pry/input_completer.rb'
|
- 'lib/pry/input_completer.rb'
|
||||||
- 'lib/pry/last_exception.rb'
|
- 'lib/pry/last_exception.rb'
|
||||||
- 'lib/pry/method.rb'
|
- 'lib/pry/method.rb'
|
||||||
- 'lib/pry/rubygem.rb'
|
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
* Deleted `install-command` ([#1979](https://github.com/pry/pry/pull/1979))
|
* Deleted `install-command` ([#1979](https://github.com/pry/pry/pull/1979))
|
||||||
* Deleted `Pry::Helpers::BaseHelpers#command_dependencies_met?`
|
* Deleted `Pry::Helpers::BaseHelpers#command_dependencies_met?`
|
||||||
([#1979](https://github.com/pry/pry/pull/1979))
|
([#1979](https://github.com/pry/pry/pull/1979))
|
||||||
|
* Deleted commands: `gem_cd`, `gem_install`, `gem_list`, `gem_open`,
|
||||||
|
`gem_readme`, `gem_search`, `gem_stats`
|
||||||
|
([#1981](https://github.com/pry/pry/pull/1981))
|
||||||
|
|
||||||
### [v0.12.2][v0.12.2] (November 12, 2018)
|
### [v0.12.2][v0.12.2] (November 12, 2018)
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@ require 'pry/color_printer'
|
||||||
require 'pry/pager'
|
require 'pry/pager'
|
||||||
require 'pry/terminal'
|
require 'pry/terminal'
|
||||||
require 'pry/editor'
|
require 'pry/editor'
|
||||||
require 'pry/rubygem'
|
|
||||||
require 'pry/indent'
|
require 'pry/indent'
|
||||||
require 'pry/object_path'
|
require 'pry/object_path'
|
||||||
require 'pry/output'
|
require 'pry/output'
|
||||||
|
@ -102,13 +101,6 @@ require 'pry/commands/exit_all'
|
||||||
require 'pry/commands/exit_program'
|
require 'pry/commands/exit_program'
|
||||||
require 'pry/commands/find_method'
|
require 'pry/commands/find_method'
|
||||||
require 'pry/commands/fix_indent'
|
require 'pry/commands/fix_indent'
|
||||||
require 'pry/commands/gem_cd'
|
|
||||||
require 'pry/commands/gem_install'
|
|
||||||
require 'pry/commands/gem_list'
|
|
||||||
require 'pry/commands/gem_open'
|
|
||||||
require 'pry/commands/gem_readme'
|
|
||||||
require 'pry/commands/gem_search'
|
|
||||||
require 'pry/commands/gem_stats'
|
|
||||||
require 'pry/commands/help'
|
require 'pry/commands/help'
|
||||||
require 'pry/commands/hist'
|
require 'pry/commands/hist'
|
||||||
require 'pry/commands/import_set'
|
require 'pry/commands/import_set'
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
class Pry
|
|
||||||
class Command
|
|
||||||
class GemCd < Pry::ClassCommand
|
|
||||||
match 'gem-cd'
|
|
||||||
group 'Gems'
|
|
||||||
description "Change working directory to specified gem's directory."
|
|
||||||
command_options argument_required: true
|
|
||||||
|
|
||||||
banner <<-'BANNER'
|
|
||||||
Usage: gem-cd GEM_NAME
|
|
||||||
|
|
||||||
Change the current working directory to that in which the given gem is
|
|
||||||
installed.
|
|
||||||
BANNER
|
|
||||||
|
|
||||||
def process(gem)
|
|
||||||
Dir.chdir(Rubygem.spec(gem).full_gem_path)
|
|
||||||
output.puts(Dir.pwd)
|
|
||||||
end
|
|
||||||
|
|
||||||
def complete(str)
|
|
||||||
Rubygem.complete(str)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Pry::Commands.add_command(Pry::Command::GemCd)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,34 +0,0 @@
|
||||||
class Pry
|
|
||||||
class Command
|
|
||||||
class GemInstall < Pry::ClassCommand
|
|
||||||
match 'gem-install'
|
|
||||||
group 'Gems'
|
|
||||||
description 'Install a gem and refresh the gem cache.'
|
|
||||||
command_options argument_required: true
|
|
||||||
|
|
||||||
banner <<-'BANNER'
|
|
||||||
Usage: gem-install GEM_NAME
|
|
||||||
|
|
||||||
Installs the given gem, refreshes the gem cache, and requires the gem for you
|
|
||||||
based on a best guess from the gem name.
|
|
||||||
|
|
||||||
gem-install pry-stack_explorer
|
|
||||||
BANNER
|
|
||||||
|
|
||||||
def setup
|
|
||||||
require 'rubygems/dependency_installer' unless defined? Gem::DependencyInstaller
|
|
||||||
end
|
|
||||||
|
|
||||||
def process(gem)
|
|
||||||
Rubygem.install(gem)
|
|
||||||
output.puts "Gem `#{green(gem)}` installed."
|
|
||||||
require gem
|
|
||||||
rescue LoadError
|
|
||||||
require_path = gem.split('-').join('/')
|
|
||||||
require require_path
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Pry::Commands.add_command(Pry::Command::GemInstall)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,35 +0,0 @@
|
||||||
class Pry
|
|
||||||
class Command
|
|
||||||
class GemList < Pry::ClassCommand
|
|
||||||
match 'gem-list'
|
|
||||||
group 'Gems'
|
|
||||||
description 'List and search installed gems.'
|
|
||||||
|
|
||||||
banner <<-'BANNER'
|
|
||||||
Usage: gem-list [REGEX]
|
|
||||||
|
|
||||||
List all installed gems, when a regex is provided, limit the output to those
|
|
||||||
that match the regex.
|
|
||||||
BANNER
|
|
||||||
|
|
||||||
def process(pattern = nil)
|
|
||||||
pattern = Regexp.compile(pattern || '')
|
|
||||||
gems = Rubygem.list(pattern).group_by(&:name)
|
|
||||||
|
|
||||||
gems.each do |gem, specs|
|
|
||||||
specs.sort! do |a, b|
|
|
||||||
Gem::Version.new(b.version) <=> Gem::Version.new(a.version)
|
|
||||||
end
|
|
||||||
|
|
||||||
versions = specs.each_with_index.map do |spec, index|
|
|
||||||
index == 0 ? bright_green(spec.version.to_s) : green(spec.version.to_s)
|
|
||||||
end
|
|
||||||
|
|
||||||
output.puts "#{default gem} (#{versions.join ', '})"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Pry::Commands.add_command(Pry::Command::GemList)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,31 +0,0 @@
|
||||||
class Pry
|
|
||||||
class Command
|
|
||||||
class GemOpen < Pry::ClassCommand
|
|
||||||
match 'gem-open'
|
|
||||||
group 'Gems'
|
|
||||||
description 'Opens the working directory of the gem in your editor.'
|
|
||||||
command_options argument_required: true
|
|
||||||
|
|
||||||
banner <<-'BANNER'
|
|
||||||
Usage: gem-open GEM_NAME
|
|
||||||
|
|
||||||
Change the current working directory to that in which the given gem is
|
|
||||||
installed, and then opens your text editor.
|
|
||||||
|
|
||||||
gem-open pry-exception_explorer
|
|
||||||
BANNER
|
|
||||||
|
|
||||||
def process(gem)
|
|
||||||
Dir.chdir(Rubygem.spec(gem).full_gem_path) do
|
|
||||||
Pry::Editor.new(_pry_).invoke_editor(".", 0, false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def complete(str)
|
|
||||||
Rubygem.complete(str)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Pry::Commands.add_command(Pry::Command::GemOpen)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,30 +0,0 @@
|
||||||
class Pry
|
|
||||||
class Command
|
|
||||||
class GemReadme < Pry::ClassCommand
|
|
||||||
match 'gem-readme'
|
|
||||||
description 'Show the readme bundled with a rubygem'
|
|
||||||
group 'Gems'
|
|
||||||
command_options argument_required: true
|
|
||||||
banner <<-BANNER
|
|
||||||
gem-readme gem
|
|
||||||
Show the readme bundled with a rubygem
|
|
||||||
BANNER
|
|
||||||
|
|
||||||
def process(name)
|
|
||||||
spec = Gem::Specification.find_by_name(name)
|
|
||||||
glob = File.join(spec.full_gem_path, 'README*')
|
|
||||||
readme = Dir[glob][0]
|
|
||||||
if File.exist?(readme.to_s)
|
|
||||||
_pry_.pager.page File.read(readme)
|
|
||||||
else
|
|
||||||
raise Pry::CommandError, "Gem '#{name}' doesn't appear to have a README"
|
|
||||||
end
|
|
||||||
rescue Gem::LoadError
|
|
||||||
raise Pry::CommandError,
|
|
||||||
"Gem '#{name}' wasn't found. Are you sure it is installed?"
|
|
||||||
end
|
|
||||||
|
|
||||||
Pry::Commands.add_command(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,45 +0,0 @@
|
||||||
class Pry
|
|
||||||
class Command
|
|
||||||
class GemSearch < Pry::ClassCommand
|
|
||||||
match 'gem-search'
|
|
||||||
description 'Search for a gem with the rubygems.org JSON API'
|
|
||||||
group 'Gems'
|
|
||||||
command_options argument_required: true
|
|
||||||
banner <<-BANNER
|
|
||||||
gem-search [options] gem
|
|
||||||
Search for a gem with the rubygems.org HTTP API
|
|
||||||
BANNER
|
|
||||||
|
|
||||||
API_ENDPOINT = 'https://rubygems.org/api/v1/search.json'.freeze
|
|
||||||
|
|
||||||
def setup
|
|
||||||
require 'json' unless defined?(JSON)
|
|
||||||
require 'net/http' unless defined?(Net::HTTP)
|
|
||||||
end
|
|
||||||
|
|
||||||
def options(opt)
|
|
||||||
opt.on :l, :limit, 'Limit the number of results (max: 30)',
|
|
||||||
default: 10,
|
|
||||||
as: Integer,
|
|
||||||
argument: true
|
|
||||||
end
|
|
||||||
|
|
||||||
def process(str)
|
|
||||||
uri = URI.parse(API_ENDPOINT)
|
|
||||||
uri.query = URI.encode_www_form(query: str)
|
|
||||||
gems = JSON.parse(Net::HTTP.get(uri))
|
|
||||||
_pry_.pager.page list_as_string(gems, opts[:limit])
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def list_as_string(gems, limit = 10)
|
|
||||||
gems[0..limit - 1].map do |gem|
|
|
||||||
name, version, info = gem.values_at 'name', 'version', 'info'
|
|
||||||
"#{bold(name)} #{bold('v' + version)} \n#{info}\n\n"
|
|
||||||
end.join
|
|
||||||
end
|
|
||||||
Pry::Commands.add_command(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,91 +0,0 @@
|
||||||
class Pry
|
|
||||||
class Command
|
|
||||||
class GemStat < Pry::ClassCommand
|
|
||||||
require 'json'
|
|
||||||
require 'net/http'
|
|
||||||
STAT_HOST = "rubygems.org".freeze
|
|
||||||
STAT_PORT = 443
|
|
||||||
STAT_PATH = "/api/v1/gems/%s.json".freeze
|
|
||||||
FAIL_WHALE = <<-FAILWHALE.freeze
|
|
||||||
W W W
|
|
||||||
W W W W
|
|
||||||
'. W
|
|
||||||
.-""-._ \ \.--|
|
|
||||||
/ "-..__) .-'
|
|
||||||
| _ /
|
|
||||||
\'-.__, .__.,'
|
|
||||||
`'----'._\--'
|
|
||||||
VVVVVVVVVVVVVVVVVVVVV
|
|
||||||
FAILWHALE
|
|
||||||
|
|
||||||
match 'gem-stat'
|
|
||||||
description 'Show the statistics of a gem (requires internet connection)'
|
|
||||||
group 'Gems'
|
|
||||||
command_options argument_required: true
|
|
||||||
banner <<-BANNER
|
|
||||||
gem-stats name
|
|
||||||
|
|
||||||
Show the statistics of a gem.
|
|
||||||
Requires an internet connection.
|
|
||||||
BANNER
|
|
||||||
|
|
||||||
def process(name)
|
|
||||||
client = Net::HTTP.start STAT_HOST, STAT_PORT, use_ssl: true
|
|
||||||
res = client.get STAT_PATH % URI.encode_www_form_component(name)
|
|
||||||
case res
|
|
||||||
when Net::HTTPOK
|
|
||||||
_pry_.pager.page format_gem(JSON.parse(res.body))
|
|
||||||
when Net::HTTPServiceUnavailable
|
|
||||||
_pry_.pager.page <<-FAILURE
|
|
||||||
#{bright_blue(FAIL_WHALE)}
|
|
||||||
#{bright_red('Ruby On Rails')}
|
|
||||||
#{bright_red('Net::HTTPServiceUnavailable')}
|
|
||||||
FAILURE
|
|
||||||
else
|
|
||||||
raise Pry::CommandError, "Bad response (#{res.class})"
|
|
||||||
end
|
|
||||||
ensure
|
|
||||||
client.finish if client
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def format_gem(h)
|
|
||||||
h = Pry::Config.from_hash(h)
|
|
||||||
format_str = unindent <<-FORMAT
|
|
||||||
%{name} %{version}
|
|
||||||
--
|
|
||||||
Total Downloads : %{downloads}
|
|
||||||
Version Downloads : %{version_downloads}
|
|
||||||
|
|
||||||
#{red('Dependencies')} (runtime)
|
|
||||||
--
|
|
||||||
%{rdependencies}
|
|
||||||
|
|
||||||
#{red('Dependencies')} (development)
|
|
||||||
%{ddependencies}
|
|
||||||
FORMAT
|
|
||||||
format(
|
|
||||||
format_str,
|
|
||||||
name: green(h.name),
|
|
||||||
version: bold("v#{h.version}"),
|
|
||||||
downloads: h.downloads,
|
|
||||||
version_downloads: h.version_downloads,
|
|
||||||
rdependencies: format_dependencies(h.dependencies.runtime),
|
|
||||||
ddependencies: format_dependencies(h.dependencies.development)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def format_dependencies(rdeps)
|
|
||||||
return bold('None') if rdeps.empty?
|
|
||||||
|
|
||||||
with_line_numbers(
|
|
||||||
rdeps.map { |h| "#{h['name']} (#{h['requirements']})" }.join("\n"),
|
|
||||||
1,
|
|
||||||
:bold
|
|
||||||
)
|
|
||||||
end
|
|
||||||
Pry::Commands.add_command(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,82 +0,0 @@
|
||||||
require 'rubygems'
|
|
||||||
|
|
||||||
class Pry
|
|
||||||
module Rubygem
|
|
||||||
class << self
|
|
||||||
def installed?(name)
|
|
||||||
if Gem::Specification.respond_to?(:find_all_by_name)
|
|
||||||
Gem::Specification.find_all_by_name(name).any?
|
|
||||||
else
|
|
||||||
Gem.source_index.find_name(name).first
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get the gem spec object for the given gem name.
|
|
||||||
#
|
|
||||||
# @param [String] name
|
|
||||||
# @return [Gem::Specification]
|
|
||||||
def spec(name)
|
|
||||||
specs = if Gem::Specification.respond_to?(:each)
|
|
||||||
Gem::Specification.find_all_by_name(name)
|
|
||||||
else
|
|
||||||
Gem.source_index.find_name(name)
|
|
||||||
end
|
|
||||||
|
|
||||||
first_spec = specs.max_by { |spec| Gem::Version.new(spec.version) }
|
|
||||||
|
|
||||||
first_spec || raise(CommandError, "Gem `#{name}` not found")
|
|
||||||
end
|
|
||||||
|
|
||||||
# List gems matching a pattern.
|
|
||||||
#
|
|
||||||
# @param [Regexp] pattern
|
|
||||||
# @return [Array<Gem::Specification>]
|
|
||||||
def list(pattern = /.*/)
|
|
||||||
if Gem::Specification.respond_to?(:each)
|
|
||||||
Gem::Specification.select { |spec| spec.name =~ pattern }
|
|
||||||
else
|
|
||||||
Gem.source_index.gems.values.select { |spec| spec.name =~ pattern }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Completion function for gem-cd and gem-open.
|
|
||||||
#
|
|
||||||
# @param [String] so_far what the user's typed so far
|
|
||||||
# @return [Array<String>] completions
|
|
||||||
def complete(so_far)
|
|
||||||
if so_far =~ / ([^ ]*)\z/
|
|
||||||
list(/\A#{$2}/).map(&:name)
|
|
||||||
else
|
|
||||||
list.map(&:name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Installs a gem with all its dependencies.
|
|
||||||
#
|
|
||||||
# @param [String] name
|
|
||||||
# @return [void]
|
|
||||||
def install(name)
|
|
||||||
require 'rubygems/dependency_installer'
|
|
||||||
gem_config = Gem.configuration['gem']
|
|
||||||
gemrc_opts = (gem_config.nil? ? "" : gem_config.split(' '))
|
|
||||||
destination = if gemrc_opts.include?('--user-install')
|
|
||||||
Gem.user_dir
|
|
||||||
elsif File.writable?(Gem.dir)
|
|
||||||
Gem.dir
|
|
||||||
else
|
|
||||||
Gem.user_dir
|
|
||||||
end
|
|
||||||
installer = Gem::DependencyInstaller.new(install_dir: destination)
|
|
||||||
installer.install(name)
|
|
||||||
rescue Errno::EACCES
|
|
||||||
raise CommandError,
|
|
||||||
"Insufficient permissions to install #{green(name)}."
|
|
||||||
rescue Gem::GemNotFoundException
|
|
||||||
raise CommandError,
|
|
||||||
"Gem #{green(name)} not found. Aborting installation."
|
|
||||||
else
|
|
||||||
Gem.refresh
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,20 +0,0 @@
|
||||||
describe "gem-list" do
|
|
||||||
it 'should not raise when invoked' do
|
|
||||||
expect { pry_eval(self, 'gem-list') }.to_not raise_error
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should work arglessly' do
|
|
||||||
list = pry_eval('gem-list')
|
|
||||||
expect(list).to match(/rspec \(/)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should find arg' do
|
|
||||||
prylist = pry_eval('gem-list method_source')
|
|
||||||
expect(prylist).to match(/method_source \(/)
|
|
||||||
expect(prylist).not_to match(/rspec/)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should return non-results as silence' do
|
|
||||||
expect(pry_eval('gem-list aoeuoueouaou')).to be_empty
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in a new issue