From 4b6fc303bbb37f03f493d621d3f92081b6165930 Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Sun, 28 Oct 2018 17:45:29 +0800 Subject: config: simplify structure * Replace `require_relative` with `require` The project tries to use the `require` form everywhere where possible, which is the common form * `require` from `pry.rb` Spreaded `require` statements where we require internal classes is confusing * Fixed namespace definition for Config classes https://github.com/rubocop-hq/ruby-style-guide#namespace-definition recommends to use explicit nesting --- lib/pry.rb | 6 + lib/pry/config.rb | 16 +- lib/pry/config/behavior.rb | 449 +++++++++++++++++++++--------------------- lib/pry/config/convenience.rb | 45 +++-- lib/pry/config/default.rb | 291 +++++++++++++-------------- lib/pry/config/memoization.rb | 78 ++++---- lib/pry/pry_class.rb | 1 - 7 files changed, 453 insertions(+), 433 deletions(-) diff --git a/lib/pry.rb b/lib/pry.rb index 2bf0eb4b..006eb74b 100644 --- a/lib/pry.rb +++ b/lib/pry.rb @@ -113,6 +113,12 @@ require 'pry/command_set' require 'pry/commands' require 'pry/plugins' require 'pry/core_extensions' +require 'pry/basic_object' +require 'pry/config/behavior' +require 'pry/config/memoization' +require 'pry/config/default' +require 'pry/config/convenience' +require 'pry/config' require 'pry/pry_class' require 'pry/pry_instance' require 'pry/cli' diff --git a/lib/pry/config.rb b/lib/pry/config.rb index 4f702863..2b1599c2 100644 --- a/lib/pry/config.rb +++ b/lib/pry/config.rb @@ -1,11 +1,9 @@ -require_relative 'basic_object' -class Pry::Config < Pry::BasicObject - require_relative 'config/behavior' - require_relative 'config/memoization' - require_relative 'config/default' - require_relative 'config/convenience' - include Pry::Config::Behavior - def self.shortcuts - Convenience::SHORTCUTS +class Pry + class Config < Pry::BasicObject + include Behavior + + def self.shortcuts + Convenience::SHORTCUTS + end end end diff --git a/lib/pry/config/behavior.rb b/lib/pry/config/behavior.rb index 9ec88dd4..0eb2dff9 100644 --- a/lib/pry/config/behavior.rb +++ b/lib/pry/config/behavior.rb @@ -1,250 +1,255 @@ -module Pry::Config::Behavior - ASSIGNMENT = "=".freeze - NODUP = [TrueClass, FalseClass, NilClass, Symbol, Numeric, Module, Proc].freeze - INSPECT_REGEXP = /#{Regexp.escape "default=#<"}/ - ReservedKeyError = Class.new(RuntimeError) - - module Builder - # - # Returns a new Behavior, non-recursively (unlike {#from_hash}). - # - # @param - # (see #from_hash) - # - # @return - # (see #from_hash) - # - def assign(attributes, default = nil) - new(default).tap do |behavior| - behavior.merge!(attributes) - end - end +class Pry + class Config < Pry::BasicObject + module Behavior + ASSIGNMENT = "=".freeze + NODUP = [TrueClass, FalseClass, NilClass, Symbol, Numeric, Module, Proc].freeze + INSPECT_REGEXP = /#{Regexp.escape "default=#<"}/ + ReservedKeyError = Class.new(RuntimeError) + + module Builder + # + # Returns a new Behavior, non-recursively (unlike {#from_hash}). + # + # @param + # (see #from_hash) + # + # @return + # (see #from_hash) + # + def assign(attributes, default = nil) + new(default).tap do |behavior| + behavior.merge!(attributes) + end + end - # - # Returns a new Behavior, recursively walking attributes. - # - # @param [Hash] attributes - # a hash to initialize an instance of self with. - # - # @param [Pry::Config, nil] default - # a default, or nil for none. - # - # @return [Pry::Config] - # returns an instance of self. - # - def from_hash(attributes, default = nil) - new(default).tap do |config| - attributes.each do |key,value| - config[key] = Hash === value ? from_hash(value, nil) : value + # + # Returns a new Behavior, recursively walking attributes. + # + # @param [Hash] attributes + # a hash to initialize an instance of self with. + # + # @param [Pry::Config, nil] default + # a default, or nil for none. + # + # @return [Pry::Config] + # returns an instance of self. + # + def from_hash(attributes, default = nil) + new(default).tap do |config| + attributes.each do |key,value| + config[key] = Hash === value ? from_hash(value, nil) : value + end + end end end - end - end - def self.included(klass) - klass.extend(Builder) - end + def self.included(klass) + klass.extend(Builder) + end - def initialize(default = Pry.config) - @default = default - @lookup = {} - @reserved_keys = methods.map(&:to_s).freeze - end + def initialize(default = Pry.config) + @default = default + @lookup = {} + @reserved_keys = methods.map(&:to_s).freeze + end - # - # @return [Pry::Config::Behavior] - # returns the default used incase a key isn't found in self. - # - def default - @default - end + # + # @return [Pry::Config::Behavior] + # returns the default used incase a key isn't found in self. + # + def default + @default + end - # - # @param [String] key - # a key (as a String) - # - # @return [Object, BasicObject] - # returns an object from self or one of its defaults. - # - def [](key) - key = key.to_s - key?(key) ? @lookup[key] : (@default and @default[key]) - end + # + # @param [String] key + # a key (as a String) + # + # @return [Object, BasicObject] + # returns an object from self or one of its defaults. + # + def [](key) + key = key.to_s + key?(key) ? @lookup[key] : (@default and @default[key]) + end - # - # Add a key and value pair to self. - # - # @param [String] key - # a key (as a String). - # - # @param [Object,BasicObject] value - # a value. - # - # @raise [Pry::Config::ReservedKeyError] - # when 'key' is a reserved key name. - # - def []=(key, value) - key = key.to_s - if @reserved_keys.include?(key) - raise ReservedKeyError, "It is not possible to use '#{key}' as a key name, please choose a different key name." - end + # + # Add a key and value pair to self. + # + # @param [String] key + # a key (as a String). + # + # @param [Object,BasicObject] value + # a value. + # + # @raise [Pry::Config::ReservedKeyError] + # when 'key' is a reserved key name. + # + def []=(key, value) + key = key.to_s + if @reserved_keys.include?(key) + raise ReservedKeyError, "It is not possible to use '#{key}' as a key name, please choose a different key name." + end - __push(key,value) - end + __push(key,value) + end - # - # Removes a key from self. - # - # @param [String] key - # a key (as a String) - # - # @return [void] - # - def forget(key) - key = key.to_s - __remove(key) - end + # + # Removes a key from self. + # + # @param [String] key + # a key (as a String) + # + # @return [void] + # + def forget(key) + key = key.to_s + __remove(key) + end - # - # @param [Hash, #to_h, #to_hash] other - # a hash to merge into self. - # - # @return [void] - # - def merge!(other) - other = __try_convert_to_hash(other) - raise TypeError, "unable to convert argument into a Hash" unless other - - other.each do |key, value| - self[key] = value - end - end + # + # @param [Hash, #to_h, #to_hash] other + # a hash to merge into self. + # + # @return [void] + # + def merge!(other) + other = __try_convert_to_hash(other) + raise TypeError, "unable to convert argument into a Hash" unless other + + other.each do |key, value| + self[key] = value + end + end - # - # @param [Hash, #to_h, #to_hash] other - # a hash to compare against the lookup table of self. - # - def ==(other) - @lookup == __try_convert_to_hash(other) - end - alias_method :eql?, :== - - # - # @param [String] key - # a key (as a String) - # - # @return [Boolean] - # returns true when "key" is a member of self. - # - def key?(key) - key = key.to_s - @lookup.key?(key) - end + # + # @param [Hash, #to_h, #to_hash] other + # a hash to compare against the lookup table of self. + # + def ==(other) + @lookup == __try_convert_to_hash(other) + end + alias_method :eql?, :== + + # + # @param [String] key + # a key (as a String) + # + # @return [Boolean] + # returns true when "key" is a member of self. + # + def key?(key) + key = key.to_s + @lookup.key?(key) + end - # - # Clear the lookup table of self. - # - # @return [void] - # - def clear - @lookup.clear - true - end + # + # Clear the lookup table of self. + # + # @return [void] + # + def clear + @lookup.clear + true + end - # - # @return [Array] - # returns an array of keys in self. - # - def keys - @lookup.keys - end + # + # @return [Array] + # returns an array of keys in self. + # + def keys + @lookup.keys + end - def eager_load! - default = @default - while default - default.memoized_methods.each {|method| self[key] = default.public_send(key)} if default.respond_to?(:memoized_methods) - default = @default.default - end - end + def eager_load! + default = @default + while default + default.memoized_methods.each {|method| self[key] = default.public_send(key)} if default.respond_to?(:memoized_methods) + default = @default.default + end + end - def last_default - last = @default - last = last.default while last and last.default - last - end + def last_default + last = @default + last = last.default while last and last.default + last + end - # - # @return [Hash] - # returns a duplicate copy of the lookup table used by self. - # - def to_hash - @lookup.dup - end - alias_method :to_h, :to_hash + # + # @return [Hash] + # returns a duplicate copy of the lookup table used by self. + # + def to_hash + @lookup.dup + end + alias_method :to_h, :to_hash - def inspect - key_str = keys.map { |key| "'#{key}'" }.join(",") - "#<#{__clip_inspect(self)} keys=[#{key_str}] default=#{@default.inspect}>" - end + def inspect + key_str = keys.map { |key| "'#{key}'" }.join(",") + "#<#{__clip_inspect(self)} keys=[#{key_str}] default=#{@default.inspect}>" + end - def pretty_print(q) - q.text inspect[1..-1].gsub(INSPECT_REGEXP, "default=<") - end + def pretty_print(q) + q.text inspect[1..-1].gsub(INSPECT_REGEXP, "default=<") + end - def method_missing(name, *args, &block) - key = name.to_s - if key[-1] == ASSIGNMENT - short_key = key[0..-2] - self[short_key] = args[0] - elsif key?(key) - self[key] - elsif @default.respond_to?(name) - value = @default.public_send(name, *args, &block) - self[key] = __dup(value) - else - nil - end - end + def method_missing(name, *args, &block) + key = name.to_s + if key[-1] == ASSIGNMENT + short_key = key[0..-2] + self[short_key] = args[0] + elsif key?(key) + self[key] + elsif @default.respond_to?(name) + value = @default.public_send(name, *args, &block) + self[key] = __dup(value) + else + nil + end + end - def respond_to_missing?(key, include_all=false) - key = key.to_s.chomp(ASSIGNMENT) - key?(key) or @default.respond_to?(key) or super(key, include_all) - end + def respond_to_missing?(key, include_all=false) + key = key.to_s.chomp(ASSIGNMENT) + key?(key) or @default.respond_to?(key) or super(key, include_all) + end -private - def __clip_inspect(obj) - "#{obj.class}:0x%x" % obj.object_id - end + private - def __try_convert_to_hash(obj) - if Hash === obj - obj - elsif obj.respond_to?(:to_h) - obj.to_h - elsif obj.respond_to?(:to_hash) - obj.to_hash - else - nil - end - end + def __clip_inspect(obj) + "#{obj.class}:0x%x" % obj.object_id + end - def __dup(value) - if NODUP.any? { |klass| klass === value } - value - else - value.dup - end - end + def __try_convert_to_hash(obj) + if Hash === obj + obj + elsif obj.respond_to?(:to_h) + obj.to_h + elsif obj.respond_to?(:to_hash) + obj.to_hash + else + nil + end + end - def __push(key,value) - unless singleton_class.method_defined? key - define_singleton_method(key) { self[key] } - define_singleton_method("#{key}=") { |val| @lookup[key] = val } - end - @lookup[key] = value - end + def __dup(value) + if NODUP.any? { |klass| klass === value } + value + else + value.dup + end + end + + def __push(key,value) + unless singleton_class.method_defined? key + define_singleton_method(key) { self[key] } + define_singleton_method("#{key}=") { |val| @lookup[key] = val } + end + @lookup[key] = value + end - def __remove(key) - @lookup.delete(key) + def __remove(key) + @lookup.delete(key) + end + end end end diff --git a/lib/pry/config/convenience.rb b/lib/pry/config/convenience.rb index ddd39f49..164bb1fb 100644 --- a/lib/pry/config/convenience.rb +++ b/lib/pry/config/convenience.rb @@ -1,25 +1,28 @@ -module Pry::Config::Convenience - SHORTCUTS = [ - :input, - :output, - :commands, - :print, - :exception_handler, - :hooks, - :color, - :pager, - :editor, - :memory_size, - :extra_sticky_locals - ] +class Pry + class Config < Pry::BasicObject + module Convenience + SHORTCUTS = [ + :input, + :output, + :commands, + :print, + :exception_handler, + :hooks, + :color, + :pager, + :editor, + :memory_size, + :extra_sticky_locals + ] - - def config_shortcut(*names) - names.each do |name| - reader = name - setter = "#{name}=" - define_method(reader) { config.public_send(name) } - define_method(setter) { |value| config.public_send(setter, value) } + def config_shortcut(*names) + names.each do |name| + reader = name + setter = "#{name}=" + define_method(reader) { config.public_send(name) } + define_method(setter) { |value| config.public_send(setter, value) } + end + end end end end diff --git a/lib/pry/config/default.rb b/lib/pry/config/default.rb index 09e9eb4c..8a6b3204 100644 --- a/lib/pry/config/default.rb +++ b/lib/pry/config/default.rb @@ -1,149 +1,154 @@ -class Pry::Config::Default - include Pry::Config::Behavior - include Pry::Config::Memoization +class Pry + class Config < Pry::BasicObject + class Default + include Config::Behavior + include Config::Memoization - def_memoized({ - input: proc { - lazy_readline - }, - output: proc { - $stdout.tap { |out| out.sync = true } - }, - commands: proc { - Pry::Commands - }, - prompt_name: proc { - Pry::Prompt::DEFAULT_NAME - }, - prompt: proc { - Pry::Prompt::DEFAULT - }, - prompt_safe_contexts: proc { - Pry::Prompt::SAFE_CONTEXTS - }, - print: proc { - Pry::DEFAULT_PRINT - }, - quiet: proc { - false - }, - exception_handler: proc { - Pry::DEFAULT_EXCEPTION_HANDLER - }, - exception_whitelist: proc { - Pry::DEFAULT_EXCEPTION_WHITELIST - }, - hooks: proc { - Pry::DEFAULT_HOOKS - }, - pager: proc { - true - }, - system: proc { - Pry::DEFAULT_SYSTEM - }, - color: proc { - Pry::Helpers::BaseHelpers.use_ansi_codes? - }, - default_window_size: proc { - 5 - }, - editor: proc { - Pry.default_editor_for_platform - }, # TODO: Pry::Platform.editor - should_load_rc: proc { - true - }, - should_load_local_rc: proc { - true - }, - should_trap_interrupts: proc { - Pry::Platform.jruby? - }, - disable_auto_reload: proc { - false - }, - command_prefix: proc { - "" - }, - auto_indent: proc { - Pry::Helpers::BaseHelpers.use_ansi_codes? - }, - correct_indent: proc { - true - }, - collision_warning: proc { - false - }, - output_prefix: proc { - "=> " - }, - requires: proc { - [] - }, - should_load_requires: proc { - true - }, - should_load_plugins: proc { - true - }, - windows_console_warning: proc { - true - }, - control_d_handler: proc { - Pry::DEFAULT_CONTROL_D_HANDLER - }, - memory_size: proc { - 100 - }, - extra_sticky_locals: proc { - {} - }, - command_completions: proc { - proc { commands.keys } - }, - file_completions: proc { - proc { Dir["."] } - }, - ls: proc { - Pry::Config.from_hash(Pry::Command::Ls::DEFAULT_OPTIONS) - }, - completer: proc { - require "pry/input_completer" - Pry::InputCompleter - }, - gist: proc { - Pry::Config.from_hash({inspecter: proc(&:pretty_inspect)}, nil) - }, - history: proc { - Pry::Config.from_hash({should_save: true, should_load: true}, nil).tap do |history| - history.file = File.expand_path("~/.pry_history") rescue nil - if history.file.nil? - self.should_load_rc = false - history.should_save = false - history.should_load = false - end + def_memoized({ + input: proc { + lazy_readline + }, + output: proc { + $stdout.tap { |out| out.sync = true } + }, + commands: proc { + Pry::Commands + }, + prompt_name: proc { + Pry::Prompt::DEFAULT_NAME + }, + prompt: proc { + Pry::Prompt::DEFAULT + }, + prompt_safe_contexts: proc { + Pry::Prompt::SAFE_CONTEXTS + }, + print: proc { + Pry::DEFAULT_PRINT + }, + quiet: proc { + false + }, + exception_handler: proc { + Pry::DEFAULT_EXCEPTION_HANDLER + }, + exception_whitelist: proc { + Pry::DEFAULT_EXCEPTION_WHITELIST + }, + hooks: proc { + Pry::DEFAULT_HOOKS + }, + pager: proc { + true + }, + system: proc { + Pry::DEFAULT_SYSTEM + }, + color: proc { + Pry::Helpers::BaseHelpers.use_ansi_codes? + }, + default_window_size: proc { + 5 + }, + editor: proc { + Pry.default_editor_for_platform + }, # TODO: Pry::Platform.editor + should_load_rc: proc { + true + }, + should_load_local_rc: proc { + true + }, + should_trap_interrupts: proc { + Pry::Platform.jruby? + }, + disable_auto_reload: proc { + false + }, + command_prefix: proc { + "" + }, + auto_indent: proc { + Pry::Helpers::BaseHelpers.use_ansi_codes? + }, + correct_indent: proc { + true + }, + collision_warning: proc { + false + }, + output_prefix: proc { + "=> " + }, + requires: proc { + [] + }, + should_load_requires: proc { + true + }, + should_load_plugins: proc { + true + }, + windows_console_warning: proc { + true + }, + control_d_handler: proc { + Pry::DEFAULT_CONTROL_D_HANDLER + }, + memory_size: proc { + 100 + }, + extra_sticky_locals: proc { + {} + }, + command_completions: proc { + proc { commands.keys } + }, + file_completions: proc { + proc { Dir["."] } + }, + ls: proc { + Pry::Config.from_hash(Pry::Command::Ls::DEFAULT_OPTIONS) + }, + completer: proc { + require "pry/input_completer" + Pry::InputCompleter + }, + gist: proc { + Pry::Config.from_hash({inspecter: proc(&:pretty_inspect)}, nil) + }, + history: proc { + Pry::Config.from_hash({should_save: true, should_load: true}, nil).tap do |history| + history.file = File.expand_path("~/.pry_history") rescue nil + if history.file.nil? + self.should_load_rc = false + history.should_save = false + history.should_load = false + end + end + }, + exec_string: proc { + "" + } + }) + + def initialize + super(nil) end - }, - exec_string: proc { - "" - } - }) - def initialize - super(nil) - end + private - private - def lazy_readline - require 'readline' - Readline - rescue LoadError - warn "Sorry, you can't use Pry without Readline or a compatible library." - warn "Possible solutions:" - warn " * Rebuild Ruby with Readline support using `--with-readline`" - warn " * Use the rb-readline gem, which is a pure-Ruby port of Readline" - warn " * Use the pry-coolline gem, a pure-ruby alternative to Readline" - raise + def lazy_readline + require 'readline' + Readline + rescue LoadError + warn "Sorry, you can't use Pry without Readline or a compatible library." + warn "Possible solutions:" + warn " * Rebuild Ruby with Readline support using `--with-readline`" + warn " * Use the rb-readline gem, which is a pure-Ruby port of Readline" + warn " * Use the pry-coolline gem, a pure-ruby alternative to Readline" + raise + end + end end end diff --git a/lib/pry/config/memoization.rb b/lib/pry/config/memoization.rb index 622f4356..bb9ca4ad 100644 --- a/lib/pry/config/memoization.rb +++ b/lib/pry/config/memoization.rb @@ -1,44 +1,48 @@ -module Pry::Config::Memoization - MEMOIZED_METHODS = Hash.new {|h,k| h[k] = [] } +class Pry + class Config < Pry::BasicObject + module Memoization + MEMOIZED_METHODS = Hash.new {|h,k| h[k] = [] } - module ClassMethods - # - # Defines one or more methods who return a constant value after being - # called once. - # - # @example - # class Foo - # include Pry::Config::Memoization - # def_memoized({ - # foo: proc {1+10}, - # bar: proc{"aaa"<<"a"} - # }) - # end - # - # @param [{String => Proc}] method_table - # - # @return [void] - # - def def_memoized(method_table) - method_table.each do |method_name, method| - define_method(method_name) do - method_table[method_name] = instance_eval(&method) if method_table[method_name].equal? method - method_table[method_name] + module ClassMethods + # + # Defines one or more methods who return a constant value after being + # called once. + # + # @example + # class Foo + # include Pry::Config::Memoization + # def_memoized({ + # foo: proc {1+10}, + # bar: proc{"aaa"<<"a"} + # }) + # end + # + # @param [{String => Proc}] method_table + # + # @return [void] + # + def def_memoized(method_table) + method_table.each do |method_name, method| + define_method(method_name) do + method_table[method_name] = instance_eval(&method) if method_table[method_name].equal? method + method_table[method_name] + end + end + MEMOIZED_METHODS[self] |= method_table.keys end end - MEMOIZED_METHODS[self] |= method_table.keys - end - end - def self.included(mod) - mod.extend(ClassMethods) - end + def self.included(mod) + mod.extend(ClassMethods) + end - # - # @return [Array] - # Returns the names of methods that have been defined by {ClassMethods#def_memoized}. - # - def memoized_methods - MEMOIZED_METHODS[self.class] + # + # @return [Array] + # Returns the names of methods that have been defined by {ClassMethods#def_memoized}. + # + def memoized_methods + MEMOIZED_METHODS[self.class] + end + end end end diff --git a/lib/pry/pry_class.rb b/lib/pry/pry_class.rb index eea5e4f7..d73339a0 100644 --- a/lib/pry/pry_class.rb +++ b/lib/pry/pry_class.rb @@ -1,4 +1,3 @@ -require 'pry/config' class Pry HOME_RC_FILE = -- cgit v1.2.1