<commit_before>require 'irb'
require 'irb/frame'
require 'stringio'
require 'active_support/core_ext/module/delegation'


module WebConsole
  module REPL
    # == IRB\ Adapter
    #
    # Adapter for the IRB REPL, which is the default Ruby on Rails console.
    class IRB
      # Monkey patch the reference Irb class to use it's specified output
      # method during printing.
      class ::IRB::Irb
        def print(*args)
          @context.instance_variable_get(:@output_method).print(*args)
        end

        def printf(str, *args)
          @context.instance_variable_get(:@output_method).print(str % args)
        end
      end

      class StringIOInputMethod < ::IRB::InputMethod
        def initialize(io)
          @io = io
        end

        delegate :eof?, :gets, to: :@io, allow_nil: true

        def encoding
          @io.external_encoding
        end
      end

      class StringIOOutputMethod < ::IRB::OutputMethod
        def initialize(io)
          @io = io
        end

        def print(*args)
          @io.write(*args)
        end
      end

      def initialize(binding = ::IRB::Frame.top(1))
        initialize_irb_session!
        input  = StringIOInputMethod.new(@input = StringIO.new)
        output = StringIOOutputMethod.new(@output = StringIO.new)
        @irb   = ::IRB::Irb.new(::IRB::WorkSpace.new(binding), input, output)
        finalize_irb_session!
      end

      def prompt
        ::IRB.conf[:PROMPT][::IRB.conf[:PROMPT_MODE]][:RETURN]
      end

      def send_input(input)
        replace_input!(input)
        @irb.eval_input
        extract_output!
      end

      private
        def initialize_irb_session!(ap_path = nil)
          ::IRB.init_config(ap_path)
        end

        def finalize_irb_session!
          ::IRB.conf[:MAIN_CONTEXT] = @irb.context
          # Require it after the setting of :MAIN_CONTEXT, as there is code
          # relying on it that is executed during require time.
          require 'irb/ext/multi-irb'
        end

        def replace_input!(input)
          # The rewinds are important here. StringIO#truncate will nullify the
          # underlying string, but won't change the current position. Therefore,
          # the next write may be preceeded by leading +\u0000+ characters.
          @input.truncate(0)
          @input.rewind
          @input.write(input)
          @input.rewind
        end

        def extract_output!
          @output.rewind
          @output.read.lstrip.tap do
            @output.truncate(0)
            @output.rewind
          end
        end
    end

    register_adapter IRB
  end<commit_msg>Explain some hacks a bit better<commit_after>require 'irb'
require 'irb/frame'
require 'stringio'
require 'active_support/core_ext/module/delegation'

module WebConsole
  module REPL
    # == IRB\ Adapter
    #
    # Adapter for the IRB REPL, which is the default Ruby on Rails console.
    class IRB
      # Monkey patch the reference Irb class so that the unqualified prints go
      # to the context's output method.
      class ::IRB::Irb
        def print(*args)
          @context.instance_variable_get(:@output_method).print(*args)
        end

        def printf(str, *args)
          @context.instance_variable_get(:@output_method).print(str % args)
        end
      end

      class StringIOInputMethod < ::IRB::InputMethod
        def initialize(io)
          @io = io
        end

        delegate :eof?, :gets, to: :@io, allow_nil: true

        def encoding
          @io.external_encoding
        end
      end

      class StringIOOutputMethod < ::IRB::OutputMethod
        def initialize(io)
          @io = io
        end

        def print(*args)
          @io.write(*args)
        end
      end

      def initialize(binding = ::IRB::Frame.top(1))
        initialize_irb_session!
        input  = StringIOInputMethod.new(@input = StringIO.new)
        output = StringIOOutputMethod.new(@output = StringIO.new)
        @irb   = ::IRB::Irb.new(::IRB::WorkSpace.new(binding), input, output)
        finalize_irb_session!
      end

      def prompt
        ::IRB.conf[:PROMPT][::IRB.conf[:PROMPT_MODE]][:RETURN]
      end

      def send_input(input)
        replace_input!(input)
        @irb.eval_input
        extract_output!
      end

      private
        def initialize_irb_session!(ap_path = nil)
          ::IRB.init_config(ap_path)
        end

        def finalize_irb_session!
          ::IRB.conf[:MAIN_CONTEXT] = @irb.context
          # Require it after the setting of :MAIN_CONTEXT, as there is code
          # relying on existing :MAIN_CONTEXT that is executed in require time.
          require 'irb/ext/multi-irb'
        end

        def replace_input!(input)
          # The rewinds are important here. StringIO#truncate will nullify the
          # underlying string, but won't change the current position. Therefore,
          # the next write may be preceeded by leading +\u0000+ characters.
          @input.truncate(0)
          @input.rewind
          @input.write(input)
          @input.rewind
        end

        def extract_output!
          @output.rewind
          @output.read.lstrip.tap do
            @output.truncate(0)
            @output.rewind
          end
        end
    end

    register_adapter IRB
  end
{'fraction_non_alphanumeric': 0.08900226757369614, 'fraction_numerical': 0.0026455026455026454, 'mean_word_length': 2.012521343198634, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1047310', 'n_tokens_mistral': 1600, 'n_tokens_neox': 1554, 'n_words': 400}