# class Reline::LineEditor

### Constants

CompletionJourneyData
DIALOG_DEFAULT_HEIGHT
MenuInfo
PROMPT_LIST_CACHE_TIMEOUT
VI_MOTIONS

### Attributes

auto_indent_proc[RW]
byte_pointer[R]
completion_append_character[RW]
completion_proc[RW]
confirm_multiline_termination_proc[RW]
dig_perfect_match_proc[RW]
line[R]

TODO: undo TODO: Use “private alias_method” idiom after drop Ruby 2.5.

output[W]
output_modifier_proc[RW]
pre_input_hook[RW]
prompt_proc[RW]

### Public Class Methods

new(config, encoding) click to toggle source

    # File lib/reline/line_editor.rb, line 56
    def initialize(config, encoding)
      @config = config
      @completion_append_character = ''
      reset_variables(encoding: encoding)
    end

### Public Instance Methods

add_dialog_proc(name, p, context = nil) click to toggle source

    # File lib/reline/line_editor.rb, line 641
    def add_dialog_proc(name, p, context = nil)
      dialog = Dialog.new(name, @config, DialogProcScope.new(self, @config, p, context))
      if index = @dialogs.find_index { |d| d.name == name }
        @dialogs[index] = dialog
      else
        @dialogs << dialog
      end
    end

backward_char(key, arg: 1)
Alias for: ed_prev_char
backward_delete_char(key, arg: 1)
Alias for: em_delete_prev_char
backward_word(key)
Alias for: ed_prev_word
beginning_of_line(key)
Alias for: ed_move_to_beg
byte_pointer=(val) click to toggle source

    # File lib/reline/line_editor.rb, line 1903
    def byte_pointer=(val)
      @byte_pointer = val
      str = @line.byteslice(0, @byte_pointer)
      @cursor = calculate_width(str)
      @cursor_max = calculate_width(@line)
    end

call_completion_proc() click to toggle source

    # File lib/reline/line_editor.rb, line 1667
    def call_completion_proc
      result = retrieve_completion_block(true)
      pre, target, post = result
      result = call_completion_proc_with_checking_args(pre, target, post)
      Reline.core.instance_variable_set(:@completion_quote_character, nil)
      result
    end

call_completion_proc_with_checking_args(pre, target, post) click to toggle source

    # File lib/reline/line_editor.rb, line 1675
    def call_completion_proc_with_checking_args(pre, target, post)
      if @completion_proc and target
        argnum = @completion_proc.parameters.inject(0) { |result, item|
          case item.first
          when :req, :opt
            result + 1
          when :rest
            break 3
          end
        }
        case argnum
        when 1
          result = @completion_proc.(target)
        when 2
          result = @completion_proc.(target, pre)
        when 3..Float::INFINITY
          result = @completion_proc.(target, pre, post)
        end
      end
      result
    end

capitalize_word(key)
Alias for: em_capitol_case
clear_screen(key)
Alias for: ed_clear_screen
confirm_multiline_termination() click to toggle source

    # File lib/reline/line_editor.rb, line 1821
    def confirm_multiline_termination
      temp_buffer = @buffer_of_lines.dup
      if @previous_line_index and @line_index == (@buffer_of_lines.size - 1)
        temp_buffer[@previous_line_index] = @line
      else
        temp_buffer[@line_index] = @line
      end
      @confirm_multiline_termination_proc.(temp_buffer.join("\n") + "\n")
    end

delete_char(key)
Alias for: em_delete
delete_char_or_list(key)
Alias for: em_delete_or_list
delete_text(start = nil, length = nil) click to toggle source

    # File lib/reline/line_editor.rb, line 1843
    def delete_text(start = nil, length = nil)
      if start.nil? and length.nil?
        if @is_multiline
          if @buffer_of_lines.size == 1
            @line&.clear
            @byte_pointer = 0
            @cursor = 0
            @cursor_max = 0
          elsif @line_index == (@buffer_of_lines.size - 1) and @line_index > 0
            @buffer_of_lines.pop
            @line_index -= 1
            @line = @buffer_of_lines[@line_index]
            @byte_pointer = 0
            @cursor = 0
            @cursor_max = calculate_width(@line)
          elsif @line_index < (@buffer_of_lines.size - 1)
            @buffer_of_lines.delete_at(@line_index)
            @line = @buffer_of_lines[@line_index]
            @byte_pointer = 0
            @cursor = 0
            @cursor_max = calculate_width(@line)
          end
        else
          @line&.clear
          @byte_pointer = 0
          @cursor = 0
          @cursor_max = 0
        end
      elsif not start.nil? and not length.nil?
        if @line
          before = @line.byteslice(0, start)
          after = @line.byteslice(start + length, @line.bytesize)
          @line = before + after
          @byte_pointer = @line.bytesize if @byte_pointer > @line.bytesize
          str = @line.byteslice(0, @byte_pointer)
          @cursor = calculate_width(str)
          @cursor_max = calculate_width(@line)
        end
      elsif start.is_a?(Range)
        range = start
        first = range.first
        last = range.last
        last = @line.bytesize - 1 if last > @line.bytesize
        last += @line.bytesize if last < 0
        first += @line.bytesize if first < 0
        range = range.exclude_end? ? first...last : first..last
        @line = @line.bytes.reject.with_index{ |c, i| range.include?(i) }.map{ |c| c.chr(Encoding::ASCII_8BIT) }.join.force_encoding(@encoding)
        @byte_pointer = @line.bytesize if @byte_pointer > @line.bytesize
        str = @line.byteslice(0, @byte_pointer)
        @cursor = calculate_width(str)
        @cursor_max = calculate_width(@line)
      else
        @line = @line.byteslice(0, start)
        @byte_pointer = @line.bytesize if @byte_pointer > @line.bytesize
        str = @line.byteslice(0, @byte_pointer)
        @cursor = calculate_width(str)
        @cursor_max = calculate_width(@line)
      end
    end

downcase_word(key)
Alias for: em_lower_case
ed_digit(key)
Alias for: ed_insert
editing_mode() click to toggle source

    # File lib/reline/line_editor.rb, line 1285
    def editing_mode
      @config.editing_mode
    end

end_of_line(key)
Alias for: ed_move_to_end
eof?() click to toggle source

    # File lib/reline/line_editor.rb, line 258
    def eof?
      @eof
    end

exchange_point_and_mark(key)
Alias for: em_exchange_mark
finalize() click to toggle source

    # File lib/reline/line_editor.rb, line 250
    def finalize
      Signal.trap('INT', @old_trap)
      begin
        Signal.trap('TSTP', @old_tstp_trap)
      rescue ArgumentError
      end
    end

finish() click to toggle source

    # File lib/reline/line_editor.rb, line 1932
    def finish
      @finished = true
      @rerender_all = true
      @config.reset
    end

finished?() click to toggle source

    # File lib/reline/line_editor.rb, line 1928
    def finished?
      @finished
    end

forward_char(key, arg: 1)
Alias for: ed_next_char
forward_search_history(key)
Alias for: vi_search_next
forward_word(key)
Alias for: em_next_word
history_search_backward(key, arg: 1)
Alias for: ed_search_prev_history
history_search_forward(key, arg: 1)
Alias for: ed_search_next_history
input_key(key) click to toggle source

    # File lib/reline/line_editor.rb, line 1592
    def input_key(key)
      @last_key = key
      @config.reset_oneshot_key_bindings
      @dialogs.each do |dialog|
        if key.char.instance_of?(Symbol) and key.char == dialog.name
          return
        end
      end
      @just_cursor_moving = nil
      if key.char.nil?
        if @first_char
          @line = nil
        end
        finish
        return
      end
      old_line = @line.dup
      @first_char = false
      completion_occurs = false
      if @config.editing_mode_is?(:emacs, :vi_insert) and key.char == "\C-i".ord
        unless @config.disable_completion
          result = call_completion_proc
          if result.is_a?(Array)
            completion_occurs = true
            process_insert
            if @config.autocompletion
              move_completed_list(result, :down)
            else
              complete(result)
            end
          end
        end
      elsif @config.editing_mode_is?(:emacs, :vi_insert) and key.char == :completion_journey_up
        if not @config.disable_completion and @config.autocompletion
          result = call_completion_proc
          if result.is_a?(Array)
            completion_occurs = true
            process_insert
            move_completed_list(result, :up)
          end
        end
      elsif not @config.disable_completion and @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char)
        unless @config.disable_completion
          result = call_completion_proc
          if result.is_a?(Array)
            completion_occurs = true
            process_insert
            move_completed_list(result, "\C-p".ord == key.char ? :up : :down)
          end
        end
      elsif Symbol === key.char and respond_to?(key.char, true)
        process_key(key.char, key.char)
      else
        normal_char(key)
      end
      unless completion_occurs
        @completion_state = CompletionState::NORMAL
        @completion_journey_data = nil
      end
      if not @in_pasting and @just_cursor_moving.nil?
        if @previous_line_index and @buffer_of_lines[@previous_line_index] == @line
          @just_cursor_moving = true
        elsif @previous_line_index.nil? and @buffer_of_lines[@line_index] == @line and old_line == @line
          @just_cursor_moving = true
        else
          @just_cursor_moving = false
        end
      else
        @just_cursor_moving = false
      end
      if @is_multiline and @auto_indent_proc and not simplified_rendering?
        process_auto_indent
      end
    end

insert_text(text) click to toggle source

    # File lib/reline/line_editor.rb, line 1831
    def insert_text(text)
      width = calculate_width(text)
      if @cursor == @cursor_max
        @line += text
      else
        @line = byteinsert(@line, @byte_pointer, text)
      end
      @byte_pointer += text.bytesize
      @cursor += width
      @cursor_max += width
    end

just_move_cursor() click to toggle source

    # File lib/reline/line_editor.rb, line 983
    def just_move_cursor
      prompt, prompt_width, prompt_list = check_multiline_prompt(@buffer_of_lines)
      move_cursor_up(@started_from)
      new_first_line_started_from =
        if @line_index.zero?
          0
        else
          calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
        end
      first_line_diff = new_first_line_started_from - @first_line_started_from
      new_cursor, new_cursor_max, new_started_from, new_byte_pointer = calculate_nearest_cursor(@buffer_of_lines[@line_index], @cursor, @started_from, @byte_pointer, false)
      new_started_from = calculate_height_by_width(prompt_width + new_cursor) - 1
      calculate_scroll_partial_screen(@highest_in_all, new_first_line_started_from + new_started_from)
      @previous_line_index = nil
      if @rerender_all
        @line = @buffer_of_lines[@line_index]
        rerender_all_lines
        @rerender_all = false
        true
      else
        @line = @buffer_of_lines[@line_index]
        @first_line_started_from = new_first_line_started_from
        @started_from = new_started_from
        @cursor = new_cursor
        @cursor_max = new_cursor_max
        @byte_pointer = new_byte_pointer
        move_cursor_down(first_line_diff + @started_from)
        Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
        false
      end
    end

kill_line(key)
Alias for: ed_kill_line
kill_whole_line(key)
Alias for: em_kill_line
multiline_off() click to toggle source

    # File lib/reline/line_editor.rb, line 323
    def multiline_off
      @is_multiline = false
    end

multiline_on() click to toggle source

    # File lib/reline/line_editor.rb, line 319
    def multiline_on
      @is_multiline = true
    end

next_history(key, arg: 1)
Alias for: ed_next_history
previous_history(key, arg: 1)
Alias for: ed_prev_history
quoted_insert(str, arg: 1)
Alias for: ed_quoted_insert
rerender() click to toggle source

    # File lib/reline/line_editor.rb, line 431
    def rerender
      return if @line.nil?
      if @menu_info
        scroll_down(@highest_in_all - @first_line_started_from)
        @rerender_all = true
      end
      if @menu_info
        show_menu
        @menu_info = nil
      end
      prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines)
      if @cleared
        clear_screen_buffer(prompt, prompt_list, prompt_width)
        @cleared = false
        return
      end
      if @is_multiline and finished? and @scroll_partial_screen
        # Re-output all code higher than the screen when finished.
        Reline::IOGate.move_cursor_up(@first_line_started_from + @started_from - @scroll_partial_screen)
        Reline::IOGate.move_cursor_column(0)
        @scroll_partial_screen = nil
        prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines)
        if @previous_line_index
          new_lines = whole_lines(index: @previous_line_index, line: @line)
        else
          new_lines = whole_lines
        end
        modify_lines(new_lines).each_with_index do |line, index|
          @output.write "#{prompt_list ? prompt_list[index] : prompt}#{line}\n"
          Reline::IOGate.erase_after_cursor
        end
        @output.flush
        clear_dialog
        return
      end
      new_highest_in_this = calculate_height_by_width(prompt_width + calculate_width(@line.nil? ? '' : @line))
      rendered = false
      if @add_newline_to_end_of_buffer
        clear_dialog_with_content
        rerender_added_newline(prompt, prompt_width)
        @add_newline_to_end_of_buffer = false
      else
        if @just_cursor_moving and not @rerender_all
          clear_dialog_with_content
          rendered = just_move_cursor
          @just_cursor_moving = false
          return
        elsif @previous_line_index or new_highest_in_this != @highest_in_this
          clear_dialog_with_content
          rerender_changed_current_line
          @previous_line_index = nil
          rendered = true
        elsif @rerender_all
          rerender_all_lines
          @rerender_all = false
          rendered = true
        else
        end
      end
      if @is_multiline
        if finished?
          # Always rerender on finish because output_modifier_proc may return a different output.
          if @previous_line_index
            new_lines = whole_lines(index: @previous_line_index, line: @line)
          else
            new_lines = whole_lines
          end
          line = modify_lines(new_lines)[@line_index]
          clear_dialog
          prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines)
          render_partial(prompt, prompt_width, line, @first_line_started_from)
          move_cursor_down(@highest_in_all - (@first_line_started_from + @highest_in_this - 1) - 1)
          scroll_down(1)
          Reline::IOGate.move_cursor_column(0)
          Reline::IOGate.erase_after_cursor
        else
          if not rendered and not @in_pasting
            line = modify_lines(whole_lines)[@line_index]
            prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines)
            render_partial(prompt, prompt_width, line, @first_line_started_from)
          end
          render_dialog((prompt_width + @cursor) % @screen_size.last)
        end
        @buffer_of_lines[@line_index] = @line
        @rest_height = 0 if @scroll_partial_screen
      else
        line = modify_lines(whole_lines)[@line_index]
        render_partial(prompt, prompt_width, line, 0)
        if finished?
          scroll_down(1)
          Reline::IOGate.move_cursor_column(0)
          Reline::IOGate.erase_after_cursor
        end
      end
    end

rerender_all() click to toggle source

    # File lib/reline/line_editor.rb, line 425
    def rerender_all
      @rerender_all = true
      process_insert(force: true)
      rerender
    end

reset(prompt = '', encoding:) click to toggle source

    # File lib/reline/line_editor.rb, line 149
    def reset(prompt = '', encoding:)
      @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
      @screen_size = Reline::IOGate.get_screen_size
      @screen_height = @screen_size.first
      reset_variables(prompt, encoding: encoding)
      Reline::IOGate.set_winch_handler do
        @resized = true
      end
      if ENV.key?('RELINE_ALT_SCROLLBAR')
        @full_block = '::'
        @upper_half_block = "''"
        @lower_half_block = '..'
        @block_elem_width = 2
      elsif Reline::IOGate.win?
        @full_block = '█'
        @upper_half_block = '▀'
        @lower_half_block = '▄'
        @block_elem_width = 1
      elsif @encoding == Encoding::UTF_8
        @full_block = '█'
        @upper_half_block = '▀'
        @lower_half_block = '▄'
        @block_elem_width = Reline::Unicode.calculate_width('█')
      else
        @full_block = '::'
        @upper_half_block = "''"
        @lower_half_block = '..'
        @block_elem_width = 2
      end
    end

reset_line() click to toggle source

    # File lib/reline/line_editor.rb, line 301
    def reset_line
      @cursor = 0
      @cursor_max = 0
      @byte_pointer = 0
      @buffer_of_lines = [String.new(encoding: @encoding)]
      @line_index = 0
      @previous_line_index = nil
      @line = @buffer_of_lines[0]
      @first_line_started_from = 0
      @move_up = 0
      @started_from = 0
      @highest_in_this = 1
      @highest_in_all = 1
      @line_backup_in_history = nil
      @multibyte_buffer = String.new(encoding: 'ASCII-8BIT')
      @check_new_auto_indent = false
    end

reset_variables(prompt = '', encoding:) click to toggle source

    # File lib/reline/line_editor.rb, line 262
    def reset_variables(prompt = '', encoding:)
      @prompt = prompt.gsub("\n", "\\n")
      @mark_pointer = nil
      @encoding = encoding
      @is_multiline = false
      @finished = false
      @cleared = false
      @rerender_all = false
      @history_pointer = nil
      @kill_ring ||= Reline::KillRing.new
      @vi_clipboard = ''
      @vi_arg = nil
      @waiting_proc = nil
      @waiting_operator_proc = nil
      @waiting_operator_vi_arg = nil
      @completion_journey_data = nil
      @completion_state = CompletionState::NORMAL
      @perfect_matched = nil
      @menu_info = nil
      @first_prompt = true
      @searching_prompt = nil
      @first_char = true
      @add_newline_to_end_of_buffer = false
      @just_cursor_moving = nil
      @cached_prompt_list = nil
      @prompt_cache_time = nil
      @eof = false
      @continuous_insertion_buffer = String.new(encoding: @encoding)
      @scroll_partial_screen = nil
      @prev_mode_string = nil
      @drop_terminate_spaces = false
      @in_pasting = false
      @auto_indent_proc = nil
      @dialogs = []
      @last_key = nil
      @resized = false
      reset_line
    end

resize() click to toggle source

    # File lib/reline/line_editor.rb, line 180
    def resize
      return unless @resized
      @resized = false
      @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
      old_screen_size = @screen_size
      @screen_size = Reline::IOGate.get_screen_size
      @screen_height = @screen_size.first
      if old_screen_size.last < @screen_size.last # columns increase
        @rerender_all = true
        rerender
      else
        back = 0
        new_buffer = whole_lines
        prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer)
        new_buffer.each_with_index do |line, index|
          prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc
          width = prompt_width + calculate_width(line)
          height = calculate_height_by_width(width)
          back += height
        end
        @highest_in_all = back
        @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
        @first_line_started_from =
          if @line_index.zero?
            0
          else
            calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
          end
        if @prompt_proc
          prompt = prompt_list[@line_index]
          prompt_width = calculate_width(prompt, true)
        end
        calculate_nearest_cursor
        @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
        Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
        @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
        @rerender_all = true
      end
    end

retrieve_completion_block(set_completion_quote_character = false) click to toggle source

    # File lib/reline/line_editor.rb, line 1739
    def retrieve_completion_block(set_completion_quote_character = false)
      if Reline.completer_word_break_characters.empty?
        word_break_regexp = nil
      else
        word_break_regexp = /\A[#{Regexp.escape(Reline.completer_word_break_characters)}]/
      end
      if Reline.completer_quote_characters.empty?
        quote_characters_regexp = nil
      else
        quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/
      end
      before = @line.byteslice(0, @byte_pointer)
      rest = nil
      break_pointer = nil
      quote = nil
      closing_quote = nil
      escaped_quote = nil
      i = 0
      while i < @byte_pointer do
        slice = @line.byteslice(i, @byte_pointer - i)
        unless slice.valid_encoding?
          i += 1
          next
        end
        if quote and slice.start_with?(closing_quote)
          quote = nil
          i += 1
          rest = nil
        elsif quote and slice.start_with?(escaped_quote)
          # skip
          i += 2
        elsif quote_characters_regexp and slice =~ quote_characters_regexp # find new "
          rest = $'
          quote = $&
          closing_quote = /(?!\\)#{Regexp.escape(quote)}/
          escaped_quote = /\\#{Regexp.escape(quote)}/
          i += 1
          break_pointer = i - 1
        elsif word_break_regexp and not quote and slice =~ word_break_regexp
          rest = $'
          i += 1
          before = @line.byteslice(i, @byte_pointer - i)
          break_pointer = i
        else
          i += 1
        end
      end
      postposing = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer)
      if rest
        preposing = @line.byteslice(0, break_pointer)
        target = rest
        if set_completion_quote_character and quote
          Reline.core.instance_variable_set(:@completion_quote_character, quote)
          if postposing !~ /(?!\\)#{Regexp.escape(quote)}/ # closing quote
            insert_text(quote)
          end
        end
      else
        preposing = ''
        if break_pointer
          preposing = @line.byteslice(0, break_pointer)
        else
          preposing = ''
        end
        target = before
      end
      if @is_multiline
        if @previous_line_index
          lines = whole_lines(index: @previous_line_index, line: @line)
        else
          lines = whole_lines
        end
        if @line_index > 0
          preposing = lines[0..(@line_index - 1)].join("\n") + "\n" + preposing
        end
        if (lines.size - 1) > @line_index
          postposing = postposing + "\n" + lines[(@line_index + 1)..-1].join("\n")
        end
      end
      [preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)]
    end

reverse_search_history(key)
Alias for: vi_search_prev
self_insert(key)
Alias for: ed_insert
set_mark(key)
Alias for: em_set_mark
set_pasting_state(in_pasting) click to toggle source

    # File lib/reline/line_editor.rb, line 62
    def set_pasting_state(in_pasting)
      @in_pasting = in_pasting
    end

set_signal_handlers() click to toggle source

    # File lib/reline/line_editor.rb, line 220
    def set_signal_handlers
      @old_trap = Signal.trap('INT') {
        clear_dialog
        if @scroll_partial_screen
          move_cursor_down(@screen_height - (@line_index - @scroll_partial_screen) - 1)
        else
          move_cursor_down(@highest_in_all - @line_index - 1)
        end
        Reline::IOGate.move_cursor_column(0)
        scroll_down(1)
        case @old_trap
        when 'DEFAULT', 'SYSTEM_DEFAULT'
          raise Interrupt
        when 'IGNORE'
          # Do nothing
        when 'EXIT'
          exit
        else
          @old_trap.call if @old_trap.respond_to?(:call)
        end
      }
      begin
        @old_tstp_trap = Signal.trap('TSTP') {
          Reline::IOGate.ungetc("\C-z".ord)
          @old_tstp_trap.call if @old_tstp_trap.respond_to?(:call)
        }
      rescue ArgumentError
      end
    end

simplified_rendering?() click to toggle source

    # File lib/reline/line_editor.rb, line 66
    def simplified_rendering?
      if finished?
        false
      elsif @just_cursor_moving and not @rerender_all
        true
      else
        not @rerender_all and not finished? and @in_pasting
      end
    end

transpose_chars(key)
Alias for: ed_transpose_chars
transpose_words(key)
Alias for: ed_transpose_words
unix_line_discard(key)
Alias for: vi_kill_line_prev
unix_word_rubout(key)
Alias for: em_kill_region
upcase_word(key)
Alias for: em_upper_case
vi_end_of_transmission(key)
Alias for: vi_list_or_eof
vi_eof_maybe(key)
Alias for: vi_list_or_eof
vi_movement_mode(key)
Alias for: vi_command_mode
whole_buffer() click to toggle source

    # File lib/reline/line_editor.rb, line 1916
    def whole_buffer
      if @buffer_of_lines.size == 1 and @line.nil?
        nil
      else
        if @previous_line_index
          whole_lines(index: @previous_line_index, line: @line).join("\n")
        else
          whole_lines.join("\n")
        end
      end
    end

whole_lines(index: @line_index, line: @line) click to toggle source

    # File lib/reline/line_editor.rb, line 1910
    def whole_lines(index: @line_index, line: @line)
      temp_lines = @buffer_of_lines.dup
      temp_lines[index] = line
      temp_lines
    end

wrap_method_call(method_symbol, method_obj, key, with_operator = false) click to toggle source

    # File lib/reline/line_editor.rb, line 1477
    def wrap_method_call(method_symbol, method_obj, key, with_operator = false)
      if @config.editing_mode_is?(:emacs, :vi_insert) and @waiting_proc.nil? and @waiting_operator_proc.nil?
        not_insertion = method_symbol != :ed_insert
        process_insert(force: not_insertion)
      end
      if @vi_arg and argumentable?(method_obj)
        if with_operator and inclusive?(method_obj)
          method_obj.(key, arg: @vi_arg, inclusive: true)
        else
          method_obj.(key, arg: @vi_arg)
        end
      else
        if with_operator and inclusive?(method_obj)
          method_obj.(key, inclusive: true)
        else
          method_obj.(key)
        end
      end
    end

yank(key)
Alias for: em_yank
yank_pop(key)
Alias for: em_yank_pop

### Private Instance Methods

argumentable?(method_obj) click to toggle source

    # File lib/reline/line_editor.rb, line 1467
            def argumentable?(method_obj)
      method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :arg }
    end

byteinsert(str, byte_pointer, other) click to toggle source

    # File lib/reline/line_editor.rb, line 1944
            def byteinsert(str, byte_pointer, other)
      new_str = str.byteslice(0, byte_pointer)
      new_str << other
      new_str << str.byteslice(byte_pointer, str.bytesize)
      new_str
    end

byteslice!(str, byte_pointer, size) click to toggle source

    # File lib/reline/line_editor.rb, line 1938
            def byteslice!(str, byte_pointer, size)
      new_str = str.byteslice(0, byte_pointer)
      new_str << str.byteslice(byte_pointer + size, str.bytesize)
      [new_str, str.byteslice(byte_pointer, size)]
    end

calculate_height_by_lines(lines, prompt) click to toggle source

    # File lib/reline/line_editor.rb, line 327
            def calculate_height_by_lines(lines, prompt)
      result = 0
      prompt_list = prompt.is_a?(Array) ? prompt : nil
      lines.each_with_index { |line, i|
        prompt = prompt_list[i] if prompt_list and prompt_list[i]
        result += calculate_height_by_width(calculate_width(prompt, true) + calculate_width(line))
      }
      result
    end

calculate_height_by_width(width) click to toggle source

    # File lib/reline/line_editor.rb, line 345
            def calculate_height_by_width(width)
      width.div(@screen_size.last) + 1
    end

calculate_nearest_cursor(line_to_calc = @line, cursor = @cursor, started_from = @started_from, byte_pointer = @byte_pointer, update = true) click to toggle source

    # File lib/reline/line_editor.rb, line 383
            def calculate_nearest_cursor(line_to_calc = @line, cursor = @cursor, started_from = @started_from, byte_pointer = @byte_pointer, update = true)
      new_cursor_max = calculate_width(line_to_calc)
      new_cursor = 0
      new_byte_pointer = 0
      height = 1
      max_width = @screen_size.last
      if @config.editing_mode_is?(:vi_command)
        last_byte_size = Reline::Unicode.get_prev_mbchar_size(line_to_calc, line_to_calc.bytesize)
        if last_byte_size > 0
          last_mbchar = line_to_calc.byteslice(line_to_calc.bytesize - last_byte_size, last_byte_size)
          last_width = Reline::Unicode.get_mbchar_width(last_mbchar)
          end_of_line_cursor = new_cursor_max - last_width
        else
        end_of_line_cursor = new_cursor_max
        end
      else
      end_of_line_cursor = new_cursor_max
      end
      line_to_calc.grapheme_clusters.each do |gc|
        mbchar = gc.encode(Encoding::UTF_8)
        mbchar_width = Reline::Unicode.get_mbchar_width(mbchar)
        now = new_cursor + mbchar_width
        if now > end_of_line_cursor or now > cursor
          break
        end
        new_cursor += mbchar_width
        if new_cursor > max_width * height
          height += 1
        end
        new_byte_pointer += gc.bytesize
      end
      new_started_from = height - 1
      if update
        @cursor = new_cursor
        @cursor_max = new_cursor_max
        @started_from = new_started_from
        @byte_pointer = new_byte_pointer
      else
        [new_cursor, new_cursor_max, new_started_from, new_byte_pointer]
      end
    end

calculate_scroll_partial_screen(highest_in_all, cursor_y) click to toggle source

    # File lib/reline/line_editor.rb, line 934
            def calculate_scroll_partial_screen(highest_in_all, cursor_y)
      if @screen_height < highest_in_all
        old_scroll_partial_screen = @scroll_partial_screen
        if cursor_y == 0
          @scroll_partial_screen = 0
        elsif cursor_y == (highest_in_all - 1)
          @scroll_partial_screen = highest_in_all - @screen_height
        else
          if @scroll_partial_screen
            if cursor_y <= @scroll_partial_screen
              @scroll_partial_screen = cursor_y
            elsif (@scroll_partial_screen + @screen_height - 1) < cursor_y
              @scroll_partial_screen = cursor_y - (@screen_height - 1)
            end
          else
            if cursor_y > (@screen_height - 1)
              @scroll_partial_screen = cursor_y - (@screen_height - 1)
            else
              @scroll_partial_screen = 0
            end
          end
        end
        if @scroll_partial_screen != old_scroll_partial_screen
          @rerender_all = true
        end
      else
        if @scroll_partial_screen
          @rerender_all = true
        end
        @scroll_partial_screen = nil
      end
    end

calculate_width(str, allow_escape_code = false) click to toggle source

    # File lib/reline/line_editor.rb, line 1951
            def calculate_width(str, allow_escape_code = false)
      Reline::Unicode.calculate_width(str, allow_escape_code)
    end

check_mode_string() click to toggle source

    # File lib/reline/line_editor.rb, line 76
            def check_mode_string
      mode_string = nil
      if @config.show_mode_in_prompt
        if @config.editing_mode_is?(:vi_command)
          mode_string = @config.vi_cmd_mode_string
        elsif @config.editing_mode_is?(:vi_insert)
          mode_string = @config.vi_ins_mode_string
        elsif @config.editing_mode_is?(:emacs)
          mode_string = @config.emacs_mode_string
        else
          mode_string = '?'
        end
      end
      if mode_string != @prev_mode_string
        @rerender_all = true
      end
      @prev_mode_string = mode_string
      mode_string
    end

check_multiline_prompt(buffer) click to toggle source

    # File lib/reline/line_editor.rb, line 96
            def check_multiline_prompt(buffer)
      if @vi_arg
        prompt = "(arg: #{@vi_arg}) "
        @rerender_all = true
      elsif @searching_prompt
        prompt = @searching_prompt
        @rerender_all = true
      else
        prompt = @prompt
      end
      if simplified_rendering?
        mode_string = check_mode_string
        prompt = mode_string + prompt if mode_string
        return [prompt, calculate_width(prompt, true), [prompt] * buffer.size]
      end
      if @prompt_proc
        use_cached_prompt_list = false
        if @cached_prompt_list
          if @just_cursor_moving
            use_cached_prompt_list = true
          elsif Time.now.to_f < (@prompt_cache_time + PROMPT_LIST_CACHE_TIMEOUT) and buffer.size == @cached_prompt_list.size
            use_cached_prompt_list = true
          end
        end
        use_cached_prompt_list = false if @rerender_all
        if use_cached_prompt_list
          prompt_list = @cached_prompt_list
        else
          prompt_list = @cached_prompt_list = @prompt_proc.(buffer).map { |pr| pr.gsub("\n", "\\n") }
          @prompt_cache_time = Time.now.to_f
        end
        prompt_list.map!{ prompt } if @vi_arg or @searching_prompt
        prompt_list = [prompt] if prompt_list.empty?
        mode_string = check_mode_string
        prompt_list = prompt_list.map{ |pr| mode_string + pr } if mode_string
        prompt = prompt_list[@line_index]
        prompt = prompt_list[0] if prompt.nil?
        prompt = prompt_list.last if prompt.nil?
        if buffer.size > prompt_list.size
          (buffer.size - prompt_list.size).times do
            prompt_list << prompt_list.last
          end
        end
        prompt_width = calculate_width(prompt, true)
        [prompt, prompt_width, prompt_list]
      else
        mode_string = check_mode_string
        prompt = mode_string + prompt if mode_string
        prompt_width = calculate_width(prompt, true)
        [prompt, prompt_width, nil]
      end
    end

clear_dialog() click to toggle source

    # File lib/reline/line_editor.rb, line 882
            def clear_dialog
      @dialogs.each do |dialog|
        clear_each_dialog(dialog)
      end
    end

clear_dialog_with_content() click to toggle source

    # File lib/reline/line_editor.rb, line 888
            def clear_dialog_with_content
      @dialogs.each do |dialog|
        clear_each_dialog(dialog)
        dialog.contents = nil
        dialog.trap_key = nil
      end
    end

clear_each_dialog(dialog) click to toggle source

    # File lib/reline/line_editor.rb, line 896
            def clear_each_dialog(dialog)
      dialog.trap_key = nil
      return unless dialog.contents
      prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines])
      visual_lines = []
      visual_lines_under_dialog = []
      visual_start = nil
      dialog.lines_backup[:lines].each_with_index { |l, i|
        pr = prompt_list ? prompt_list[i] : prompt
        vl, _ = split_by_width(pr + l, @screen_size.last)
        vl.compact!
        if i == dialog.lines_backup[:line_index]
          visual_start = visual_lines.size + dialog.lines_backup[:started_from] + dialog.vertical_offset
        end
        visual_lines.concat(vl)
      }
      visual_lines_under_dialog = visual_lines[visual_start, dialog.contents.size]
      visual_lines_under_dialog = [] if visual_lines_under_dialog.nil?
      Reline::IOGate.hide_cursor
      move_cursor_down(dialog.vertical_offset)
      dialog_vertical_size = dialog.contents.size
      dialog_vertical_size.times do |i|
        if i < visual_lines_under_dialog.size
          Reline::IOGate.move_cursor_column(dialog.column)
          str = Reline::Unicode.take_range(visual_lines_under_dialog[i], dialog.column, dialog.width)
          str = padding_space_with_escape_sequences(str, dialog.width)
          @output.write "\e[0m#{str}\e[0m"
        else
          Reline::IOGate.move_cursor_column(dialog.column)
          @output.write "\e[0m#{' ' * dialog.width}\e[0m"
        end
        move_cursor_down(1) if i < (dialog_vertical_size - 1)
      end
      move_cursor_up(dialog_vertical_size - 1 + dialog.vertical_offset)
      Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
      Reline::IOGate.show_cursor
    end

clear_screen_buffer(prompt, prompt_list, prompt_width) click to toggle source

    # File lib/reline/line_editor.rb, line 1264
            def clear_screen_buffer(prompt, prompt_list, prompt_width)
      Reline::IOGate.clear_screen
      back = 0
      modify_lines(whole_lines).each_with_index do |line, index|
        if @prompt_proc
          pr = prompt_list[index]
          height = render_partial(pr, calculate_width(pr), line, back, with_control: false)
        else
          height = render_partial(prompt, prompt_width, line, back, with_control: false)
        end
        if index < (@buffer_of_lines.size - 1)
          move_cursor_down(1)
          back += height
        end
      end
      move_cursor_up(back)
      move_cursor_down(@first_line_started_from + @started_from)
      @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
      Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
    end

complete(list, just_show_list = false) click to toggle source

    # File lib/reline/line_editor.rb, line 1339
            def complete(list, just_show_list = false)
      case @completion_state
      when CompletionState::NORMAL, CompletionState::JOURNEY
        @completion_state = CompletionState::COMPLETION
      when CompletionState::PERFECT_MATCH
        @dig_perfect_match_proc&.(@perfect_matched)
      end
      if just_show_list
        is_menu = true
      elsif @completion_state == CompletionState::MENU
        is_menu = true
      elsif @completion_state == CompletionState::MENU_WITH_PERFECT_MATCH
        is_menu = true
      else
        is_menu = false
      end
      result = complete_internal_proc(list, is_menu)
      if @completion_state == CompletionState::MENU_WITH_PERFECT_MATCH
        @completion_state = CompletionState::PERFECT_MATCH
      end
      return if result.nil?
      target, preposing, completed, postposing = result
      return if completed.nil?
      if target <= completed and (@completion_state == CompletionState::COMPLETION)
        if list.include?(completed)
          if list.one?
            @completion_state = CompletionState::PERFECT_MATCH
          else
            @completion_state = CompletionState::MENU_WITH_PERFECT_MATCH
          end
          @perfect_matched = completed
        else
          @completion_state = CompletionState::MENU
        end
        if not just_show_list and target < completed
          @line = preposing + completed + completion_append_character.to_s + postposing
          line_to_pointer = preposing + completed + completion_append_character.to_s
          @cursor_max = calculate_width(@line)
          @cursor = calculate_width(line_to_pointer)
          @byte_pointer = line_to_pointer.bytesize
        end
      end
    end

complete_internal_proc(list, is_menu) click to toggle source

    # File lib/reline/line_editor.rb, line 1293
            def complete_internal_proc(list, is_menu)
      preposing, target, postposing = retrieve_completion_block
      list = list.select { |i|
        if i and not Encoding.compatible?(target.encoding, i.encoding)
          raise Encoding::CompatibilityError, "#{target.encoding.name} is not compatible with #{i.encoding.name}"
        end
        if @config.completion_ignore_case
          i&.downcase&.start_with?(target.downcase)
        else
          i&.start_with?(target)
        end
      }.uniq
      if is_menu
        menu(target, list)
        return nil
      end
      completed = list.inject { |memo, item|
        begin
          memo_mbchars = memo.unicode_normalize.grapheme_clusters
          item_mbchars = item.unicode_normalize.grapheme_clusters
        rescue Encoding::CompatibilityError
          memo_mbchars = memo.grapheme_clusters
          item_mbchars = item.grapheme_clusters
        end
        size = [memo_mbchars.size, item_mbchars.size].min
        result = ''
        size.times do |i|
          if @config.completion_ignore_case
            if memo_mbchars[i].casecmp?(item_mbchars[i])
              result << memo_mbchars[i]
            else
              break
            end
          else
            if memo_mbchars[i] == item_mbchars[i]
              result << memo_mbchars[i]
            else
              break
            end
          end
        end
        result
      }
      [target, preposing, completed, postposing]
    end

copy_for_vi(text) click to toggle source

    # File lib/reline/line_editor.rb, line 2864
            def copy_for_vi(text)
      if @config.editing_mode_is?(:vi_insert) or @config.editing_mode_is?(:vi_command)
        @vi_clipboard = text
      end
    end

ed_argument_digit(key) click to toggle source

    # File lib/reline/line_editor.rb, line 3163
            def ed_argument_digit(key)
      if @vi_arg.nil?
        if key.chr.to_i.zero?
          if key.anybits?(0b10000000)
            unescaped_key = key ^ 0b10000000
            unless unescaped_key.chr.to_i.zero?
              @vi_arg = unescaped_key.chr.to_i
            end
          end
        else
          @vi_arg = key.chr.to_i
        end
      else
        @vi_arg = @vi_arg * 10 + key.chr.to_i
      end
    end

ed_clear_screen(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2730
            def ed_clear_screen(key)
      @cleared = true
    end

Also aliased as: clear_screen
ed_delete_next_char(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 3075
            def ed_delete_next_char(key, arg: 1)
      byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
      unless @line.empty? || byte_size == 0
        @line, mbchar = byteslice!(@line, @byte_pointer, byte_size)
        copy_for_vi(mbchar)
        width = Reline::Unicode.get_mbchar_width(mbchar)
        @cursor_max -= width
        if @cursor > 0 and @cursor >= @cursor_max
          byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer)
          mbchar = @line.byteslice(@byte_pointer - byte_size, byte_size)
          width = Reline::Unicode.get_mbchar_width(mbchar)
          @byte_pointer -= byte_size
          @cursor -= width
        end
      end
      arg -= 1
      ed_delete_next_char(key, arg: arg) if arg > 0
    end

ed_delete_prev_char(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2993
            def ed_delete_prev_char(key, arg: 1)
      deleted = ''
      arg.times do
        if @cursor > 0
          byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer)
          @byte_pointer -= byte_size
          @line, mbchar = byteslice!(@line, @byte_pointer, byte_size)
          deleted.prepend(mbchar)
          width = Reline::Unicode.get_mbchar_width(mbchar)
          @cursor -= width
          @cursor_max -= width
        end
      end
      copy_for_vi(deleted)
    end

ed_delete_prev_word(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2762
            def ed_delete_prev_word(key)
      if @byte_pointer > 0
        byte_size, width = Reline::Unicode.em_backward_word(@line, @byte_pointer)
        @line, word = byteslice!(@line, @byte_pointer - byte_size, byte_size)
        @kill_ring.append(word, true)
        @byte_pointer -= byte_size
        @cursor -= width
        @cursor_max -= width
      end
    end

ed_insert(key) click to toggle source

Editline

  `ed-insert` (vi input: almost all; emacs: printable characters) In insert mode, insert the input character left of the cursor position. In replace mode, overwrite the character at the cursor and move the cursor to the right by one character position. Accept an argument to do this repeatedly. It is an error if the input character is the NUL character (`Ctrl-@`). Failure to enlarge the edit buffer also results in an error.

Editline

  `ed-digit` (emacs: 0 to 9) If in argument input mode, append the input digit to the argument being read. Otherwise, call `ed-insert`. It is an error if the input character is not a digit or if the existing argument is already greater than a million.

GNU `Readline`

  `self-insert` (a, b, A, 1, !, …) Insert yourself.

    # File lib/reline/line_editor.rb, line 2006
            def ed_insert(key)
      str = nil
      width = nil
      bytesize = nil
      if key.instance_of?(String)
        begin
          key.encode(Encoding::UTF_8)
        rescue Encoding::UndefinedConversionError
          return
        end
        str = key
        bytesize = key.bytesize
      else
        begin
          key.chr.encode(Encoding::UTF_8)
        rescue Encoding::UndefinedConversionError
          return
        end
        str = key.chr
        bytesize = 1
      end
      if @in_pasting
        @continuous_insertion_buffer << str
        return
      elsif not @continuous_insertion_buffer.empty?
        process_insert
      end
      width = Reline::Unicode.get_mbchar_width(str)
      if @cursor == @cursor_max
        @line += str
      else
        @line = byteinsert(@line, @byte_pointer, str)
      end
      last_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer)
      @byte_pointer += bytesize
      last_mbchar = @line.byteslice((@byte_pointer - bytesize - last_byte_size), last_byte_size)
      combined_char = last_mbchar + str
      if last_byte_size != 0 and combined_char.grapheme_clusters.size == 1
        # combined char
        last_mbchar_width = Reline::Unicode.get_mbchar_width(last_mbchar)
        combined_char_width = Reline::Unicode.get_mbchar_width(combined_char)
        if combined_char_width > last_mbchar_width
          width = combined_char_width - last_mbchar_width
        else
          width = 0
        end
      end
      @cursor += width
      @cursor_max += width
    end

Also aliased as: ed_digit, self_insert
ed_kill_line(key) click to toggle source

Editline

  `ed-kill-line` (vi command: `D`, `Ctrl-K`; emacs: `Ctrl-K`, `Ctrl-U`) + Kill from the cursor to the end of the line.

GNU `Readline`

  `kill-line` (`C-k`) Kill the text from point to the end of the line. With a negative numeric argument, kill backward from the cursor to the beginning of the current line.

    # File lib/reline/line_editor.rb, line 2613
            def ed_kill_line(key)
      if @line.bytesize > @byte_pointer
        @line, deleted = byteslice!(@line, @byte_pointer, @line.bytesize - @byte_pointer)
        @byte_pointer = @line.bytesize
        @cursor = @cursor_max = calculate_width(@line)
        @kill_ring.append(deleted)
      elsif @is_multiline and @byte_pointer == @line.bytesize and @buffer_of_lines.size > @line_index + 1
        @cursor = calculate_width(@line)
        @byte_pointer = @line.bytesize
        @line += @buffer_of_lines.delete_at(@line_index + 1)
        @cursor_max = calculate_width(@line)
        @buffer_of_lines[@line_index] = @line
        @rerender_all = true
        @rest_height += 1
      end
    end

Also aliased as: kill_line
ed_move_to_beg(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2119
            def ed_move_to_beg(key)
      @byte_pointer = @cursor = 0
    end

Also aliased as: beginning_of_line
ed_move_to_end(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2124
            def ed_move_to_end(key)
      @byte_pointer = 0
      @cursor = 0
      byte_size = 0
      while @byte_pointer < @line.bytesize
        byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
        if byte_size > 0
          mbchar = @line.byteslice(@byte_pointer, byte_size)
          @cursor += Reline::Unicode.get_mbchar_width(mbchar)
        end
        @byte_pointer += byte_size
      end
    end

Also aliased as: end_of_line
ed_newline(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2552
            def ed_newline(key)
      process_insert(force: true)
      if @is_multiline
        if @config.editing_mode_is?(:vi_command)
          if @line_index < (@buffer_of_lines.size - 1)
            ed_next_history(key) # means cursor down
          else
            # should check confirm_multiline_termination to finish?
            finish
          end
        else
          if @line_index == (@buffer_of_lines.size - 1)
            if confirm_multiline_termination
              finish
            else
              key_newline(key)
            end
          else
            # should check confirm_multiline_termination to finish?
            @previous_line_index = @line_index
            @line_index = @buffer_of_lines.size - 1
            finish
          end
        end
      else
        if @history_pointer
          Reline::HISTORY[@history_pointer] = @line
          @history_pointer = nil
        end
        finish
      end
    end

ed_next_char(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2075
            def ed_next_char(key, arg: 1)
      byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
      if (@byte_pointer < @line.bytesize)
        mbchar = @line.byteslice(@byte_pointer, byte_size)
        width = Reline::Unicode.get_mbchar_width(mbchar)
        @cursor += width if width
        @byte_pointer += byte_size
      elsif @is_multiline and @config.editing_mode_is?(:emacs) and @byte_pointer == @line.bytesize and @line_index < @buffer_of_lines.size - 1
        next_line = @buffer_of_lines[@line_index + 1]
        @cursor = 0
        @byte_pointer = 0
        @cursor_max = calculate_width(next_line)
        @previous_line_index = @line_index
        @line_index += 1
      end
      arg -= 1
      ed_next_char(key, arg: arg) if arg > 0
    end

Also aliased as: forward_char
ed_next_history(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2504
            def ed_next_history(key, arg: 1)
      if @is_multiline and @line_index < (@buffer_of_lines.size - 1)
        @previous_line_index = @line_index
        @line_index += 1
        return
      end
      if @history_pointer.nil?
        return
      elsif @history_pointer == (Reline::HISTORY.size - 1)
        if @is_multiline
          @history_pointer = nil
          @buffer_of_lines = @line_backup_in_history.split("\n")
          @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
          @line_index = 0
          @line = @buffer_of_lines.first
          @rerender_all = true
        else
          @history_pointer = nil
          @line = @line_backup_in_history
        end
      else
        if @is_multiline
          Reline::HISTORY[@history_pointer] = whole_buffer
          @history_pointer += 1
          @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n")
          @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
          @line_index = 0
          @line = @buffer_of_lines.first
          @rerender_all = true
        else
          Reline::HISTORY[@history_pointer] = @line
          @history_pointer += 1
          @line = Reline::HISTORY[@history_pointer]
        end
      end
      @line = '' unless @line
      if @config.editing_mode_is?(:emacs, :vi_insert)
        @cursor_max = @cursor = calculate_width(@line)
        @byte_pointer = @line.bytesize
      elsif @config.editing_mode_is?(:vi_command)
        @byte_pointer = @cursor = 0
        @cursor_max = calculate_width(@line)
      end
      arg -= 1
      ed_next_history(key, arg: arg) if arg > 0
    end

Also aliased as: next_history
ed_prev_char(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2095
            def ed_prev_char(key, arg: 1)
      if @cursor > 0
        byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer)
        @byte_pointer -= byte_size
        mbchar = @line.byteslice(@byte_pointer, byte_size)
        width = Reline::Unicode.get_mbchar_width(mbchar)
        @cursor -= width
      elsif @is_multiline and @config.editing_mode_is?(:emacs) and @byte_pointer == 0 and @line_index > 0
        prev_line = @buffer_of_lines[@line_index - 1]
        @cursor = calculate_width(prev_line)
        @byte_pointer = prev_line.bytesize
        @cursor_max = calculate_width(prev_line)
        @previous_line_index = @line_index
        @line_index -= 1
      end
      arg -= 1
      ed_prev_char(key, arg: arg) if arg > 0
    end

Also aliased as: backward_char
ed_prev_history(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2453
            def ed_prev_history(key, arg: 1)
      if @is_multiline and @line_index > 0
        @previous_line_index = @line_index
        @line_index -= 1
        return
      end
      if Reline::HISTORY.empty?
        return
      end
      if @history_pointer.nil?
        @history_pointer = Reline::HISTORY.size - 1
        if @is_multiline
          @line_backup_in_history = whole_buffer
          @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n")
          @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
          @line_index = @buffer_of_lines.size - 1
          @line = @buffer_of_lines.last
          @rerender_all = true
        else
          @line_backup_in_history = @line
          @line = Reline::HISTORY[@history_pointer]
        end
      elsif @history_pointer.zero?
        return
      else
        if @is_multiline
          Reline::HISTORY[@history_pointer] = whole_buffer
          @history_pointer -= 1
          @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n")
          @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
          @line_index = @buffer_of_lines.size - 1
          @line = @buffer_of_lines.last
          @rerender_all = true
        else
          Reline::HISTORY[@history_pointer] = @line
          @history_pointer -= 1
          @line = Reline::HISTORY[@history_pointer]
        end
      end
      if @config.editing_mode_is?(:emacs, :vi_insert)
        @cursor_max = @cursor = calculate_width(@line)
        @byte_pointer = @line.bytesize
      elsif @config.editing_mode_is?(:vi_command)
        @byte_pointer = @cursor = 0
        @cursor_max = calculate_width(@line)
      end
      arg -= 1
      ed_prev_history(key, arg: arg) if arg > 0
    end

Also aliased as: previous_history
ed_prev_word(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2744
            def ed_prev_word(key)
      if @byte_pointer > 0
        byte_size, width = Reline::Unicode.em_backward_word(@line, @byte_pointer)
        @byte_pointer -= byte_size
        @cursor -= width
      end
    end

Also aliased as: backward_word
ed_quoted_insert(str, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2059
            def ed_quoted_insert(str, arg: 1)
      @waiting_proc = proc { |key|
        arg.times do
          if key == "\C-j".ord or key == "\C-m".ord
            key_newline(key)
          elsif key == 0
            # Ignore NUL.
          else
            ed_insert(key)
          end
        end
        @waiting_proc = nil
      }
    end

Also aliased as: quoted_insert
ed_search_next_history(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2401
            def ed_search_next_history(key, arg: 1)
      substr = @line.slice(0, @byte_pointer)
      if @history_pointer.nil?
        return
      elsif @history_pointer == (Reline::HISTORY.size - 1) and not substr.empty?
        return
      end
      history = Reline::HISTORY.slice((@history_pointer + 1)..-1)
      h_pointer = nil
      line_no = nil
      if @is_multiline
        h_pointer = history.index { |h|
          h.split("\n").each_with_index { |l, i|
            if l.start_with?(substr)
              line_no = i
              break
            end
          }
          not line_no.nil?
        }
      else
        h_pointer = history.index { |l|
          l.start_with?(substr)
        }
      end
      h_pointer += @history_pointer + 1 if h_pointer and @history_pointer
      return if h_pointer.nil? and not substr.empty?
      @history_pointer = h_pointer
      if @is_multiline
        if @history_pointer.nil? and substr.empty?
          @buffer_of_lines = []
          @line_index = 0
        else
          @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n")
          @line_index = line_no
        end
        @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
        @line = @buffer_of_lines[@line_index]
        @rerender_all = true
      else
        if @history_pointer.nil? and substr.empty?
          @line = ''
        else
          @line = Reline::HISTORY[@history_pointer]
        end
      end
      @cursor_max = calculate_width(@line)
      arg -= 1
      ed_search_next_history(key, arg: arg) if arg > 0
    end

Also aliased as: history_search_forward
ed_search_prev_history(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2354
            def ed_search_prev_history(key, arg: 1)
      history = nil
      h_pointer = nil
      line_no = nil
      substr = @line.slice(0, @byte_pointer)
      if @history_pointer.nil?
        return if not @line.empty? and substr.empty?
        history = Reline::HISTORY
      elsif @history_pointer.zero?
        history = nil
        h_pointer = nil
      else
        history = Reline::HISTORY.slice(0, @history_pointer)
      end
      return if history.nil?
      if @is_multiline
        h_pointer = history.rindex { |h|
          h.split("\n").each_with_index { |l, i|
            if l.start_with?(substr)
              line_no = i
              break
            end
          }
          not line_no.nil?
        }
      else
        h_pointer = history.rindex { |l|
          l.start_with?(substr)
        }
      end
      return if h_pointer.nil?
      @history_pointer = h_pointer
      if @is_multiline
        @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n")
        @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
        @line_index = line_no
        @line = @buffer_of_lines[@line_index]
        @rerender_all = true
      else
        @line = Reline::HISTORY[@history_pointer]
      end
      @cursor_max = calculate_width(@line)
      arg -= 1
      ed_search_prev_history(key, arg: arg) if arg > 0
    end

Also aliased as: history_search_backward
ed_transpose_chars(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2773
            def ed_transpose_chars(key)
      if @byte_pointer > 0
        if @cursor_max > @cursor
          byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
          mbchar = @line.byteslice(@byte_pointer, byte_size)
          width = Reline::Unicode.get_mbchar_width(mbchar)
          @cursor += width
          @byte_pointer += byte_size
        end
        back1_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer)
        if (@byte_pointer - back1_byte_size) > 0
          back2_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer - back1_byte_size)
          back2_pointer = @byte_pointer - back1_byte_size - back2_byte_size
          @line, back2_mbchar = byteslice!(@line, back2_pointer, back2_byte_size)
          @line = byteinsert(@line, @byte_pointer - back2_byte_size, back2_mbchar)
        end
      end
    end

Also aliased as: transpose_chars
ed_transpose_words(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2793
            def ed_transpose_words(key)
      left_word_start, middle_start, right_word_start, after_start = Reline::Unicode.ed_transpose_words(@line, @byte_pointer)
      before = @line.byteslice(0, left_word_start)
      left_word = @line.byteslice(left_word_start, middle_start - left_word_start)
      middle = @line.byteslice(middle_start, right_word_start - middle_start)
      right_word = @line.byteslice(right_word_start, after_start - right_word_start)
      after = @line.byteslice(after_start, @line.bytesize - after_start)
      return if left_word.empty? or right_word.empty?
      @line = before + right_word + middle + left_word + after
      from_head_to_left_word = before + right_word + middle + left_word
      @byte_pointer = from_head_to_left_word.bytesize
      @cursor = calculate_width(from_head_to_left_word)
    end

Also aliased as: transpose_words
ed_unassigned(key) click to toggle source

Editline

  `ed-unassigned` This editor command always results in an error.

GNU `Readline`

  There is no corresponding macro.

    # File lib/reline/line_editor.rb, line 1976
    def ed_unassigned(key) end

em_capitol_case(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2808
            def em_capitol_case(key)
      if @line.bytesize > @byte_pointer
        byte_size, _, new_str = Reline::Unicode.em_forward_word_with_capitalization(@line, @byte_pointer)
        before = @line.byteslice(0, @byte_pointer)
        after = @line.byteslice((@byte_pointer + byte_size)..-1)
        @line = before + new_str + after
        @byte_pointer += new_str.bytesize
        @cursor += calculate_width(new_str)
      end
    end

Also aliased as: capitalize_word
em_delete(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2662
            def em_delete(key)
      if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
        @line = nil
        if @buffer_of_lines.size > 1
          scroll_down(@highest_in_all - @first_line_started_from)
        end
        Reline::IOGate.move_cursor_column(0)
        @eof = true
        finish
      elsif @byte_pointer < @line.bytesize
        splitted_last = @line.byteslice(@byte_pointer, @line.bytesize)
        mbchar = splitted_last.grapheme_clusters.first
        width = Reline::Unicode.get_mbchar_width(mbchar)
        @cursor_max -= width
        @line, = byteslice!(@line, @byte_pointer, mbchar.bytesize)
      elsif @is_multiline and @byte_pointer == @line.bytesize and @buffer_of_lines.size > @line_index + 1
        @cursor = calculate_width(@line)
        @byte_pointer = @line.bytesize
        @line += @buffer_of_lines.delete_at(@line_index + 1)
        @cursor_max = calculate_width(@line)
        @buffer_of_lines[@line_index] = @line
        @rerender_all = true
        @rest_height += 1
      end
    end

Also aliased as: delete_char
em_delete_next_word(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2753
            def em_delete_next_word(key)
      if @line.bytesize > @byte_pointer
        byte_size, width = Reline::Unicode.em_forward_word(@line, @byte_pointer)
        @line, word = byteslice!(@line, @byte_pointer, byte_size)
        @kill_ring.append(word)
        @cursor_max -= width
      end
    end

em_delete_or_list(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2689
            def em_delete_or_list(key)
      if @line.empty? or @byte_pointer < @line.bytesize
        em_delete(key)
      else # show completed list
        result = call_completion_proc
        if result.is_a?(Array)
          complete(result, true)
        end
      end
    end

Also aliased as: delete_char_or_list
em_delete_prev_char(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2585
            def em_delete_prev_char(key, arg: 1)
      if @is_multiline and @cursor == 0 and @line_index > 0
        @buffer_of_lines[@line_index] = @line
        @cursor = calculate_width(@buffer_of_lines[@line_index - 1])
        @byte_pointer = @buffer_of_lines[@line_index - 1].bytesize
        @buffer_of_lines[@line_index - 1] += @buffer_of_lines.delete_at(@line_index)
        @line_index -= 1
        @line = @buffer_of_lines[@line_index]
        @cursor_max = calculate_width(@line)
        @rerender_all = true
      elsif @cursor > 0
        byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer)
        @byte_pointer -= byte_size
        @line, mbchar = byteslice!(@line, @byte_pointer, byte_size)
        width = Reline::Unicode.get_mbchar_width(mbchar)
        @cursor -= width
        @cursor_max -= width
      end
      arg -= 1
      em_delete_prev_char(key, arg: arg) if arg > 0
    end

Also aliased as: backward_delete_char
em_exchange_mark(key) click to toggle source

    # File lib/reline/line_editor.rb, line 3347
            def em_exchange_mark(key)
      return unless @mark_pointer
      new_pointer = [@byte_pointer, @line_index]
      @previous_line_index = @line_index
      @byte_pointer, @line_index = @mark_pointer
      @cursor = calculate_width(@line.byteslice(0, @byte_pointer))
      @cursor_max = calculate_width(@line)
      @mark_pointer = new_pointer
    end

Also aliased as: exchange_point_and_mark
em_kill_line(key) click to toggle source

Editline

  `em-kill-line` (not bound) Delete the entire contents of the edit buffer and save it to the cut buffer. `vi-kill-line-prev`

GNU `Readline`

  `kill-whole-line` (not bound) Kill all characters on the current line, no matter where point is.

    # File lib/reline/line_editor.rb, line 2651
            def em_kill_line(key)
      if @line.size > 0
        @kill_ring.append(@line.dup, true)
        @line.clear
        @byte_pointer = 0
        @cursor_max = 0
        @cursor = 0
      end
    end

Also aliased as: kill_whole_line
em_kill_region(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2852
            def em_kill_region(key)
      if @byte_pointer > 0
        byte_size, width = Reline::Unicode.em_big_backward_word(@line, @byte_pointer)
        @line, deleted = byteslice!(@line, @byte_pointer - byte_size, byte_size)
        @byte_pointer -= byte_size
        @cursor -= width
        @cursor_max -= width
        @kill_ring.append(deleted, true)
      end
    end

Also aliased as: unix_word_rubout
em_lower_case(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2820
            def em_lower_case(key)
      if @line.bytesize > @byte_pointer
        byte_size, = Reline::Unicode.em_forward_word(@line, @byte_pointer)
        part = @line.byteslice(@byte_pointer, byte_size).grapheme_clusters.map { |mbchar|
          mbchar =~ /[A-Z]/ ? mbchar.downcase : mbchar
        }.join
        rest = @line.byteslice((@byte_pointer + byte_size)..-1)
        @line = @line.byteslice(0, @byte_pointer) + part
        @byte_pointer = @line.bytesize
        @cursor = calculate_width(@line)
        @cursor_max = @cursor + calculate_width(rest)
        @line += rest
      end
    end

Also aliased as: downcase_word
em_next_word(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2735
            def em_next_word(key)
      if @line.bytesize > @byte_pointer
        byte_size, width = Reline::Unicode.em_forward_word(@line, @byte_pointer)
        @byte_pointer += byte_size
        @cursor += width
      end
    end

Also aliased as: forward_word
em_set_mark(key) click to toggle source

    # File lib/reline/line_editor.rb, line 3342
            def em_set_mark(key)
      @mark_pointer = [@byte_pointer, @line_index]
    end

Also aliased as: set_mark
em_upper_case(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2836
            def em_upper_case(key)
      if @line.bytesize > @byte_pointer
        byte_size, = Reline::Unicode.em_forward_word(@line, @byte_pointer)
        part = @line.byteslice(@byte_pointer, byte_size).grapheme_clusters.map { |mbchar|
          mbchar =~ /[a-z]/ ? mbchar.upcase : mbchar
        }.join
        rest = @line.byteslice((@byte_pointer + byte_size)..-1)
        @line = @line.byteslice(0, @byte_pointer) + part
        @byte_pointer = @line.bytesize
        @cursor = calculate_width(@line)
        @cursor_max = @cursor + calculate_width(rest)
        @line += rest
      end
    end

Also aliased as: upcase_word
em_yank(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2701
            def em_yank(key)
      yanked = @kill_ring.yank
      if yanked
        @line = byteinsert(@line, @byte_pointer, yanked)
        yanked_width = calculate_width(yanked)
        @cursor += yanked_width
        @cursor_max += yanked_width
        @byte_pointer += yanked.bytesize
      end
    end

Also aliased as: yank
em_yank_pop(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2713
            def em_yank_pop(key)
      yanked, prev_yank = @kill_ring.yank_pop
      if yanked
        prev_yank_width = calculate_width(prev_yank)
        @cursor -= prev_yank_width
        @cursor_max -= prev_yank_width
        @byte_pointer -= prev_yank.bytesize
        @line, = byteslice!(@line, @byte_pointer, prev_yank.bytesize)
        @line = byteinsert(@line, @byte_pointer, yanked)
        yanked_width = calculate_width(yanked)
        @cursor += yanked_width
        @cursor_max += yanked_width
        @byte_pointer += yanked.bytesize
      end
    end

Also aliased as: yank_pop
generate_searcher() click to toggle source

    # File lib/reline/line_editor.rb, line 2139
            def generate_searcher
      Fiber.new do |first_key|
        prev_search_key = first_key
        search_word = String.new(encoding: @encoding)
        multibyte_buf = String.new(encoding: 'ASCII-8BIT')
        last_hit = nil
        case first_key
        when "\C-r".ord
          prompt_name = 'reverse-i-search'
        when "\C-s".ord
          prompt_name = 'i-search'
        end
        loop do
          key = Fiber.yield(search_word)
          search_again = false
          case key
          when -1 # determined
            Reline.last_incremental_search = search_word
            break
          when "\C-h".ord, "\C-?".ord
            grapheme_clusters = search_word.grapheme_clusters
            if grapheme_clusters.size > 0
              grapheme_clusters.pop
              search_word = grapheme_clusters.join
            end
          when "\C-r".ord, "\C-s".ord
            search_again = true if prev_search_key == key
            prev_search_key = key
          else
            multibyte_buf << key
            if multibyte_buf.dup.force_encoding(@encoding).valid_encoding?
              search_word << multibyte_buf.dup.force_encoding(@encoding)
              multibyte_buf.clear
            end
          end
          hit = nil
          if not search_word.empty? and @line_backup_in_history&.include?(search_word)
            @history_pointer = nil
            hit = @line_backup_in_history
          else
            if search_again
              if search_word.empty? and Reline.last_incremental_search
                search_word = Reline.last_incremental_search
              end
              if @history_pointer
                case prev_search_key
                when "\C-r".ord
                  history_pointer_base = 0
                  history = Reline::HISTORY[0..(@history_pointer - 1)]
                when "\C-s".ord
                  history_pointer_base = @history_pointer + 1
                  history = Reline::HISTORY[(@history_pointer + 1)..-1]
                end
              else
                history_pointer_base = 0
                history = Reline::HISTORY
              end
            elsif @history_pointer
              case prev_search_key
              when "\C-r".ord
                history_pointer_base = 0
                history = Reline::HISTORY[0..@history_pointer]
              when "\C-s".ord
                history_pointer_base = @history_pointer
                history = Reline::HISTORY[@history_pointer..-1]
              end
            else
              history_pointer_base = 0
              history = Reline::HISTORY
            end
            case prev_search_key
            when "\C-r".ord
              hit_index = history.rindex { |item|
                item.include?(search_word)
              }
            when "\C-s".ord
              hit_index = history.index { |item|
                item.include?(search_word)
              }
            end
            if hit_index
              @history_pointer = history_pointer_base + hit_index
              hit = Reline::HISTORY[@history_pointer]
            end
          end
          case prev_search_key
          when "\C-r".ord
            prompt_name = 'reverse-i-search'
          when "\C-s".ord
            prompt_name = 'i-search'
          end
          if hit
            if @is_multiline
              @buffer_of_lines = hit.split("\n")
              @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
              @line_index = @buffer_of_lines.size - 1
              @line = @buffer_of_lines.last
              @byte_pointer = @line.bytesize
              @cursor = @cursor_max = calculate_width(@line)
              @rerender_all = true
              @searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
            else
              @line = hit
              @searching_prompt = "(%s)`%s': %s" % [prompt_name, search_word, hit]
            end
            last_hit = hit
          else
            if @is_multiline
              @rerender_all = true
              @searching_prompt = "(failed %s)`%s'" % [prompt_name, search_word]
            else
              @searching_prompt = "(failed %s)`%s': %s" % [prompt_name, search_word, last_hit]
            end
          end
        end
      end
    end

inclusive?(method_obj) click to toggle source

    # File lib/reline/line_editor.rb, line 1471
            def inclusive?(method_obj)
      # If a motion method with the keyword argument "inclusive" follows the
      # operator, it must contain the character at the cursor position.
      method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :inclusive }
    end

incremental_search_history(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2257
            def incremental_search_history(key)
      unless @history_pointer
        if @is_multiline
          @line_backup_in_history = whole_buffer
        else
          @line_backup_in_history = @line
        end
      end
      searcher = generate_searcher
      searcher.resume(key)
      @searching_prompt = "(reverse-i-search)`': "
      termination_keys = ["\C-j".ord]
      termination_keys.concat(@config.isearch_terminators&.chars&.map(&:ord)) if @config.isearch_terminators
      @waiting_proc = ->(k) {
        case k
        when *termination_keys
          if @history_pointer
            buffer = Reline::HISTORY[@history_pointer]
          else
            buffer = @line_backup_in_history
          end
          if @is_multiline
            @buffer_of_lines = buffer.split("\n")
            @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
            @line_index = @buffer_of_lines.size - 1
            @line = @buffer_of_lines.last
            @rerender_all = true
          else
            @line = buffer
          end
          @searching_prompt = nil
          @waiting_proc = nil
          @cursor_max = calculate_width(@line)
          @cursor = @byte_pointer = 0
          @rerender_all = true
          @cached_prompt_list = nil
          searcher.resume(-1)
        when "\C-g".ord
          if @is_multiline
            @buffer_of_lines = @line_backup_in_history.split("\n")
            @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
            @line_index = @buffer_of_lines.size - 1
            @line = @buffer_of_lines.last
            @rerender_all = true
          else
            @line = @line_backup_in_history
          end
          @history_pointer = nil
          @searching_prompt = nil
          @waiting_proc = nil
          @line_backup_in_history = nil
          @cursor_max = calculate_width(@line)
          @cursor = @byte_pointer = 0
          @rerender_all = true
        else
          chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT)
          if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k == "\C-?".ord or k == "\C-r".ord or k == "\C-s".ord
            searcher.resume(k)
          else
            if @history_pointer
              line = Reline::HISTORY[@history_pointer]
            else
              line = @line_backup_in_history
            end
            if @is_multiline
              @line_backup_in_history = whole_buffer
              @buffer_of_lines = line.split("\n")
              @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
              @line_index = @buffer_of_lines.size - 1
              @line = @buffer_of_lines.last
              @rerender_all = true
            else
              @line_backup_in_history = @line
              @line = line
            end
            @searching_prompt = nil
            @waiting_proc = nil
            @cursor_max = calculate_width(@line)
            @cursor = @byte_pointer = 0
            @rerender_all = true
            @cached_prompt_list = nil
            searcher.resume(-1)
          end
        end
      }
    end

insert_new_line(cursor_line, next_line) click to toggle source

    # File lib/reline/line_editor.rb, line 337
            def insert_new_line(cursor_line, next_line)
      @line = cursor_line
      @buffer_of_lines.insert(@line_index + 1, String.new(next_line, encoding: @encoding))
      @previous_line_index = @line_index
      @line_index += 1
      @just_cursor_moving = false
    end

key_delete(key) click to toggle source

    # File lib/reline/line_editor.rb, line 1955
            def key_delete(key)
      if @config.editing_mode_is?(:vi_insert, :emacs)
        ed_delete_next_char(key)
      end
    end

key_newline(key) click to toggle source

    # File lib/reline/line_editor.rb, line 1961
            def key_newline(key)
      if @is_multiline
        if (@buffer_of_lines.size - 1) == @line_index and @line.bytesize == @byte_pointer
          @add_newline_to_end_of_buffer = true
        end
        next_line = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer)
        cursor_line = @line.byteslice(0, @byte_pointer)
        insert_new_line(cursor_line, next_line)
        @cursor = 0
        @check_new_auto_indent = true unless @in_pasting
      end
    end

modify_lines(before) click to toggle source

    # File lib/reline/line_editor.rb, line 1241
            def modify_lines(before)
      return before if before.nil? || before.empty? || simplified_rendering?

      if after = @output_modifier_proc&.call("#{before.join("\n")}\n", complete: finished?)
        after.lines("\n").map { |l| l.chomp('') }
      else
        before
      end
    end

move_completed_list(list, direction) click to toggle source

    # File lib/reline/line_editor.rb, line 1383
            def move_completed_list(list, direction)
      case @completion_state
      when CompletionState::NORMAL, CompletionState::COMPLETION,
           CompletionState::MENU, CompletionState::MENU_WITH_PERFECT_MATCH
        @completion_state = CompletionState::JOURNEY
        result = retrieve_completion_block
        return if result.nil?
        preposing, target, postposing = result
        @completion_journey_data = CompletionJourneyData.new(
          preposing, postposing,
          [target] + list.select{ |item| item.start_with?(target) }, 0)
        if @completion_journey_data.list.size == 1
          @completion_journey_data.pointer = 0
        else
          case direction
          when :up
            @completion_journey_data.pointer = @completion_journey_data.list.size - 1
          when :down
            @completion_journey_data.pointer = 1
          end
        end
        @completion_state = CompletionState::JOURNEY
      else
        case direction
        when :up
          @completion_journey_data.pointer -= 1
          if @completion_journey_data.pointer < 0
            @completion_journey_data.pointer = @completion_journey_data.list.size - 1
          end
        when :down
          @completion_journey_data.pointer += 1
          if @completion_journey_data.pointer >= @completion_journey_data.list.size
            @completion_journey_data.pointer = 0
          end
        end
      end
      completed = @completion_journey_data.list[@completion_journey_data.pointer]
      new_line = (@completion_journey_data.preposing + completed + @completion_journey_data.postposing).split("\n")[@line_index]
      @line = new_line.nil? ? String.new(encoding: @encoding) : new_line
      line_to_pointer = (@completion_journey_data.preposing + completed).split("\n").last
      line_to_pointer = String.new(encoding: @encoding) if line_to_pointer.nil?
      @cursor_max = calculate_width(@line)
      @cursor = calculate_width(line_to_pointer)
      @byte_pointer = line_to_pointer.bytesize
    end

move_cursor_down(val) click to toggle source

    # File lib/reline/line_editor.rb, line 373
            def move_cursor_down(val)
      if val > 0
        Reline::IOGate.move_cursor_down(val)
        @rest_height -= val
        @rest_height = 0 if @rest_height < 0
      elsif val < 0
        move_cursor_up(-val)
      end
    end

move_cursor_up(val) click to toggle source

    # File lib/reline/line_editor.rb, line 364
            def move_cursor_up(val)
      if val > 0
        Reline::IOGate.move_cursor_up(val)
        @rest_height += val
      elsif val < 0
        move_cursor_down(-val)
      end
    end

normal_char(key) click to toggle source

    # File lib/reline/line_editor.rb, line 1554
            def normal_char(key)
      method_symbol = method_obj = nil
      if key.combined_char.is_a?(Symbol)
        process_key(key.combined_char, key.combined_char)
        return
      end
      @multibyte_buffer << key.combined_char
      if @multibyte_buffer.size > 1
        if @multibyte_buffer.dup.force_encoding(@encoding).valid_encoding?
          process_key(@multibyte_buffer.dup.force_encoding(@encoding), nil)
          @multibyte_buffer.clear
        else
          # invalid
          return
        end
      else # single byte
        return if key.char >= 128 # maybe, first byte of multi byte
        method_symbol = @config.editing_mode.get_method(key.combined_char)
        if key.with_meta and method_symbol == :ed_unassigned
          # split ESC + key
          method_symbol = @config.editing_mode.get_method("\e".ord)
          process_key("\e".ord, method_symbol)
          method_symbol = @config.editing_mode.get_method(key.char)
          process_key(key.char, method_symbol)
        else
          process_key(key.combined_char, method_symbol)
        end
        @multibyte_buffer.clear
      end
      if @config.editing_mode_is?(:vi_command) and @cursor > 0 and @cursor == @cursor_max
        byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer)
        @byte_pointer -= byte_size
        mbchar = @line.byteslice(@byte_pointer, byte_size)
        width = Reline::Unicode.get_mbchar_width(mbchar)
        @cursor -= width
      end
    end

padding_space_with_escape_sequences(str, width) click to toggle source

    # File lib/reline/line_editor.rb, line 657
            def padding_space_with_escape_sequences(str, width)
      padding_width = width - calculate_width(str, true)
      # padding_width should be only positive value. But macOS and Alacritty returns negative value.
      padding_width = 0 if padding_width < 0
      str + (' ' * padding_width)
    end

process_auto_indent() click to toggle source

    # File lib/reline/line_editor.rb, line 1697
            def process_auto_indent
      return if not @check_new_auto_indent and @previous_line_index # move cursor up or down
      if @check_new_auto_indent and @previous_line_index and @previous_line_index > 0 and @line_index > @previous_line_index
        # Fix indent of a line when a newline is inserted to the next
        new_lines = whole_lines(index: @previous_line_index, line: @line)
        new_indent = @auto_indent_proc.(new_lines[0..-3].push(''), @line_index - 1, 0, true)
        md = @line.match(/\A */)
        prev_indent = md[0].count(' ')
        @line = ' ' * new_indent + @line.lstrip

        new_indent = nil
        result = @auto_indent_proc.(new_lines[0..-2], @line_index - 1, (new_lines[-2].size + 1), false)
        if result
          new_indent = result
        end
        if new_indent&.>= 0
          @line = ' ' * new_indent + @line.lstrip
        end
      end
      if @previous_line_index
        new_lines = whole_lines(index: @previous_line_index, line: @line)
      else
        new_lines = whole_lines
      end
      new_indent = @auto_indent_proc.(new_lines, @line_index, @byte_pointer, @check_new_auto_indent)
      new_indent = @cursor_max if new_indent&.> @cursor_max
      if new_indent&.>= 0
        md = new_lines[@line_index].match(/\A */)
        prev_indent = md[0].count(' ')
        if @check_new_auto_indent
          @buffer_of_lines[@line_index] = ' ' * new_indent + @buffer_of_lines[@line_index].lstrip
          @cursor = new_indent
          @byte_pointer = new_indent
        else
          @line = ' ' * new_indent + @line.lstrip
          @cursor += new_indent - prev_indent
          @byte_pointer += new_indent - prev_indent
        end
      end
      @check_new_auto_indent = false
    end

process_insert(force: false) click to toggle source

    # File lib/reline/line_editor.rb, line 1978
            def process_insert(force: false)
      return if @continuous_insertion_buffer.empty? or (@in_pasting and not force)
      width = Reline::Unicode.calculate_width(@continuous_insertion_buffer)
      bytesize = @continuous_insertion_buffer.bytesize
      if @cursor == @cursor_max
        @line += @continuous_insertion_buffer
      else
        @line = byteinsert(@line, @byte_pointer, @continuous_insertion_buffer)
      end
      @byte_pointer += bytesize
      @cursor += width
      @cursor_max += width
      @continuous_insertion_buffer.clear
    end

process_key(key, method_symbol) click to toggle source

    # File lib/reline/line_editor.rb, line 1497
            def process_key(key, method_symbol)
      if method_symbol and respond_to?(method_symbol, true)
        method_obj = method(method_symbol)
      else
        method_obj = nil
      end
      if method_symbol and key.is_a?(Symbol)
        if @vi_arg and argumentable?(method_obj)
          run_for_operators(key, method_symbol) do |with_operator|
            wrap_method_call(method_symbol, method_obj, key, with_operator)
          end
        else
          wrap_method_call(method_symbol, method_obj, key) if method_obj
        end
        @kill_ring.process
        if @vi_arg
          @rerender_al = true
          @vi_arg = nil
        end
      elsif @vi_arg
        if key.chr =~ /[0-9]/
          ed_argument_digit(key)
        else
          if argumentable?(method_obj)
            run_for_operators(key, method_symbol) do |with_operator|
              wrap_method_call(method_symbol, method_obj, key, with_operator)
            end
          elsif @waiting_proc
            @waiting_proc.(key)
          elsif method_obj
            wrap_method_call(method_symbol, method_obj, key)
          else
            ed_insert(key) unless @config.editing_mode_is?(:vi_command)
          end
          @kill_ring.process
          if @vi_arg
            @rerender_all = true
            @vi_arg = nil
          end
        end
      elsif @waiting_proc
        @waiting_proc.(key)
        @kill_ring.process
      elsif method_obj
        if method_symbol == :ed_argument_digit
          wrap_method_call(method_symbol, method_obj, key)
        else
          run_for_operators(key, method_symbol) do |with_operator|
            wrap_method_call(method_symbol, method_obj, key, with_operator)
          end
        end
        @kill_ring.process
      else
        ed_insert(key) unless @config.editing_mode_is?(:vi_command)
      end
    end

render_dialog(cursor_column) click to toggle source

    # File lib/reline/line_editor.rb, line 651
            def render_dialog(cursor_column)
      @dialogs.each do |dialog|
        render_each_dialog(dialog, cursor_column)
      end
    end

render_each_dialog(dialog, cursor_column) click to toggle source

    # File lib/reline/line_editor.rb, line 664
            def render_each_dialog(dialog, cursor_column)
      if @in_pasting
        clear_each_dialog(dialog)
        dialog.contents = nil
        dialog.trap_key = nil
        return
      end
      dialog.set_cursor_pos(cursor_column, @first_line_started_from + @started_from)
      dialog_render_info = dialog.call(@last_key)
      if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty?
        dialog.lines_backup = {
          lines: modify_lines(whole_lines),
          line_index: @line_index,
          first_line_started_from: @first_line_started_from,
          started_from: @started_from,
          byte_pointer: @byte_pointer
        }
        clear_each_dialog(dialog)
        dialog.contents = nil
        dialog.trap_key = nil
        return
      end
      old_dialog = dialog.clone
      dialog.contents = dialog_render_info.contents
      pointer = dialog.pointer
      if dialog_render_info.width
        dialog.width = dialog_render_info.width
      else
        dialog.width = dialog.contents.map { |l| calculate_width(l, true) }.max
      end
      height = dialog_render_info.height || DIALOG_DEFAULT_HEIGHT
      height = dialog.contents.size if dialog.contents.size < height
      if dialog.contents.size > height
        if dialog.pointer
          if dialog.pointer < 0
            dialog.scroll_top = 0
          elsif (dialog.pointer - dialog.scroll_top) >= (height - 1)
            dialog.scroll_top = dialog.pointer - (height - 1)
          elsif (dialog.pointer - dialog.scroll_top) < 0
            dialog.scroll_top = dialog.pointer
          end
          pointer = dialog.pointer - dialog.scroll_top
        end
        dialog.contents = dialog.contents[dialog.scroll_top, height]
      end
      if dialog.contents and dialog.scroll_top >= dialog.contents.size
        dialog.scroll_top = dialog.contents.size - height
      end
      if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
        bar_max_height = height * 2
        moving_distance = (dialog_render_info.contents.size - height) * 2
        position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance)
        bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
        dialog.scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i
      else
        dialog.scrollbar_pos = nil
      end
      upper_space = @first_line_started_from - @started_from
      dialog.column = dialog_render_info.pos.x
      dialog.width += @block_elem_width if dialog.scrollbar_pos
      diff = (dialog.column + dialog.width) - (@screen_size.last)
      if diff > 0
        dialog.column -= diff
      end
      if (@rest_height - dialog_render_info.pos.y) >= height
        dialog.vertical_offset = dialog_render_info.pos.y + 1
      elsif upper_space >= height
        dialog.vertical_offset = dialog_render_info.pos.y - height
      else
        if (@rest_height - dialog_render_info.pos.y) < height
          scroll_down(height + dialog_render_info.pos.y)
          move_cursor_up(height + dialog_render_info.pos.y)
        end
        dialog.vertical_offset = dialog_render_info.pos.y + 1
      end
      Reline::IOGate.hide_cursor
      if dialog.column < 0
        dialog.column = 0
        dialog.width = @screen_size.last
      end
      reset_dialog(dialog, old_dialog)
      move_cursor_down(dialog.vertical_offset)
      Reline::IOGate.move_cursor_column(dialog.column)
      dialog.contents.each_with_index do |item, i|
        if i == pointer
          fg_color = dialog_render_info.pointer_fg_color
          bg_color = dialog_render_info.pointer_bg_color
        else
          fg_color = dialog_render_info.fg_color
          bg_color = dialog_render_info.bg_color
        end
        str_width = dialog.width - (dialog.scrollbar_pos.nil? ? 0 : @block_elem_width)
        str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
        @output.write "\e[#{bg_color}m\e[#{fg_color}m#{str}"
        if dialog.scrollbar_pos and (dialog.scrollbar_pos != old_dialog.scrollbar_pos or dialog.column != old_dialog.column)
          @output.write "\e[37m"
          if dialog.scrollbar_pos <= (i * 2) and (i * 2 + 1) < (dialog.scrollbar_pos + bar_height)
            @output.write @full_block
          elsif dialog.scrollbar_pos <= (i * 2) and (i * 2) < (dialog.scrollbar_pos + bar_height)
            @output.write @upper_half_block
          elsif dialog.scrollbar_pos <= (i * 2 + 1) and (i * 2) < (dialog.scrollbar_pos + bar_height)
            @output.write @lower_half_block
          else
            @output.write ' ' * @block_elem_width
          end
        end
        @output.write "\e[0m"
        Reline::IOGate.move_cursor_column(dialog.column)
        move_cursor_down(1) if i < (dialog.contents.size - 1)
      end
      Reline::IOGate.move_cursor_column(cursor_column)
      move_cursor_up(dialog.vertical_offset + dialog.contents.size - 1)
      Reline::IOGate.show_cursor
      dialog.lines_backup = {
        lines: modify_lines(whole_lines),
        line_index: @line_index,
        first_line_started_from: @first_line_started_from,
        started_from: @started_from,
        byte_pointer: @byte_pointer
      }
    end

render_partial(prompt, prompt_width, line_to_render, this_started_from, with_control: true) click to toggle source

    # File lib/reline/line_editor.rb, line 1144
            def render_partial(prompt, prompt_width, line_to_render, this_started_from, with_control: true)
      visual_lines, height = split_by_width(line_to_render.nil? ? prompt : prompt + line_to_render, @screen_size.last)
      cursor_up_from_last_line = 0
      if @scroll_partial_screen
        last_visual_line = this_started_from + (height - 1)
        last_screen_line = @scroll_partial_screen + (@screen_height - 1)
        if (@scroll_partial_screen - this_started_from) >= height
          # Render nothing because this line is before the screen.
          visual_lines = []
        elsif this_started_from > last_screen_line
          # Render nothing because this line is after the screen.
          visual_lines = []
        else
          deleted_lines_before_screen = []
          if @scroll_partial_screen > this_started_from and last_visual_line >= @scroll_partial_screen
            # A part of visual lines are before the screen.
            deleted_lines_before_screen = visual_lines.shift((@scroll_partial_screen - this_started_from) * 2)
            deleted_lines_before_screen.compact!
          end
          if this_started_from <= last_screen_line and last_screen_line < last_visual_line
            # A part of visual lines are after the screen.
            visual_lines.pop((last_visual_line - last_screen_line) * 2)
          end
          move_cursor_up(deleted_lines_before_screen.size - @started_from)
          cursor_up_from_last_line = @started_from - deleted_lines_before_screen.size
        end
      end
      if with_control
        if height > @highest_in_this
          diff = height - @highest_in_this
          scroll_down(diff)
          @highest_in_all += diff
          @highest_in_this = height
          move_cursor_up(diff)
        elsif height < @highest_in_this
          diff = @highest_in_this - height
          @highest_in_all -= diff
          @highest_in_this = height
        end
        move_cursor_up(@started_from)
        @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
        cursor_up_from_last_line = height - 1 - @started_from
      end
      if Reline::Unicode::CSI_REGEXP.match?(prompt + line_to_render)
        @output.write "\e[0m" # clear character decorations
      end
      visual_lines.each_with_index do |line, index|
        Reline::IOGate.move_cursor_column(0)
        if line.nil?
          if calculate_width(visual_lines[index - 1], true) == Reline::IOGate.get_screen_size.last
            # reaches the end of line
            if Reline::IOGate.win? and Reline::IOGate.win_legacy_console?
              # A newline is automatically inserted if a character is rendered at
              # eol on command prompt.
            else
              # When the cursor is at the end of the line and erases characters
              # after the cursor, some terminals delete the character at the
              # cursor position.
              move_cursor_down(1)
              Reline::IOGate.move_cursor_column(0)
            end
          else
            Reline::IOGate.erase_after_cursor
            move_cursor_down(1)
            Reline::IOGate.move_cursor_column(0)
          end
          next
        end
        @output.write line
        if Reline::IOGate.win? and Reline::IOGate.win_legacy_console? and calculate_width(line, true) == Reline::IOGate.get_screen_size.last
          # A newline is automatically inserted if a character is rendered at eol on command prompt.
          @rest_height -= 1 if @rest_height > 0
        end
        @output.flush
        if @first_prompt
          @first_prompt = false
          @pre_input_hook&.call
        end
      end
      unless visual_lines.empty?
        Reline::IOGate.erase_after_cursor
        Reline::IOGate.move_cursor_column(0)
      end
      if with_control
        # Just after rendring, so the cursor is on the last line.
        if finished?
          Reline::IOGate.move_cursor_column(0)
        else
          # Moves up from bottom of lines to the cursor position.
          move_cursor_up(cursor_up_from_last_line)
          # This logic is buggy if a fullwidth char is wrapped because there is only one halfwidth at end of a line.
          Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
        end
      end
      height
    end

render_whole_lines(lines, prompt, prompt_width) click to toggle source

    # File lib/reline/line_editor.rb, line 1118
            def render_whole_lines(lines, prompt, prompt_width)
      rendered_height = 0
      modify_lines(lines).each_with_index do |line, index|
        if prompt.is_a?(Array)
          line_prompt = prompt[index]
          prompt_width = calculate_width(line_prompt, true)
        else
          line_prompt = prompt
        end
        height = render_partial(line_prompt, prompt_width, line, rendered_height, with_control: false)
        if index < (lines.size - 1)
          if @scroll_partial_screen
            if (@scroll_partial_screen - height) < rendered_height and (@scroll_partial_screen + @screen_height - 1) >= (rendered_height + height)
              move_cursor_down(1)
            end
          else
            scroll_down(1)
          end
          rendered_height += height
        else
          rendered_height += height - 1
        end
      end
      rendered_height
    end

rerender_added_newline(prompt, prompt_width) click to toggle source

    # File lib/reline/line_editor.rb, line 967
            def rerender_added_newline(prompt, prompt_width)
      scroll_down(1)
      @buffer_of_lines[@previous_line_index] = @line
      @line = @buffer_of_lines[@line_index]
      unless @in_pasting
        render_partial(prompt, prompt_width, @line, @first_line_started_from + @started_from + 1, with_control: false)
      end
      @cursor = @cursor_max = calculate_width(@line)
      @byte_pointer = @line.bytesize
      @highest_in_all += @highest_in_this
      @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
      @first_line_started_from += @started_from + 1
      @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
      @previous_line_index = nil
    end

rerender_all_lines() click to toggle source

    # File lib/reline/line_editor.rb, line 1063
            def rerender_all_lines
      move_cursor_up(@first_line_started_from + @started_from)
      Reline::IOGate.move_cursor_column(0)
      back = 0
      new_buffer = whole_lines
      prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer)
      new_buffer.each_with_index do |line, index|
        prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc
        width = prompt_width + calculate_width(line)
        height = calculate_height_by_width(width)
        back += height
      end
      old_highest_in_all = @highest_in_all
      if @line_index.zero?
        new_first_line_started_from = 0
      else
        new_first_line_started_from = calculate_height_by_lines(new_buffer[0..(@line_index - 1)], prompt_list || prompt)
      end
      new_started_from = calculate_height_by_width(prompt_width + @cursor) - 1
      calculate_scroll_partial_screen(back, new_first_line_started_from + new_started_from)
      if @scroll_partial_screen
        move_cursor_up(@first_line_started_from + @started_from)
        scroll_down(@screen_height - 1)
        move_cursor_up(@screen_height)
        Reline::IOGate.move_cursor_column(0)
      elsif back > old_highest_in_all
        scroll_down(back - 1)
        move_cursor_up(back - 1)
      elsif back < old_highest_in_all
        scroll_down(back)
        Reline::IOGate.erase_after_cursor
        (old_highest_in_all - back - 1).times do
          scroll_down(1)
          Reline::IOGate.erase_after_cursor
        end
        move_cursor_up(old_highest_in_all - 1)
      end
      render_whole_lines(new_buffer, prompt_list || prompt, prompt_width)
      if @prompt_proc
        prompt = prompt_list[@line_index]
        prompt_width = calculate_width(prompt, true)
      end
      @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
      @highest_in_all = back
      @first_line_started_from = new_first_line_started_from
      @started_from = new_started_from
      if @scroll_partial_screen
        Reline::IOGate.move_cursor_up(@screen_height - (@first_line_started_from + @started_from - @scroll_partial_screen) - 1)
        Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
      else
        move_cursor_down(@first_line_started_from + @started_from - back + 1)
        Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
      end
    end

rerender_changed_current_line() click to toggle source

    # File lib/reline/line_editor.rb, line 1015
            def rerender_changed_current_line
      if @previous_line_index
        new_lines = whole_lines(index: @previous_line_index, line: @line)
      else
        new_lines = whole_lines
      end
      prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines)
      all_height = calculate_height_by_lines(new_lines, prompt_list || prompt)
      diff = all_height - @highest_in_all
      move_cursor_down(@highest_in_all - @first_line_started_from - @started_from - 1)
      if diff > 0
        scroll_down(diff)
        move_cursor_up(all_height - 1)
      elsif diff < 0
        (-diff).times do
          Reline::IOGate.move_cursor_column(0)
          Reline::IOGate.erase_after_cursor
          move_cursor_up(1)
        end
        move_cursor_up(all_height - 1)
      else
        move_cursor_up(all_height - 1)
      end
      @highest_in_all = all_height
      back = render_whole_lines(new_lines, prompt_list || prompt, prompt_width)
      move_cursor_up(back)
      if @previous_line_index
        @buffer_of_lines[@previous_line_index] = @line
        @line = @buffer_of_lines[@line_index]
      end
      @first_line_started_from =
        if @line_index.zero?
          0
        else
          calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
        end
      if @prompt_proc
        prompt = prompt_list[@line_index]
        prompt_width = calculate_width(prompt, true)
      end
      move_cursor_down(@first_line_started_from)
      calculate_nearest_cursor
      @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
      move_cursor_down(@started_from)
      Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
      @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
    end

reset_dialog(dialog, old_dialog) click to toggle source

    # File lib/reline/line_editor.rb, line 786
            def reset_dialog(dialog, old_dialog)
      return if dialog.lines_backup.nil? or old_dialog.contents.nil?
      prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines])
      visual_lines = []
      visual_start = nil
      dialog.lines_backup[:lines].each_with_index { |l, i|
        pr = prompt_list ? prompt_list[i] : prompt
        vl, _ = split_by_width(pr + l, @screen_size.last)
        vl.compact!
        if i == dialog.lines_backup[:line_index]
          visual_start = visual_lines.size + dialog.lines_backup[:started_from]
        end
        visual_lines.concat(vl)
      }
      old_y = dialog.lines_backup[:first_line_started_from] + dialog.lines_backup[:started_from]
      y = @first_line_started_from + @started_from
      y_diff = y - old_y
      if (old_y + old_dialog.vertical_offset) < (y + dialog.vertical_offset)
        # rerender top
        move_cursor_down(old_dialog.vertical_offset - y_diff)
        start = visual_start + old_dialog.vertical_offset
        line_num = dialog.vertical_offset - old_dialog.vertical_offset
        line_num.times do |i|
          Reline::IOGate.move_cursor_column(old_dialog.column)
          if visual_lines[start + i].nil?
            s = ' ' * old_dialog.width
          else
            s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width)
            s = padding_space_with_escape_sequences(s, old_dialog.width)
          end
          @output.write "\e[0m#{s}\e[0m"
          move_cursor_down(1) if i < (line_num - 1)
        end
        move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
      end
      if (old_y + old_dialog.vertical_offset + old_dialog.contents.size) > (y + dialog.vertical_offset + dialog.contents.size)
        # rerender bottom
        move_cursor_down(dialog.vertical_offset + dialog.contents.size - y_diff)
        start = visual_start + dialog.vertical_offset + dialog.contents.size
        line_num = (old_dialog.vertical_offset + old_dialog.contents.size) - (dialog.vertical_offset + dialog.contents.size)
        line_num.times do |i|
          Reline::IOGate.move_cursor_column(old_dialog.column)
          if visual_lines[start + i].nil?
            s = ' ' * old_dialog.width
          else
            s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width)
            s = padding_space_with_escape_sequences(s, old_dialog.width)
          end
          @output.write "\e[0m#{s}\e[0m"
          move_cursor_down(1) if i < (line_num - 1)
        end
        move_cursor_up(dialog.vertical_offset + dialog.contents.size + line_num - 1 - y_diff)
      end
      if old_dialog.column < dialog.column
        # rerender left
        move_cursor_down(old_dialog.vertical_offset - y_diff)
        width = dialog.column - old_dialog.column
        start = visual_start + old_dialog.vertical_offset
        line_num = old_dialog.contents.size
        line_num.times do |i|
          Reline::IOGate.move_cursor_column(old_dialog.column)
          if visual_lines[start + i].nil?
            s = ' ' * width
          else
            s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, width)
            s = padding_space_with_escape_sequences(s, dialog.width)
          end
          @output.write "\e[0m#{s}\e[0m"
          move_cursor_down(1) if i < (line_num - 1)
        end
        move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
      end
      if (old_dialog.column + old_dialog.width) > (dialog.column + dialog.width)
        # rerender right
        move_cursor_down(old_dialog.vertical_offset + y_diff)
        width = (old_dialog.column + old_dialog.width) - (dialog.column + dialog.width)
        start = visual_start + old_dialog.vertical_offset
        line_num = old_dialog.contents.size
        line_num.times do |i|
          Reline::IOGate.move_cursor_column(old_dialog.column + dialog.width)
          if visual_lines[start + i].nil?
            s = ' ' * width
          else
            s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column + dialog.width, width)
            rerender_width = old_dialog.width - dialog.width
            s = padding_space_with_escape_sequences(s, rerender_width)
          end
          Reline::IOGate.move_cursor_column(dialog.column + dialog.width)
          @output.write "\e[0m#{s}\e[0m"
          move_cursor_down(1) if i < (line_num - 1)
        end
        move_cursor_up(old_dialog.vertical_offset + line_num - 1 + y_diff)
      end
      Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
    end

run_for_operators(key, method_symbol, &block) click to toggle source

    # File lib/reline/line_editor.rb, line 1429
            def run_for_operators(key, method_symbol, &block)
      if @waiting_operator_proc
        if VI_MOTIONS.include?(method_symbol)
          old_cursor, old_byte_pointer = @cursor, @byte_pointer
          @vi_arg = @waiting_operator_vi_arg if @waiting_operator_vi_arg&.> 1
          block.(true)
          unless @waiting_proc
            cursor_diff, byte_pointer_diff = @cursor - old_cursor, @byte_pointer - old_byte_pointer
            @cursor, @byte_pointer = old_cursor, old_byte_pointer
            @waiting_operator_proc.(cursor_diff, byte_pointer_diff)
          else
            old_waiting_proc = @waiting_proc
            old_waiting_operator_proc = @waiting_operator_proc
            current_waiting_operator_proc = @waiting_operator_proc
            @waiting_proc = proc { |k|
              old_cursor, old_byte_pointer = @cursor, @byte_pointer
              old_waiting_proc.(k)
              cursor_diff, byte_pointer_diff = @cursor - old_cursor, @byte_pointer - old_byte_pointer
              @cursor, @byte_pointer = old_cursor, old_byte_pointer
              current_waiting_operator_proc.(cursor_diff, byte_pointer_diff)
              @waiting_operator_proc = old_waiting_operator_proc
            }
          end
        else
          # Ignores operator when not motion is given.
          block.(false)
        end
        @waiting_operator_proc = nil
        @waiting_operator_vi_arg = nil
        if @vi_arg
          @rerender_all = true
          @vi_arg = nil
        end
      else
        block.(false)
      end
    end

scroll_down(val) click to toggle source

    # File lib/reline/line_editor.rb, line 353
            def scroll_down(val)
      if val <= @rest_height
        Reline::IOGate.move_cursor_down(val)
        @rest_height -= val
      else
        Reline::IOGate.move_cursor_down(@rest_height)
        Reline::IOGate.scroll_down(val - @rest_height)
        @rest_height = 0
      end
    end

search_next_char(key, arg, need_prev_char: false, inclusive: false) click to toggle source

    # File lib/reline/line_editor.rb, line 3231
            def search_next_char(key, arg, need_prev_char: false, inclusive: false)
      if key.instance_of?(String)
        inputed_char = key
      else
        inputed_char = key.chr
      end
      prev_total = nil
      total = nil
      found = false
      @line.byteslice(@byte_pointer..-1).grapheme_clusters.each do |mbchar|
        # total has [byte_size, cursor]
        unless total
          # skip cursor point
          width = Reline::Unicode.get_mbchar_width(mbchar)
          total = [mbchar.bytesize, width]
        else
          if inputed_char == mbchar
            arg -= 1
            if arg.zero?
              found = true
              break
            end
          end
          width = Reline::Unicode.get_mbchar_width(mbchar)
          prev_total = total
          total = [total.first + mbchar.bytesize, total.last + width]
        end
      end
      if not need_prev_char and found and total
        byte_size, width = total
        @byte_pointer += byte_size
        @cursor += width
      elsif need_prev_char and found and prev_total
        byte_size, width = prev_total
        @byte_pointer += byte_size
        @cursor += width
      end
      if inclusive
        byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
        if byte_size > 0
          c = @line.byteslice(@byte_pointer, byte_size)
          width = Reline::Unicode.get_mbchar_width(c)
          @byte_pointer += byte_size
          @cursor += width
        end
      end
      @waiting_proc = nil
    end

search_prev_char(key, arg, need_next_char = false) click to toggle source

    # File lib/reline/line_editor.rb, line 3288
            def search_prev_char(key, arg, need_next_char = false)
      if key.instance_of?(String)
        inputed_char = key
      else
        inputed_char = key.chr
      end
      prev_total = nil
      total = nil
      found = false
      @line.byteslice(0..@byte_pointer).grapheme_clusters.reverse_each do |mbchar|
        # total has [byte_size, cursor]
        unless total
          # skip cursor point
          width = Reline::Unicode.get_mbchar_width(mbchar)
          total = [mbchar.bytesize, width]
        else
          if inputed_char == mbchar
            arg -= 1
            if arg.zero?
              found = true
              break
            end
          end
          width = Reline::Unicode.get_mbchar_width(mbchar)
          prev_total = total
          total = [total.first + mbchar.bytesize, total.last + width]
        end
      end
      if not need_next_char and found and total
        byte_size, width = total
        @byte_pointer -= byte_size
        @cursor -= width
      elsif need_next_char and found and prev_total
        byte_size, width = prev_total
        @byte_pointer -= byte_size
        @cursor -= width
      end
      @waiting_proc = nil
    end

split_by_width(str, max_width) click to toggle source

    # File lib/reline/line_editor.rb, line 349
            def split_by_width(str, max_width)
      Reline::Unicode.split_by_width(str, max_width, @encoding)
    end

vi_add(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2874
            def vi_add(key)
      @config.editing_mode = :vi_insert
      ed_next_char(key)
    end

vi_add_at_eol(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2988
            def vi_add_at_eol(key)
      ed_move_to_end(key)
      @config.editing_mode = :vi_insert
    end

vi_change_meta(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 3014
            def vi_change_meta(key, arg: 1)
      @drop_terminate_spaces = true
      @waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff|
        if byte_pointer_diff > 0
          @line, cut = byteslice!(@line, @byte_pointer, byte_pointer_diff)
        elsif byte_pointer_diff < 0
          @line, cut = byteslice!(@line, @byte_pointer + byte_pointer_diff, -byte_pointer_diff)
        end
        copy_for_vi(cut)
        @cursor += cursor_diff if cursor_diff < 0
        @cursor_max -= cursor_diff.abs
        @byte_pointer += byte_pointer_diff if byte_pointer_diff < 0
        @config.editing_mode = :vi_insert
        @drop_terminate_spaces = false
      }
      @waiting_operator_vi_arg = arg
    end

vi_command_mode(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2879
            def vi_command_mode(key)
      ed_prev_char(key)
      @config.editing_mode = :vi_command
    end

Also aliased as: vi_movement_mode
vi_delete_meta(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 3032
            def vi_delete_meta(key, arg: 1)
      @waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff|
        if byte_pointer_diff > 0
          @line, cut = byteslice!(@line, @byte_pointer, byte_pointer_diff)
        elsif byte_pointer_diff < 0
          @line, cut = byteslice!(@line, @byte_pointer + byte_pointer_diff, -byte_pointer_diff)
        end
        copy_for_vi(cut)
        @cursor += cursor_diff if cursor_diff < 0
        @cursor_max -= cursor_diff.abs
        @byte_pointer += byte_pointer_diff if byte_pointer_diff < 0
      }
      @waiting_operator_vi_arg = arg
    end

vi_delete_prev_char(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2963
            def vi_delete_prev_char(key)
      if @is_multiline and @cursor == 0 and @line_index > 0
        @buffer_of_lines[@line_index] = @line
        @cursor = calculate_width(@buffer_of_lines[@line_index - 1])
        @byte_pointer = @buffer_of_lines[@line_index - 1].bytesize
        @buffer_of_lines[@line_index - 1] += @buffer_of_lines.delete_at(@line_index)
        @line_index -= 1
        @line = @buffer_of_lines[@line_index]
        @cursor_max = calculate_width(@line)
        @rerender_all = true
      elsif @cursor > 0
        byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer)
        @byte_pointer -= byte_size
        @line, mbchar = byteslice!(@line, @byte_pointer, byte_size)
        width = Reline::Unicode.get_mbchar_width(mbchar)
        @cursor -= width
        @cursor_max -= width
      end
    end

vi_end_big_word(key, arg: 1, inclusive: false) click to toggle source

    # File lib/reline/line_editor.rb, line 2944
            def vi_end_big_word(key, arg: 1, inclusive: false)
      if @line.bytesize > @byte_pointer
        byte_size, width = Reline::Unicode.vi_big_forward_end_word(@line, @byte_pointer)
        @byte_pointer += byte_size
        @cursor += width
      end
      arg -= 1
      if inclusive and arg.zero?
        byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
        if byte_size > 0
          c = @line.byteslice(@byte_pointer, byte_size)
          width = Reline::Unicode.get_mbchar_width(c)
          @byte_pointer += byte_size
          @cursor += width
        end
      end
      vi_end_big_word(key, arg: arg) if arg > 0
    end

vi_end_word(key, arg: 1, inclusive: false) click to toggle source

    # File lib/reline/line_editor.rb, line 2905
            def vi_end_word(key, arg: 1, inclusive: false)
      if @line.bytesize > @byte_pointer
        byte_size, width = Reline::Unicode.vi_forward_end_word(@line, @byte_pointer)
        @byte_pointer += byte_size
        @cursor += width
      end
      arg -= 1
      if inclusive and arg.zero?
        byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
        if byte_size > 0
          c = @line.byteslice(@byte_pointer, byte_size)
          width = Reline::Unicode.get_mbchar_width(c)
          @byte_pointer += byte_size
          @cursor += width
        end
      end
      vi_end_word(key, arg: arg) if arg > 0
    end

vi_first_print(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2115
            def vi_first_print(key)
      @byte_pointer, @cursor = Reline::Unicode.vi_first_print(@line)
    end

vi_histedit(key) click to toggle source

    # File lib/reline/line_editor.rb, line 3117
            def vi_histedit(key)
      path = Tempfile.open { |fp|
        if @is_multiline
          fp.write whole_lines.join("\n")
        else
          fp.write @line
        end
        fp.path
      }
      system("#{ENV['EDITOR']} #{path}")
      if @is_multiline
        @buffer_of_lines = File.read(path).split("\n")
        @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
        @line_index = 0
        @line = @buffer_of_lines[@line_index]
        @rerender_all = true
      else
        @line = File.read(path)
      end
      finish
    end

vi_insert(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2870
            def vi_insert(key)
      @config.editing_mode = :vi_insert
    end

vi_insert_at_bol(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2983
            def vi_insert_at_bol(key)
      ed_move_to_beg(key)
      @config.editing_mode = :vi_insert
    end

vi_join_lines(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 3328
            def vi_join_lines(key, arg: 1)
      if @is_multiline and @buffer_of_lines.size > @line_index + 1
        @cursor = calculate_width(@line)
        @byte_pointer = @line.bytesize
        @line += ' ' + @buffer_of_lines.delete_at(@line_index + 1).lstrip
        @cursor_max = calculate_width(@line)
        @buffer_of_lines[@line_index] = @line
        @rerender_all = true
        @rest_height += 1
      end
      arg -= 1
      vi_join_lines(key, arg: arg) if arg > 0
    end

vi_kill_line_prev(key) click to toggle source

Editline

  `vi-kill-line-prev` (vi: `Ctrl-U`) Delete the string from the beginning of the edit buffer to the cursor and save it to the cut buffer.

GNU `Readline`

  `unix-line-discard` (`C-u`) Kill backward from the cursor to the beginning of the current line.

    # File lib/reline/line_editor.rb, line 2636
            def vi_kill_line_prev(key)
      if @byte_pointer > 0
        @line, deleted = byteslice!(@line, 0, @byte_pointer)
        @byte_pointer = 0
        @kill_ring.append(deleted, true)
        @cursor_max = calculate_width(@line)
        @cursor = 0
      end
    end

Also aliased as: unix_line_discard
vi_list_or_eof(key) click to toggle source

    # File lib/reline/line_editor.rb, line 3059
            def vi_list_or_eof(key)
      if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
        @line = nil
        if @buffer_of_lines.size > 1
          scroll_down(@highest_in_all - @first_line_started_from)
        end
        Reline::IOGate.move_cursor_column(0)
        @eof = true
        finish
      else
        ed_newline(key)
      end
    end

Also aliased as: vi_end_of_transmission, vi_eof_maybe
vi_next_big_word(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2924
            def vi_next_big_word(key, arg: 1)
      if @line.bytesize > @byte_pointer
        byte_size, width = Reline::Unicode.vi_big_forward_word(@line, @byte_pointer)
        @byte_pointer += byte_size
        @cursor += width
      end
      arg -= 1
      vi_next_big_word(key, arg: arg) if arg > 0
    end

vi_next_char(key, arg: 1, inclusive: false) click to toggle source

    # File lib/reline/line_editor.rb, line 3223
            def vi_next_char(key, arg: 1, inclusive: false)
      @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, inclusive: inclusive) }
    end

vi_next_word(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2885
            def vi_next_word(key, arg: 1)
      if @line.bytesize > @byte_pointer
        byte_size, width = Reline::Unicode.vi_forward_word(@line, @byte_pointer, @drop_terminate_spaces)
        @byte_pointer += byte_size
        @cursor += width
      end
      arg -= 1
      vi_next_word(key, arg: arg) if arg > 0
    end

vi_paste_next(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 3151
            def vi_paste_next(key, arg: 1)
      if @vi_clipboard.size > 0
        byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
        @line = byteinsert(@line, @byte_pointer + byte_size, @vi_clipboard)
        @cursor_max += calculate_width(@vi_clipboard)
        @cursor += calculate_width(@vi_clipboard)
        @byte_pointer += @vi_clipboard.bytesize
      end
      arg -= 1
      vi_paste_next(key, arg: arg) if arg > 0
    end

vi_paste_prev(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 3139
            def vi_paste_prev(key, arg: 1)
      if @vi_clipboard.size > 0
        @line = byteinsert(@line, @byte_pointer, @vi_clipboard)
        @cursor_max += calculate_width(@vi_clipboard)
        cursor_point = @vi_clipboard.grapheme_clusters[0..-2].join
        @cursor += calculate_width(cursor_point)
        @byte_pointer += cursor_point.bytesize
      end
      arg -= 1
      vi_paste_prev(key, arg: arg) if arg > 0
    end

vi_prev_big_word(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2934
            def vi_prev_big_word(key, arg: 1)
      if @byte_pointer > 0
        byte_size, width = Reline::Unicode.vi_big_backward_word(@line, @byte_pointer)
        @byte_pointer -= byte_size
        @cursor -= width
      end
      arg -= 1
      vi_prev_big_word(key, arg: arg) if arg > 0
    end

vi_prev_char(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 3280
            def vi_prev_char(key, arg: 1)
      @waiting_proc = ->(key_for_proc) { search_prev_char(key_for_proc, arg) }
    end

vi_prev_word(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 2895
            def vi_prev_word(key, arg: 1)
      if @byte_pointer > 0
        byte_size, width = Reline::Unicode.vi_backward_word(@line, @byte_pointer)
        @byte_pointer -= byte_size
        @cursor -= width
      end
      arg -= 1
      vi_prev_word(key, arg: arg) if arg > 0
    end

vi_replace_char(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 3195
            def vi_replace_char(key, arg: 1)
      @waiting_proc = ->(k) {
        if arg == 1
          byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
          before = @line.byteslice(0, @byte_pointer)
          remaining_point = @byte_pointer + byte_size
          after = @line.byteslice(remaining_point, @line.bytesize - remaining_point)
          @line = before + k.chr + after
          @cursor_max = calculate_width(@line)
          @waiting_proc = nil
        elsif arg > 1
          byte_size = 0
          arg.times do
            byte_size += Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer + byte_size)
          end
          before = @line.byteslice(0, @byte_pointer)
          remaining_point = @byte_pointer + byte_size
          after = @line.byteslice(remaining_point, @line.bytesize - remaining_point)
          replaced = k.chr * arg
          @line = before + replaced + after
          @byte_pointer += replaced.bytesize
          @cursor += calculate_width(replaced)
          @cursor_max = calculate_width(@line)
          @waiting_proc = nil
        end
      }
    end

vi_search_next(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2349
            def vi_search_next(key)
      incremental_search_history(key)
    end

Also aliased as: forward_search_history
vi_search_prev(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2344
            def vi_search_prev(key)
      incremental_search_history(key)
    end

Also aliased as: reverse_search_history
vi_to_column(key, arg: 0) click to toggle source

    # File lib/reline/line_editor.rb, line 3180
            def vi_to_column(key, arg: 0)
      @byte_pointer, @cursor = @line.grapheme_clusters.inject([0, 0]) { |total, gc|
        # total has [byte_size, cursor]
        mbchar_width = Reline::Unicode.get_mbchar_width(gc)
        if (total.last + mbchar_width) >= arg
          break total
        elsif (total.last + mbchar_width) >= @cursor_max
          break total
        else
          total = [total.first + gc.bytesize, total.last + mbchar_width]
          total
        end
      }
    end

vi_to_history_line(key) click to toggle source

    # File lib/reline/line_editor.rb, line 3094
            def vi_to_history_line(key)
      if Reline::HISTORY.empty?
        return
      end
      if @history_pointer.nil?
        @history_pointer = 0
        @line_backup_in_history = @line
        @line = Reline::HISTORY[@history_pointer]
        @cursor_max = calculate_width(@line)
        @cursor = 0
        @byte_pointer = 0
      elsif @history_pointer.zero?
        return
      else
        Reline::HISTORY[@history_pointer] = @line
        @history_pointer = 0
        @line = Reline::HISTORY[@history_pointer]
        @cursor_max = calculate_width(@line)
        @cursor = 0
        @byte_pointer = 0
      end
    end

vi_to_next_char(key, arg: 1, inclusive: false) click to toggle source

    # File lib/reline/line_editor.rb, line 3227
            def vi_to_next_char(key, arg: 1, inclusive: false)
      @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, need_prev_char: true, inclusive: inclusive) }
    end

vi_to_prev_char(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 3284
            def vi_to_prev_char(key, arg: 1)
      @waiting_proc = ->(key_for_proc) { search_prev_char(key_for_proc, arg, true) }
    end

vi_yank(key, arg: 1) click to toggle source

    # File lib/reline/line_editor.rb, line 3047
            def vi_yank(key, arg: 1)
      @waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff|
        if byte_pointer_diff > 0
          cut = @line.byteslice(@byte_pointer, byte_pointer_diff)
        elsif byte_pointer_diff < 0
          cut = @line.byteslice(@byte_pointer + byte_pointer_diff, -byte_pointer_diff)
        end
        copy_for_vi(cut)
      }
      @waiting_operator_vi_arg = arg
    end

vi_zero(key) click to toggle source

    # File lib/reline/line_editor.rb, line 3009
            def vi_zero(key)
      @byte_pointer = 0
      @cursor = 0
    end