mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	From Reidline to Reline
Update description used in take_corresponding_syntax_to_kw_do and is_the_in_correspond_to_a_for methods
Use possessive noun correctly
Second element
4fa9714d6f
		
	
			
		
			
				
	
	
		
			441 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			441 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
# frozen_string_literal: false
 | 
						|
#
 | 
						|
#   irb/input-method.rb - input methods used irb
 | 
						|
#   	$Release Version: 0.9.6$
 | 
						|
#   	$Revision$
 | 
						|
#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
 | 
						|
#
 | 
						|
# --
 | 
						|
#
 | 
						|
#
 | 
						|
#
 | 
						|
require_relative 'src_encoding'
 | 
						|
require_relative 'magic-file'
 | 
						|
require_relative 'completion'
 | 
						|
require 'io/console'
 | 
						|
require 'reline'
 | 
						|
require 'rdoc'
 | 
						|
 | 
						|
module IRB
 | 
						|
  STDIN_FILE_NAME = "(line)" # :nodoc:
 | 
						|
  class InputMethod
 | 
						|
 | 
						|
    # Creates a new input method object
 | 
						|
    def initialize(file = STDIN_FILE_NAME)
 | 
						|
      @file_name = file
 | 
						|
    end
 | 
						|
    # The file name of this input method, usually given during initialization.
 | 
						|
    attr_reader :file_name
 | 
						|
 | 
						|
    # The irb prompt associated with this input method
 | 
						|
    attr_accessor :prompt
 | 
						|
 | 
						|
    # Reads the next line from this input method.
 | 
						|
    #
 | 
						|
    # See IO#gets for more information.
 | 
						|
    def gets
 | 
						|
      fail NotImplementedError, "gets"
 | 
						|
    end
 | 
						|
    public :gets
 | 
						|
 | 
						|
    def winsize
 | 
						|
      if instance_variable_defined?(:@stdout)
 | 
						|
        @stdout.winsize
 | 
						|
      else
 | 
						|
        [24, 80]
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    # Whether this input method is still readable when there is no more data to
 | 
						|
    # read.
 | 
						|
    #
 | 
						|
    # See IO#eof for more information.
 | 
						|
    def readable_after_eof?
 | 
						|
      false
 | 
						|
    end
 | 
						|
 | 
						|
    # For debug message
 | 
						|
    def inspect
 | 
						|
      'Abstract InputMethod'
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  class StdioInputMethod < InputMethod
 | 
						|
    # Creates a new input method object
 | 
						|
    def initialize
 | 
						|
      super
 | 
						|
      @line_no = 0
 | 
						|
      @line = []
 | 
						|
      @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
 | 
						|
      @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
 | 
						|
    end
 | 
						|
 | 
						|
    # Reads the next line from this input method.
 | 
						|
    #
 | 
						|
    # See IO#gets for more information.
 | 
						|
    def gets
 | 
						|
      print @prompt
 | 
						|
      line = @stdin.gets
 | 
						|
      @line[@line_no += 1] = line
 | 
						|
    end
 | 
						|
 | 
						|
    # Whether the end of this input method has been reached, returns +true+ if
 | 
						|
    # there is no more data to read.
 | 
						|
    #
 | 
						|
    # See IO#eof? for more information.
 | 
						|
    def eof?
 | 
						|
      rs, = IO.select([@stdin], [], [], 0.00001)
 | 
						|
      if rs and rs[0]
 | 
						|
        c = @stdin.getc
 | 
						|
        result = c.nil? ? true : false
 | 
						|
        @stdin.ungetc(c) unless c.nil?
 | 
						|
        result
 | 
						|
      else # buffer is empty
 | 
						|
        false
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    # Whether this input method is still readable when there is no more data to
 | 
						|
    # read.
 | 
						|
    #
 | 
						|
    # See IO#eof for more information.
 | 
						|
    def readable_after_eof?
 | 
						|
      true
 | 
						|
    end
 | 
						|
 | 
						|
    # Returns the current line number for #io.
 | 
						|
    #
 | 
						|
    # #line counts the number of times #gets is called.
 | 
						|
    #
 | 
						|
    # See IO#lineno for more information.
 | 
						|
    def line(line_no)
 | 
						|
      @line[line_no]
 | 
						|
    end
 | 
						|
 | 
						|
    # The external encoding for standard input.
 | 
						|
    def encoding
 | 
						|
      @stdin.external_encoding
 | 
						|
    end
 | 
						|
 | 
						|
    # For debug message
 | 
						|
    def inspect
 | 
						|
      'StdioInputMethod'
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  # Use a File for IO with irb, see InputMethod
 | 
						|
  class FileInputMethod < InputMethod
 | 
						|
    class << self
 | 
						|
      def open(file, &block)
 | 
						|
        begin
 | 
						|
          io = new(file)
 | 
						|
          block.call(io)
 | 
						|
        ensure
 | 
						|
          io&.close
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    # Creates a new input method object
 | 
						|
    def initialize(file)
 | 
						|
      super
 | 
						|
      @io = IRB::MagicFile.open(file)
 | 
						|
      @external_encoding = @io.external_encoding
 | 
						|
    end
 | 
						|
    # The file name of this input method, usually given during initialization.
 | 
						|
    attr_reader :file_name
 | 
						|
 | 
						|
    # Whether the end of this input method has been reached, returns +true+ if
 | 
						|
    # there is no more data to read.
 | 
						|
    #
 | 
						|
    # See IO#eof? for more information.
 | 
						|
    def eof?
 | 
						|
      @io.closed? || @io.eof?
 | 
						|
    end
 | 
						|
 | 
						|
    # Reads the next line from this input method.
 | 
						|
    #
 | 
						|
    # See IO#gets for more information.
 | 
						|
    def gets
 | 
						|
      print @prompt
 | 
						|
      @io.gets
 | 
						|
    end
 | 
						|
 | 
						|
    # The external encoding for standard input.
 | 
						|
    def encoding
 | 
						|
      @external_encoding
 | 
						|
    end
 | 
						|
 | 
						|
    # For debug message
 | 
						|
    def inspect
 | 
						|
      'FileInputMethod'
 | 
						|
    end
 | 
						|
 | 
						|
    def close
 | 
						|
      @io.close
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  begin
 | 
						|
    class ReadlineInputMethod < InputMethod
 | 
						|
      def self.initialize_readline
 | 
						|
        require "readline"
 | 
						|
      rescue LoadError
 | 
						|
      else
 | 
						|
        include ::Readline
 | 
						|
      end
 | 
						|
 | 
						|
      # Creates a new input method object using Readline
 | 
						|
      def initialize
 | 
						|
        self.class.initialize_readline
 | 
						|
        if Readline.respond_to?(:encoding_system_needs)
 | 
						|
          IRB.__send__(:set_encoding, Readline.encoding_system_needs.name, override: false)
 | 
						|
        end
 | 
						|
        super
 | 
						|
 | 
						|
        @line_no = 0
 | 
						|
        @line = []
 | 
						|
        @eof = false
 | 
						|
 | 
						|
        @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
 | 
						|
        @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
 | 
						|
 | 
						|
        if Readline.respond_to?("basic_word_break_characters=")
 | 
						|
          Readline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS
 | 
						|
        end
 | 
						|
        Readline.completion_append_character = nil
 | 
						|
        Readline.completion_proc = IRB::InputCompletor::CompletionProc
 | 
						|
      end
 | 
						|
 | 
						|
      # Reads the next line from this input method.
 | 
						|
      #
 | 
						|
      # See IO#gets for more information.
 | 
						|
      def gets
 | 
						|
        Readline.input = @stdin
 | 
						|
        Readline.output = @stdout
 | 
						|
        if l = readline(@prompt, false)
 | 
						|
          HISTORY.push(l) if !l.empty?
 | 
						|
          @line[@line_no += 1] = l + "\n"
 | 
						|
        else
 | 
						|
          @eof = true
 | 
						|
          l
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      # Whether the end of this input method has been reached, returns +true+
 | 
						|
      # if there is no more data to read.
 | 
						|
      #
 | 
						|
      # See IO#eof? for more information.
 | 
						|
      def eof?
 | 
						|
        @eof
 | 
						|
      end
 | 
						|
 | 
						|
      # Whether this input method is still readable when there is no more data to
 | 
						|
      # read.
 | 
						|
      #
 | 
						|
      # See IO#eof for more information.
 | 
						|
      def readable_after_eof?
 | 
						|
        true
 | 
						|
      end
 | 
						|
 | 
						|
      # Returns the current line number for #io.
 | 
						|
      #
 | 
						|
      # #line counts the number of times #gets is called.
 | 
						|
      #
 | 
						|
      # See IO#lineno for more information.
 | 
						|
      def line(line_no)
 | 
						|
        @line[line_no]
 | 
						|
      end
 | 
						|
 | 
						|
      # The external encoding for standard input.
 | 
						|
      def encoding
 | 
						|
        @stdin.external_encoding
 | 
						|
      end
 | 
						|
 | 
						|
      # For debug message
 | 
						|
      def inspect
 | 
						|
        readline_impl = (defined?(Reline) && Readline == Reline) ? 'Reline' : 'ext/readline'
 | 
						|
        str = "ReadlineInputMethod with #{readline_impl} #{Readline::VERSION}"
 | 
						|
        inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc')
 | 
						|
        str += " and #{inputrc_path}" if File.exist?(inputrc_path)
 | 
						|
        str
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  class ReidlineInputMethod < InputMethod
 | 
						|
    include Reline
 | 
						|
 | 
						|
    # Creates a new input method object using Reline
 | 
						|
    def initialize
 | 
						|
      IRB.__send__(:set_encoding, Reline.encoding_system_needs.name, override: false)
 | 
						|
      super
 | 
						|
 | 
						|
      @line_no = 0
 | 
						|
      @line = []
 | 
						|
      @eof = false
 | 
						|
 | 
						|
      @stdin = ::IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
 | 
						|
      @stdout = ::IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
 | 
						|
 | 
						|
      if Reline.respond_to?("basic_word_break_characters=")
 | 
						|
        Reline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS
 | 
						|
      end
 | 
						|
      Reline.completion_append_character = nil
 | 
						|
      Reline.completer_quote_characters = ''
 | 
						|
      Reline.completion_proc = IRB::InputCompletor::CompletionProc
 | 
						|
      Reline.output_modifier_proc =
 | 
						|
        if IRB.conf[:USE_COLORIZE]
 | 
						|
          proc do |output, complete: |
 | 
						|
            next unless IRB::Color.colorable?
 | 
						|
            IRB::Color.colorize_code(output, complete: complete)
 | 
						|
          end
 | 
						|
        else
 | 
						|
          proc do |output|
 | 
						|
            Reline::Unicode.escape_for_print(output)
 | 
						|
          end
 | 
						|
        end
 | 
						|
      Reline.dig_perfect_match_proc = IRB::InputCompletor::PerfectMatchedProc
 | 
						|
      Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE]
 | 
						|
      if IRB.conf[:USE_AUTOCOMPLETE]
 | 
						|
        Reline.add_dialog_proc(:show_doc, SHOW_DOC_DIALOG, Reline::DEFAULT_DIALOG_CONTEXT)
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    def check_termination(&block)
 | 
						|
      @check_termination_proc = block
 | 
						|
    end
 | 
						|
 | 
						|
    def dynamic_prompt(&block)
 | 
						|
      @prompt_proc = block
 | 
						|
    end
 | 
						|
 | 
						|
    def auto_indent(&block)
 | 
						|
      @auto_indent_proc = block
 | 
						|
    end
 | 
						|
 | 
						|
    SHOW_DOC_DIALOG = ->() {
 | 
						|
      dialog.trap_key = nil
 | 
						|
      alt_d = [
 | 
						|
        [Reline::Key.new(nil, 0xE4, true)], # Normal Alt+d.
 | 
						|
        [195, 164] # The "ä" that appears when Alt+d is pressed on xterm.
 | 
						|
      ]
 | 
						|
 | 
						|
      if just_cursor_moving and completion_journey_data.nil?
 | 
						|
        return nil
 | 
						|
      end
 | 
						|
      cursor_pos_to_render, result, pointer, autocomplete_dialog = context.pop(4)
 | 
						|
      return nil if result.nil? or pointer.nil? or pointer < 0
 | 
						|
      name = result[pointer]
 | 
						|
      name = IRB::InputCompletor.retrieve_completion_data(name, doc_namespace: true)
 | 
						|
 | 
						|
      driver = RDoc::RI::Driver.new
 | 
						|
 | 
						|
      if key.match?(dialog.name)
 | 
						|
        begin
 | 
						|
          driver.display_names([name])
 | 
						|
        rescue RDoc::RI::Driver::NotFoundError
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      begin
 | 
						|
        name = driver.expand_name(name)
 | 
						|
      rescue RDoc::RI::Driver::NotFoundError
 | 
						|
        return nil
 | 
						|
      rescue
 | 
						|
        return nil # unknown error
 | 
						|
      end
 | 
						|
      doc = nil
 | 
						|
      used_for_class = false
 | 
						|
      if not name =~ /#|\./
 | 
						|
        found, klasses, includes, extends = driver.classes_and_includes_and_extends_for(name)
 | 
						|
        if not found.empty?
 | 
						|
          doc = driver.class_document(name, found, klasses, includes, extends)
 | 
						|
          used_for_class = true
 | 
						|
        end
 | 
						|
      end
 | 
						|
      unless used_for_class
 | 
						|
        doc = RDoc::Markup::Document.new
 | 
						|
        begin
 | 
						|
          driver.add_method(doc, name)
 | 
						|
        rescue RDoc::RI::Driver::NotFoundError
 | 
						|
          doc = nil
 | 
						|
        rescue
 | 
						|
          return nil # unknown error
 | 
						|
        end
 | 
						|
      end
 | 
						|
      return nil if doc.nil?
 | 
						|
      width = 40
 | 
						|
      formatter = RDoc::Markup::ToAnsi.new
 | 
						|
      formatter.width = width
 | 
						|
      dialog.trap_key = alt_d
 | 
						|
      message = 'Press Alt+d to read the full document'
 | 
						|
      contents = [message] + doc.accept(formatter).split("\n")
 | 
						|
 | 
						|
      x = cursor_pos_to_render.x + autocomplete_dialog.width
 | 
						|
      x = autocomplete_dialog.column - width if x + width >= screen_width
 | 
						|
      y = cursor_pos_to_render.y
 | 
						|
      DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: '49')
 | 
						|
    }
 | 
						|
 | 
						|
    # Reads the next line from this input method.
 | 
						|
    #
 | 
						|
    # See IO#gets for more information.
 | 
						|
    def gets
 | 
						|
      Reline.input = @stdin
 | 
						|
      Reline.output = @stdout
 | 
						|
      Reline.prompt_proc = @prompt_proc
 | 
						|
      Reline.auto_indent_proc = @auto_indent_proc if @auto_indent_proc
 | 
						|
      if l = readmultiline(@prompt, false, &@check_termination_proc)
 | 
						|
        HISTORY.push(l) if !l.empty?
 | 
						|
        @line[@line_no += 1] = l + "\n"
 | 
						|
      else
 | 
						|
        @eof = true
 | 
						|
        l
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    # Whether the end of this input method has been reached, returns +true+
 | 
						|
    # if there is no more data to read.
 | 
						|
    #
 | 
						|
    # See IO#eof? for more information.
 | 
						|
    def eof?
 | 
						|
      @eof
 | 
						|
    end
 | 
						|
 | 
						|
    # Whether this input method is still readable when there is no more data to
 | 
						|
    # read.
 | 
						|
    #
 | 
						|
    # See IO#eof for more information.
 | 
						|
    def readable_after_eof?
 | 
						|
      true
 | 
						|
    end
 | 
						|
 | 
						|
    # Returns the current line number for #io.
 | 
						|
    #
 | 
						|
    # #line counts the number of times #gets is called.
 | 
						|
    #
 | 
						|
    # See IO#lineno for more information.
 | 
						|
    def line(line_no)
 | 
						|
      @line[line_no]
 | 
						|
    end
 | 
						|
 | 
						|
    # The external encoding for standard input.
 | 
						|
    def encoding
 | 
						|
      @stdin.external_encoding
 | 
						|
    end
 | 
						|
 | 
						|
    # For debug message
 | 
						|
    def inspect
 | 
						|
      config = Reline::Config.new
 | 
						|
      str = "ReidlineInputMethod with Reline #{Reline::VERSION}"
 | 
						|
      if config.respond_to?(:inputrc_path)
 | 
						|
        inputrc_path = File.expand_path(config.inputrc_path)
 | 
						|
      else
 | 
						|
        inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc')
 | 
						|
      end
 | 
						|
      str += " and #{inputrc_path}" if File.exist?(inputrc_path)
 | 
						|
      str
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |