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 40
    %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 67

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 146

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 103

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

#basic_word_break_characters=(v) (writeonly)

[ GitHub ]

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

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 107

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

#completer_word_break_characters=(v) (writeonly)

[ GitHub ]

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

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 83

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 123

def completion_case_fold
  @config.completion_ignore_case
end

#completion_case_fold=(v) (rw)

[ GitHub ]

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

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

#completion_proc=(p) (writeonly)

Raises:

  • (ArgumentError)
[ GitHub ]

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

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 56

attr_accessor :config

#dig_perfect_match_proc=(p) (writeonly)

Raises:

  • (ArgumentError)
[ GitHub ]

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

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 195

def emacs_editing_mode
  config.editing_mode = :emacs
  nil
end

#emacs_editing_mode?Boolean (readonly)

[ GitHub ]

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

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

#filename_quote_characters=(v) (writeonly)

[ GitHub ]

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

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

#input=(val) (writeonly)

Raises:

  • (TypeError)
[ GitHub ]

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

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 57

attr_accessor :key_stroke

#last_incremental_search (rw)

[ GitHub ]

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

attr_accessor :last_incremental_search

#line_editor (rw)

[ GitHub ]

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

attr_accessor :line_editor

#output (rw)

[ GitHub ]

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

attr_reader :output

#output=(val) (rw)

Raises:

  • (TypeError)
[ GitHub ]

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

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

#output_modifier_proc=(p) (writeonly)

Raises:

  • (ArgumentError)
[ GitHub ]

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

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 151

def pre_input_hook=(p)
  @pre_input_hook = p
end

#prompt_proc=(p) (writeonly)

Raises:

  • (ArgumentError)
[ GitHub ]

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

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 115

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

#vi_editing_mode (readonly)

[ GitHub ]

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

def vi_editing_mode
  config.editing_mode = :vi_insert
  nil
end

#vi_editing_mode?Boolean (readonly)

[ GitHub ]

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

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 161

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 409

def ambiguous_width
  may_req_ambiguous_char_width unless defined? @ambiguous_width
  @ambiguous_width
end

#completion_quote_character

[ GitHub ]

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

def completion_quote_character
  @completion_quote_character
end

#dialog_proc(name_sym)

[ GitHub ]

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

def dialog_proc(name_sym)
  @dialog_proc_list[name_sym]
end

#encoding

[ GitHub ]

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

def encoding
  io_gate.encoding
end

#get_screen_size

[ GitHub ]

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

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 294

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
  line_editor.reset(prompt, encoding: encoding)
  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.output = output
  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 75

def io_gate
  Reline::IOGate
end

#may_req_ambiguous_char_width (private)

[ GitHub ]

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

private def may_req_ambiguous_char_width
  @ambiguous_width = 2 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
  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 379

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 277

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 251

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