# class IRB::RelineInputMethod

### Constants

HISTORY

### Public Class Methods

new(completor) click to toggle source

Creates a new input method object using `Reline`

Calls superclass method `IRB::StdioInputMethod::new`

    # File lib/irb/input-method.rb, line 250
    def initialize(completor)
      IRB.__send__(:set_encoding, Reline.encoding_system_needs.name, override: false)

      super()

      @eof = false
      @completor = completor

      Reline.basic_word_break_characters = BASIC_WORD_BREAK_CHARACTERS
      Reline.completion_append_character = nil
      Reline.completer_quote_characters = ''
      Reline.completion_proc = ->(target, preposing, postposing) {
        bind = IRB.conf[:MAIN_CONTEXT].workspace.binding
        @completion_params = [preposing, target, postposing, bind]
        @completor.completion_candidates(preposing, target, postposing, bind: bind)
      }
      Reline.output_modifier_proc =
        if IRB.conf[:USE_COLORIZE]
          proc do |output, complete: |
            next unless IRB::Color.colorable?
            lvars = IRB.CurrentContext&.local_variables || []
            IRB::Color.colorize_code(output, complete: complete, local_variables: lvars)
          end
        else
          proc do |output|
            Reline::Unicode.escape_for_print(output)
          end
        end
      Reline.dig_perfect_match_proc = ->(matched) { display_document(matched) }
      Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE]

      if IRB.conf[:USE_AUTOCOMPLETE]
        begin
          require 'rdoc'
          Reline.add_dialog_proc(:show_doc, show_doc_dialog_proc, Reline::DEFAULT_DIALOG_CONTEXT)
        rescue LoadError
        end
      end
    end

### Public Instance Methods

auto_indent(&block) click to toggle source

    # File lib/irb/input-method.rb, line 303
    def auto_indent(&block)
      @auto_indent_proc = block
    end

check_termination(&block) click to toggle source

    # File lib/irb/input-method.rb, line 295
    def check_termination(&block)
      @check_termination_proc = block
    end

completion_info() click to toggle source

    # File lib/irb/input-method.rb, line 290
    def completion_info
      autocomplete_message = Reline.autocompletion ? 'Autocomplete' : 'Tab Complete'
      "#{autocomplete_message}, #{@completor.inspect}"
    end

display_document(matched) click to toggle source

    # File lib/irb/input-method.rb, line 437
    def display_document(matched)
      driver = rdoc_ri_driver
      return unless driver

      if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
        IRB.__send__(:easter_egg)
        return
      end

      namespace = retrieve_doc_namespace(matched)
      return unless namespace

      if namespace.is_a?(Array)
        out = RDoc::Markup::Document.new
        namespace.each do |m|
          begin
            driver.add_method(out, m)
          rescue RDoc::RI::Driver::NotFoundError
          end
        end
        driver.display(out)
      else
        begin
          driver.display_names([namespace])
        rescue RDoc::RI::Driver::NotFoundError
        end
      end
    end

dynamic_prompt(&block) click to toggle source

    # File lib/irb/input-method.rb, line 299
    def dynamic_prompt(&block)
      @prompt_proc = block
    end

eof?() click to toggle source

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.

    # File lib/irb/input-method.rb, line 487
    def eof?
      @eof
    end

gets() click to toggle source

Reads the next line from this input method.

See `IO#gets` for more information.

    # File lib/irb/input-method.rb, line 469
    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 = Reline.readmultiline(@prompt, false, &@check_termination_proc)
        Reline::HISTORY.push(l) if !l.empty?
        @line[@line_no += 1] = l + "\n"
      else
        @eof = true
        l
      end
    end

inspect() click to toggle source

For debug message

    # File lib/irb/input-method.rb, line 496
    def inspect
      config = Reline::Config.new
      str = "RelineInputMethod with Reline #{Reline::VERSION}"
      inputrc_path = File.expand_path(config.inputrc_path)
      str += " and #{inputrc_path}" if File.exist?(inputrc_path)
      str
    end

prompting?() click to toggle source

    # File lib/irb/input-method.rb, line 491
    def prompting?
      true
    end

rdoc_ri_driver() click to toggle source

    # File lib/irb/input-method.rb, line 312
    def rdoc_ri_driver
      return @rdoc_ri_driver if defined?(@rdoc_ri_driver)

      begin
        require 'rdoc'
      rescue LoadError
        @rdoc_ri_driver = nil
      else
        options = {}
        options[:extra_doc_dirs] = IRB.conf[:EXTRA_DOC_DIRS] unless IRB.conf[:EXTRA_DOC_DIRS].empty?
        @rdoc_ri_driver = RDoc::RI::Driver.new(options)
      end
    end

retrieve_doc_namespace(matched) click to toggle source

    # File lib/irb/input-method.rb, line 307
    def retrieve_doc_namespace(matched)
      preposing, _target, postposing, bind = @completion_params
      @completor.doc_namespace(preposing, matched, postposing, bind: bind)
    end

show_doc_dialog_proc() click to toggle source

    # File lib/irb/input-method.rb, line 326
    def show_doc_dialog_proc
      input_method = self # self is changed in the lambda below.
      ->() {
        dialog.trap_key = nil
        alt_d = [
          [Reline::Key.new(nil, 0xE4, true)], # Normal Alt+d.
          [27, 100], # Normal Alt+d when convert-meta isn't used.
          [195, 164], # The "ä" that appears when Alt+d is pressed on xterm.
          [226, 136, 130] # The "∂" that appears when Alt+d in pressed on iTerm2.
        ]

        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 = input_method.retrieve_doc_namespace(result[pointer])
        # Use first one because document dialog does not support multiple namespaces.
        name = name.first if name.is_a?(Array)

        show_easter_egg = name&.match?(/\ARubyVM/) && !ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']

        driver = input_method.rdoc_ri_driver

        if key.match?(dialog.name)
          if show_easter_egg
            IRB.__send__(:easter_egg)
          else
            begin
              driver.display_names([name])
            rescue RDoc::RI::Driver::NotFoundError
            end
          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

        right_x = cursor_pos_to_render.x + autocomplete_dialog.width
        if right_x + width > screen_width
          right_width = screen_width - (right_x + 1)
          left_x = autocomplete_dialog.column - width
          left_x = 0 if left_x < 0
          left_width = width > autocomplete_dialog.column ? autocomplete_dialog.column : width
          if right_width.positive? and left_width.positive?
            if right_width >= left_width
              width = right_width
              x = right_x
            else
              width = left_width
              x = left_x
            end
          elsif right_width.positive? and left_width <= 0
            width = right_width
            x = right_x
          elsif right_width <= 0 and left_width.positive?
            width = left_width
            x = left_x
          else # Both are negative width.
            return nil
          end
        else
          x = right_x
        end
        formatter = RDoc::Markup::ToAnsi.new
        formatter.width = width
        dialog.trap_key = alt_d
        mod_key = RUBY_PLATFORM.match?(/darwin/) ? "Option" : "Alt"
        if show_easter_egg
          type = STDOUT.external_encoding == Encoding::UTF_8 ? :unicode : :ascii
          contents = IRB.send(:easter_egg_logo, type).split("\n")
          message = "Press #{mod_key}+d to see more"
          contents[0][0, message.size] = message
        else
          message = "Press #{mod_key}+d to read the full document"
          contents = [message] + doc.accept(formatter).split("\n")
        end
        contents = contents.take(preferred_dialog_height)

        y = cursor_pos_to_render.y
        Reline::DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: '49')
      }
    end