reline 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/BSDL +22 -0
- data/COPYING +56 -0
- data/README.md +7 -0
- data/lib/reline.rb +196 -0
- data/lib/reline/ansi.rb +87 -0
- data/lib/reline/config.rb +235 -0
- data/lib/reline/key_actor.rb +7 -0
- data/lib/reline/key_actor/base.rb +7 -0
- data/lib/reline/key_actor/emacs.rb +518 -0
- data/lib/reline/key_actor/vi_command.rb +519 -0
- data/lib/reline/key_actor/vi_insert.rb +518 -0
- data/lib/reline/key_stroke.rb +74 -0
- data/lib/reline/kill_ring.rb +113 -0
- data/lib/reline/line_editor.rb +1357 -0
- data/lib/reline/unicode.rb +415 -0
- data/lib/reline/unicode/east_asian_width.rb +1145 -0
- data/lib/reline/version.rb +3 -0
- data/lib/reline/windows.rb +132 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 34664ed4926dba843c8d0b5c161a8783384afbe37ef601a6ef7130e6acfe614f
|
4
|
+
data.tar.gz: c006411fd71550186facf348787d964f51f8e7ad03d87c7718ab2689a973b2c0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f8307b181652977ca88bc9858533a41cdb9305b27c5fdd1584b6c9c7931e96fbf4c86c73d84b0d09cb4d27a7061adbf5e5f7c327f65864986eea2fd75c55937f
|
7
|
+
data.tar.gz: 47453f12ee20b6438751008216abfb04bf8ff06e9e1b5ab9bcb5e73319bc39aeecb1748d2ad54f5293385a04fba877f3fe6fa219d1e36afacb41851106ebf22c
|
data/BSDL
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions
|
5
|
+
are met:
|
6
|
+
1. Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
13
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
14
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
15
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
16
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
17
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
18
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
19
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
20
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
21
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
22
|
+
SUCH DAMAGE.
|
data/COPYING
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
|
2
|
+
You can redistribute it and/or modify it under either the terms of the
|
3
|
+
2-clause BSDL (see the file BSDL), or the conditions below:
|
4
|
+
|
5
|
+
1. You may make and give away verbatim copies of the source form of the
|
6
|
+
software without restriction, provided that you duplicate all of the
|
7
|
+
original copyright notices and associated disclaimers.
|
8
|
+
|
9
|
+
2. You may modify your copy of the software in any way, provided that
|
10
|
+
you do at least ONE of the following:
|
11
|
+
|
12
|
+
a) place your modifications in the Public Domain or otherwise
|
13
|
+
make them Freely Available, such as by posting said
|
14
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
15
|
+
the author to include your modifications in the software.
|
16
|
+
|
17
|
+
b) use the modified software only within your corporation or
|
18
|
+
organization.
|
19
|
+
|
20
|
+
c) give non-standard binaries non-standard names, with
|
21
|
+
instructions on where to get the original software distribution.
|
22
|
+
|
23
|
+
d) make other distribution arrangements with the author.
|
24
|
+
|
25
|
+
3. You may distribute the software in object code or binary form,
|
26
|
+
provided that you do at least ONE of the following:
|
27
|
+
|
28
|
+
a) distribute the binaries and library files of the software,
|
29
|
+
together with instructions (in the manual page or equivalent)
|
30
|
+
on where to get the original distribution.
|
31
|
+
|
32
|
+
b) accompany the distribution with the machine-readable source of
|
33
|
+
the software.
|
34
|
+
|
35
|
+
c) give non-standard binaries non-standard names, with
|
36
|
+
instructions on where to get the original software distribution.
|
37
|
+
|
38
|
+
d) make other distribution arrangements with the author.
|
39
|
+
|
40
|
+
4. You may modify and include the part of the software into any other
|
41
|
+
software (possibly commercial). But some files in the distribution
|
42
|
+
are not written by the author, so that they are not under these terms.
|
43
|
+
|
44
|
+
For the list of those files and their copying conditions, see the
|
45
|
+
file LEGAL.
|
46
|
+
|
47
|
+
5. The scripts and library files supplied as input to or produced as
|
48
|
+
output from the software do not automatically fall under the
|
49
|
+
copyright of the software, but belong to whomever generated them,
|
50
|
+
and may be sold commercially, and may be aggregated with this
|
51
|
+
software.
|
52
|
+
|
53
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
54
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
55
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
56
|
+
PURPOSE.
|
data/README.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# Reline
|
2
|
+
|
3
|
+
Reline is compatible with the API of Ruby's stdlib 'readline', GNU Readline and Editline by pure Ruby implementation.
|
4
|
+
|
5
|
+
## License
|
6
|
+
|
7
|
+
The gem is available as open source under the terms of the [Ruby License](https://www.ruby-lang.org/en/about/license.txt).
|
data/lib/reline.rb
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'io/console'
|
2
|
+
require 'reline/version'
|
3
|
+
require 'reline/config'
|
4
|
+
require 'reline/key_actor'
|
5
|
+
require 'reline/key_stroke'
|
6
|
+
require 'reline/line_editor'
|
7
|
+
|
8
|
+
module Reline
|
9
|
+
extend self
|
10
|
+
FILENAME_COMPLETION_PROC = nil
|
11
|
+
USERNAME_COMPLETION_PROC = nil
|
12
|
+
HISTORY = Array.new
|
13
|
+
|
14
|
+
if RUBY_PLATFORM =~ /mswin|mingw/
|
15
|
+
require 'Win32API'
|
16
|
+
IS_WINDOWS = true
|
17
|
+
else
|
18
|
+
IS_WINDOWS = false
|
19
|
+
end
|
20
|
+
|
21
|
+
CursorPos = Struct.new(:x, :y)
|
22
|
+
|
23
|
+
class << self
|
24
|
+
attr_accessor :basic_quote_characters
|
25
|
+
attr_accessor :completer_quote_characters
|
26
|
+
attr_accessor :completer_word_break_characters
|
27
|
+
attr_reader :completion_append_character
|
28
|
+
attr_accessor :completion_case_fold
|
29
|
+
attr_accessor :filename_quote_characters
|
30
|
+
attr_writer :input
|
31
|
+
attr_writer :output
|
32
|
+
end
|
33
|
+
|
34
|
+
@@ambiguous_width = nil
|
35
|
+
@@config = nil
|
36
|
+
|
37
|
+
@basic_quote_characters = '"\''
|
38
|
+
@completer_quote_characters
|
39
|
+
@completer_word_break_characters = @basic_word_break_characters.dup
|
40
|
+
@completion_append_character
|
41
|
+
def self.completion_append_character=(val)
|
42
|
+
if val.nil?
|
43
|
+
@completion_append_character = nil
|
44
|
+
elsif val.size == 1
|
45
|
+
@completion_append_character = val
|
46
|
+
elsif val.size > 1
|
47
|
+
@completion_append_character = val[0]
|
48
|
+
else
|
49
|
+
@completion_append_character = val
|
50
|
+
end
|
51
|
+
end
|
52
|
+
@completion_case_fold
|
53
|
+
@filename_quote_characters
|
54
|
+
|
55
|
+
@@basic_word_break_characters = " \t\n`><=;|&{("
|
56
|
+
def self.basic_word_break_characters
|
57
|
+
@@basic_word_break_characters
|
58
|
+
end
|
59
|
+
def self.basic_word_break_characters=(v)
|
60
|
+
@@basic_word_break_characters = v
|
61
|
+
end
|
62
|
+
|
63
|
+
@@completion_proc = nil
|
64
|
+
def self.completion_proc
|
65
|
+
@@completion_proc
|
66
|
+
end
|
67
|
+
def self.completion_proc=(p)
|
68
|
+
@@completion_proc = p
|
69
|
+
end
|
70
|
+
|
71
|
+
@@dig_perfect_match_proc = nil
|
72
|
+
def self.dig_perfect_match_proc
|
73
|
+
@@dig_perfect_match_proc
|
74
|
+
end
|
75
|
+
def self.dig_perfect_match_proc=(p)
|
76
|
+
@@dig_perfect_match_proc = p
|
77
|
+
end
|
78
|
+
|
79
|
+
if IS_WINDOWS
|
80
|
+
require 'reline/windows'
|
81
|
+
else
|
82
|
+
require 'reline/ansi'
|
83
|
+
end
|
84
|
+
|
85
|
+
def retrieve_completion_block(line, byte_pointer)
|
86
|
+
break_regexp = /[#{Regexp.escape(@@basic_word_break_characters)}]/
|
87
|
+
before_pointer = line.byteslice(0, byte_pointer)
|
88
|
+
break_point = before_pointer.rindex(break_regexp)
|
89
|
+
if break_point
|
90
|
+
preposing = before_pointer[0..(break_point)]
|
91
|
+
block = before_pointer[(break_point + 1)..-1]
|
92
|
+
else
|
93
|
+
preposing = ''
|
94
|
+
block = before_pointer
|
95
|
+
end
|
96
|
+
postposing = line.byteslice(byte_pointer, line.bytesize)
|
97
|
+
[preposing, block, postposing]
|
98
|
+
end
|
99
|
+
|
100
|
+
def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
|
101
|
+
if block_given?
|
102
|
+
inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
|
103
|
+
else
|
104
|
+
inner_readline(prompt, add_hist, true)
|
105
|
+
end
|
106
|
+
|
107
|
+
if add_hist and @line_editor.whole_buffer and @line_editor.whole_buffer.chomp.size > 0
|
108
|
+
Reline::HISTORY << @line_editor.whole_buffer
|
109
|
+
end
|
110
|
+
|
111
|
+
@line_editor.whole_buffer
|
112
|
+
end
|
113
|
+
|
114
|
+
def readline(prompt = '', add_hist = false)
|
115
|
+
inner_readline(prompt, add_hist, false)
|
116
|
+
|
117
|
+
if add_hist and @line_editor.line and @line_editor.line.chomp.size > 0
|
118
|
+
Reline::HISTORY << @line_editor.line.chomp
|
119
|
+
end
|
120
|
+
|
121
|
+
@line_editor.line
|
122
|
+
end
|
123
|
+
|
124
|
+
def inner_readline(prompt, add_hist, multiline, &confirm_multiline_termination)
|
125
|
+
if @@config.nil?
|
126
|
+
@@config = Reline::Config.new
|
127
|
+
@@config.read
|
128
|
+
end
|
129
|
+
otio = prep
|
130
|
+
|
131
|
+
may_req_ambiguous_char_width
|
132
|
+
@line_editor = Reline::LineEditor.new(@@config, prompt)
|
133
|
+
if multiline
|
134
|
+
@line_editor.multiline_on
|
135
|
+
if block_given?
|
136
|
+
@line_editor.confirm_multiline_termination_proc = confirm_multiline_termination
|
137
|
+
end
|
138
|
+
end
|
139
|
+
@line_editor.completion_proc = @@completion_proc
|
140
|
+
@line_editor.dig_perfect_match_proc = @@dig_perfect_match_proc
|
141
|
+
@line_editor.retrieve_completion_block = method(:retrieve_completion_block)
|
142
|
+
@line_editor.rerender
|
143
|
+
|
144
|
+
if IS_WINDOWS
|
145
|
+
config = {
|
146
|
+
key_mapping: {
|
147
|
+
[224, 72] => :ed_prev_history, # ↑
|
148
|
+
[224, 80] => :ed_next_history, # ↓
|
149
|
+
[224, 77] => :ed_next_char, # →
|
150
|
+
[224, 75] => :ed_prev_char # ←
|
151
|
+
}
|
152
|
+
}
|
153
|
+
else
|
154
|
+
config = {
|
155
|
+
key_mapping: {
|
156
|
+
[27, 91, 65] => :ed_prev_history, # ↑
|
157
|
+
[27, 91, 66] => :ed_next_history, # ↓
|
158
|
+
[27, 91, 67] => :ed_next_char, # →
|
159
|
+
[27, 91, 68] => :ed_prev_char # ←
|
160
|
+
}
|
161
|
+
}
|
162
|
+
end
|
163
|
+
|
164
|
+
key_stroke = Reline::KeyStroke.new(config)
|
165
|
+
begin
|
166
|
+
while c = getc
|
167
|
+
key_stroke.input_to!(c)&.then { |inputs|
|
168
|
+
inputs.each { |c|
|
169
|
+
@line_editor.input_key(c)
|
170
|
+
@line_editor.rerender
|
171
|
+
}
|
172
|
+
}
|
173
|
+
break if @line_editor.finished?
|
174
|
+
end
|
175
|
+
Reline.move_cursor_column(0)
|
176
|
+
rescue StandardError => e
|
177
|
+
deprep(otio)
|
178
|
+
raise e
|
179
|
+
end
|
180
|
+
|
181
|
+
deprep(otio)
|
182
|
+
end
|
183
|
+
|
184
|
+
def may_req_ambiguous_char_width
|
185
|
+
return if @@ambiguous_width
|
186
|
+
Reline.move_cursor_column(0)
|
187
|
+
print "\u{25bd}"
|
188
|
+
@@ambiguous_width = Reline.cursor_pos.x
|
189
|
+
Reline.move_cursor_column(0)
|
190
|
+
Reline.erase_after_cursor
|
191
|
+
end
|
192
|
+
|
193
|
+
def self.ambiguous_width
|
194
|
+
@@ambiguous_width
|
195
|
+
end
|
196
|
+
end
|
data/lib/reline/ansi.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
module Reline
|
2
|
+
def getc
|
3
|
+
c = nil
|
4
|
+
until c
|
5
|
+
return nil if @line_editor.finished?
|
6
|
+
result = select([$stdin], [], [], 0.1)
|
7
|
+
next if result.nil?
|
8
|
+
c = $stdin.read(1)
|
9
|
+
end
|
10
|
+
c.ord
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.get_screen_size
|
14
|
+
$stdin.winsize
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.set_screen_size(rows, columns)
|
18
|
+
$stdin.winsize = [rows, columns]
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.cursor_pos
|
23
|
+
res = ''
|
24
|
+
$stdin.raw do |stdin|
|
25
|
+
$stdout << "\e[6n"
|
26
|
+
$stdout.flush
|
27
|
+
while (c = stdin.getc) != 'R'
|
28
|
+
res << c if c
|
29
|
+
end
|
30
|
+
end
|
31
|
+
m = res.match(/(?<row>\d+);(?<column>\d+)/)
|
32
|
+
CursorPos.new(m[:column].to_i - 1, m[:row].to_i - 1)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.move_cursor_column(x)
|
36
|
+
print "\e[#{x + 1}G"
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.move_cursor_up(x)
|
40
|
+
if x > 0
|
41
|
+
print "\e[#{x}A" if x > 0
|
42
|
+
elsif x < 0
|
43
|
+
move_cursor_down(-x)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.move_cursor_down(x)
|
48
|
+
if x > 0
|
49
|
+
print "\e[#{x}B" if x > 0
|
50
|
+
elsif x < 0
|
51
|
+
move_cursor_up(-x)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.erase_after_cursor
|
56
|
+
print "\e[K"
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.scroll_down(x)
|
60
|
+
return if x.zero?
|
61
|
+
print "\e[#{x}S"
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.clear_screen
|
65
|
+
print "\e[2J"
|
66
|
+
print "\e[1;1H"
|
67
|
+
end
|
68
|
+
|
69
|
+
def prep
|
70
|
+
int_handle = Signal.trap('INT', 'IGNORE')
|
71
|
+
otio = `stty -g`.chomp
|
72
|
+
setting = ' -echo -icrnl cbreak'
|
73
|
+
if (`stty -a`.scan(/-parenb\b/).first == '-parenb')
|
74
|
+
setting << ' pass8'
|
75
|
+
end
|
76
|
+
setting << ' -ixoff'
|
77
|
+
`stty #{setting}`
|
78
|
+
Signal.trap('INT', int_handle)
|
79
|
+
otio
|
80
|
+
end
|
81
|
+
|
82
|
+
def deprep(otio)
|
83
|
+
int_handle = Signal.trap('INT', 'IGNORE')
|
84
|
+
`stty #{otio}`
|
85
|
+
Signal.trap('INT', int_handle)
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
class Reline::Config
|
4
|
+
DEFAULT_PATH = Pathname.new(Dir.home).join('.inputrc')
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@skip_section = nil
|
8
|
+
@if_stack = []
|
9
|
+
@editing_mode_label = :emacs
|
10
|
+
@keymap_label = :emacs
|
11
|
+
@key_actors = {}
|
12
|
+
@key_actors[:emacs] = Reline::KeyActor::Emacs.new
|
13
|
+
@key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new
|
14
|
+
@key_actors[:vi_command] = Reline::KeyActor::ViCommand.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset
|
18
|
+
if editing_mode_is?(:vi_command)
|
19
|
+
@editing_mode_label = :vi_insert
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def editing_mode
|
24
|
+
@key_actors[@editing_mode_label]
|
25
|
+
end
|
26
|
+
|
27
|
+
def editing_mode=(val)
|
28
|
+
@editing_mode_label = val
|
29
|
+
end
|
30
|
+
|
31
|
+
def editing_mode_is?(*val)
|
32
|
+
(val.respond_to?(:any?) ? val : [val]).any?(@editing_mode_label)
|
33
|
+
end
|
34
|
+
|
35
|
+
def keymap
|
36
|
+
@key_actors[@keymap_label]
|
37
|
+
end
|
38
|
+
|
39
|
+
def read(file = DEFAULT_PATH)
|
40
|
+
begin
|
41
|
+
if file.respond_to?(:readlines)
|
42
|
+
lines = file.readlines
|
43
|
+
else
|
44
|
+
File.open(file, 'rt') do |f|
|
45
|
+
lines = f.readlines
|
46
|
+
end
|
47
|
+
end
|
48
|
+
rescue Errno::ENOENT
|
49
|
+
$stderr.puts "no such file #{file}"
|
50
|
+
return nil
|
51
|
+
end
|
52
|
+
|
53
|
+
read_lines(lines)
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_lines(lines)
|
58
|
+
lines.each do |line|
|
59
|
+
line = line.chomp.gsub(/^\s*/, '')
|
60
|
+
if line[0, 1] == '$'
|
61
|
+
handle_directive(line[1..-1])
|
62
|
+
next
|
63
|
+
end
|
64
|
+
|
65
|
+
next if @skip_section
|
66
|
+
|
67
|
+
if line.match(/^set +([^ ]+) +([^ ]+)/i)
|
68
|
+
var, value = $1.downcase, $2.downcase
|
69
|
+
bind_variable(var, value)
|
70
|
+
next
|
71
|
+
end
|
72
|
+
|
73
|
+
if line =~ /\s*(.*)\s*:\s*(.*)\s*$/
|
74
|
+
key, func_name = $1, $2
|
75
|
+
bind_key(key, func_name)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def handle_directive(directive)
|
81
|
+
directive, args = directive.split(' ')
|
82
|
+
case directive
|
83
|
+
when 'if'
|
84
|
+
condition = false
|
85
|
+
case args # TODO: variables
|
86
|
+
when 'mode'
|
87
|
+
when 'term'
|
88
|
+
when 'version'
|
89
|
+
else # application name
|
90
|
+
condition = true if args == 'Ruby'
|
91
|
+
end
|
92
|
+
unless @skip_section.nil?
|
93
|
+
@if_stack << @skip_section
|
94
|
+
end
|
95
|
+
@skip_section = !condition
|
96
|
+
when 'else'
|
97
|
+
@skip_section = !@skip_section
|
98
|
+
when 'endif'
|
99
|
+
@skip_section = nil
|
100
|
+
unless @if_stack.empty?
|
101
|
+
@skip_section = @if_stack.pop
|
102
|
+
end
|
103
|
+
when 'include'
|
104
|
+
read(args)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def bind_variable(name, value)
|
109
|
+
case name
|
110
|
+
when %w{
|
111
|
+
bind-tty-special-chars
|
112
|
+
blink-matching-paren
|
113
|
+
byte-oriented
|
114
|
+
completion-ignore-case
|
115
|
+
convert-meta
|
116
|
+
disable-completion
|
117
|
+
enable-keypad
|
118
|
+
expand-tilde
|
119
|
+
history-preserve-point
|
120
|
+
horizontal-scroll-mode
|
121
|
+
input-meta
|
122
|
+
mark-directories
|
123
|
+
mark-modified-lines
|
124
|
+
mark-symlinked-directories
|
125
|
+
match-hidden-files
|
126
|
+
meta-flag
|
127
|
+
output-meta
|
128
|
+
page-completions
|
129
|
+
prefer-visible-bell
|
130
|
+
print-completions-horizontally
|
131
|
+
show-all-if-ambiguous
|
132
|
+
show-all-if-unmodified
|
133
|
+
visible-stats
|
134
|
+
} then
|
135
|
+
variable_name = :"@#{name.tr(?-, ?_)}"
|
136
|
+
instance_variable_set(variable_name, value.nil? || value == '1' || value == 'on')
|
137
|
+
when 'bell-style'
|
138
|
+
@bell_style =
|
139
|
+
case value
|
140
|
+
when 'none', 'off'
|
141
|
+
:none
|
142
|
+
when 'audible', 'on'
|
143
|
+
:audible
|
144
|
+
when 'visible'
|
145
|
+
:visible
|
146
|
+
else
|
147
|
+
:audible
|
148
|
+
end
|
149
|
+
when 'comment-begin'
|
150
|
+
@comment_begin = value.dup
|
151
|
+
when 'completion-query-items'
|
152
|
+
@completion_query_items = value.to_i
|
153
|
+
when 'isearch-terminators'
|
154
|
+
@isearch_terminators = instance_eval(value)
|
155
|
+
when 'editing-mode'
|
156
|
+
case value
|
157
|
+
when 'emacs'
|
158
|
+
@editing_mode_label = :emacs
|
159
|
+
@keymap_label = :emacs
|
160
|
+
when 'vi'
|
161
|
+
@editing_mode_label = :vi_insert
|
162
|
+
@keymap_label = :vi_insert
|
163
|
+
end
|
164
|
+
when 'keymap'
|
165
|
+
case value
|
166
|
+
when 'emacs', 'emacs-standard', 'emacs-meta', 'emacs-ctlx'
|
167
|
+
@keymap_label = :emacs
|
168
|
+
when 'vi', 'vi-move', 'vi-command'
|
169
|
+
@keymap_label = :vi_command
|
170
|
+
when 'vi-insert'
|
171
|
+
@keymap_label = :vi_insert
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def bind_key(key, func_name)
|
177
|
+
if key =~ /"(.*)"/
|
178
|
+
keyseq = parse_keyseq($1).force_encoding('ASCII-8BIT')
|
179
|
+
else
|
180
|
+
keyseq = nil
|
181
|
+
end
|
182
|
+
if func_name =~ /"(.*)"/
|
183
|
+
func = parse_keyseq($1).force_encoding('ASCII-8BIT')
|
184
|
+
else
|
185
|
+
func = func_name.to_sym # It must be macro.
|
186
|
+
end
|
187
|
+
[keyseq, func]
|
188
|
+
end
|
189
|
+
|
190
|
+
def key_notation_to_char(notation)
|
191
|
+
case notation
|
192
|
+
when /\\C-([A-Za-z_])/
|
193
|
+
(1 + $1.downcase.ord - ?a.ord).chr('ASCII-8BIT')
|
194
|
+
when /\\M-([0-9A-Za-z_])/
|
195
|
+
modified_key = $1
|
196
|
+
code =
|
197
|
+
case $1
|
198
|
+
when /[0-9]/
|
199
|
+
?\M-0.bytes.first + (modified_key.ord - ?0.ord)
|
200
|
+
when /[A-Z]/
|
201
|
+
?\M-A.bytes.first + (modified_key.ord - ?A.ord)
|
202
|
+
when /[a-z]/
|
203
|
+
?\M-a.bytes.first + (modified_key.ord - ?a.ord)
|
204
|
+
end
|
205
|
+
code.chr('ASCII-8BIT')
|
206
|
+
when /\\C-M-[A-Za-z_]/, /\\M-C-[A-Za-z_]/
|
207
|
+
# 129 M-^A
|
208
|
+
when /\\(\d{1,3})/ then $1.to_i(8).chr # octal
|
209
|
+
when /\\x(\h{1,2})/ then $1.to_i(16).chr # hexadecimal
|
210
|
+
when "\\e" then ?\e
|
211
|
+
when "\\\\" then ?\\
|
212
|
+
when "\\\"" then ?"
|
213
|
+
when "\\'" then ?'
|
214
|
+
when "\\a" then ?\a
|
215
|
+
when "\\b" then ?\b
|
216
|
+
when "\\d" then ?\d
|
217
|
+
when "\\f" then ?\f
|
218
|
+
when "\\n" then ?\n
|
219
|
+
when "\\r" then ?\r
|
220
|
+
when "\\t" then ?\t
|
221
|
+
when "\\v" then ?\v
|
222
|
+
else notation
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def parse_keyseq(str)
|
227
|
+
# TODO: Control- and Meta-
|
228
|
+
ret = String.new(encoding: 'ASCII-8BIT')
|
229
|
+
while str =~ /(\\C-[A-Za-z_]|\\M-[0-9A-Za-z_]|\\C-M-[A-Za-z_]|\\M-C-[A-Za-z_]|\\e|\\\\|\\"|\\'|\\a|\\b|\\d|\\f|\\n|\\r|\\t|\\v|\\\d{1,3}|\\x\h{1,2}|.)/
|
230
|
+
ret << key_notation_to_char($&)
|
231
|
+
str = $'
|
232
|
+
end
|
233
|
+
ret
|
234
|
+
end
|
235
|
+
end
|