1
0
Fork 0
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:
Kyrylo Silin 2013-11-30 17:49:18 +02:00
parent 63f12424d1
commit 94db19efc1
5 changed files with 159 additions and 10 deletions

View file

@ -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)

View 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

View 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

View 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

View 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