123456789_123456789_123456789_123456789_123456789_

Class: Reline::LineEditor

Relationships & Source Files
Namespace Children
Modules:
Classes:
Inherits: Object
Defined in: lib/reline/line_editor.rb

Constant Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(config, encoding) ⇒ LineEditor

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 56

def initialize(config, encoding)
  @config = config
  @completion_append_character = ''
  reset_variables(encoding: encoding)
end

Instance Attribute Details

#auto_indent_proc (rw)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 16

attr_accessor :auto_indent_proc

#byte_pointer (rw)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 10

attr_reader :byte_pointer

#byte_pointer=(val) (rw)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1893

def byte_pointer=(val)
  @byte_pointer = val
  str = @line.byteslice(0, @byte_pointer)
  @cursor = calculate_width(str)
  @cursor_max = calculate_width(@line)
end

#completion_append_character (rw)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 13

attr_accessor :completion_append_character

#completion_proc (rw)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 12

attr_accessor :completion_proc

#confirm_multiline_termination_proc (rw)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 11

attr_accessor :confirm_multiline_termination_proc

#dig_perfect_match_proc (rw)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 18

attr_accessor :dig_perfect_match_proc

#eof?Boolean (readonly)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 258

def eof?
  @eof
end

#finished?Boolean (readonly)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1918

def finished?
  @finished
end

#line (readonly)

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

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 9

attr_reader :line

#output=(value) (writeonly)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 19

attr_writer :output

#output_modifier_proc (rw)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 14

attr_accessor :output_modifier_proc

#pre_input_hook (rw)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 17

attr_accessor :pre_input_hook

#prompt_proc (rw)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 15

attr_accessor :prompt_proc

#simplified_rendering?Boolean (readonly)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 66

def simplified_rendering?
  if finished?
    false
  elsif @just_cursor_moving and not @rerender_all
    true
  else
    not @rerender_all and not finished? and @in_pasting
  end
end

Instance Method Details

#add_dialog_proc(name, p, context = nil)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 639

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

#argumentable?(method_obj) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1457

private def argumentable?(method_obj)
  method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :arg }
end

#backward_char(key, arg: 1)

Alias for #ed_prev_char.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2103

alias_method :backward_char, :ed_prev_char

#backward_delete_char(key, arg: 1)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2594

alias_method :backward_delete_char, :em_delete_prev_char

#backward_word(key)

Alias for #ed_prev_word.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2739

alias_method :backward_word, :ed_prev_word

#beginning_of_line(key)

Alias for #ed_move_to_beg.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2112

alias_method :beginning_of_line, :ed_move_to_beg

#byteinsert(str, byte_pointer, other) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1934

private 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) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1928

private def byteslice!(str, byte_pointer, size)
  new_str = str.byteslice(0, byte_pointer)
  new_str << str.byteslice(byte_pointer + size, str.bytesize)
  [new_str, str.byteslice(byte_pointer, size)]
end

#calculate_height_by_lines(lines, prompt) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 327

private def (lines, prompt)
  result = 0
  prompt_list = prompt.is_a?(Array) ? prompt : nil
  lines.each_with_index { |line, i|
    prompt = prompt_list[i] if prompt_list and prompt_list[i]
    result += calculate_height_by_width(calculate_width(prompt, true) + calculate_width(line))
  }
  result
end

#calculate_height_by_width(width) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 345

private def calculate_height_by_width(width)
  width.div(@screen_size.last) + 1
end

#calculate_nearest_cursor(line_to_calc = @line, cursor = @cursor, started_from = @started_from, byte_pointer = @byte_pointer, update = true) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 383

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

#calculate_scroll_partial_screen(highest_in_all, cursor_y) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 924

private def calculate_scroll_partial_screen(highest_in_all, cursor_y)
  if @screen_height < highest_in_all
    old_scroll_partial_screen = @scroll_partial_screen
    if cursor_y == 0
      @scroll_partial_screen = 0
    elsif cursor_y == (highest_in_all - 1)
      @scroll_partial_screen = highest_in_all - @screen_height
    else
      if @scroll_partial_screen
        if cursor_y <= @scroll_partial_screen
          @scroll_partial_screen = cursor_y
        elsif (@scroll_partial_screen + @screen_height - 1) < cursor_y
          @scroll_partial_screen = cursor_y - (@screen_height - 1)
        end
      else
        if cursor_y > (@screen_height - 1)
          @scroll_partial_screen = cursor_y - (@screen_height - 1)
        else
          @scroll_partial_screen = 0
        end
      end
    end
    if @scroll_partial_screen != old_scroll_partial_screen
      @rerender_all = true
    end
  else
    if @scroll_partial_screen
      @rerender_all = true
    end
    @scroll_partial_screen = nil
  end
end

#calculate_width(str, allow_escape_code = false) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1941

private def calculate_width(str, allow_escape_code = false)
  Reline::Unicode.calculate_width(str, allow_escape_code)
end

#call_completion_proc

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1657

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)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1665

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.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2806

alias_method :capitalize_word, :em_capitol_case

#check_mode_string (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 76

private def check_mode_string
  mode_string = nil
  if @config.show_mode_in_prompt
    if @config.editing_mode_is?(:vi_command)
      mode_string = @config.vi_cmd_mode_string
    elsif @config.editing_mode_is?(:vi_insert)
      mode_string = @config.vi_ins_mode_string
    elsif @config.editing_mode_is?(:emacs)
      mode_string = @config.emacs_mode_string
    else
      mode_string = '?'
    end
  end
  if mode_string != @prev_mode_string
    @rerender_all = true
  end
  @prev_mode_string = mode_string
  mode_string
end

#check_multiline_prompt(buffer) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 96

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

#clear_dialog (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 880

private def clear_dialog
  @dialogs.each do |dialog|
    clear_each_dialog(dialog)
  end
end

#clear_each_dialog(dialog) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 886

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

#clear_screen(key)

Alias for #ed_clear_screen.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2721

alias_method :clear_screen, :ed_clear_screen

#clear_screen_buffer(prompt, prompt_list, prompt_width) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1254

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

#complete(list, just_show_list = false) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1329

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

#complete_internal_proc(list, is_menu) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1283

private 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

#confirm_multiline_termination

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1811

def confirm_multiline_termination
  temp_buffer = @buffer_of_lines.dup
  if @previous_line_index and @line_index == (@buffer_of_lines.size - 1)
    temp_buffer[@previous_line_index] = @line
  else
    temp_buffer[@line_index] = @line
  end
  @confirm_multiline_termination_proc.(temp_buffer.join("\n") + "\n")
end

#copy_for_vi(text) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2852

private def copy_for_vi(text)
  if @config.editing_mode_is?(:vi_insert) or @config.editing_mode_is?(:vi_command)
    @vi_clipboard = text
  end
end

#delete_char(key)

Alias for #em_delete.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2675

alias_method :delete_char, :em_delete

#delete_char_or_list(key)

Alias for #em_delete_or_list.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2687

alias_method :delete_char_or_list, :em_delete_or_list

#delete_text(start = nil, length = nil)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1833

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

#downcase_word(key)

Alias for #em_lower_case.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2822

alias_method :downcase_word, :em_lower_case

#ed_argument_digit(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3151

private 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) (private) Also known as: #clear_screen

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2718

private def ed_clear_screen(key)
  @cleared = true
end

#ed_delete_next_char(key, arg: 1) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3063

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

#ed_delete_prev_char(key, arg: 1) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2981

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

#ed_delete_prev_word(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2750

private def ed_delete_prev_word(key)
  if @byte_pointer > 0
    byte_size, width = Reline::Unicode.em_backward_word(@line, @byte_pointer)
    @line, word = byteslice!(@line, @byte_pointer - byte_size, byte_size)
    @kill_ring.append(word, true)
    @byte_pointer -= byte_size
    @cursor -= width
    @cursor_max -= width
  end
end

#ed_digit(key)

Alias for #ed_insert.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2046

alias_method :ed_digit, :ed_insert

#ed_insert(key) (private) Also known as: #ed_digit, #self_insert

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.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1996

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

#ed_kill_line(key) (private) Also known as: #kill_line

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.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2601

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

#ed_move_to_beg(key) (private) Also known as: #beginning_of_line

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2109

private def ed_move_to_beg(key)
  @byte_pointer = @cursor = 0
end

#ed_move_to_end(key) (private) Also known as: #end_of_line

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2114

private def ed_move_to_end(key)
  @byte_pointer = 0
  @cursor = 0
  byte_size = 0
  while @byte_pointer < @line.bytesize
    byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
    if byte_size > 0
      mbchar = @line.byteslice(@byte_pointer, byte_size)
      @cursor += Reline::Unicode.get_mbchar_width(mbchar)
    end
    @byte_pointer += byte_size
  end
end

#ed_newline(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2540

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

#ed_next_char(key, arg: 1) (private) Also known as: #forward_char

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2065

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

#ed_next_history(key, arg: 1) (private) Also known as: #next_history

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2492

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

#ed_prev_char(key, arg: 1) (private) Also known as: #backward_char

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2085

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

#ed_prev_history(key, arg: 1) (private) Also known as: #previous_history

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2441

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

#ed_prev_word(key) (private) Also known as: #backward_word

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2732

private def ed_prev_word(key)
  if @byte_pointer > 0
    byte_size, width = Reline::Unicode.em_backward_word(@line, @byte_pointer)
    @byte_pointer -= byte_size
    @cursor -= width
  end
end

#ed_quoted_insert(str, arg: 1) (private) Also known as: #quoted_insert

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2049

private 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

#ed_search_next_history(key, arg: 1) (private) Also known as: #history_search_forward

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2389

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

#ed_search_prev_history(key, arg: 1) (private) Also known as: #history_search_backward

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2342

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

#ed_transpose_chars(key) (private) Also known as: #transpose_chars

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2761

private def ed_transpose_chars(key)
  if @byte_pointer > 0
    if @cursor_max > @cursor
      byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
      mbchar = @line.byteslice(@byte_pointer, byte_size)
      width = Reline::Unicode.get_mbchar_width(mbchar)
      @cursor += width
      @byte_pointer += byte_size
    end
    back1_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer)
    if (@byte_pointer - back1_byte_size) > 0
      back2_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer - back1_byte_size)
      back2_pointer = @byte_pointer - back1_byte_size - back2_byte_size
      @line, back2_mbchar = byteslice!(@line, back2_pointer, back2_byte_size)
      @line = byteinsert(@line, @byte_pointer - back2_byte_size, back2_mbchar)
    end
  end
end

#ed_transpose_words(key) (private) Also known as: #transpose_words

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2781

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

#ed_unassigned(key) (private)

do nothing

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1966

private def ed_unassigned(key) end

#editing_mode

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1275

def editing_mode
  @config.editing_mode
end

#em_capitol_case(key) (private) Also known as: #capitalize_word

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2796

private def em_capitol_case(key)
  if @line.bytesize > @byte_pointer
    byte_size, _, new_str = Reline::Unicode.em_forward_word_with_capitalization(@line, @byte_pointer)
    before = @line.byteslice(0, @byte_pointer)
    after = @line.byteslice((@byte_pointer + byte_size)..-1)
    @line = before + new_str + after
    @byte_pointer += new_str.bytesize
    @cursor += calculate_width(new_str)
  end
end

#em_delete(key) (private) Also known as: #delete_char

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2650

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

#em_delete_next_word(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2741

private def em_delete_next_word(key)
  if @line.bytesize > @byte_pointer
    byte_size, width = Reline::Unicode.em_forward_word(@line, @byte_pointer)
    @line, word = byteslice!(@line, @byte_pointer, byte_size)
    @kill_ring.append(word)
    @cursor_max -= width
  end
end

#em_delete_or_list(key) (private) Also known as: #delete_char_or_list

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2677

private def em_delete_or_list(key)
  if @line.empty? or @byte_pointer < @line.bytesize
    em_delete(key)
  else # show completed list
    result = call_completion_proc
    if result.is_a?(Array)
      complete(result, true)
    end
  end
end

#em_delete_prev_char(key, arg: 1) (private) Also known as: #backward_delete_char

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2573

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

#em_exchange_mark(key) (private) Also known as: #exchange_point_and_mark

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3335

private def em_exchange_mark(key)
  return unless @mark_pointer
  new_pointer = [@byte_pointer, @line_index]
  @previous_line_index = @line_index
  @byte_pointer, @line_index = @mark_pointer
  @cursor = calculate_width(@line.byteslice(0, @byte_pointer))
  @cursor_max = calculate_width(@line)
  @mark_pointer = new_pointer
end

#em_kill_line(key) (private) Also known as: #kill_whole_line

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.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2639

private def em_kill_line(key)
  if @line.size > 0
    @kill_ring.append(@line.dup, true)
    @line.clear
    @byte_pointer = 0
    @cursor_max = 0
    @cursor = 0
  end
end

#em_kill_region(key) (private) Also known as: #unix_word_rubout

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2840

private def em_kill_region(key)
  if @byte_pointer > 0
    byte_size, width = Reline::Unicode.em_big_backward_word(@line, @byte_pointer)
    @line, deleted = byteslice!(@line, @byte_pointer - byte_size, byte_size)
    @byte_pointer -= byte_size
    @cursor -= width
    @cursor_max -= width
    @kill_ring.append(deleted, true)
  end
end

#em_lower_case(key) (private) Also known as: #downcase_word

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2808

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

#em_next_word(key) (private) Also known as: #forward_word

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2723

private def em_next_word(key)
  if @line.bytesize > @byte_pointer
    byte_size, width = Reline::Unicode.em_forward_word(@line, @byte_pointer)
    @byte_pointer += byte_size
    @cursor += width
  end
end

#em_set_mark(key) (private) Also known as: #set_mark

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3330

private def em_set_mark(key)
  @mark_pointer = [@byte_pointer, @line_index]
end

#em_upper_case(key) (private) Also known as: #upcase_word

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2824

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

#em_yank(key) (private) Also known as: #yank

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2689

private def em_yank(key)
  yanked = @kill_ring.yank
  if yanked
    @line = byteinsert(@line, @byte_pointer, yanked)
    yanked_width = calculate_width(yanked)
    @cursor += yanked_width
    @cursor_max += yanked_width
    @byte_pointer += yanked.bytesize
  end
end

#em_yank_pop(key) (private) Also known as: #yank_pop

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2701

private def em_yank_pop(key)
  yanked, prev_yank = @kill_ring.yank_pop
  if yanked
    prev_yank_width = calculate_width(prev_yank)
    @cursor -= prev_yank_width
    @cursor_max -= prev_yank_width
    @byte_pointer -= prev_yank.bytesize
    @line, = byteslice!(@line, @byte_pointer, prev_yank.bytesize)
    @line = byteinsert(@line, @byte_pointer, yanked)
    yanked_width = calculate_width(yanked)
    @cursor += yanked_width
    @cursor_max += yanked_width
    @byte_pointer += yanked.bytesize
  end
end

#end_of_line(key)

Alias for #ed_move_to_end.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2127

alias_method :end_of_line, :ed_move_to_end

#exchange_point_and_mark(key)

Alias for #em_exchange_mark.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3344

alias_method :exchange_point_and_mark, :em_exchange_mark

#finalize

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 250

def finalize
  Signal.trap('INT', @old_trap)
  begin
    Signal.trap('TSTP', @old_tstp_trap)
  rescue ArgumentError
  end
end

#finish

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1922

def finish
  @finished = true
  @rerender_all = true
  @config.reset
end

#forward_char(key, arg: 1)

Alias for #ed_next_char.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2083

alias_method :forward_char, :ed_next_char

#forward_search_history(key)

Alias for #vi_search_next.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2340

alias_method :forward_search_history, :vi_search_next

#forward_word(key)

Alias for #em_next_word.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2730

alias_method :forward_word, :em_next_word

#generate_searcher (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2129

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

#history_search_backward(key, arg: 1)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2387

alias_method :history_search_backward, :ed_search_prev_history

#history_search_forward(key, arg: 1)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2439

alias_method :history_search_forward, :ed_search_next_history

#inclusive?(method_obj) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1461

private 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) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2245

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

#input_key(key)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1582

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

#insert_new_line(cursor_line, next_line) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 337

private def insert_new_line(cursor_line, next_line)
  @line = cursor_line
  @buffer_of_lines.insert(@line_index + 1, String.new(next_line, encoding: @encoding))
  @previous_line_index = @line_index
  @line_index += 1
  @just_cursor_moving = false
end

#insert_text(text)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1821

def insert_text(text)
  width = calculate_width(text)
  if @cursor == @cursor_max
    @line += text
  else
    @line = byteinsert(@line, @byte_pointer, text)
  end
  @byte_pointer += text.bytesize
  @cursor += width
  @cursor_max += width
end

#just_move_cursor

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 973

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

#key_delete(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1945

private def key_delete(key)
  if @config.editing_mode_is?(:vi_insert, :emacs)
    ed_delete_next_char(key)
  end
end

#key_newline(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1951

private def key_newline(key)
  if @is_multiline
    if (@buffer_of_lines.size - 1) == @line_index and @line.bytesize == @byte_pointer
      @add_newline_to_end_of_buffer = true
    end
    next_line = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer)
    cursor_line = @line.byteslice(0, @byte_pointer)
    insert_new_line(cursor_line, next_line)
    @cursor = 0
    @check_new_auto_indent = true unless @in_pasting
  end
end

#kill_line(key)

Alias for #ed_kill_line.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2617

alias_method :kill_line, :ed_kill_line

#kill_whole_line(key)

Alias for #em_kill_line.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2648

alias_method :kill_whole_line, :em_kill_line

#modify_lines(before) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1231

private def modify_lines(before)
  return before if before.nil? || before.empty? || simplified_rendering?

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

#move_completed_list(list, direction) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1373

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

#move_cursor_down(val) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 373

private def move_cursor_down(val)
  if val > 0
    Reline::IOGate.move_cursor_down(val)
    @rest_height -= val
    @rest_height = 0 if @rest_height < 0
  elsif val < 0
    move_cursor_up(-val)
  end
end

#move_cursor_up(val) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 364

private def move_cursor_up(val)
  if val > 0
    Reline::IOGate.move_cursor_up(val)
    @rest_height += val
  elsif val < 0
    move_cursor_down(-val)
  end
end

#multiline_off

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 323

def multiline_off
  @is_multiline = false
end

#multiline_on

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 319

def multiline_on
  @is_multiline = true
end

#next_history(key, arg: 1)

Alias for #ed_next_history.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2538

alias_method :next_history, :ed_next_history

#normal_char(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1544

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

#padding_space_with_escape_sequences(str, width) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 655

private def padding_space_with_escape_sequences(str, width)
  str + (' ' * (width - calculate_width(str, true)))
end

#previous_history(key, arg: 1)

Alias for #ed_prev_history.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2490

alias_method :previous_history, :ed_prev_history

#process_auto_indent (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1687

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

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

#process_insert(force: false) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1968

private def process_insert(force: false)
  return if @continuous_insertion_buffer.empty? or (@in_pasting and not force)
  width = Reline::Unicode.calculate_width(@continuous_insertion_buffer)
  bytesize = @continuous_insertion_buffer.bytesize
  if @cursor == @cursor_max
    @line += @continuous_insertion_buffer
  else
    @line = byteinsert(@line, @byte_pointer, @continuous_insertion_buffer)
  end
  @byte_pointer += bytesize
  @cursor += width
  @cursor_max += width
  @continuous_insertion_buffer.clear
end

#process_key(key, method_symbol) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1487

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

#quoted_insert(str, arg: 1)

Alias for #ed_quoted_insert.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2063

alias_method :quoted_insert, :ed_quoted_insert

#render_dialog(cursor_column) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 649

private def render_dialog(cursor_column)
  @dialogs.each do |dialog|
    render_each_dialog(dialog, cursor_column)
  end
end

#render_each_dialog(dialog, cursor_column) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 659

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

#render_partial(prompt, prompt_width, line_to_render, this_started_from, with_control: true) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1134

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

#render_whole_lines(lines, prompt, prompt_width) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1108

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

#rerender

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 431

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

#rerender_added_newline(prompt, prompt_width) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 957

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

#rerender_all

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 425

def rerender_all
  @rerender_all = true
  process_insert(force: true)
  rerender
end

#rerender_all_lines (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1053

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

#rerender_changed_current_line (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1005

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

#reset(prompt = '', encoding:)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 149

def reset(prompt = '', encoding:)
  @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
  @screen_size = Reline::IOGate.get_screen_size
  @screen_height = @screen_size.first
  reset_variables(prompt, encoding: encoding)
  Reline::IOGate.set_winch_handler do
    @resized = true
  end
  if ENV.key?('RELINE_ALT_SCROLLBAR')
    @full_block = '::'
    @upper_half_block = "''"
    @lower_half_block = '..'
    @block_elem_width = 2
  elsif Reline::IOGate.win?
    @full_block = ''
    @upper_half_block = ''
    @lower_half_block = ''
    @block_elem_width = 1
  elsif @encoding == Encoding::UTF_8
    @full_block = ''
    @upper_half_block = ''
    @lower_half_block = ''
    @block_elem_width = Reline::Unicode.calculate_width('')
  else
    @full_block = '::'
    @upper_half_block = "''"
    @lower_half_block = '..'
    @block_elem_width = 2
  end
end

#reset_dialog(dialog, old_dialog) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 784

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

#reset_line

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 301

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

#reset_variables(prompt = '', encoding:)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 262

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

#resize

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 180

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

#retrieve_completion_block(set_completion_quote_character = false)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1729

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

#reverse_search_history(key)

Alias for #vi_search_prev.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2335

alias_method :reverse_search_history, :vi_search_prev

#run_for_operators(key, method_symbol, &block) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1419

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

#scroll_down(val) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 353

private def scroll_down(val)
  if val <= @rest_height
    Reline::IOGate.move_cursor_down(val)
    @rest_height -= val
  else
    Reline::IOGate.move_cursor_down(@rest_height)
    Reline::IOGate.scroll_down(val - @rest_height)
    @rest_height = 0
  end
end

#search_next_char(key, arg, need_prev_char: false, inclusive: false) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3219

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

#search_prev_char(key, arg, need_next_char = false) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3276

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

#self_insert(key)

Alias for #ed_insert.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2047

alias_method :self_insert, :ed_insert

#set_mark(key)

Alias for #em_set_mark.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3333

alias_method :set_mark, :em_set_mark

#set_pasting_state(in_pasting)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 62

def set_pasting_state(in_pasting)
  @in_pasting = in_pasting
end

#set_signal_handlers

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 220

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

#show_menu (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1241

private def show_menu
  scroll_down(@highest_in_all - @first_line_started_from)
  @rerender_all = true
  @menu_info.list.sort!.each do |item|
    Reline::IOGate.move_cursor_column(0)
    @output.write item
    @output.flush
    scroll_down(1)
  end
  scroll_down(@highest_in_all - 1)
  move_cursor_up(@highest_in_all - 1 - @first_line_started_from)
end

#split_by_width(str, max_width) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 349

private def split_by_width(str, max_width)
  Reline::Unicode.split_by_width(str, max_width, @encoding)
end

#transpose_chars(key)

Alias for #ed_transpose_chars.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2779

alias_method :transpose_chars, :ed_transpose_chars

#transpose_words(key)

Alias for #ed_transpose_words.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2794

alias_method :transpose_words, :ed_transpose_words

#unix_line_discard(key)

Alias for #vi_kill_line_prev.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2633

alias_method :unix_line_discard, :vi_kill_line_prev

#unix_word_rubout(key)

Alias for #em_kill_region.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2850

alias_method :unix_word_rubout, :em_kill_region

#upcase_word(key)

Alias for #em_upper_case.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2838

alias_method :upcase_word, :em_upper_case

#vi_add(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2862

private def vi_add(key)
  @config.editing_mode = :vi_insert
  ed_next_char(key)
end

#vi_add_at_eol(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2976

private def vi_add_at_eol(key)
  ed_move_to_end(key)
  @config.editing_mode = :vi_insert
end

#vi_change_meta(key, arg: 1) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3002

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

#vi_command_mode(key) (private) Also known as: #vi_movement_mode

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2867

private def vi_command_mode(key)
  ed_prev_char(key)
  @config.editing_mode = :vi_command
end

#vi_delete_meta(key, arg: 1) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3020

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

#vi_delete_prev_char(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2951

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

#vi_end_big_word(key, arg: 1, inclusive: false) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2932

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

#vi_end_of_transmission(key)

Alias for #vi_list_or_eof.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3060

alias_method :vi_end_of_transmission, :vi_list_or_eof

#vi_end_word(key, arg: 1, inclusive: false) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2893

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

#vi_eof_maybe(key)

Alias for #vi_list_or_eof.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3061

alias_method :vi_eof_maybe, :vi_list_or_eof

#vi_first_print(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2105

private def vi_first_print(key)
  @byte_pointer, @cursor = Reline::Unicode.vi_first_print(@line)
end

#vi_histedit(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3105

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

#vi_insert(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2858

private def vi_insert(key)
  @config.editing_mode = :vi_insert
end

#vi_insert_at_bol(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2971

private def vi_insert_at_bol(key)
  ed_move_to_beg(key)
  @config.editing_mode = :vi_insert
end

#vi_join_lines(key, arg: 1) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3316

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

#vi_kill_line_prev(key) (private) Also known as: #unix_line_discard

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.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2624

private def vi_kill_line_prev(key)
  if @byte_pointer > 0
    @line, deleted = byteslice!(@line, 0, @byte_pointer)
    @byte_pointer = 0
    @kill_ring.append(deleted, true)
    @cursor_max = calculate_width(@line)
    @cursor = 0
  end
end

#vi_list_or_eof(key) (private) Also known as: #vi_end_of_transmission, #vi_eof_maybe

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3047

private def vi_list_or_eof(key)
  if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
    @line = nil
    if @buffer_of_lines.size > 1
      scroll_down(@highest_in_all - @first_line_started_from)
    end
    Reline::IOGate.move_cursor_column(0)
    @eof = true
    finish
  else
    ed_newline(key)
  end
end

#vi_movement_mode(key)

Alias for #vi_command_mode.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2871

alias_method :vi_movement_mode, :vi_command_mode

#vi_next_big_word(key, arg: 1) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2912

private def vi_next_big_word(key, arg: 1)
  if @line.bytesize > @byte_pointer
    byte_size, width = Reline::Unicode.vi_big_forward_word(@line, @byte_pointer)
    @byte_pointer += byte_size
    @cursor += width
  end
  arg -= 1
  vi_next_big_word(key, arg: arg) if arg > 0
end

#vi_next_char(key, arg: 1, inclusive: false) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3211

private 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) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2873

private def vi_next_word(key, arg: 1)
  if @line.bytesize > @byte_pointer
    byte_size, width = Reline::Unicode.vi_forward_word(@line, @byte_pointer, @drop_terminate_spaces)
    @byte_pointer += byte_size
    @cursor += width
  end
  arg -= 1
  vi_next_word(key, arg: arg) if arg > 0
end

#vi_paste_next(key, arg: 1) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3139

private def vi_paste_next(key, arg: 1)
  if @vi_clipboard.size > 0
    byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
    @line = byteinsert(@line, @byte_pointer + byte_size, @vi_clipboard)
    @cursor_max += calculate_width(@vi_clipboard)
    @cursor += calculate_width(@vi_clipboard)
    @byte_pointer += @vi_clipboard.bytesize
  end
  arg -= 1
  vi_paste_next(key, arg: arg) if arg > 0
end

#vi_paste_prev(key, arg: 1) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3127

private def vi_paste_prev(key, arg: 1)
  if @vi_clipboard.size > 0
    @line = byteinsert(@line, @byte_pointer, @vi_clipboard)
    @cursor_max += calculate_width(@vi_clipboard)
    cursor_point = @vi_clipboard.grapheme_clusters[0..-2].join
    @cursor += calculate_width(cursor_point)
    @byte_pointer += cursor_point.bytesize
  end
  arg -= 1
  vi_paste_prev(key, arg: arg) if arg > 0
end

#vi_prev_big_word(key, arg: 1) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2922

private def vi_prev_big_word(key, arg: 1)
  if @byte_pointer > 0
    byte_size, width = Reline::Unicode.vi_big_backward_word(@line, @byte_pointer)
    @byte_pointer -= byte_size
    @cursor -= width
  end
  arg -= 1
  vi_prev_big_word(key, arg: arg) if arg > 0
end

#vi_prev_char(key, arg: 1) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3268

private 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) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2883

private def vi_prev_word(key, arg: 1)
  if @byte_pointer > 0
    byte_size, width = Reline::Unicode.vi_backward_word(@line, @byte_pointer)
    @byte_pointer -= byte_size
    @cursor -= width
  end
  arg -= 1
  vi_prev_word(key, arg: arg) if arg > 0
end

#vi_replace_char(key, arg: 1) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3183

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

#vi_search_next(key) (private) Also known as: #forward_search_history

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2337

private def vi_search_next(key)
  incremental_search_history(key)
end

#vi_search_prev(key) (private) Also known as: #reverse_search_history

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2332

private def vi_search_prev(key)
  incremental_search_history(key)
end

#vi_to_column(key, arg: 0) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3168

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

#vi_to_history_line(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3082

private def vi_to_history_line(key)
  if Reline::HISTORY.empty?
    return
  end
  if @history_pointer.nil?
    @history_pointer = 0
    @line_backup_in_history = @line
    @line = Reline::HISTORY[@history_pointer]
    @cursor_max = calculate_width(@line)
    @cursor = 0
    @byte_pointer = 0
  elsif @history_pointer.zero?
    return
  else
    Reline::HISTORY[@history_pointer] = @line
    @history_pointer = 0
    @line = Reline::HISTORY[@history_pointer]
    @cursor_max = calculate_width(@line)
    @cursor = 0
    @byte_pointer = 0
  end
end

#vi_to_next_char(key, arg: 1, inclusive: false) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3215

private 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) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3272

private def vi_to_prev_char(key, arg: 1)
  @waiting_proc = ->(key_for_proc) { search_prev_char(key_for_proc, arg, true) }
end

#vi_yank(key, arg: 1) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 3035

private def vi_yank(key, arg: 1)
  @waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff|
    if byte_pointer_diff > 0
      cut = @line.byteslice(@byte_pointer, byte_pointer_diff)
    elsif byte_pointer_diff < 0
      cut = @line.byteslice(@byte_pointer + byte_pointer_diff, -byte_pointer_diff)
    end
    copy_for_vi(cut)
  }
  @waiting_operator_vi_arg = arg
end

#vi_zero(key) (private)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2997

private def vi_zero(key)
  @byte_pointer = 0
  @cursor = 0
end

#whole_buffer

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1906

def whole_buffer
  if @buffer_of_lines.size == 1 and @line.nil?
    nil
  else
    if @previous_line_index
      whole_lines(index: @previous_line_index, line: @line).join("\n")
    else
      whole_lines.join("\n")
    end
  end
end

#whole_lines(index: @line_index, line: @line)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1900

def whole_lines(index: @line_index, line: @line)
  temp_lines = @buffer_of_lines.dup
  temp_lines[index] = line
  temp_lines
end

#wrap_method_call(method_symbol, method_obj, key, with_operator = false)

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 1467

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

#yank(key)

Alias for #em_yank.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2699

alias_method :yank, :em_yank

#yank_pop(key)

Alias for #em_yank_pop.

[ GitHub ]

  
# File 'lib/reline/line_editor.rb', line 2716

alias_method :yank_pop, :em_yank_pop