mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
Refactor the way how ls
displays methods
Also, split a lot of code into the nice small modules.
This commit is contained in:
parent
63f12424d1
commit
94db19efc1
5 changed files with 159 additions and 10 deletions
|
@ -1,7 +1,11 @@
|
|||
require 'pry/commands/ls/interrogateable'
|
||||
|
||||
class Pry
|
||||
class Command::Ls < Pry::ClassCommand
|
||||
class Constants < Pry::Command::Ls::Formatter
|
||||
|
||||
include Pry::Command::Ls::Interrogateable
|
||||
|
||||
def initialize(interrogatee, target, has_any_opts, opts)
|
||||
super(target)
|
||||
@interrogatee = interrogatee
|
||||
|
@ -14,16 +18,6 @@ class Pry
|
|||
super || (!@has_any_opts && Module === @interrogatee)
|
||||
end
|
||||
|
||||
def interrogatee_mod
|
||||
if Module === @interrogatee
|
||||
@interrogatee
|
||||
else
|
||||
class << @interrogatee
|
||||
ancestors.grep(::Class).reject { |c| c == self }.first
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def output_self
|
||||
mod = interrogatee_mod
|
||||
constants = WrappedModule.new(mod).constants(@verbose_switch)
|
||||
|
|
13
lib/pry/commands/ls/interrogateable.rb
Normal file
13
lib/pry/commands/ls/interrogateable.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
module Pry::Command::Ls::Interrogateable
|
||||
|
||||
def interrogatee_mod
|
||||
if Module === @interrogatee
|
||||
@interrogatee
|
||||
else
|
||||
class << @interrogatee
|
||||
ancestors.grep(::Class).reject { |c| c == self }.first
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
47
lib/pry/commands/ls/jruby_hacks.rb
Normal file
47
lib/pry/commands/ls/jruby_hacks.rb
Normal file
|
@ -0,0 +1,47 @@
|
|||
module Pry::Command::Ls::JRubyHacks
|
||||
|
||||
# JRuby creates lots of aliases for methods imported from java in an attempt
|
||||
# to make life easier for ruby programmers. (e.g. getFooBar becomes
|
||||
# get_foo_bar and foo_bar, and maybe foo_bar? if it returns a Boolean). The
|
||||
# full transformations are in the assignAliases method of:
|
||||
# https://github.com/jruby/jruby/blob/master/src/org/jruby/javasupport/JavaClass.java
|
||||
#
|
||||
# This has the unfortunate side-effect of making the output of ls even more
|
||||
# incredibly verbose than it normally would be for these objects; and so we
|
||||
# filter out all but the nicest of these aliases here.
|
||||
#
|
||||
# TODO: This is a little bit vague, better heuristics could be used.
|
||||
# JRuby also has a lot of scala-specific logic, which we don't copy.
|
||||
def trim_jruby_aliases(methods)
|
||||
grouped = methods.group_by do |m|
|
||||
m.name.sub(/\A(is|get|set)(?=[A-Z_])/, '').gsub(/[_?=]/, '').downcase
|
||||
end
|
||||
|
||||
grouped.map do |key, values|
|
||||
values = values.sort_by do |m|
|
||||
rubbishness(m.name)
|
||||
end
|
||||
|
||||
found = []
|
||||
values.select do |x|
|
||||
(!found.any? { |y| x == y }) && found << x
|
||||
end
|
||||
end.flatten(1)
|
||||
end
|
||||
|
||||
# When removing jruby aliases, we want to keep the alias that is
|
||||
# "least rubbish" according to this metric.
|
||||
def rubbishness(name)
|
||||
name.each_char.map { |x|
|
||||
case x
|
||||
when /[A-Z]/
|
||||
1
|
||||
when '?', '=', '!'
|
||||
-2
|
||||
else
|
||||
0
|
||||
end
|
||||
}.inject(&:+) + (name.size / 100.0)
|
||||
end
|
||||
|
||||
end
|
55
lib/pry/commands/ls/methods.rb
Normal file
55
lib/pry/commands/ls/methods.rb
Normal file
|
@ -0,0 +1,55 @@
|
|||
require 'pry/commands/ls/jruby_hacks'
|
||||
require 'pry/commands/ls/methods_helper'
|
||||
require 'pry/commands/ls/interrogateable'
|
||||
|
||||
class Pry
|
||||
class Command::Ls < Pry::ClassCommand
|
||||
class Methods < Pry::Command::Ls::Formatter
|
||||
|
||||
include Pry::Command::Ls::Interrogateable
|
||||
include Pry::Command::Ls::JRubyHacks
|
||||
include Pry::Command::Ls::MethodsHelper
|
||||
|
||||
def initialize(interrogatee, has_any_opts, opts)
|
||||
@interrogatee = interrogatee
|
||||
@has_any_opts = has_any_opts
|
||||
@default_switch = opts[:methods]
|
||||
@instance_methods_switch = opts['instance-methods']
|
||||
@ppp_switch = opts[:ppp]
|
||||
@jruby_switch = opts['all-java']
|
||||
@quiet_switch = opts[:quiet]
|
||||
end
|
||||
|
||||
def correct_opts?
|
||||
super || @instance_methods_switch || @ppp_switch || !@has_any_opts
|
||||
end
|
||||
|
||||
def output_self
|
||||
methods = all_methods.group_by(&:owner)
|
||||
# Reverse the resolution order so that the most useful information
|
||||
# appears right by the prompt.
|
||||
resolution_order.take_while(&below_ceiling).reverse.map do |klass|
|
||||
methods_here = grep.regexp[format((methods[klass] || []))]
|
||||
heading = "#{ Pry::WrappedModule.new(klass).method_prefix }methods"
|
||||
output_section(heading, methods_here)
|
||||
end.join('')
|
||||
end
|
||||
|
||||
# Format and colourise a list of methods.
|
||||
def format(methods)
|
||||
methods.sort_by(&:name).map do |method|
|
||||
if method.name == 'method_missing'
|
||||
color(:method_missing, 'method_missing')
|
||||
elsif method.visibility == :private
|
||||
color(:private_method, method.name)
|
||||
elsif method.visibility == :protected
|
||||
color(:protected_method, method.name)
|
||||
else
|
||||
color(:public_method, method.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
40
lib/pry/commands/ls/methods_helper.rb
Normal file
40
lib/pry/commands/ls/methods_helper.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
module Pry::Command::Ls::MethodsHelper
|
||||
|
||||
# Get all the methods that we'll want to output.
|
||||
def all_methods(instance_methods = false)
|
||||
methods = if instance_methods || @instance_methods_switch
|
||||
Pry::Method.all_from_class(@interrogatee)
|
||||
else
|
||||
Pry::Method.all_from_obj(@interrogatee)
|
||||
end
|
||||
|
||||
if Pry::Helpers::BaseHelpers.jruby? && !@jruby_switch
|
||||
methods = trim_jruby_aliases(methods)
|
||||
end
|
||||
|
||||
methods.select { |method| @ppp_switch || method.visibility == :public }
|
||||
end
|
||||
|
||||
def resolution_order
|
||||
if @instance_methods_switch
|
||||
Pry::Method.instance_resolution_order(@interrogatee)
|
||||
else
|
||||
Pry::Method.resolution_order(@interrogatee)
|
||||
end
|
||||
end
|
||||
|
||||
# Get a lambda that can be used with `take_while` to prevent over-eager
|
||||
# traversal of the Object's ancestry graph.
|
||||
def below_ceiling
|
||||
ceiling = if @quiet_switch
|
||||
[Pry::Method.safe_send(interrogatee_mod, :ancestors)[1]] +
|
||||
Pry.config.ls.ceiling
|
||||
elsif @verbose_switch
|
||||
[]
|
||||
else
|
||||
Pry.config.ls.ceiling.dup
|
||||
end
|
||||
lambda { |klass| !ceiling.include?(klass) }
|
||||
end
|
||||
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue