class RubyLex
def configure_io(io)
def configure_io(io) @io = io if @io.respond_to?(:check_termination) @io.check_termination do |code| if Reline::IOGate.in_pasting? rest = check_termination_in_prev_line(code) if rest Reline.delete_text rest.bytes.reverse_each do |c| Reline.ungetc(c) end true else false end else # Accept any single-line input for symbol aliases or commands that transform args next true if single_line_command?(code) _tokens, _opens, terminated = check_code_state(code) terminated end end end if @io.respond_to?(:dynamic_prompt) @io.dynamic_prompt do |lines| lines << '' if lines.empty? tokens = self.class.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, context: @context) line_results = IRB::NestingParser.parse_by_line(tokens) tokens_until_line = [] line_results.map.with_index do |(line_tokens, _prev_opens, next_opens, _min_depth), line_num_offset| line_tokens.each do |token, _s| # Avoid appending duplicated token. Tokens that include "\n" like multiline tstring_content can exist in multiple lines. tokens_until_line << token if token != tokens_until_line.last end continue = should_continue?(tokens_until_line) prompt(next_opens, continue, line_num_offset) end end end if @io.respond_to?(:auto_indent) and @context.auto_indent_mode @io.auto_indent do |lines, line_index, byte_pointer, is_newline| next nil if lines == [nil] # Workaround for exit IRB with CTRL+d next nil if !is_newline && lines[line_index]&.byteslice(0, byte_pointer)&.match?(/\A\s*\z/) code = lines[0..line_index].map { |l| "#{l}\n" }.join tokens = self.class.ripper_lex_without_warning(code, context: @context) process_indent_level(tokens, lines, line_index, is_newline) end end end