Object
# File reline/config.rb, line 48
def initialize
@additional_key_bindings = {} # from inputrc
@default_key_bindings = {} # environment-dependent
@skip_section = nil
@if_stack = nil
@editing_mode_label = :emacs
@keymap_label = :emacs
@key_actors = {}
@key_actors[:emacs] = Reline::KeyActor::Emacs.new
@key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new
@key_actors[:vi_command] = Reline::KeyActor::ViCommand.new
@vi_cmd_mode_string = '(cmd)'
@vi_ins_mode_string = '(ins)'
@emacs_mode_string = '@'
# https://tiswww.case.edu/php/chet/readline/readline.html#IDX25
@history_size = -1 # unlimited
@keyseq_timeout = 500
@test_mode = false
end
# File reline/config.rb, line 142
def add_default_key_binding(keystroke, target)
@default_key_bindings[keystroke] = target
end
# File reline/config.rb, line 292
def bind_key(key, func_name)
if key =~ /\A"(.*)"\z/
keyseq = parse_keyseq($1)
else
keyseq = nil
end
if func_name =~ /"(.*)"/
func = parse_keyseq($1)
else
func = func_name.tr(?-, ?_).to_sym # It must be macro.
end
[keyseq, func]
end
# File reline/config.rb, line 217
def bind_variable(name, value)
case name
when 'history-size'
begin
@history_size = Integer(value)
rescue ArgumentError
@history_size = 500
end
when 'bell-style'
@bell_style =
case value
when 'none', 'off'
:none
when 'audible', 'on'
:audible
when 'visible'
:visible
else
:audible
end
when 'comment-begin'
@comment_begin = value.dup
when 'completion-query-items'
@completion_query_items = value.to_i
when 'isearch-terminators'
@isearch_terminators = retrieve_string(value)
when 'editing-mode'
case value
when 'emacs'
@editing_mode_label = :emacs
@keymap_label = :emacs
when 'vi'
@editing_mode_label = :vi_insert
@keymap_label = :vi_insert
end
when 'keymap'
case value
when 'emacs', 'emacs-standard', 'emacs-meta', 'emacs-ctlx'
@keymap_label = :emacs
when 'vi', 'vi-move', 'vi-command'
@keymap_label = :vi_command
when 'vi-insert'
@keymap_label = :vi_insert
end
when 'keyseq-timeout'
@keyseq_timeout = value.to_i
when 'show-mode-in-prompt'
case value
when 'off'
@show_mode_in_prompt = false
when 'on'
@show_mode_in_prompt = true
else
@show_mode_in_prompt = false
end
when 'vi-cmd-mode-string'
@vi_cmd_mode_string = retrieve_string(value)
when 'vi-ins-mode-string'
@vi_ins_mode_string = retrieve_string(value)
when 'emacs-mode-string'
@emacs_mode_string = retrieve_string(value)
when *VARIABLE_NAMES then
variable_name = :"@#{name.tr(?-, ?_)}"
instance_variable_set(variable_name, value.nil? || value == '1' || value == 'on')
end
end
# File reline/config.rb, line 76
def editing_mode
@key_actors[@editing_mode_label]
end
# File reline/config.rb, line 80
def editing_mode=(val)
@editing_mode_label = val
end
# File reline/config.rb, line 84
def editing_mode_is?(*val)
(val.respond_to?(:any?) ? val : [val]).any?(@editing_mode_label)
end
# File reline/config.rb, line 187
def handle_directive(directive, file, no)
directive, args = directive.split(' ')
case directive
when 'if'
condition = false
case args
when 'mode'
when 'term'
when 'version'
else # application name
condition = true if args == 'Ruby'
condition = true if args == 'Reline'
end
@if_stack << [file, no, @skip_section]
@skip_section = !condition
when 'else'
if @if_stack.empty?
raise InvalidInputrc, "#{file}:#{no}: unmatched else"
end
@skip_section = !@skip_section
when 'endif'
if @if_stack.empty?
raise InvalidInputrc, "#{file}:#{no}: unmatched endif"
end
@skip_section = @if_stack.pop
when 'include'
read(args)
end
end
# File reline/config.rb, line 92
def inputrc_path
case ENV['INPUTRC']
when nil, ''
else
return File.expand_path(ENV['INPUTRC'])
end
# In the XDG Specification, if ~/.config/readline/inputrc exists, then
# ~/.inputrc should not be read, but for compatibility with GNU Readline,
# if ~/.inputrc exists, then it is given priority.
home_rc_path = File.expand_path('~/.inputrc')
return home_rc_path if File.exist?(home_rc_path)
case path = ENV['XDG_CONFIG_HOME']
when nil, ''
else
path = File.join(path, 'readline/inputrc')
return path if File.exist?(path) and path == File.expand_path(path)
end
path = File.expand_path('~/.config/readline/inputrc')
return path if File.exist?(path)
return home_rc_path
end
# File reline/config.rb, line 137
def key_bindings
# override @default_key_bindings with @additional_key_bindings
@default_key_bindings.merge(@additional_key_bindings)
end
# File reline/config.rb, line 306
def key_notation_to_code(notation)
case notation
when /\\(?:C|Control)-([A-Za-z_])/
(1 + $1.downcase.ord - ?a.ord)
when /\\(?:M|Meta)-([0-9A-Za-z_])/
modified_key = $1
case $1
when /[0-9]/
?\M-0.bytes.first + (modified_key.ord - ?0.ord)
when /[A-Z]/
?\M-A.bytes.first + (modified_key.ord - ?A.ord)
when /[a-z]/
?\M-a.bytes.first + (modified_key.ord - ?a.ord)
end
when /\\(?:C|Control)-(?:M|Meta)-[A-Za-z_]/, /\\(?:M|Meta)-(?:C|Control)-[A-Za-z_]/
# 129 M-^A
when /\\(\d{1,3})/ then $1.to_i(8) # octal
when /\\x(\h{1,2})/ then $1.to_i(16) # hexadecimal
when "\\e" then ?\e.ord
when "\\\\" then ?\\.ord
when "\\\"" then ?".ord
when "\\'" then ?'.ord
when "\\a" then ?\a.ord
when "\\b" then ?\b.ord
when "\\d" then ?\d.ord
when "\\f" then ?\f.ord
when "\\n" then ?\n.ord
when "\\r" then ?\r.ord
when "\\t" then ?\t.ord
when "\\v" then ?\v.ord
else notation.ord
end
end
# File reline/config.rb, line 88
def keymap
@key_actors[@keymap_label]
end
# File reline/config.rb, line 340
def parse_keyseq(str)
ret = []
str.scan(KEYSEQ_PATTERN) do
ret << key_notation_to_code($&)
end
ret
end
# File reline/config.rb, line 118
def read(file = nil)
file ||= inputrc_path
begin
if file.respond_to?(:readlines)
lines = file.readlines
else
lines = File.readlines(file)
end
rescue Errno::ENOENT
return nil
end
read_lines(lines, file)
self
rescue InvalidInputrc => e
warn e.message
nil
end
# File reline/config.rb, line 150
def read_lines(lines, file = nil)
conditions = [@skip_section, @if_stack]
@skip_section = nil
@if_stack = []
lines.each_with_index do |line, no|
next if line.match(/\A\s*#/)
no += 1
line = line.chomp.lstrip
if line.start_with?('$')
handle_directive(line[1..-1], file, no)
next
end
next if @skip_section
case line
when /^set +([^ ]+) +([^ ]+)/i
var, value = $1.downcase, $2
bind_variable(var, value)
next
when /\s*("#{KEYSEQ_PATTERN}+")\s*:\s*(.*)\s*$/o
key, func_name = $1, $2
keystroke, func = bind_key(key, func_name)
next unless keystroke
@additional_key_bindings[keystroke] = func
end
end
unless @if_stack.empty?
raise InvalidInputrc, "#{file}:#{@if_stack.last[1]}: unclosed if"
end
ensure
@skip_section, @if_stack = conditions
end
# File reline/config.rb, line 68
def reset
if editing_mode_is?(:vi_command)
@editing_mode_label = :vi_insert
end
@additional_key_bindings = {}
@default_key_bindings = {}
end