123456789_123456789_123456789_123456789_123456789_

Class: Reline::Core

Relationships & Source Files
Namespace Children
Classes:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Forwardable
Inherits: Object
Defined in: lib/reline.rb

Constant Summary

  • ATTR_READER_NAMES =
    # File 'lib/reline.rb', line 39
    %i(
      completion_append_character
      basic_word_break_characters
      completer_word_break_characters
      basic_quote_characters
      completer_quote_characters
      filename_quote_characters
      special_prefixes
      completion_proc
      output_modifier_proc
      prompt_proc
      auto_indent_proc
      pre_input_hook
      dig_perfect_match_proc
    ).each(&method(:attr_reader))

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new {|_self| ... } ⇒ Core

Yields:

  • (_self)

Yield Parameters:

  • _self (Core)

    the object that the method was called on

[ GitHub ]

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

def initialize
  self.output = STDOUT
  @mutex = Mutex.new
  @dialog_proc_list = {}
  yield self
  @completion_quote_character = nil
end

Instance Attribute Details

#auto_indent_proc=(p) (writeonly)

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/reline.rb', line 145

def auto_indent_proc=(p)
  raise ArgumentError unless p.respond_to?(:call) or p.nil?
  @auto_indent_proc = p
end

#basic_quote_characters=(v) (writeonly)

[ GitHub ]

  
# File 'lib/reline.rb', line 102

def basic_quote_characters=(v)
  @basic_quote_characters = v.encode(encoding)
end

#basic_word_break_characters=(v) (writeonly)

[ GitHub ]

  
# File 'lib/reline.rb', line 94

def basic_word_break_characters=(v)
  @basic_word_break_characters = v.encode(encoding)
end

#completer_quote_characters=(v) (writeonly)

[ GitHub ]

  
# File 'lib/reline.rb', line 106

def completer_quote_characters=(v)
  @completer_quote_characters = v.encode(encoding)
end

#completer_word_break_characters=(v) (writeonly)

[ GitHub ]

  
# File 'lib/reline.rb', line 98

def completer_word_break_characters=(v)
  @completer_word_break_characters = v.encode(encoding)
end

#completion_append_character=(val) (writeonly)

[ GitHub ]

  
# File 'lib/reline.rb', line 82

def completion_append_character=(val)
  if val.nil?
    @completion_append_character = nil
  elsif val.size == 1
    @completion_append_character = val.encode(encoding)
  elsif val.size > 1
    @completion_append_character = val[0].encode(encoding)
  else
    @completion_append_character = nil
  end
end

#completion_case_fold (rw)

[ GitHub ]

  
# File 'lib/reline.rb', line 122

def completion_case_fold
  @config.completion_ignore_case
end

#completion_case_fold=(v) (rw)

[ GitHub ]

  
# File 'lib/reline.rb', line 118

def completion_case_fold=(v)
  @config.completion_ignore_case = v
end

#completion_proc=(p) (writeonly)

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/reline.rb', line 130

def completion_proc=(p)
  raise ArgumentError unless p.respond_to?(:call) or p.nil?
  @completion_proc = p
end

#config (rw)

[ GitHub ]

  
# File 'lib/reline.rb', line 55

attr_accessor :config

#dig_perfect_match_proc=(p) (writeonly)

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/reline.rb', line 154

def dig_perfect_match_proc=(p)
  raise ArgumentError unless p.respond_to?(:call) or p.nil?
  @dig_perfect_match_proc = p
end

#emacs_editing_mode (readonly)

[ GitHub ]

  
# File 'lib/reline.rb', line 192

def emacs_editing_mode
  config.editing_mode = :emacs
  nil
end

#emacs_editing_mode?Boolean (readonly)

[ GitHub ]

  
# File 'lib/reline.rb', line 201

def emacs_editing_mode?
  config.editing_mode_is?(:emacs)
end

#filename_quote_characters=(v) (writeonly)

[ GitHub ]

  
# File 'lib/reline.rb', line 110

def filename_quote_characters=(v)
  @filename_quote_characters = v.encode(encoding)
end

#input=(val) (writeonly)

Raises:

  • (TypeError)
[ GitHub ]

  
# File 'lib/reline.rb', line 174

def input=(val)
  raise TypeError unless val.respond_to?(:getc) or val.nil?
  if val.respond_to?(:getc) && io_gate.respond_to?(:input=)
    io_gate.input = val
  end
end

#key_stroke (rw)

[ GitHub ]

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

attr_accessor :key_stroke

#last_incremental_search (rw)

[ GitHub ]

  
# File 'lib/reline.rb', line 58

attr_accessor :last_incremental_search

#line_editor (rw)

[ GitHub ]

  
# File 'lib/reline.rb', line 57

attr_accessor :line_editor

#output (rw)

[ GitHub ]

  
# File 'lib/reline.rb', line 59

attr_reader :output

#output=(val) (rw)

Raises:

  • (TypeError)
[ GitHub ]

  
# File 'lib/reline.rb', line 181

def output=(val)
  raise TypeError unless val.respond_to?(:write) or val.nil?
  @output = val
  io_gate.output = val
end

#output_modifier_proc=(p) (writeonly)

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/reline.rb', line 135

def output_modifier_proc=(p)
  raise ArgumentError unless p.respond_to?(:call) or p.nil?
  @output_modifier_proc = p
end

#pre_input_hook=(p) (writeonly)

[ GitHub ]

  
# File 'lib/reline.rb', line 150

def pre_input_hook=(p)
  @pre_input_hook = p
end

#prompt_proc=(p) (writeonly)

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/reline.rb', line 140

def prompt_proc=(p)
  raise ArgumentError unless p.respond_to?(:call) or p.nil?
  @prompt_proc = p
end

#special_prefixes=(v) (writeonly)

[ GitHub ]

  
# File 'lib/reline.rb', line 114

def special_prefixes=(v)
  @special_prefixes = v.encode(encoding)
end

#vi_editing_mode (readonly)

[ GitHub ]

  
# File 'lib/reline.rb', line 187

def vi_editing_mode
  config.editing_mode = :vi_insert
  nil
end

#vi_editing_mode?Boolean (readonly)

[ GitHub ]

  
# File 'lib/reline.rb', line 197

def vi_editing_mode?
  config.editing_mode_is?(:vi_insert, :vi_command)
end

Instance Method Details

#add_dialog_proc(name_sym, p, context = nil)

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/reline.rb', line 160

def add_dialog_proc(name_sym, p, context = nil)
  raise ArgumentError unless name_sym.instance_of?(Symbol)
  if p.nil?
    @dialog_proc_list.delete(name_sym)
  else
    raise ArgumentError unless p.respond_to?(:call)
    @dialog_proc_list[name_sym] = DialogProc.new(p, context)
  end
end

#ambiguous_width

[ GitHub ]

  
# File 'lib/reline.rb', line 406

def ambiguous_width
  may_req_ambiguous_char_width unless defined? @ambiguous_width
  @ambiguous_width
end

#completion_quote_character

[ GitHub ]

  
# File 'lib/reline.rb', line 126

def completion_quote_character
  @completion_quote_character
end

#dialog_proc(name_sym)

[ GitHub ]

  
# File 'lib/reline.rb', line 170

def dialog_proc(name_sym)
  @dialog_proc_list[name_sym]
end

#encoding

[ GitHub ]

  
# File 'lib/reline.rb', line 78

def encoding
  io_gate.encoding
end

#get_screen_size

[ GitHub ]

  
# File 'lib/reline.rb', line 205

def get_screen_size
  io_gate.get_screen_size
end

#inner_readline(prompt, add_hist, multiline, &confirm_multiline_termination) (private)

[ GitHub ]

  
# File 'lib/reline.rb', line 291

private def inner_readline(prompt, add_hist, multiline, &confirm_multiline_termination)
  if ENV['RELINE_STDERR_TTY']
    if io_gate.win?
      $stderr = File.open(ENV['RELINE_STDERR_TTY'], 'a')
    else
      $stderr.reopen(ENV['RELINE_STDERR_TTY'], 'w')
    end
    $stderr.sync = true
    $stderr.puts "Reline is used by #{Process.pid}"
  end
  unless config.test_mode or config.loaded?
    config.read
    io_gate.set_default_key_bindings(config)
  end
  otio = io_gate.prep

  may_req_ambiguous_char_width
  key_stroke.encoding = encoding
  line_editor.reset(prompt)
  if multiline
    line_editor.multiline_on
    if block_given?
      line_editor.confirm_multiline_termination_proc = confirm_multiline_termination
    end
  else
    line_editor.multiline_off
  end
  line_editor.completion_proc = completion_proc
  line_editor.completion_append_character = completion_append_character
  line_editor.output_modifier_proc = output_modifier_proc
  line_editor.prompt_proc = prompt_proc
  line_editor.auto_indent_proc = auto_indent_proc
  line_editor.dig_perfect_match_proc = dig_perfect_match_proc

  # Readline calls pre_input_hook just after printing the first prompt.
  line_editor.print_nomultiline_prompt
  pre_input_hook&.call

  unless Reline::IOGate.dumb?
    @dialog_proc_list.each_pair do |name_sym, d|
      line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
    end
  end

  line_editor.update_dialogs
  line_editor.rerender

  begin
    line_editor.set_signal_handlers
    loop do
      read_io(config.keyseq_timeout) { |inputs|
        line_editor.set_pasting_state(io_gate.in_pasting?)
        inputs.each do |key|
          if key.char == :bracketed_paste_start
            text = io_gate.read_bracketed_paste
            line_editor.insert_multiline_text(text)
            line_editor.scroll_into_view
          else
            line_editor.update(key)
          end
        end
      }
      if line_editor.finished?
        line_editor.render_finished
        break
      else
        line_editor.set_pasting_state(io_gate.in_pasting?)
        line_editor.rerender
      end
    end
    io_gate.move_cursor_column(0)
  rescue Errno::EIO
    # Maybe the I/O has been closed.
  ensure
    line_editor.finalize
    io_gate.deprep(otio)
  end
end

#io_gate

[ GitHub ]

  
# File 'lib/reline.rb', line 74

def io_gate
  Reline::IOGate
end

#may_req_ambiguous_char_width (private)

[ GitHub ]

  
# File 'lib/reline.rb', line 411

private def may_req_ambiguous_char_width
  @ambiguous_width = 1 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
  return if defined? @ambiguous_width
  io_gate.move_cursor_column(0)
  begin
    output.write "\u{25bd}"
  rescue Encoding::UndefinedConversionError
    # LANG=C
    @ambiguous_width = 1
  else
    @ambiguous_width = io_gate.cursor_pos.x == 2 ? 2 : 1
  end
  io_gate.move_cursor_column(0)
  io_gate.erase_after_cursor
end

#read_io(keyseq_timeout, &block) (private)

GNU Readline watis for “keyseq-timeout” milliseconds when the input is ambiguous whether it is matching or matched. If the next character does not arrive within the specified timeout, input is considered as matched. ESC is ambiguous because it can be a standalone ESC (matched) or part of ESC char or part of CSI sequence (matching).

[ GitHub ]

  
# File 'lib/reline.rb', line 376

private def read_io(keyseq_timeout, &block)
  buffer = []
  status = KeyStroke::MATCHING
  loop do
    timeout = status == KeyStroke::MATCHING_MATCHED ? keyseq_timeout.fdiv(1000) : Float::INFINITY
    c = io_gate.getc(timeout)
    if c.nil? || c == -1
      if status == KeyStroke::MATCHING_MATCHED
        status = KeyStroke::MATCHED
      elsif buffer.empty?
        # io_gate is closed and reached EOF
        block.call([Key.new(nil, nil, false)])
        return
      else
        status = KeyStroke::UNMATCHED
      end
    else
      buffer << c
      status = key_stroke.match_status(buffer)
    end

    if status == KeyStroke::MATCHED || status == KeyStroke::UNMATCHED
      expanded, rest_bytes = key_stroke.expand(buffer)
      rest_bytes.reverse_each { |c| io_gate.ungetc(c) }
      block.call(expanded)
      return
    end
  end
end

#readline(prompt = '', add_hist = false)

[ GitHub ]

  
# File 'lib/reline.rb', line 274

def readline(prompt = '', add_hist = false)
  @mutex.synchronize do
    io_gate.with_raw_input do
      inner_readline(prompt, add_hist, false)
    end

    line = line_editor.line.dup
    line.taint if RUBY_VERSION < '2.7'
    if add_hist and line and line.chomp("\n").size > 0
      Reline::HISTORY << line.chomp("\n")
    end

    line_editor.reset_line if line_editor.line.nil?
    line
  end
end

#readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)

[ GitHub ]

  
# File 'lib/reline.rb', line 248

def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
  @mutex.synchronize do
    unless confirm_multiline_termination
      raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
    end

    io_gate.with_raw_input do
      inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
    end

    whole_buffer = line_editor.whole_buffer.dup
    whole_buffer.taint if RUBY_VERSION < '2.7'
    if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
      Reline::HISTORY << whole_buffer
    end

    if line_editor.eof?
      line_editor.reset_line
      # Return nil if the input is aborted by C-d.
      nil
    else
      whole_buffer
    end
  end
end