class Reline::LineEditor - Documentation for Ruby 3.3

# class Reline::LineEditor

### Constants

CompletionJourneyState
DIALOG_DEFAULT_HEIGHT
MAX_INPUT_LINES
MINIMUM_SCROLLBAR_HEIGHT
NullActionState
RenderedScreen
VI_MOTIONS

### Attributes

auto_indent_proc[RW]
byte_pointer[R]

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

completion_append_character[RW]
completion_proc[RW]
confirm_multiline_termination_proc[RW]
dig_perfect_match_proc[RW]
output[W]
output_modifier_proc[RW]
prompt_proc[RW]

### Public Class Methods

new(config, encoding) click to toggle source

    # File lib/reline/line_editor.rb, line 75
    def initialize(config, encoding)
      @config = config
      @completion_append_character = ''
      @screen_size = [0, 0] # Should be initialized with actual winsize in LineEditor#reset
      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 681
    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_kill_word(key)
Alias for: ed_delete_prev_word
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 1380
    def byte_pointer=(val)
      @byte_pointer = val
    end

calculate_overlay_levels(overlay_levels) click to toggle source

    # File lib/reline/line_editor.rb, line 398
    def calculate_overlay_levels(overlay_levels)
      levels = []
      overlay_levels.each do |x, w, l|
        levels.fill(l, x, w)
      end
      levels
    end

call_completion_proc() click to toggle source

    # File lib/reline/line_editor.rb, line 1165
    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 1173
    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_dialogs() click to toggle source

    # File lib/reline/line_editor.rb, line 446
    def clear_dialogs
      @dialogs.each do |dialog|
        dialog.contents = nil
        dialog.trap_key = nil
      end
    end

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

    # File lib/reline/line_editor.rb, line 1319
    def confirm_multiline_termination
      temp_buffer = @buffer_of_lines.dup
      @confirm_multiline_termination_proc.(temp_buffer.join("\n") + "\n")
    end

current_byte_pointer_cursor() click to toggle source

    # File lib/reline/line_editor.rb, line 304
    def current_byte_pointer_cursor
      calculate_width(current_line.byteslice(0, @byte_pointer))
    end

current_line() click to toggle source

    # File lib/reline/line_editor.rb, line 1216
    def current_line
      @buffer_of_lines[@line_index]
    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 1346
    def delete_text(start = nil, length = nil)
      if start.nil? and length.nil?
        if @buffer_of_lines.size == 1
          @buffer_of_lines[@line_index] = ''
          @byte_pointer = 0
        elsif @line_index == (@buffer_of_lines.size - 1) and @line_index > 0
          @buffer_of_lines.pop
          @line_index -= 1
          @byte_pointer = 0
        elsif @line_index < (@buffer_of_lines.size - 1)
          @buffer_of_lines.delete_at(@line_index)
          @byte_pointer = 0
        end
      elsif not start.nil? and not length.nil?
        if current_line
          before = current_line.byteslice(0, start)
          after = current_line.byteslice(start + length, current_line.bytesize)
          set_current_line(before + after)
        end
      elsif start.is_a?(Range)
        range = start
        first = range.first
        last = range.last
        last = current_line.bytesize - 1 if last > current_line.bytesize
        last += current_line.bytesize if last < 0
        first += current_line.bytesize if first < 0
        range = range.exclude_end? ? first...last : first..last
        line = current_line.bytes.reject.with_index{ |c, i| range.include?(i) }.map{ |c| c.chr(Encoding::ASCII_8BIT) }.join.force_encoding(@encoding)
        set_current_line(line)
      else
        set_current_line(current_line.byteslice(0, start))
      end
    end

dialog_proc_scope_completion_journey_data() click to toggle source

    # File lib/reline/line_editor.rb, line 888
    def dialog_proc_scope_completion_journey_data
      return nil unless @completion_journey_state
      line_index = @completion_journey_state.line_index
      pre_lines = @buffer_of_lines[0...line_index].map { |line| line + "\n" }
      post_lines = @buffer_of_lines[(line_index + 1)..-1].map { |line| line + "\n" }
      DialogProcScope::CompletionJourneyData.new(
        pre_lines.join + @completion_journey_state.pre,
        @completion_journey_state.post + post_lines.join,
        @completion_journey_state.list,
        @completion_journey_state.pointer
      )
    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 790
    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 218
    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 214
    def finalize
      Signal.trap('INT', @old_trap)
    end

finish() click to toggle source

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

finished?() click to toggle source

    # File lib/reline/line_editor.rb, line 1396
    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
handle_signal() click to toggle source

    # File lib/reline/line_editor.rb, line 166
    def handle_signal
      handle_interrupted
      handle_resized
    end

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 1086
    def input_key(key)
      save_old_buffer
      @config.reset_oneshot_key_bindings
      @dialogs.each do |dialog|
        if key.char.instance_of?(Symbol) and key.char == dialog.name
          return
        end
      end
      if key.char.nil?
        process_insert(force: true)
        @eof = buffer_empty?
        finish
        return
      end
      @completion_occurs = false

      if key.char.is_a?(Symbol)
        process_key(key.char, key.char)
      else
        normal_char(key)
      end

      @prev_action_state, @next_action_state = @next_action_state, NullActionState

      unless @completion_occurs
        @completion_state = CompletionState::NORMAL
        @completion_journey_state = nil
      end

      push_input_lines unless @undoing
      @undoing = false

      if @in_pasting
        clear_dialogs
        return
      end

      modified = @old_buffer_of_lines != @buffer_of_lines
      if !@completion_occurs && modified && !@config.disable_completion && @config.autocompletion
        # Auto complete starts only when edited
        process_insert(force: true)
        @completion_journey_state = retrieve_completion_journey_state
      end
      modified
    end

insert_multiline_text(text) click to toggle source

    # File lib/reline/line_editor.rb, line 1324
    def insert_multiline_text(text)
      save_old_buffer
      pre = @buffer_of_lines[@line_index].byteslice(0, @byte_pointer)
      post = @buffer_of_lines[@line_index].byteslice(@byte_pointer..)
      lines = (pre + text.gsub(/\r\n?/, "\n") + post).split("\n", -1)
      lines << '' if lines.empty?
      @buffer_of_lines[@line_index, 1] = lines
      @line_index += lines.size - 1
      @byte_pointer = @buffer_of_lines[@line_index].bytesize - post.bytesize
      push_input_lines
    end

insert_text(text) click to toggle source

    # File lib/reline/line_editor.rb, line 1336
    def insert_text(text)
      if @buffer_of_lines[@line_index].bytesize == @byte_pointer
        @buffer_of_lines[@line_index] += text
      else
        @buffer_of_lines[@line_index] = byteinsert(@buffer_of_lines[@line_index], @byte_pointer, text)
      end
      @byte_pointer += text.bytesize
      process_auto_indent
    end

io_gate() click to toggle source

    # File lib/reline/line_editor.rb, line 82
    def io_gate
      Reline::IOGate
    end

kill_line(key)
Alias for: ed_kill_line
kill_whole_line(key)
Alias for: em_kill_line
kill_word(key)
Alias for: em_delete_next_word
line() click to toggle source

    # File lib/reline/line_editor.rb, line 1212
    def line()
      @buffer_of_lines.join("\n") unless eof?
    end

modified_lines() click to toggle source

    # File lib/reline/line_editor.rb, line 351
    def modified_lines
      with_cache(__method__, whole_lines, finished?) do |whole, complete|
        modify_lines(whole, complete)
      end
    end

multiline_off() click to toggle source

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

multiline_on() click to toggle source

    # File lib/reline/line_editor.rb, line 269
    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
print_nomultiline_prompt() click to toggle source

    # File lib/reline/line_editor.rb, line 471
    def print_nomultiline_prompt
      # Readline's test `TestRelineAsReadline#test_readline` requires first output to be prompt, not cursor reset escape sequence.
      @output.write @prompt if @prompt && !@is_multiline
    end

prompt_list() click to toggle source

    # File lib/reline/line_editor.rb, line 357
    def prompt_list
      with_cache(__method__, whole_lines, check_mode_string, @vi_arg, @searching_prompt) do |lines, mode_string|
        check_multiline_prompt(lines, mode_string)
      end
    end

push_input_lines() click to toggle source

    # File lib/reline/line_editor.rb, line 1136
    def push_input_lines
      if @old_buffer_of_lines == @buffer_of_lines
        @input_lines[@input_lines_position] = [@buffer_of_lines.dup, @byte_pointer, @line_index]
      else
        @input_lines = @input_lines[0..@input_lines_position]
        @input_lines_position += 1
        @input_lines.push([@buffer_of_lines.dup, @byte_pointer, @line_index])
      end
      trim_input_lines
    end

quoted_insert(str, arg: 1)
Alias for: ed_quoted_insert
render() click to toggle source

    # File lib/reline/line_editor.rb, line 476
    def render
      wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
      new_lines = wrapped_prompt_and_input_lines.flatten(1)[screen_scroll_top, screen_height].map do |prompt, line|
        prompt_width = Reline::Unicode.calculate_width(prompt, true)
        [[0, prompt_width, prompt], [prompt_width, Reline::Unicode.calculate_width(line, true), line]]
      end
      if @menu_info
        @menu_info.lines(screen_width).each do |item|
          new_lines << [[0, Reline::Unicode.calculate_width(item), item]]
        end
        @menu_info = nil # TODO: do not change state here
      end

      @dialogs.each_with_index do |dialog, index|
        next unless dialog.contents

        x_range, y_range = dialog_range dialog, wrapped_cursor_y - screen_scroll_top
        y_range.each do |row|
          next if row < 0 || row >= screen_height

          dialog_rows = new_lines[row] ||= []
          # index 0 is for prompt, index 1 is for line, index 2.. is for dialog
          dialog_rows[index + 2] = [x_range.begin, dialog.width, dialog.contents[row - y_range.begin]]
        end
      end

      render_differential new_lines, wrapped_cursor_x, wrapped_cursor_y - screen_scroll_top
    end

render_finished() click to toggle source

    # File lib/reline/line_editor.rb, line 461
    def render_finished
      render_differential([], 0, 0)
      lines = @buffer_of_lines.size.times.map do |i|
        line = prompt_list[i] + modified_lines[i]
        wrapped_lines, = split_by_width(line, screen_width)
        wrapped_lines.last.empty? ? "#{line} " : line
      end
      @output.puts lines.map { |l| "#{l}\r\n" }.join
    end

render_line_differential(old_items, new_items) click to toggle source

    # File lib/reline/line_editor.rb, line 406
    def render_line_differential(old_items, new_items)
      old_levels = calculate_overlay_levels(old_items.zip(new_items).each_with_index.map {|((x, w, c), (nx, _nw, nc)), i| [x, w, c == nc && x == nx ? i : -1] if x }.compact)
      new_levels = calculate_overlay_levels(new_items.each_with_index.map { |(x, w), i| [x, w, i] if x }.compact).take(screen_width)
      base_x = 0
      new_levels.zip(old_levels).chunk { |n, o| n == o ? :skip : n || :blank }.each do |level, chunk|
        width = chunk.size
        if level == :skip
          # do nothing
        elsif level == :blank
          Reline::IOGate.move_cursor_column base_x
          @output.write "#{Reline::IOGate.reset_color_sequence}#{' ' * width}"
        else
          x, w, content = new_items[level]
          cover_begin = base_x != 0 && new_levels[base_x - 1] == level
          cover_end = new_levels[base_x + width] == level
          pos = 0
          unless x == base_x && w == width
            content, pos = Reline::Unicode.take_mbchar_range(content, base_x - x, width, cover_begin: cover_begin, cover_end: cover_end, padding: true)
          end
          Reline::IOGate.move_cursor_column x + pos
          @output.write "#{Reline::IOGate.reset_color_sequence}#{content}#{Reline::IOGate.reset_color_sequence}"
        end
        base_x += width
      end
      if old_levels.size > new_levels.size
        Reline::IOGate.move_cursor_column new_levels.size
        Reline::IOGate.erase_after_cursor
      end
    end

rerender() click to toggle source

    # File lib/reline/line_editor.rb, line 554
    def rerender
      render unless @in_pasting
    end

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

    # File lib/reline/line_editor.rb, line 139
    def reset(prompt = '', encoding:)
      @screen_size = Reline::IOGate.get_screen_size
      reset_variables(prompt, encoding: encoding)
      @rendered_screen.base_y = Reline::IOGate.cursor_pos.y
      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 260
    def reset_line
      @byte_pointer = 0
      @buffer_of_lines = [String.new(encoding: @encoding)]
      @line_index = 0
      @cache.clear
      @line_backup_in_history = nil
      @multibyte_buffer = String.new(encoding: 'ASCII-8BIT')
    end

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

    # File lib/reline/line_editor.rb, line 222
    def reset_variables(prompt = '', encoding:)
      @prompt = prompt.gsub("\n", "\\n")
      @mark_pointer = nil
      @encoding = encoding
      @is_multiline = false
      @finished = false
      @history_pointer = nil
      @kill_ring ||= Reline::KillRing.new
      @vi_clipboard = ''
      @vi_arg = nil
      @waiting_proc = nil
      @vi_waiting_operator = nil
      @vi_waiting_operator_arg = nil
      @completion_journey_state = nil
      @completion_state = CompletionState::NORMAL
      @perfect_matched = nil
      @menu_info = nil
      @searching_prompt = nil
      @just_cursor_moving = false
      @eof = false
      @continuous_insertion_buffer = String.new(encoding: @encoding)
      @scroll_partial_screen = 0
      @drop_terminate_spaces = false
      @in_pasting = false
      @auto_indent_proc = nil
      @dialogs = []
      @interrupted = false
      @resized = false
      @cache = {}
      @rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0)
      @input_lines = [[[""], 0, 0]]
      @input_lines_position = 0
      @undoing = false
      @prev_action_state = NullActionState
      @next_action_state = NullActionState
      reset_line
    end

rest_height(wrapped_cursor_y) click to toggle source

    # File lib/reline/line_editor.rb, line 550
    def rest_height(wrapped_cursor_y)
      screen_height - wrapped_cursor_y + screen_scroll_top - @rendered_screen.base_y - 1
    end

retrieve_completion_block(set_completion_quote_character = false) click to toggle source

    # File lib/reline/line_editor.rb, line 1243
    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 = current_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 = current_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 = current_line.byteslice(i, @byte_pointer - i)
          break_pointer = i
        else
          i += 1
        end
      end
      postposing = current_line.byteslice(@byte_pointer, current_line.bytesize - @byte_pointer)
      if rest
        preposing = current_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 = current_line.byteslice(0, break_pointer)
        else
          preposing = ''
        end
        target = before
      end
      lines = whole_lines
      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
      [preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)]
    end

reverse_search_history(key)
Alias for: vi_search_prev
save_old_buffer() click to toggle source

    # File lib/reline/line_editor.rb, line 1132
    def save_old_buffer
      @old_buffer_of_lines = @buffer_of_lines.dup
    end

screen_height() click to toggle source

    # File lib/reline/line_editor.rb, line 363
    def screen_height
      @screen_size.first
    end

screen_scroll_top() click to toggle source

    # File lib/reline/line_editor.rb, line 371
    def screen_scroll_top
      @scroll_partial_screen
    end

screen_width() click to toggle source

    # File lib/reline/line_editor.rb, line 367
    def screen_width
      @screen_size.last
    end

scroll_into_view() click to toggle source

    # File lib/reline/line_editor.rb, line 1155
    def scroll_into_view
      _wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
      if wrapped_cursor_y < screen_scroll_top
        @scroll_partial_screen = wrapped_cursor_y
      end
      if wrapped_cursor_y >= screen_scroll_top + screen_height
        @scroll_partial_screen = wrapped_cursor_y - screen_height + 1
      end
    end

self_insert(key)
Alias for: ed_insert
set_current_line(line, byte_pointer = nil) click to toggle source

    # File lib/reline/line_editor.rb, line 1220
    def set_current_line(line, byte_pointer = nil)
      cursor = current_byte_pointer_cursor
      @buffer_of_lines[@line_index] = line
      if byte_pointer
        @byte_pointer = byte_pointer
      else
        calculate_nearest_cursor(cursor)
      end
      process_auto_indent
    end

set_current_lines(lines, byte_pointer = nil, line_index = 0) click to toggle source

    # File lib/reline/line_editor.rb, line 1231
    def set_current_lines(lines, byte_pointer = nil, line_index = 0)
      cursor = current_byte_pointer_cursor
      @buffer_of_lines = lines
      @line_index = line_index
      if byte_pointer
        @byte_pointer = byte_pointer
      else
        calculate_nearest_cursor(cursor)
      end
      process_auto_indent
    end

set_mark(key)
Alias for: em_set_mark
set_pasting_state(in_pasting) click to toggle source

    # File lib/reline/line_editor.rb, line 86
    def set_pasting_state(in_pasting)
      # While pasting, text to be inserted is stored to @continuous_insertion_buffer.
      # After pasting, this buffer should be force inserted.
      process_insert(force: true) if @in_pasting && !in_pasting
      @in_pasting = in_pasting
    end

set_signal_handlers() click to toggle source

    # File lib/reline/line_editor.rb, line 205
    def set_signal_handlers
      Reline::IOGate.set_winch_handler do
        @resized = true
      end
      @old_trap = Signal.trap('INT') do
        @interrupted = true
      end
    end

transpose_chars(key)
Alias for: ed_transpose_chars
transpose_words(key)
Alias for: ed_transpose_words
trim_input_lines() click to toggle source

    # File lib/reline/line_editor.rb, line 1148
    def trim_input_lines
      if @input_lines.size > MAX_INPUT_LINES
        @input_lines.shift
        @input_lines_position -= 1
      end
    end

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
update(key) click to toggle source

    # File lib/reline/line_editor.rb, line 1076
    def update(key)
      modified = input_key(key)
      unless @in_pasting
        scroll_into_view
        @just_cursor_moving = !modified
        update_dialogs(key)
        @just_cursor_moving = false
      end
    end

update_dialogs(key = nil) click to toggle source

    # File lib/reline/line_editor.rb, line 453
    def update_dialogs(key = nil)
      wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
      @dialogs.each do |dialog|
        dialog.trap_key = nil
        update_each_dialog(dialog, wrapped_cursor_x, wrapped_cursor_y - screen_scroll_top, key)
      end
    end

upper_space_height(wrapped_cursor_y) click to toggle source

    # File lib/reline/line_editor.rb, line 546
    def upper_space_height(wrapped_cursor_y)
      wrapped_cursor_y - screen_scroll_top
    end

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
vi_zero(key)
Alias for: ed_move_to_beg
whole_buffer() click to toggle source

    # File lib/reline/line_editor.rb, line 1388
    def whole_buffer
      whole_lines.join("\n")
    end

whole_lines() click to toggle source

    # File lib/reline/line_editor.rb, line 1384
    def whole_lines
      @buffer_of_lines.dup
    end

with_cache(key, *deps) { |*deps, cached_deps, value| ... } click to toggle source

    # File lib/reline/line_editor.rb, line 343
    def with_cache(key, *deps)
      cached_deps, value = @cache[key]
      if cached_deps != deps
        @cache[key] = [deps, value = yield(*deps, cached_deps, value)]
      end
      value
    end

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

    # File lib/reline/line_editor.rb, line 962
    def wrap_method_call(method_symbol, method_obj, key, with_operator = false)
      if @config.editing_mode_is?(:emacs, :vi_insert) and @vi_waiting_operator.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

wrapped_cursor_position() click to toggle source

Calculate cursor position in word wrapped content.

    # File lib/reline/line_editor.rb, line 437
    def wrapped_cursor_position
      prompt_width = calculate_width(prompt_list[@line_index], true)
      line_before_cursor = whole_lines[@line_index].byteslice(0, @byte_pointer)
      wrapped_line_before_cursor = split_by_width(' ' * prompt_width + line_before_cursor, screen_width).first.compact
      wrapped_cursor_y = wrapped_prompt_and_input_lines[0...@line_index].sum(&:size) + wrapped_line_before_cursor.size - 1
      wrapped_cursor_x = calculate_width(wrapped_line_before_cursor.last)
      [wrapped_cursor_x, wrapped_cursor_y]
    end

wrapped_prompt_and_input_lines() click to toggle source

    # File lib/reline/line_editor.rb, line 375
    def wrapped_prompt_and_input_lines
      with_cache(__method__, @buffer_of_lines.size, modified_lines, prompt_list, screen_width) do |n, lines, prompts, width, prev_cache_key, cached_value|
        prev_n, prev_lines, prev_prompts, prev_width = prev_cache_key
        cached_wraps = {}
        if prev_width == width
          prev_n.times do |i|
            cached_wraps[[prev_prompts[i], prev_lines[i]]] = cached_value[i]
          end
        end

        n.times.map do |i|
          prompt = prompts[i] || ''
          line = lines[i] || ''
          if (cached = cached_wraps[[prompt, line]])
            next cached
          end
          *wrapped_prompts, code_line_prompt = split_by_width(prompt, width).first.compact
          wrapped_lines = split_by_width(line, width, offset: calculate_width(code_line_prompt, true)).first.compact
          wrapped_prompts.map { |p| [p, ''] } + [[code_line_prompt, wrapped_lines.first]] + wrapped_lines.drop(1).map { |c| ['', c] }
        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 952
            def argumentable?(method_obj)
      method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :arg }
    end

buffer_empty?() click to toggle source

    # File lib/reline/line_editor.rb, line 1392
            def buffer_empty?
      current_line.empty? and @buffer_of_lines.size == 1
    end

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

    # File lib/reline/line_editor.rb, line 1411
            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 1405
            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_nearest_cursor(cursor) click to toggle source

    # File lib/reline/line_editor.rb, line 308
            def calculate_nearest_cursor(cursor)
      line_to_calc = current_line
      new_cursor_max = calculate_width(line_to_calc)
      new_cursor = 0
      new_byte_pointer = 0
      height = 1
      max_width = screen_width
      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
      @byte_pointer = new_byte_pointer
    end

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

    # File lib/reline/line_editor.rb, line 1418
            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 93
            def check_mode_string
      if @config.show_mode_in_prompt
        if @config.editing_mode_is?(:vi_command)
          @config.vi_cmd_mode_string
        elsif @config.editing_mode_is?(:vi_insert)
          @config.vi_ins_mode_string
        elsif @config.editing_mode_is?(:emacs)
          @config.emacs_mode_string
        else
          '?'
        end
      end
    end

check_multiline_prompt(buffer, mode_string) click to toggle source

    # File lib/reline/line_editor.rb, line 107
            def check_multiline_prompt(buffer, mode_string)
      if @vi_arg
        prompt = "(arg: #{@vi_arg}) "
      elsif @searching_prompt
        prompt = @searching_prompt
      else
        prompt = @prompt
      end
      if !@is_multiline
        mode_string = check_mode_string
        prompt = mode_string + prompt if mode_string
        [prompt] + [''] * (buffer.size - 1)
      elsif @prompt_proc
        prompt_list = @prompt_proc.(buffer).map { |pr| pr.gsub("\n", "\\n") }
        prompt_list.map!{ prompt } if @vi_arg or @searching_prompt
        prompt_list = [prompt] if prompt_list.empty?
        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_list
      else
        prompt = mode_string + prompt if mode_string
        [prompt] * buffer.size
      end
    end

cleanup_waiting() click to toggle source

    # File lib/reline/line_editor.rb, line 982
            def cleanup_waiting
      @waiting_proc = nil
      @vi_waiting_operator = nil
      @vi_waiting_operator_arg = nil
      @searching_prompt = nil
      @drop_terminate_spaces = false
    end

clear_rendered_screen_cache() click to toggle source

    # File lib/reline/line_editor.rb, line 541
            def clear_rendered_screen_cache
      @rendered_screen.lines = []
      @rendered_screen.cursor_y = 0
    end

complete(_key) click to toggle source

    # File lib/reline/line_editor.rb, line 1438
            def complete(_key)
      return if @config.disable_completion

      process_insert(force: true)
      if @config.autocompletion
        @completion_state = CompletionState::NORMAL
        @completion_occurs = move_completed_list(:down)
      else
        @completion_journey_state = nil
        result = call_completion_proc
        if result.is_a?(Array)
          @completion_occurs = true
          perform_completion(result, false)
        end
      end
    end

complete_internal_proc(list, is_menu) click to toggle source

    # File lib/reline/line_editor.rb, line 798
            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

completion_journey_move(direction) click to toggle source

    # File lib/reline/line_editor.rb, line 1455
            def completion_journey_move(direction)
      return if @config.disable_completion

      process_insert(force: true)
      @completion_state = CompletionState::NORMAL
      @completion_occurs = move_completed_list(direction)
    end

completion_journey_up(_key) click to toggle source

    # File lib/reline/line_editor.rb, line 1471
            def completion_journey_up(_key)
      completion_journey_move(:up) if @config.autocompletion
    end

copy_for_vi(text) click to toggle source

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

dialog_range(dialog, dialog_y) click to toggle source

    # File lib/reline/line_editor.rb, line 692
            def dialog_range(dialog, dialog_y)
      x_range = dialog.column...dialog.column + dialog.width
      y_range = dialog_y + dialog.vertical_offset...dialog_y + dialog.vertical_offset + dialog.contents.size
      [x_range, y_range]
    end

ed_argument_digit(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2339
            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 1966
            def ed_clear_screen(key)
      Reline::IOGate.clear_screen
      @screen_size = Reline::IOGate.get_screen_size
      @rendered_screen.base_y = 0
      clear_rendered_screen_cache
    end

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

    # File lib/reline/line_editor.rb, line 2285
            def ed_delete_next_char(key, arg: 1)
      byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
      unless current_line.empty? || byte_size == 0
        line, mbchar = byteslice!(current_line, @byte_pointer, byte_size)
        copy_for_vi(mbchar)
        if @byte_pointer > 0 && current_line.bytesize == @byte_pointer + byte_size
          byte_size = Reline::Unicode.get_prev_mbchar_size(line, @byte_pointer)
          set_current_line(line, @byte_pointer - byte_size)
        else
          set_current_line(line, @byte_pointer)
        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 2197
            def ed_delete_prev_char(key, arg: 1)
      deleted = +''
      arg.times do
        if @byte_pointer > 0
          byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer)
          @byte_pointer -= byte_size
          line, mbchar = byteslice!(current_line, @byte_pointer, byte_size)
          set_current_line(line)
          deleted.prepend(mbchar)
        end
      end
      copy_for_vi(deleted)
    end

ed_delete_prev_word(key) click to toggle source

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

Also aliased as: backward_kill_word
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 1498
            def ed_insert(key)
      if key.instance_of?(String)
        begin
          key.encode(Encoding::UTF_8)
        rescue Encoding::UndefinedConversionError
          return
        end
        str = key
      else
        begin
          key.chr.encode(Encoding::UTF_8)
        rescue Encoding::UndefinedConversionError
          return
        end
        str = key.chr
      end
      if @in_pasting
        @continuous_insertion_buffer << str
        return
      elsif not @continuous_insertion_buffer.empty?
        process_insert
      end

      insert_text(str)
    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 1879
            def ed_kill_line(key)
      if current_line.bytesize > @byte_pointer
        line, deleted = byteslice!(current_line, @byte_pointer, current_line.bytesize - @byte_pointer)
        set_current_line(line, line.bytesize)
        @kill_ring.append(deleted)
      elsif @byte_pointer == current_line.bytesize and @buffer_of_lines.size > @line_index + 1
        set_current_line(current_line + @buffer_of_lines.delete_at(@line_index + 1), current_line.bytesize)
      end
    end

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

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

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

    # File lib/reline/line_editor.rb, line 1578
            def ed_move_to_end(key)
      @byte_pointer = current_line.bytesize
    end

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

    # File lib/reline/line_editor.rb, line 1829
            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?
            @line_index = @buffer_of_lines.size - 1
            @byte_pointer = current_line.bytesize
            finish
          end
        end
      else
        finish
      end
    end

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

    # File lib/reline/line_editor.rb, line 1542
            def ed_next_char(key, arg: 1)
      byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
      if (@byte_pointer < current_line.bytesize)
        @byte_pointer += byte_size
      elsif @config.editing_mode_is?(:emacs) and @byte_pointer == current_line.bytesize and @line_index < @buffer_of_lines.size - 1
        @byte_pointer = 0
        @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 1812
            def ed_next_history(key, arg: 1)
      if @line_index < (@buffer_of_lines.size - 1)
        cursor = current_byte_pointer_cursor
        @line_index += 1
        calculate_nearest_cursor(cursor)
        return
      end
      move_history(
        (@history_pointer || Reline::HISTORY.size) + 1,
        line: :start,
        cursor: @config.editing_mode_is?(:vi_command) ? :start : :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 1555
            def ed_prev_char(key, arg: 1)
      if @byte_pointer > 0
        byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer)
        @byte_pointer -= byte_size
      elsif @config.editing_mode_is?(:emacs) and @byte_pointer == 0 and @line_index > 0
        @line_index -= 1
        @byte_pointer = current_line.bytesize
      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 1795
            def ed_prev_history(key, arg: 1)
      if @line_index > 0
        cursor = current_byte_pointer_cursor
        @line_index -= 1
        calculate_nearest_cursor(cursor)
        return
      end
      move_history(
        (@history_pointer || Reline::HISTORY.size) - 1,
        line: :end,
        cursor: @config.editing_mode_is?(:vi_command) ? :start : :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 1982
            def ed_prev_word(key)
      if @byte_pointer > 0
        byte_size, _ = Reline::Unicode.em_backward_word(current_line, @byte_pointer)
        @byte_pointer -= byte_size
      end
    end

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

    # File lib/reline/line_editor.rb, line 1526
            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 1758
            def ed_search_next_history(key, arg: 1)
      substr = prev_action_state_value(:search_history) == :empty ? '' : current_line.byteslice(0, @byte_pointer)
      return if @history_pointer.nil?

      history_range = @history_pointer + 1...Reline::HISTORY.size
      h_pointer, line_index = search_history(substr, history_range)
      return if h_pointer.nil? and not substr.empty?

      move_history(h_pointer, line: line_index || :start, cursor: substr.empty? ? :end : @byte_pointer)
      arg -= 1
      set_next_action_state(:search_history, :empty) if substr.empty?
      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 1743
            def ed_search_prev_history(key, arg: 1)
      substr = prev_action_state_value(:search_history) == :empty ? '' : current_line.byteslice(0, @byte_pointer)
      return if @history_pointer == 0
      return if @history_pointer.nil? && substr.empty? && !current_line.empty?

      history_range = 0...(@history_pointer || Reline::HISTORY.size)
      h_pointer, line_index = search_history(substr, history_range.reverse_each)
      return unless h_pointer
      move_history(h_pointer, line: line_index || :start, cursor: substr.empty? ? :end : @byte_pointer)
      arg -= 1
      set_next_action_state(:search_history, :empty) if substr.empty?
      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 2010
            def ed_transpose_chars(key)
      if @byte_pointer > 0
        if @byte_pointer < current_line.bytesize
          byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
          @byte_pointer += byte_size
        end
        back1_byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer)
        if (@byte_pointer - back1_byte_size) > 0
          back2_byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer - back1_byte_size)
          back2_pointer = @byte_pointer - back1_byte_size - back2_byte_size
          line, back2_mbchar = byteslice!(current_line, back2_pointer, back2_byte_size)
          set_current_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 2027
            def ed_transpose_words(key)
      left_word_start, middle_start, right_word_start, after_start = Reline::Unicode.ed_transpose_words(current_line, @byte_pointer)
      before = current_line.byteslice(0, left_word_start)
      left_word = current_line.byteslice(left_word_start, middle_start - left_word_start)
      middle = current_line.byteslice(middle_start, right_word_start - middle_start)
      right_word = current_line.byteslice(right_word_start, after_start - right_word_start)
      after = current_line.byteslice(after_start, current_line.bytesize - after_start)
      return if left_word.empty? or right_word.empty?
      from_head_to_left_word = before + right_word + middle + left_word
      set_current_line(from_head_to_left_word + after, from_head_to_left_word.bytesize)
    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 1477
    def ed_unassigned(key) end

em_capitol_case(key) click to toggle source

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

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

    # File lib/reline/line_editor.rb, line 1923
            def em_delete(key)
      if buffer_empty? and key == "\C-d".ord
        @eof = true
        finish
      elsif @byte_pointer < current_line.bytesize
        splitted_last = current_line.byteslice(@byte_pointer, current_line.bytesize)
        mbchar = splitted_last.grapheme_clusters.first
        line, = byteslice!(current_line, @byte_pointer, mbchar.bytesize)
        set_current_line(line)
      elsif @byte_pointer == current_line.bytesize and @buffer_of_lines.size > @line_index + 1
        set_current_line(current_line + @buffer_of_lines.delete_at(@line_index + 1), current_line.bytesize)
      end
    end

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

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

Also aliased as: kill_word
em_delete_or_list(key) click to toggle source

    # File lib/reline/line_editor.rb, line 1938
            def em_delete_or_list(key)
      if current_line.empty? or @byte_pointer < current_line.bytesize
        em_delete(key)
      elsif !@config.autocompletion # show completed list
        result = call_completion_proc
        if result.is_a?(Array)
          perform_completion(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 1858
            def em_delete_prev_char(key, arg: 1)
      arg.times do
        if @byte_pointer == 0 and @line_index > 0
          @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
        elsif @byte_pointer > 0
          byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer)
          line, = byteslice!(current_line, @byte_pointer - byte_size, byte_size)
          set_current_line(line, @byte_pointer - byte_size)
        end
      end
      process_auto_indent
    end

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

    # File lib/reline/line_editor.rb, line 2501
            def em_exchange_mark(key)
      return unless @mark_pointer
      new_pointer = [@byte_pointer, @line_index]
      @byte_pointer, @line_index = @mark_pointer
      @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 1915
            def em_kill_line(key)
      if current_line.size > 0
        @kill_ring.append(current_line.dup, true)
        set_current_line('', 0)
      end
    end

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

    # File lib/reline/line_editor.rb, line 2076
            def em_kill_region(key)
      if @byte_pointer > 0
        byte_size, _ = Reline::Unicode.em_big_backward_word(current_line, @byte_pointer)
        line, deleted = byteslice!(current_line, @byte_pointer - byte_size, byte_size)
        set_current_line(line, @byte_pointer - byte_size)
        @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 2050
            def em_lower_case(key)
      if current_line.bytesize > @byte_pointer
        byte_size, = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
        part = current_line.byteslice(@byte_pointer, byte_size).grapheme_clusters.map { |mbchar|
          mbchar =~ /[A-Z]/ ? mbchar.downcase : mbchar
        }.join
        rest = current_line.byteslice((@byte_pointer + byte_size)..-1)
        line = current_line.byteslice(0, @byte_pointer) + part
        set_current_line(line + rest, line.bytesize)
      end
    end

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

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

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

    # File lib/reline/line_editor.rb, line 2496
            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 2063
            def em_upper_case(key)
      if current_line.bytesize > @byte_pointer
        byte_size, = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
        part = current_line.byteslice(@byte_pointer, byte_size).grapheme_clusters.map { |mbchar|
          mbchar =~ /[a-z]/ ? mbchar.upcase : mbchar
        }.join
        rest = current_line.byteslice((@byte_pointer + byte_size)..-1)
        line = current_line.byteslice(0, @byte_pointer) + part
        set_current_line(line + rest, line.bytesize)
      end
    end

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

    # File lib/reline/line_editor.rb, line 1950
            def em_yank(key)
      yanked = @kill_ring.yank
      insert_text(yanked) if yanked
    end

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

    # File lib/reline/line_editor.rb, line 1956
            def em_yank_pop(key)
      yanked, prev_yank = @kill_ring.yank_pop
      if yanked
        line, = byteslice!(current_line, @byte_pointer - prev_yank.bytesize, prev_yank.bytesize)
        set_current_line(line, @byte_pointer - prev_yank.bytesize)
        insert_text(yanked)
      end
    end

Also aliased as: yank_pop
emacs_editing_mode(key) click to toggle source

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

generate_searcher(search_key) click to toggle source

    # File lib/reline/line_editor.rb, line 1583
            def generate_searcher(search_key)
      search_word = String.new(encoding: @encoding)
      multibyte_buf = String.new(encoding: 'ASCII-8BIT')
      hit_pointer = nil
      lambda do |key|
        search_again = false
        case key
        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 search_key == key
          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)
          hit_pointer = Reline::HISTORY.size
          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 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 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 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
            hit_pointer = history_pointer_base + hit_index
            hit = Reline::HISTORY[hit_pointer]
          end
        end
        case search_key
        when "\C-r".ord
          prompt_name = 'reverse-i-search'
        when "\C-s".ord
          prompt_name = 'i-search'
        end
        prompt_name = "failed #{prompt_name}" unless hit
        [search_word, prompt_name, hit_pointer]
      end
    end

handle_interrupted() click to toggle source

    # File lib/reline/line_editor.rb, line 183
            def handle_interrupted
      return unless @interrupted

      @interrupted = false
      clear_dialogs
      render
      cursor_to_bottom_offset = @rendered_screen.lines.size - @rendered_screen.cursor_y
      Reline::IOGate.scroll_down cursor_to_bottom_offset
      Reline::IOGate.move_cursor_column 0
      clear_rendered_screen_cache
      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
    end

handle_resized() click to toggle source

    # File lib/reline/line_editor.rb, line 171
            def handle_resized
      return unless @resized

      @screen_size = Reline::IOGate.get_screen_size
      @resized = false
      scroll_into_view
      Reline::IOGate.move_cursor_up @rendered_screen.cursor_y
      @rendered_screen.base_y = Reline::IOGate.cursor_pos.y
      clear_rendered_screen_cache
      render
    end

inclusive?(method_obj) click to toggle source

    # File lib/reline/line_editor.rb, line 956
            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 1667
            def incremental_search_history(key)
      unless @history_pointer
        @line_backup_in_history = whole_buffer
      end
      searcher = generate_searcher(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
          @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
          @searching_prompt = nil
          @waiting_proc = nil
          @byte_pointer = 0
        when "\C-g".ord
          @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
          move_history(nil, line: :end, cursor: :end, save_buffer: false)
          @searching_prompt = nil
          @waiting_proc = nil
          @byte_pointer = 0
        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
            search_word, prompt_name, hit_pointer = searcher.call(k)
            Reline.last_incremental_search = search_word
            @searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
            @searching_prompt += ': ' unless @is_multiline
            move_history(hit_pointer, line: :end, cursor: :end, save_buffer: false) if hit_pointer
          else
            if @history_pointer
              line = Reline::HISTORY[@history_pointer]
            else
              line = @line_backup_in_history
            end
            @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
            @searching_prompt = nil
            @waiting_proc = nil
            @byte_pointer = 0
          end
        end
      }
    end

insert_new_line(cursor_line, next_line) click to toggle source

    # File lib/reline/line_editor.rb, line 277
            def insert_new_line(cursor_line, next_line)
      @buffer_of_lines.insert(@line_index + 1, String.new(next_line, encoding: @encoding))
      @buffer_of_lines[@line_index] = cursor_line
      @line_index += 1
      @byte_pointer = 0
      if @auto_indent_proc && !@in_pasting
        if next_line.empty?
          (
            # For compatibility, use this calculation instead of just `process_auto_indent @line_index - 1, cursor_dependent: false`
            indent1 = @auto_indent_proc.(@buffer_of_lines.take(@line_index - 1).push(''), @line_index - 1, 0, true)
            indent2 = @auto_indent_proc.(@buffer_of_lines.take(@line_index), @line_index - 1, @buffer_of_lines[@line_index - 1].bytesize, false)
            indent = indent2 || indent1
            @buffer_of_lines[@line_index - 1] = ' ' * indent + @buffer_of_lines[@line_index - 1].gsub(/\A\s*/, '')
          )
          process_auto_indent @line_index, add_newline: true
        else
          process_auto_indent @line_index - 1, cursor_dependent: false
          process_auto_indent @line_index, add_newline: true # Need for compatibility
          process_auto_indent @line_index, cursor_dependent: false
        end
      end
    end

key_delete(key) click to toggle source

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

key_newline(key) click to toggle source

    # File lib/reline/line_editor.rb, line 1430
            def key_newline(key)
      if @is_multiline
        next_line = current_line.byteslice(@byte_pointer, current_line.bytesize - @byte_pointer)
        cursor_line = current_line.byteslice(0, @byte_pointer)
        insert_new_line(cursor_line, next_line)
      end
    end

modify_lines(before, complete) click to toggle source

    # File lib/reline/line_editor.rb, line 782
            def modify_lines(before, complete)
      if after = @output_modifier_proc&.call("#{before.join("\n")}\n", complete: complete)
        after.lines("\n").map { |l| l.chomp('') }
      else
        before.map { |l| Reline::Unicode.escape_for_print(l) }
      end
    end

move_completed_list(direction) click to toggle source

    # File lib/reline/line_editor.rb, line 901
            def move_completed_list(direction)
      @completion_journey_state ||= retrieve_completion_journey_state
      return false unless @completion_journey_state

      if (delta = { up: -1, down: +1 }[direction])
        @completion_journey_state.pointer = (@completion_journey_state.pointer + delta) % @completion_journey_state.list.size
      end
      completed = @completion_journey_state.list[@completion_journey_state.pointer]
      set_current_line(@completion_journey_state.pre + completed + @completion_journey_state.post, @completion_journey_state.pre.bytesize + completed.bytesize)
      true
    end

move_history(history_pointer, line:, cursor:, save_buffer: true) click to toggle source

    # File lib/reline/line_editor.rb, line 1773
            def move_history(history_pointer, line:, cursor:, save_buffer: true)
      history_pointer ||= Reline::HISTORY.size
      return if history_pointer < 0 || history_pointer > Reline::HISTORY.size
      old_history_pointer = @history_pointer || Reline::HISTORY.size
      if old_history_pointer == Reline::HISTORY.size
        @line_backup_in_history = save_buffer ? whole_buffer : ''
      else
        Reline::HISTORY[old_history_pointer] = whole_buffer if save_buffer
      end
      if history_pointer == Reline::HISTORY.size
        buf = @line_backup_in_history
        @history_pointer = @line_backup_in_history = nil
      else
        buf = Reline::HISTORY[history_pointer]
        @history_pointer = history_pointer
      end
      @buffer_of_lines = buf.split("\n")
      @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
      @line_index = line == :start ? 0 : line == :end ? @buffer_of_lines.size - 1 : line
      @byte_pointer = cursor == :start ? 0 : cursor == :end ? current_line.bytesize : cursor
    end

normal_char(key) click to toggle source

    # File lib/reline/line_editor.rb, line 1054
            def normal_char(key)
      @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)
        process_key(key.combined_char, method_symbol)
        @multibyte_buffer.clear
      end
      if @config.editing_mode_is?(:vi_command) and @byte_pointer > 0 and @byte_pointer == current_line.bytesize
        byte_size = Reline::Unicode.get_prev_mbchar_size(@buffer_of_lines[@line_index], @byte_pointer)
        @byte_pointer -= byte_size
      end
    end

perform_completion(list, just_show_list) click to toggle source

    # File lib/reline/line_editor.rb, line 844
            def perform_completion(list, just_show_list)
      case @completion_state
      when CompletionState::NORMAL
        @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
            perform_completion(list, true) if @config.show_all_if_ambiguous
          end
          @perfect_matched = completed
        else
          @completion_state = CompletionState::MENU
          perform_completion(list, true) if @config.show_all_if_ambiguous
        end
        if not just_show_list and target < completed
          @buffer_of_lines[@line_index] = (preposing + completed + completion_append_character.to_s + postposing).split("\n")[@line_index] || String.new(encoding: @encoding)
          line_to_pointer = (preposing + completed + completion_append_character.to_s).split("\n")[@line_index] || String.new(encoding: @encoding)
          @byte_pointer = line_to_pointer.bytesize
        end
      end
    end

prev_action_state_value(type) click to toggle source

    # File lib/reline/line_editor.rb, line 2537
            def prev_action_state_value(type)
      @prev_action_state[0] == type ? @prev_action_state[1] : nil
    end

process_auto_indent(line_index = @line_index, cursor_dependent: true, add_newline: false) click to toggle source

    # File lib/reline/line_editor.rb, line 1195
            def process_auto_indent(line_index = @line_index, cursor_dependent: true, add_newline: false)
      return if @in_pasting
      return unless @auto_indent_proc

      line = @buffer_of_lines[line_index]
      byte_pointer = cursor_dependent && @line_index == line_index ? @byte_pointer : line.bytesize
      new_indent = @auto_indent_proc.(@buffer_of_lines.take(line_index + 1).push(''), line_index, byte_pointer, add_newline)
      return unless new_indent

      new_line = ' ' * new_indent + line.lstrip
      @buffer_of_lines[line_index] = new_line
      if @line_index == line_index
        indent_diff = new_line.bytesize - line.bytesize
        @byte_pointer = [@byte_pointer + indent_diff, 0].max
      end
    end

process_insert(force: false) click to toggle source

    # File lib/reline/line_editor.rb, line 1479
            def process_insert(force: false)
      return if @continuous_insertion_buffer.empty? or (@in_pasting and not force)
      insert_text(@continuous_insertion_buffer)
      @continuous_insertion_buffer.clear
    end

process_key(key, method_symbol) click to toggle source

    # File lib/reline/line_editor.rb, line 990
            def process_key(key, method_symbol)
      if key.is_a?(Symbol)
        cleanup_waiting
      elsif @waiting_proc
        old_byte_pointer = @byte_pointer
        @waiting_proc.call(key)
        if @vi_waiting_operator
          byte_pointer_diff = @byte_pointer - old_byte_pointer
          @byte_pointer = old_byte_pointer
          method_obj = method(@vi_waiting_operator)
          wrap_method_call(@vi_waiting_operator, method_obj, byte_pointer_diff)
          cleanup_waiting
        end
        @kill_ring.process
        return
      end

      if method_symbol and respond_to?(method_symbol, true)
        method_obj = method(method_symbol)
      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
          @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 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
            @vi_arg = nil
          end
        end
      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

re_read_init_file(_key) click to toggle source

    # File lib/reline/line_editor.rb, line 2545
            def re_read_init_file(_key)
      @config.reload
    end

redo(_key) click to toggle source

    # File lib/reline/line_editor.rb, line 2527
            def redo(_key)
      @undoing = true

      return if @input_lines_position >= @input_lines.size - 1

      @input_lines_position += 1
      target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
      set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
    end

render_differential(new_lines, new_cursor_x, new_cursor_y) click to toggle source

Reflects lines to be rendered and new cursor position to the screen by calculating the difference from the previous render.

    # File lib/reline/line_editor.rb, line 508
            def render_differential(new_lines, new_cursor_x, new_cursor_y)
      rendered_lines = @rendered_screen.lines
      cursor_y = @rendered_screen.cursor_y
      if new_lines != rendered_lines
        # Hide cursor while rendering to avoid cursor flickering.
        Reline::IOGate.hide_cursor
        num_lines = [[new_lines.size, rendered_lines.size].max, screen_height].min
        if @rendered_screen.base_y + num_lines > screen_height
          Reline::IOGate.scroll_down(num_lines - cursor_y - 1)
          @rendered_screen.base_y = screen_height - num_lines
          cursor_y = num_lines - 1
        end
        num_lines.times do |i|
          rendered_line = rendered_lines[i] || []
          line_to_render = new_lines[i] || []
          next if rendered_line == line_to_render

          Reline::IOGate.move_cursor_down i - cursor_y
          cursor_y = i
          unless rendered_lines[i]
            Reline::IOGate.move_cursor_column 0
            Reline::IOGate.erase_after_cursor
          end
          render_line_differential(rendered_line, line_to_render)
        end
        @rendered_screen.lines = new_lines
        Reline::IOGate.show_cursor
      end
      Reline::IOGate.move_cursor_column new_cursor_x
      Reline::IOGate.move_cursor_down new_cursor_y - cursor_y
      @rendered_screen.cursor_y = new_cursor_y
    end

retrieve_completion_journey_state() click to toggle source

    # File lib/reline/line_editor.rb, line 913
            def retrieve_completion_journey_state
      preposing, target, postposing = retrieve_completion_block
      list = call_completion_proc
      return unless list.is_a?(Array)

      candidates = list.select{ |item| item.start_with?(target) }
      return if candidates.empty?

      pre = preposing.split("\n", -1).last || ''
      post = postposing.split("\n", -1).first || ''
      CompletionJourneyState.new(
        @line_index, pre, target, post, [target] + candidates, 0
      )
    end

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

    # File lib/reline/line_editor.rb, line 928
            def run_for_operators(key, method_symbol, &block)
      if @vi_waiting_operator
        if VI_MOTIONS.include?(method_symbol)
          old_byte_pointer = @byte_pointer
          @vi_arg = (@vi_arg || 1) * @vi_waiting_operator_arg
          block.(true)
          unless @waiting_proc
            byte_pointer_diff = @byte_pointer - old_byte_pointer
            @byte_pointer = old_byte_pointer
            method_obj = method(@vi_waiting_operator)
            wrap_method_call(@vi_waiting_operator, method_obj, byte_pointer_diff)
            cleanup_waiting
          end
        else
          # Ignores operator when not motion is given.
          block.(false)
          cleanup_waiting
        end
        @vi_arg = nil
      else
        block.(false)
      end
    end

search_history(prefix, pointer_range) click to toggle source

    # File lib/reline/line_editor.rb, line 1733
            def search_history(prefix, pointer_range)
      pointer_range.each do |pointer|
        lines = Reline::HISTORY[pointer].split("\n")
        lines.each_with_index do |line, index|
          return [pointer, index] if line.start_with?(prefix)
        end
      end
      nil
    end

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

    # File lib/reline/line_editor.rb, line 2397
            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
      current_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, _ = total
        @byte_pointer += byte_size
      elsif need_prev_char and found and prev_total
        byte_size, _ = prev_total
        @byte_pointer += byte_size
      end
      if inclusive
        byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
        if byte_size > 0
          @byte_pointer += byte_size
        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 2449
            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
      current_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, _ = total
        @byte_pointer -= byte_size
      elsif need_next_char and found and prev_total
        byte_size, _ = prev_total
        @byte_pointer -= byte_size
      end
      @waiting_proc = nil
    end

set_next_action_state(type, value) click to toggle source

    # File lib/reline/line_editor.rb, line 2541
            def set_next_action_state(type, value)
      @next_action_state = [type, value]
    end

split_by_width(str, max_width, offset: 0) click to toggle source

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

undo(_key) click to toggle source

    # File lib/reline/line_editor.rb, line 2517
            def undo(_key)
      @undoing = true

      return if @input_lines_position <= 0

      @input_lines_position -= 1
      target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
      set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
    end

update_each_dialog(dialog, cursor_column, cursor_row, key = nil) click to toggle source

    # File lib/reline/line_editor.rb, line 698
            def update_each_dialog(dialog, cursor_column, cursor_row, key = nil)
      dialog.set_cursor_pos(cursor_column, cursor_row)
      dialog_render_info = dialog.call(key)
      if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty?
        dialog.contents = nil
        dialog.trap_key = nil
        return
      end
      contents = dialog_render_info.contents
      pointer = dialog.pointer
      if dialog_render_info.width
        dialog.width = dialog_render_info.width
      else
        dialog.width = contents.map { |l| calculate_width(l, true) }.max
      end
      height = dialog_render_info.height || DIALOG_DEFAULT_HEIGHT
      height = contents.size if contents.size < height
      if 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
        else
          dialog.scroll_top = 0
        end
        contents = contents[dialog.scroll_top, 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 * ((contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
        bar_height = MINIMUM_SCROLLBAR_HEIGHT if bar_height < MINIMUM_SCROLLBAR_HEIGHT
        scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i
      else
        scrollbar_pos = nil
      end
      dialog.column = dialog_render_info.pos.x
      dialog.width += @block_elem_width if scrollbar_pos
      diff = (dialog.column + dialog.width) - screen_width
      if diff > 0
        dialog.column -= diff
      end
      if rest_height(screen_scroll_top + cursor_row) - dialog_render_info.pos.y >= height
        dialog.vertical_offset = dialog_render_info.pos.y + 1
      elsif cursor_row >= height
        dialog.vertical_offset = dialog_render_info.pos.y - height
      else
        dialog.vertical_offset = dialog_render_info.pos.y + 1
      end
      if dialog.column < 0
        dialog.column = 0
        dialog.width = screen_width
      end
      face = Reline::Face[dialog_render_info.face || :default]
      scrollbar_sgr = face[:scrollbar]
      default_sgr = face[:default]
      enhanced_sgr = face[:enhanced]
      dialog.contents = contents.map.with_index do |item, i|
        line_sgr = i == pointer ? enhanced_sgr : default_sgr
        str_width = dialog.width - (scrollbar_pos.nil? ? 0 : @block_elem_width)
        str, = Reline::Unicode.take_mbchar_range(item, 0, str_width, padding: true)
        colored_content = "#{line_sgr}#{str}"
        if scrollbar_pos
          if scrollbar_pos <= (i * 2) and (i * 2 + 1) < (scrollbar_pos + bar_height)
            colored_content + scrollbar_sgr + @full_block
          elsif scrollbar_pos <= (i * 2) and (i * 2) < (scrollbar_pos + bar_height)
            colored_content + scrollbar_sgr + @upper_half_block
          elsif scrollbar_pos <= (i * 2 + 1) and (i * 2) < (scrollbar_pos + bar_height)
            colored_content + scrollbar_sgr + @lower_half_block
          else
            colored_content + scrollbar_sgr + ' ' * @block_elem_width
          end
        else
          colored_content
        end
      end
    end

vi_add(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2096
            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 2192
            def vi_add_at_eol(key)
      ed_move_to_end(key)
      @config.editing_mode = :vi_insert
    end

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

    # File lib/reline/line_editor.rb, line 2211
            def vi_change_meta(key, arg: nil)
      if @vi_waiting_operator
        set_current_line('', 0) if @vi_waiting_operator == :vi_change_meta_confirm && arg.nil?
        @vi_waiting_operator = nil
        @vi_waiting_operator_arg = nil
      else
        @drop_terminate_spaces = true
        @vi_waiting_operator = :vi_change_meta_confirm
        @vi_waiting_operator_arg = arg || 1
      end
    end

vi_change_meta_confirm(byte_pointer_diff) click to toggle source

    # File lib/reline/line_editor.rb, line 2223
            def vi_change_meta_confirm(byte_pointer_diff)
      vi_delete_meta_confirm(byte_pointer_diff)
      @config.editing_mode = :vi_insert
      @drop_terminate_spaces = false
    end

vi_change_to_eol(key) click to toggle source

Editline

  `vi_change_to_eol` (vi command: `C`) + Kill and change from the cursor to the end of the line.

    # File lib/reline/line_editor.rb, line 1891
            def vi_change_to_eol(key)
      ed_kill_line(key)

      @config.editing_mode = :vi_insert
    end

vi_command_mode(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2101
            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: nil) click to toggle source

    # File lib/reline/line_editor.rb, line 2229
            def vi_delete_meta(key, arg: nil)
      if @vi_waiting_operator
        set_current_line('', 0) if @vi_waiting_operator == :vi_delete_meta_confirm && arg.nil?
        @vi_waiting_operator = nil
        @vi_waiting_operator_arg = nil
      else
        @vi_waiting_operator = :vi_delete_meta_confirm
        @vi_waiting_operator_arg = arg || 1
      end
    end

vi_delete_meta_confirm(byte_pointer_diff) click to toggle source

    # File lib/reline/line_editor.rb, line 2240
            def vi_delete_meta_confirm(byte_pointer_diff)
      if byte_pointer_diff > 0
        line, cut = byteslice!(current_line, @byte_pointer, byte_pointer_diff)
      elsif byte_pointer_diff < 0
        line, cut = byteslice!(current_line, @byte_pointer + byte_pointer_diff, -byte_pointer_diff)
      else
        return
      end
      copy_for_vi(cut)
      set_current_line(line, @byte_pointer + (byte_pointer_diff < 0 ? byte_pointer_diff : 0))
    end

vi_delete_prev_char(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2173
            def vi_delete_prev_char(key)
      if @byte_pointer == 0 and @line_index > 0
        @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
        process_auto_indent cursor_dependent: false
      elsif @byte_pointer > 0
        byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer)
        @byte_pointer -= byte_size
        line, _ = byteslice!(current_line, @byte_pointer, byte_size)
        set_current_line(line)
      end
    end

vi_editing_mode(key) click to toggle source

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

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

    # File lib/reline/line_editor.rb, line 2158
            def vi_end_big_word(key, arg: 1, inclusive: false)
      if current_line.bytesize > @byte_pointer
        byte_size, _ = Reline::Unicode.vi_big_forward_end_word(current_line, @byte_pointer)
        @byte_pointer += byte_size
      end
      arg -= 1
      if inclusive and arg.zero?
        byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
        if byte_size > 0
          @byte_pointer += byte_size
        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 2125
            def vi_end_word(key, arg: 1, inclusive: false)
      if current_line.bytesize > @byte_pointer
        byte_size, _ = Reline::Unicode.vi_forward_end_word(current_line, @byte_pointer)
        @byte_pointer += byte_size
      end
      arg -= 1
      if inclusive and arg.zero?
        byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
        if byte_size > 0
          @byte_pointer += byte_size
        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 1568
            def vi_first_print(key)
      @byte_pointer, = Reline::Unicode.vi_first_print(current_line)
    end

vi_histedit(key) click to toggle source

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

vi_insert(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2092
            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 2187
            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 2487
            def vi_join_lines(key, arg: 1)
      if @buffer_of_lines.size > @line_index + 1
        next_line = @buffer_of_lines.delete_at(@line_index + 1).lstrip
        set_current_line(current_line + ' ' + next_line, current_line.bytesize)
      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 1902
            def vi_kill_line_prev(key)
      if @byte_pointer > 0
        line, deleted = byteslice!(current_line, 0, @byte_pointer)
        set_current_line(line, 0)
        @kill_ring.append(deleted, true)
      end
    end

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

    # File lib/reline/line_editor.rb, line 2274
            def vi_list_or_eof(key)
      if buffer_empty?
        @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 2140
            def vi_next_big_word(key, arg: 1)
      if current_line.bytesize > @byte_pointer
        byte_size, _ = Reline::Unicode.vi_big_forward_word(current_line, @byte_pointer)
        @byte_pointer += byte_size
      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 2389
            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 2107
            def vi_next_word(key, arg: 1)
      if current_line.bytesize > @byte_pointer
        byte_size, _ = Reline::Unicode.vi_forward_word(current_line, @byte_pointer, @drop_terminate_spaces)
        @byte_pointer += byte_size
      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 2329
            def vi_paste_next(key, arg: 1)
      if @vi_clipboard.size > 0
        byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
        line = byteinsert(current_line, @byte_pointer + byte_size, @vi_clipboard)
        set_current_line(line, @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 2320
            def vi_paste_prev(key, arg: 1)
      if @vi_clipboard.size > 0
        cursor_point = @vi_clipboard.grapheme_clusters[0..-2].join
        set_current_line(byteinsert(current_line, @byte_pointer, @vi_clipboard), @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 2149
            def vi_prev_big_word(key, arg: 1)
      if @byte_pointer > 0
        byte_size, _ = Reline::Unicode.vi_big_backward_word(current_line, @byte_pointer)
        @byte_pointer -= byte_size
      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 2441
            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 2116
            def vi_prev_word(key, arg: 1)
      if @byte_pointer > 0
        byte_size, _ = Reline::Unicode.vi_backward_word(current_line, @byte_pointer)
        @byte_pointer -= byte_size
      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 2365
            def vi_replace_char(key, arg: 1)
      @waiting_proc = ->(k) {
        if arg == 1
          byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
          before = current_line.byteslice(0, @byte_pointer)
          remaining_point = @byte_pointer + byte_size
          after = current_line.byteslice(remaining_point, current_line.bytesize - remaining_point)
          set_current_line(before + k.chr + after)
          @waiting_proc = nil
        elsif arg > 1
          byte_size = 0
          arg.times do
            byte_size += Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer + byte_size)
          end
          before = current_line.byteslice(0, @byte_pointer)
          remaining_point = @byte_pointer + byte_size
          after = current_line.byteslice(remaining_point, current_line.bytesize - remaining_point)
          replaced = k.chr * arg
          set_current_line(before + replaced + after, @byte_pointer + replaced.bytesize)
          @waiting_proc = nil
        end
      }
    end

vi_search_next(key) click to toggle source

    # File lib/reline/line_editor.rb, line 1728
            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 1723
            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 2356
            def vi_to_column(key, arg: 0)
      # Implementing behavior of vi, not Readline's vi-mode.
      @byte_pointer, = current_line.grapheme_clusters.inject([0, 0]) { |(total_byte_size, total_width), gc|
        mbchar_width = Reline::Unicode.get_mbchar_width(gc)
        break [total_byte_size, total_width] if (total_width + mbchar_width) >= arg
        [total_byte_size + gc.bytesize, total_width + mbchar_width]
      }
    end

vi_to_history_line(key) click to toggle source

    # File lib/reline/line_editor.rb, line 2301
            def vi_to_history_line(key)
      if Reline::HISTORY.empty?
        return
      end
      move_history(0, line: :start, cursor: :start)
    end

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

    # File lib/reline/line_editor.rb, line 2393
            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 2445
            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: nil) click to toggle source

    # File lib/reline/line_editor.rb, line 2252
            def vi_yank(key, arg: nil)
      if @vi_waiting_operator
        copy_for_vi(current_line) if @vi_waiting_operator == :vi_yank_confirm && arg.nil?
        @vi_waiting_operator = nil
        @vi_waiting_operator_arg = nil
      else
        @vi_waiting_operator = :vi_yank_confirm
        @vi_waiting_operator_arg = arg || 1
      end
    end

vi_yank_confirm(byte_pointer_diff) click to toggle source

    # File lib/reline/line_editor.rb, line 2263
            def vi_yank_confirm(byte_pointer_diff)
      if byte_pointer_diff > 0
        cut = current_line.byteslice(@byte_pointer, byte_pointer_diff)
      elsif byte_pointer_diff < 0
        cut = current_line.byteslice(@byte_pointer + byte_pointer_diff, -byte_pointer_diff)
      else
        return
      end
      copy_for_vi(cut)
    end