mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	with inheritance. [fix GH-1227] Patch by @adrfer * lib/irb/*: ditto. * lib/prime.rb: ditto. * lib/shell/builtin-command.rb: ditto. * object.c: ditto. * sample/*.rb: ditto. * test/-ext-/method/test_arity.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56371 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			232 lines
		
	
	
	
		
			7.2 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			232 lines
		
	
	
	
		
			7.2 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
# frozen_string_literal: false
 | 
						|
#
 | 
						|
#   notifier.rb - output methods used by irb
 | 
						|
#   	$Release Version: 0.9.6$
 | 
						|
#   	$Revision$
 | 
						|
#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
 | 
						|
#
 | 
						|
# --
 | 
						|
#
 | 
						|
#
 | 
						|
#
 | 
						|
 | 
						|
require "e2mmap"
 | 
						|
require "irb/output-method"
 | 
						|
 | 
						|
module IRB
 | 
						|
  # An output formatter used internally by the lexer.
 | 
						|
  module Notifier
 | 
						|
    extend Exception2MessageMapper
 | 
						|
    def_exception :ErrUndefinedNotifier,
 | 
						|
      "undefined notifier level: %d is specified"
 | 
						|
    def_exception :ErrUnrecognizedLevel,
 | 
						|
      "unrecognized notifier level: %s is specified"
 | 
						|
 | 
						|
    # Define a new Notifier output source, returning a new CompositeNotifier
 | 
						|
    # with the given +prefix+ and +output_method+.
 | 
						|
    #
 | 
						|
    # The optional +prefix+ will be appended to all objects being inspected
 | 
						|
    # during output, using the given +output_method+ as the output source. If
 | 
						|
    # no +output_method+ is given, StdioOutputMethod will be used, and all
 | 
						|
    # expressions will be sent directly to STDOUT without any additional
 | 
						|
    # formatting.
 | 
						|
    def def_notifier(prefix = "", output_method = StdioOutputMethod.new)
 | 
						|
      CompositeNotifier.new(prefix, output_method)
 | 
						|
    end
 | 
						|
    module_function :def_notifier
 | 
						|
 | 
						|
    # An abstract class, or superclass, for CompositeNotifier and
 | 
						|
    # LeveledNotifier to inherit. It provides several wrapper methods for the
 | 
						|
    # OutputMethod object used by the Notifier.
 | 
						|
    class AbstractNotifier
 | 
						|
      # Creates a new Notifier object
 | 
						|
      def initialize(prefix, base_notifier)
 | 
						|
        @prefix = prefix
 | 
						|
        @base_notifier = base_notifier
 | 
						|
      end
 | 
						|
 | 
						|
      # The +prefix+ for this Notifier, which is appended to all objects being
 | 
						|
      # inspected during output.
 | 
						|
      attr_reader :prefix
 | 
						|
 | 
						|
      # A wrapper method used to determine whether notifications are enabled.
 | 
						|
      #
 | 
						|
      # Defaults to +true+.
 | 
						|
      def notify?
 | 
						|
        true
 | 
						|
      end
 | 
						|
 | 
						|
      # See OutputMethod#print for more detail.
 | 
						|
      def print(*opts)
 | 
						|
        @base_notifier.print prefix, *opts if notify?
 | 
						|
      end
 | 
						|
 | 
						|
      # See OutputMethod#printn for more detail.
 | 
						|
      def printn(*opts)
 | 
						|
        @base_notifier.printn prefix, *opts if notify?
 | 
						|
      end
 | 
						|
 | 
						|
      # See OutputMethod#printf for more detail.
 | 
						|
      def printf(format, *opts)
 | 
						|
        @base_notifier.printf(prefix + format, *opts) if notify?
 | 
						|
      end
 | 
						|
 | 
						|
      # See OutputMethod#puts for more detail.
 | 
						|
      def puts(*objs)
 | 
						|
        if notify?
 | 
						|
          @base_notifier.puts(*objs.collect{|obj| prefix + obj.to_s})
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      # Same as #ppx, except it uses the #prefix given during object
 | 
						|
      # initialization.
 | 
						|
      # See OutputMethod#ppx for more detail.
 | 
						|
      def pp(*objs)
 | 
						|
        if notify?
 | 
						|
          @base_notifier.ppx @prefix, *objs
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      # Same as #pp, except it concatenates the given +prefix+ with the #prefix
 | 
						|
      # given during object initialization.
 | 
						|
      #
 | 
						|
      # See OutputMethod#ppx for more detail.
 | 
						|
      def ppx(prefix, *objs)
 | 
						|
        if notify?
 | 
						|
          @base_notifier.ppx @prefix+prefix, *objs
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      # Execute the given block if notifications are enabled.
 | 
						|
      def exec_if
 | 
						|
        yield(@base_notifier) if notify?
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    # A class that can be used to create a group of notifier objects with the
 | 
						|
    # intent of representing a leveled notification system for irb.
 | 
						|
    #
 | 
						|
    # This class will allow you to generate other notifiers, and assign them
 | 
						|
    # the appropriate level for output.
 | 
						|
    #
 | 
						|
    # The Notifier class provides a class-method Notifier.def_notifier to
 | 
						|
    # create a new composite notifier. Using the first composite notifier
 | 
						|
    # object you create, sibling notifiers can be initialized with
 | 
						|
    # #def_notifier.
 | 
						|
    class CompositeNotifier < AbstractNotifier
 | 
						|
      # Create a new composite notifier object with the given +prefix+, and
 | 
						|
      # +base_notifier+ to use for output.
 | 
						|
      def initialize(prefix, base_notifier)
 | 
						|
        super
 | 
						|
 | 
						|
        @notifiers = [D_NOMSG]
 | 
						|
        @level_notifier = D_NOMSG
 | 
						|
      end
 | 
						|
 | 
						|
      # List of notifiers in the group
 | 
						|
      attr_reader :notifiers
 | 
						|
 | 
						|
      # Creates a new LeveledNotifier in the composite #notifiers group.
 | 
						|
      #
 | 
						|
      # The given +prefix+ will be assigned to the notifier, and +level+ will
 | 
						|
      # be used as the index of the #notifiers Array.
 | 
						|
      #
 | 
						|
      # This method returns the newly created instance.
 | 
						|
      def def_notifier(level, prefix = "")
 | 
						|
        notifier = LeveledNotifier.new(self, level, prefix)
 | 
						|
        @notifiers[level] = notifier
 | 
						|
        notifier
 | 
						|
      end
 | 
						|
 | 
						|
      # Returns the leveled notifier for this object
 | 
						|
      attr_reader :level_notifier
 | 
						|
      alias level level_notifier
 | 
						|
 | 
						|
      # Sets the leveled notifier for this object.
 | 
						|
      #
 | 
						|
      # When the given +value+ is an instance of AbstractNotifier,
 | 
						|
      # #level_notifier is set to the given object.
 | 
						|
      #
 | 
						|
      # When an Integer is given, #level_notifier is set to the notifier at the
 | 
						|
      # index +value+ in the #notifiers Array.
 | 
						|
      #
 | 
						|
      # If no notifier exists at the index +value+ in the #notifiers Array, an
 | 
						|
      # ErrUndefinedNotifier exception is raised.
 | 
						|
      #
 | 
						|
      # An ErrUnrecognizedLevel exception is raised if the given +value+ is not
 | 
						|
      # found in the existing #notifiers Array, or an instance of
 | 
						|
      # AbstractNotifier
 | 
						|
      def level_notifier=(value)
 | 
						|
        case value
 | 
						|
        when AbstractNotifier
 | 
						|
          @level_notifier = value
 | 
						|
        when Integer
 | 
						|
          l = @notifiers[value]
 | 
						|
          Notifier.Raise ErrUndefinedNotifier, value unless l
 | 
						|
          @level_notifier = l
 | 
						|
        else
 | 
						|
          Notifier.Raise ErrUnrecognizedLevel, value unless l
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      alias level= level_notifier=
 | 
						|
    end
 | 
						|
 | 
						|
    # A leveled notifier is comparable to the composite group from
 | 
						|
    # CompositeNotifier#notifiers.
 | 
						|
    class LeveledNotifier < AbstractNotifier
 | 
						|
      include Comparable
 | 
						|
 | 
						|
      # Create a new leveled notifier with the given +base+, and +prefix+ to
 | 
						|
      # send to AbstractNotifier.new
 | 
						|
      #
 | 
						|
      # The given +level+ is used to compare other leveled notifiers in the
 | 
						|
      # CompositeNotifier group to determine whether or not to output
 | 
						|
      # notifications.
 | 
						|
      def initialize(base, level, prefix)
 | 
						|
        super(prefix, base)
 | 
						|
 | 
						|
        @level = level
 | 
						|
      end
 | 
						|
 | 
						|
      # The current level of this notifier object
 | 
						|
      attr_reader :level
 | 
						|
 | 
						|
      # Compares the level of this notifier object with the given +other+
 | 
						|
      # notifier.
 | 
						|
      #
 | 
						|
      # See the Comparable module for more information.
 | 
						|
      def <=>(other)
 | 
						|
        @level <=> other.level
 | 
						|
      end
 | 
						|
 | 
						|
      # Whether to output messages to the output method, depending on the level
 | 
						|
      # of this notifier object.
 | 
						|
      def notify?
 | 
						|
        @base_notifier.level >= self
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    # NoMsgNotifier is a LeveledNotifier that's used as the default notifier
 | 
						|
    # when creating a new CompositeNotifier.
 | 
						|
    #
 | 
						|
    # This notifier is used as the +zero+ index, or level +0+, for
 | 
						|
    # CompositeNotifier#notifiers, and will not output messages of any sort.
 | 
						|
    class NoMsgNotifier < LeveledNotifier
 | 
						|
      # Creates a new notifier that should not be used to output messages.
 | 
						|
      def initialize
 | 
						|
        @base_notifier = nil
 | 
						|
        @level = 0
 | 
						|
        @prefix = ""
 | 
						|
      end
 | 
						|
 | 
						|
      # Ensures notifications are ignored, see AbstractNotifier#notify? for
 | 
						|
      # more information.
 | 
						|
      def notify?
 | 
						|
        false
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    D_NOMSG = NoMsgNotifier.new # :nodoc:
 | 
						|
  end
 | 
						|
end
 |