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 41
    %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 68

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 147

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 104

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

#basic_word_break_characters=(v) (writeonly)

[ GitHub ]

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

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 108

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

#completer_word_break_characters=(v) (writeonly)

[ GitHub ]

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

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 84

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 124

def completion_case_fold
  @config.completion_ignore_case
end

#completion_case_fold=(v) (rw)

[ GitHub ]

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

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

#completion_proc=(p) (writeonly)

Raises:

  • (ArgumentError)
[ GitHub ]

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

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 57

attr_accessor :config

#dig_perfect_match_proc=(p) (writeonly)

Raises:

  • (ArgumentError)
[ GitHub ]

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

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 194

def emacs_editing_mode
  config.editing_mode = :emacs
  nil
end

#emacs_editing_mode?Boolean (readonly)

[ GitHub ]

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

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

#filename_quote_characters=(v) (writeonly)

[ GitHub ]

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

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

#input=(val) (writeonly)

Raises:

  • (TypeError)
[ GitHub ]

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

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 58

attr_accessor :key_stroke

#last_incremental_search (rw)

[ GitHub ]

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

attr_accessor :last_incremental_search

#line_editor (rw)

[ GitHub ]

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

attr_accessor :line_editor

#output (rw)

[ GitHub ]

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

attr_reader :output

#output=(val) (rw)

Raises:

  • (TypeError)
[ GitHub ]

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

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 137

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 152

def pre_input_hook=(p)
  @pre_input_hook = p
end

#prompt_proc=(p) (writeonly)

Raises:

  • (ArgumentError)
[ GitHub ]

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

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 116

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

#vi_editing_mode (readonly)

[ GitHub ]

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

def vi_editing_mode
  config.editing_mode = :vi_insert
  nil
end

#vi_editing_mode?Boolean (readonly)

[ GitHub ]

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

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 162

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 128

def completion_quote_character
  @completion_quote_character
end

#dialog_proc(name_sym)

[ GitHub ]

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

def dialog_proc(name_sym)
  @dialog_proc_list[name_sym]
end

#encoding

[ GitHub ]

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

def encoding
  io_gate.encoding
end

#get_screen_size

[ GitHub ]

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

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 293

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|
          case key.method_symbol
          when :bracketed_paste_start
            # io_gate is Reline::ANSI because the key :bracketed_paste_start is only assigned in Reline::ANSI
            key = Reline::Key.new(io_gate.read_bracketed_paste, :insert_multiline_text)
          when :quoted_insert, :ed_quoted_insert
            key = Reline::Key.new(io_gate.read_single_char(config.keyseq_timeout), :insert_raw_char)
          end
          line_editor.update(key)
        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 76

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 = 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 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 276

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 250

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