rb-readline 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +12 -1
- data/README +6 -3
- data/Rakefile +12 -3
- data/examples/multi-line.rb +61 -0
- data/examples/prompt.rb +18 -0
- data/examples/shell2.rb +58 -0
- data/examples/term.rb +3 -0
- data/lib/rbreadline.rb +38 -21
- data/lib/readline.rb +13 -1
- data/test/filesystem_completion_helper.rb +53 -0
- data/test/test_completion.rb +103 -0
- data/test/test_filename_completion_proc.rb +69 -0
- data/test/test_readline.rb +38 -0
- metadata +16 -11
data/CHANGES
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
=== 0.4.1 / 2011-07-29
|
2
|
+
|
3
|
+
* Bugfixes:
|
4
|
+
* Fix crash with double tab and an empty line buffer. GH-26 [phasis68]
|
5
|
+
* Accessing rl_line_buffer before initialization. GH-27 [phasis68]
|
6
|
+
* Fix hanging bug when completer finds a quote char. [Spakman]
|
7
|
+
* Filename completion on paths with directory components. GH-35 [Spakman]
|
8
|
+
* Attempted completion function now returns correct array. GH-34 [Spakman]
|
9
|
+
* Ensure @rl_filname_dequoting_function is used if defined. [Spakman]
|
10
|
+
* Remove deprecations with recent versions of RubyGems. [luislavena]
|
11
|
+
|
1
12
|
=== 0.4.0 / 2011-01-10
|
2
13
|
|
3
14
|
* Enhancements:
|
@@ -40,4 +51,4 @@
|
|
40
51
|
* Accept 'dumb' as valid terminal. Closes GH-7
|
41
52
|
* Fix crash when performing reverse look search. Closes GH-6
|
42
53
|
|
43
|
-
=== 0.1.2 / 2009-05-18
|
54
|
+
=== 0.1.2 / 2009-05-18
|
data/README
CHANGED
@@ -10,9 +10,9 @@ of the standard library.
|
|
10
10
|
|
11
11
|
loop do
|
12
12
|
line = Readline::readline('> ')
|
13
|
+
break if line.nil? || line == 'quit'
|
13
14
|
Readline::HISTORY.push(line)
|
14
15
|
puts "You typed: #{line}"
|
15
|
-
break if line == 'quit'
|
16
16
|
end
|
17
17
|
|
18
18
|
= Motivation
|
@@ -43,8 +43,10 @@ authors to write their own interface as they see fit.
|
|
43
43
|
= Tutorial
|
44
44
|
|
45
45
|
For an excellent tutorial on how to use Readline in practice, please see
|
46
|
-
Joseph Pecoraro's examples at http://bogojoker.com/readline/.
|
47
|
-
|
46
|
+
Joseph Pecoraro's examples at http://bogojoker.com/readline/.
|
47
|
+
|
48
|
+
You can also take a look at Ruby 1.9 stdlib Readline documentation located
|
49
|
+
at http://rubydoc.info/stdlib/readline/1.9.2/frames
|
48
50
|
|
49
51
|
= Alternatives
|
50
52
|
|
@@ -58,3 +60,4 @@ compatibility mode.
|
|
58
60
|
* Park Heesob (C translation, code donated as part of bounty)
|
59
61
|
* Daniel Berger (Documentation and testing)
|
60
62
|
* Luis Lavena (Maintainer)
|
63
|
+
* Mark Somerville (Contributor/Maintainer)
|
data/Rakefile
CHANGED
@@ -28,7 +28,6 @@ spec = Gem::Specification.new do |s|
|
|
28
28
|
s.require_path = 'lib'
|
29
29
|
|
30
30
|
# documentation
|
31
|
-
s.has_rdoc = true
|
32
31
|
s.rdoc_options << '--main' << 'README' << '--title' << 'Rb-Readline - Documentation'
|
33
32
|
|
34
33
|
s.extra_rdoc_files = %w(README LICENSE CHANGES)
|
@@ -38,8 +37,8 @@ spec = Gem::Specification.new do |s|
|
|
38
37
|
s.licenses = ['BSD']
|
39
38
|
|
40
39
|
# author and contributors
|
41
|
-
s.authors = ['Park Heesob', 'Daniel Berger', 'Luis Lavena']
|
42
|
-
s.email = ['phasis@gmail.com', 'djberg96@gmail.com', 'luislavena@gmail.com']
|
40
|
+
s.authors = ['Park Heesob', 'Daniel Berger', 'Luis Lavena', 'Mark Somerville']
|
41
|
+
s.email = ['phasis@gmail.com', 'djberg96@gmail.com', 'luislavena@gmail.com', 'mark@scottishclimbs.com']
|
43
42
|
end
|
44
43
|
|
45
44
|
Gem::PackageTask.new(spec) do |pkg|
|
@@ -50,3 +49,13 @@ Rake::TestTask.new do |t|
|
|
50
49
|
t.warning = true
|
51
50
|
t.verbose = true
|
52
51
|
end
|
52
|
+
|
53
|
+
desc "Install the gem locally"
|
54
|
+
task :install => :gem do
|
55
|
+
Dir.chdir(File.dirname(__FILE__)) do
|
56
|
+
sh %{gem install --local pkg/#{spec.name}-#{spec.version}}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "The default is to test everything."
|
61
|
+
task :default => :test
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rb-readline'
|
2
|
+
|
3
|
+
module RbReadline
|
4
|
+
def self.return_key(count, key)
|
5
|
+
if rl_line_buffer.split("\n").size > 2
|
6
|
+
@rl_done = true
|
7
|
+
puts
|
8
|
+
else
|
9
|
+
rl_insert(count, "\n")
|
10
|
+
rl_redisplay
|
11
|
+
rl_insert(1, "#{" " * (@rl_visible_prompt_length-2)}> ") unless @rl_done
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.multiline_prompt
|
16
|
+
' ' * (@rl_visible_prompt_length-2) + "> "
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.up_a_line(count, key)
|
20
|
+
lines = (multiline_prompt + rl_line_buffer[0...@rl_point]).split("\n")
|
21
|
+
return if lines.size == 1
|
22
|
+
|
23
|
+
current_line, previous_line = lines.pop, lines.pop
|
24
|
+
|
25
|
+
chars_back = current_line.length + 1
|
26
|
+
if previous_line.length >= @_rl_last_c_pos
|
27
|
+
chars_back += (previous_line.length - @_rl_last_c_pos)
|
28
|
+
end
|
29
|
+
|
30
|
+
@rl_point -= chars_back
|
31
|
+
rl_redisplay
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.down_a_line(count, key)
|
35
|
+
lines = (multiline_prompt + rl_line_buffer).split("\n")
|
36
|
+
return if @_rl_last_v_pos == (lines.size - 1)
|
37
|
+
|
38
|
+
current_line, next_line = lines[@_rl_last_v_pos], lines[@_rl_last_v_pos+1]
|
39
|
+
|
40
|
+
chars_forward = current_line.length - @_rl_last_c_pos + 1
|
41
|
+
if next_line.length < @_rl_last_c_pos
|
42
|
+
chars_forward += next_line.length
|
43
|
+
else
|
44
|
+
chars_forward += @_rl_last_c_pos
|
45
|
+
end
|
46
|
+
|
47
|
+
@rl_point += chars_forward
|
48
|
+
rl_redisplay
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
RbReadline.rl_bind_key "\r", :return_key
|
53
|
+
RbReadline.rl_bind_key "\n", :return_key
|
54
|
+
RbReadline.rl_bind_key "\e[A", :up_a_line
|
55
|
+
RbReadline.rl_bind_key "\e[B", :down_a_line
|
56
|
+
|
57
|
+
loop do
|
58
|
+
line = Readline.readline("Multi> ", true)
|
59
|
+
line = line.lines.to_a.map { |l| l.sub(/^ +> /, "") }.join
|
60
|
+
p line
|
61
|
+
end
|
data/examples/prompt.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rb-readline'
|
2
|
+
|
3
|
+
Cyan = "\001\e[0;36m\002"
|
4
|
+
Green = "\001\e[1;32m\002"
|
5
|
+
Reset = "\001\e[0m\002"
|
6
|
+
prompt = "\001\e[0;36m\002screwy\001\e[m\002 % "
|
7
|
+
prompt = "\001\e[0;36m\002this is long enough to cause a problem\001\e[m\002 % "
|
8
|
+
prompt = "[ ] > "
|
9
|
+
|
10
|
+
loop do
|
11
|
+
Readline.readline(prompt, true)
|
12
|
+
RbReadline.rl_set_prompt "[*] > "
|
13
|
+
# RbReadline.rl_maybe_replace_line
|
14
|
+
# RbReadline.rl_redisplay
|
15
|
+
RbReadline.rl_refresh_line nil, nil
|
16
|
+
sleep 2
|
17
|
+
puts
|
18
|
+
end
|
data/examples/shell2.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib/"
|
3
|
+
require 'readline'
|
4
|
+
|
5
|
+
RbReadline.rl_completer_quote_characters = "\\" if defined? RbReadline
|
6
|
+
RbReadline.rl_filename_quote_characters = " " if defined? RbReadline
|
7
|
+
|
8
|
+
module RbReadline
|
9
|
+
# IMPORTANT - this somehow gets changed...
|
10
|
+
@rl_completion_quote_character = "\\"
|
11
|
+
|
12
|
+
@rl_filename_dequoting_function = :dequote_filename
|
13
|
+
@rl_filename_quoting_function = :quote_filename
|
14
|
+
@rl_char_is_quoted_p = :char_is_quoted?
|
15
|
+
|
16
|
+
def self.char_is_quoted?(buffer, point)
|
17
|
+
buffer[point-1,1] == "\\" || buffer[point,1] == "\\"
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.dequote_filename(filename, quote_char)
|
21
|
+
quote_char = "\\" if quote_char == 0.chr
|
22
|
+
filename.delete quote_char
|
23
|
+
# @filename.gsub!(quote_char, "") if @filename
|
24
|
+
end
|
25
|
+
|
26
|
+
# def self.directory_completion_hook(filename)
|
27
|
+
# @dirname.gsub!("\\", "") if @dirname
|
28
|
+
# end
|
29
|
+
|
30
|
+
def self.quote_filename(filename, mtype, quote_char)
|
31
|
+
# if mtype == SINGLE_MATCH
|
32
|
+
# @rl_filename_quote_characters.each_char do |c|
|
33
|
+
# filename.sub!(//, "\\#{c}")
|
34
|
+
# end
|
35
|
+
# elsif mtype == MULT_MATCH
|
36
|
+
f = filename.dup
|
37
|
+
@rl_filename_quote_characters.each_char do |c|
|
38
|
+
f.gsub!(c, "\\#{c}")
|
39
|
+
end
|
40
|
+
f
|
41
|
+
# @rl_filename_quote_characters.each_char do |c|
|
42
|
+
# #p c
|
43
|
+
# index = filename.rindex(c)
|
44
|
+
# filename.insert(index, '\\') unless filename[index-1,1] == '\\'
|
45
|
+
# filename.gsub!(//, "\\#{c}")
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
# filename
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
loop do
|
54
|
+
line = Readline::readline('> ')
|
55
|
+
Readline::HISTORY.push(line)
|
56
|
+
puts "You typed: #{line}"
|
57
|
+
break if line == 'quit'
|
58
|
+
end
|
data/examples/term.rb
ADDED
data/lib/rbreadline.rb
CHANGED
@@ -15,7 +15,7 @@ module RbReadline
|
|
15
15
|
|
16
16
|
RL_LIBRARY_VERSION = "5.2"
|
17
17
|
RL_READLINE_VERSION = 0x0502
|
18
|
-
RB_READLINE_VERSION = "0.4.
|
18
|
+
RB_READLINE_VERSION = "0.4.1"
|
19
19
|
|
20
20
|
EOF = "\xFF"
|
21
21
|
ESC = "\C-["
|
@@ -774,7 +774,7 @@ module RbReadline
|
|
774
774
|
@rl_num_chars_to_read = 0
|
775
775
|
|
776
776
|
# Line buffer and maintenence.
|
777
|
-
@rl_line_buffer =
|
777
|
+
@rl_line_buffer = ""
|
778
778
|
|
779
779
|
# Key sequence `contexts'
|
780
780
|
@_rl_kscxt = nil
|
@@ -1104,10 +1104,11 @@ module RbReadline
|
|
1104
1104
|
:rl_readline_name,:history_length,:history_base
|
1105
1105
|
|
1106
1106
|
module_function
|
1107
|
+
|
1107
1108
|
# Okay, now we write the entry_function for filename completion. In the
|
1108
|
-
#
|
1109
|
-
#
|
1110
|
-
#
|
1109
|
+
# general case. Note that completion in the shell is a little different
|
1110
|
+
# because of all the pathnames that must be followed when looking up the
|
1111
|
+
# completion for a command.
|
1111
1112
|
def rl_filename_completion_function(text, state)
|
1112
1113
|
# If we don't have any state, then do some initialization.
|
1113
1114
|
if (state == 0)
|
@@ -1117,12 +1118,23 @@ module RbReadline
|
|
1117
1118
|
@directory.close
|
1118
1119
|
@directory = nil
|
1119
1120
|
end
|
1121
|
+
|
1120
1122
|
text.delete!(0.chr)
|
1121
|
-
@filename = text.dup
|
1122
1123
|
if text.length == 0
|
1123
|
-
|
1124
|
+
@dirname = "."
|
1125
|
+
@filename = ""
|
1126
|
+
elsif text.rindex(File::SEPARATOR) == text.length-1
|
1127
|
+
@dirname = text
|
1128
|
+
@filename = ""
|
1129
|
+
else
|
1130
|
+
@dirname, @filename = File.split(text)
|
1131
|
+
|
1132
|
+
# This preserves the "./" when the user types "./dirname<tab>".
|
1133
|
+
if @dirname == "." && text[0,2] == ".#{File::SEPARATOR}"
|
1134
|
+
@dirname += File::SEPARATOR
|
1135
|
+
end
|
1124
1136
|
end
|
1125
|
-
|
1137
|
+
|
1126
1138
|
# We aren't done yet. We also support the "~user" syntax.
|
1127
1139
|
|
1128
1140
|
# Save the version of the directory that the user typed.
|
@@ -1138,16 +1150,20 @@ module RbReadline
|
|
1138
1150
|
@users_dirname = @dirname.dup
|
1139
1151
|
elsif (@rl_completion_found_quote && @rl_filename_dequoting_function)
|
1140
1152
|
# delete single and double quotes
|
1141
|
-
|
1153
|
+
temp = send(@rl_filename_dequoting_function, @users_dirname, @rl_completion_quote_character)
|
1142
1154
|
@users_dirname = temp
|
1155
|
+
@dirname = @users_dirname.dup
|
1143
1156
|
end
|
1144
1157
|
|
1145
|
-
|
1158
|
+
begin
|
1159
|
+
@directory = Dir.new(@dirname)
|
1160
|
+
rescue Errno::ENOENT, Errno::ENOTDIR
|
1161
|
+
end
|
1146
1162
|
|
1147
1163
|
# Now dequote a non-null filename.
|
1148
1164
|
if (@filename && @filename.length>0 && @rl_completion_found_quote && @rl_filename_dequoting_function)
|
1149
1165
|
# delete single and double quotes
|
1150
|
-
temp = send(@rl_filename_dequoting_function
|
1166
|
+
temp = send(@rl_filename_dequoting_function, @filename, @rl_completion_quote_character)
|
1151
1167
|
@filename = temp
|
1152
1168
|
end
|
1153
1169
|
|
@@ -1197,13 +1213,13 @@ module RbReadline
|
|
1197
1213
|
if (@dirname != '.')
|
1198
1214
|
if (@rl_complete_with_tilde_expansion && @users_dirname[0,1] == "~")
|
1199
1215
|
temp = @dirname
|
1200
|
-
if(temp[-1,1] !=
|
1201
|
-
temp +=
|
1216
|
+
if(temp[-1,1] != File::SEPARATOR)
|
1217
|
+
temp += File::SEPARATOR
|
1202
1218
|
end
|
1203
1219
|
else
|
1204
1220
|
temp = @users_dirname
|
1205
|
-
if(temp[-1,1] !=
|
1206
|
-
temp +=
|
1221
|
+
if(temp[-1,1] != File::SEPARATOR)
|
1222
|
+
temp += File::SEPARATOR
|
1207
1223
|
end
|
1208
1224
|
end
|
1209
1225
|
temp += entry
|
@@ -4845,7 +4861,7 @@ module RbReadline
|
|
4845
4861
|
text = nil
|
4846
4862
|
end
|
4847
4863
|
@rl_end -= diff
|
4848
|
-
@rl_line_buffer[@rl_end] = 0.chr
|
4864
|
+
@rl_line_buffer[@rl_end,1] = 0.chr
|
4849
4865
|
return (diff)
|
4850
4866
|
end
|
4851
4867
|
|
@@ -6074,6 +6090,12 @@ module RbReadline
|
|
6074
6090
|
scan = 0
|
6075
6091
|
pass_next = false
|
6076
6092
|
while scan < _end
|
6093
|
+
if !@rl_byte_oriented
|
6094
|
+
scan = _rl_find_next_mbchar(@rl_line_buffer, scan, 1, MB_FIND_ANY)
|
6095
|
+
else
|
6096
|
+
scan += 1
|
6097
|
+
end
|
6098
|
+
|
6077
6099
|
if (pass_next)
|
6078
6100
|
pass_next = false
|
6079
6101
|
next
|
@@ -6111,11 +6133,6 @@ module RbReadline
|
|
6111
6133
|
found_quote |= RL_QF_OTHER_QUOTE
|
6112
6134
|
end
|
6113
6135
|
end
|
6114
|
-
if !@rl_byte_oriented
|
6115
|
-
scan = _rl_find_next_mbchar(@rl_line_buffer, scan, 1, MB_FIND_ANY)
|
6116
|
-
else
|
6117
|
-
scan += 1
|
6118
|
-
end
|
6119
6136
|
end
|
6120
6137
|
end
|
6121
6138
|
|
data/lib/readline.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# readline.rb -- GNU Readline module
|
2
|
-
# Copyright (C) 1997-2001 Shugo
|
2
|
+
# Copyright (C) 1997-2001 Shugo Maeda
|
3
3
|
#
|
4
4
|
# Ruby translation by Park Heesob phasis@gmail.com
|
5
5
|
|
@@ -110,6 +110,17 @@ module Readline
|
|
110
110
|
@completion_case_fold
|
111
111
|
end
|
112
112
|
|
113
|
+
# Returns nil if no matches are found or an array of strings:
|
114
|
+
#
|
115
|
+
# [0] is the replacement for text
|
116
|
+
# [1..n] the possible matches
|
117
|
+
# [n+1] nil
|
118
|
+
#
|
119
|
+
# The possible matches should not include [0].
|
120
|
+
#
|
121
|
+
# If this method sets RbReadline.rl_attempted_completion_over to true,
|
122
|
+
# then the default completion function will not be called when this
|
123
|
+
# function returns nil.
|
113
124
|
def self.readline_attempted_completion_function(text,start,_end)
|
114
125
|
proc = @completion_proc
|
115
126
|
return nil if proc.nil?
|
@@ -134,6 +145,7 @@ module Readline
|
|
134
145
|
|
135
146
|
if(matches==1)
|
136
147
|
result[0] = result[1].dup
|
148
|
+
result[1] = nil
|
137
149
|
else
|
138
150
|
i = 1
|
139
151
|
low = 100000
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
|
3
|
+
module FilesystemCompletionHelper
|
4
|
+
SEP = File::SEPARATOR
|
5
|
+
COMP_TEST_DIR = "comp_test#{SEP}"
|
6
|
+
SUB_DIR = "#{COMP_TEST_DIR}a_sub_dir#{SEP}"
|
7
|
+
SUB_SUB_DIR = "#{SUB_DIR}another_sub_dir#{SEP}"
|
8
|
+
DIR_WITH_SPACES = "#{COMP_TEST_DIR}dir with spaces#{SEP}"
|
9
|
+
SUB_DIR_WITH_SPACES = "#{DIR_WITH_SPACES}sub dir with spaces#{SEP}"
|
10
|
+
|
11
|
+
# This creates:
|
12
|
+
#
|
13
|
+
# comp_test/
|
14
|
+
# abc
|
15
|
+
# aaa
|
16
|
+
# a_sub_dir/
|
17
|
+
# abc
|
18
|
+
# aaa
|
19
|
+
# another_sub_dir/
|
20
|
+
# aaa
|
21
|
+
# dir with spaces/
|
22
|
+
# filename with spaces
|
23
|
+
# sub dir with spaces/
|
24
|
+
# another filename with spaces
|
25
|
+
def setup_filesystem_for_completion
|
26
|
+
FileUtils.mkdir_p("#{SUB_SUB_DIR}")
|
27
|
+
FileUtils.mkdir_p("#{SUB_DIR_WITH_SPACES}")
|
28
|
+
@comp_test_dir = Dir.new COMP_TEST_DIR
|
29
|
+
@sub_dir = Dir.new SUB_DIR
|
30
|
+
@sub_sub_dir = Dir.new SUB_SUB_DIR
|
31
|
+
@dir_with_spaces = Dir.new DIR_WITH_SPACES
|
32
|
+
@sub_dir_with_spaces = Dir.new SUB_DIR_WITH_SPACES
|
33
|
+
|
34
|
+
FileUtils.touch("#{@comp_test_dir.path}abc")
|
35
|
+
FileUtils.touch("#{@comp_test_dir.path}aaa")
|
36
|
+
FileUtils.touch("#{@sub_dir.path}abc")
|
37
|
+
FileUtils.touch("#{@sub_dir.path}aaa")
|
38
|
+
FileUtils.touch("#{@sub_sub_dir.path}aaa")
|
39
|
+
FileUtils.touch("#{@dir_with_spaces.path}filename with spaces")
|
40
|
+
FileUtils.touch("#{@sub_dir_with_spaces.path}another filename with spaces")
|
41
|
+
|
42
|
+
# The previous Dir.new calls seem to cache the dir entries on Windows.
|
43
|
+
@comp_test_dir = Dir.new COMP_TEST_DIR
|
44
|
+
@sub_dir = Dir.new SUB_DIR
|
45
|
+
@sub_sub_dir = Dir.new SUB_SUB_DIR
|
46
|
+
@sub_dir_with_spaces = Dir.new SUB_DIR_WITH_SPACES
|
47
|
+
@dir_with_spaces = Dir.new DIR_WITH_SPACES
|
48
|
+
end
|
49
|
+
|
50
|
+
def teardown_filesystem_after_completion
|
51
|
+
FileUtils.rm_r(COMP_TEST_DIR)
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require 'timeout'
|
3
|
+
require "readline"
|
4
|
+
require "#{File.expand_path(File.dirname(__FILE__))}/filesystem_completion_helper"
|
5
|
+
|
6
|
+
class TestCompletion < Test::Unit::TestCase
|
7
|
+
include RbReadline
|
8
|
+
include FilesystemCompletionHelper
|
9
|
+
|
10
|
+
def filename_quoting_function(filename, mtype, quote_char)
|
11
|
+
quoted_filename = filename.dup
|
12
|
+
@rl_filename_quote_characters.split("").each do |c|
|
13
|
+
quoted_filename.gsub!(c, "\\#{c}")
|
14
|
+
end
|
15
|
+
quoted_filename
|
16
|
+
end
|
17
|
+
|
18
|
+
def filename_dequoting_function(filename, quote_char = "\\")
|
19
|
+
filename.delete quote_char
|
20
|
+
end
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@rl_completion_word_break_hook, @rl_char_is_quoted_p = nil
|
24
|
+
@rl_basic_quote_characters, @rl_special_prefixes = nil
|
25
|
+
@rl_completer_word_break_characters = Readline.basic_word_break_characters
|
26
|
+
@rl_completer_quote_characters = "\\"
|
27
|
+
@rl_completion_quote_character = "\\"
|
28
|
+
@rl_filename_quote_characters = " "
|
29
|
+
@rl_byte_oriented = true
|
30
|
+
@rl_filename_quoting_desired = true
|
31
|
+
@rl_filename_completion_desired = true
|
32
|
+
@rl_complete_with_tilde_expansion = true
|
33
|
+
@_rl_match_hidden_files = false
|
34
|
+
@rl_completion_found_quote = false
|
35
|
+
@_rl_completion_case_fold = false
|
36
|
+
@directory = nil
|
37
|
+
|
38
|
+
@rl_filename_quoting_function = :filename_quoting_function
|
39
|
+
@rl_filename_dequoting_function = :filename_dequoting_function
|
40
|
+
@rl_directory_completion_hook = nil
|
41
|
+
|
42
|
+
setup_filesystem_for_completion
|
43
|
+
end
|
44
|
+
|
45
|
+
def teardown
|
46
|
+
teardown_filesystem_after_completion
|
47
|
+
end
|
48
|
+
|
49
|
+
def set_line_buffer(text)
|
50
|
+
@rl_line_buffer = text
|
51
|
+
@rl_point = @rl_line_buffer.size
|
52
|
+
@rl_line_buffer << 0.chr
|
53
|
+
end
|
54
|
+
|
55
|
+
def test__find_completion_word_doesnt_hang_on_completer_quote_character
|
56
|
+
set_line_buffer "#{@dir_with_spaces.path}filename\\ w"
|
57
|
+
|
58
|
+
assert_nothing_raised do
|
59
|
+
Timeout::timeout(3) do
|
60
|
+
assert_equal([ "\000", true, "\000" ], _rl_find_completion_word)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def test__find_completion_word_without_quote_characters
|
66
|
+
set_line_buffer "#{@comp_test_dir.path}a"
|
67
|
+
assert_equal([ "\000", false, "\000" ], _rl_find_completion_word)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_make_quoted_replacement_calls_filename_quoting_function
|
71
|
+
match = RbReadline::SINGLE_MATCH
|
72
|
+
|
73
|
+
assert_equal "dir/with\\ space", make_quoted_replacement("dir/with space", RbReadline::SINGLE_MATCH, 0.chr)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_rl_filname_completion_function_calls_dequoting_function
|
77
|
+
@rl_completion_found_quote = true
|
78
|
+
dir = filename_quoting_function(@dir_with_spaces.path, nil, 0.chr)
|
79
|
+
|
80
|
+
# rl_filename_completion_function is called with an increasing state in
|
81
|
+
# order to iterate through directory entries.
|
82
|
+
|
83
|
+
entries = [ "#{@dir_with_spaces.path}sub dir with spaces", "#{@dir_with_spaces.path}filename with spaces" ]
|
84
|
+
|
85
|
+
assert entries.include?(rl_filename_completion_function(dir, 0))
|
86
|
+
assert entries.include?(rl_filename_completion_function(dir, 1))
|
87
|
+
assert_nil rl_filename_completion_function(dir, 2)
|
88
|
+
ensure
|
89
|
+
@rl_completion_found_quote = false
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_completing_path_starting_dot_slash
|
93
|
+
assert_equal "./#{COMP_TEST_DIR.chop}", rl_filename_completion_function("./#{COMP_TEST_DIR.chop}", 0)
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_completing_non_existant_directory
|
97
|
+
assert_nil rl_filename_completion_function("/this/dir/does/not/exist", 0)
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_completing_a_file_as_a_directory
|
101
|
+
assert_nil rl_filename_completion_function("#{File.expand_path(__FILE__)}/", 0)
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'readline'
|
4
|
+
require "#{File.expand_path(File.dirname(__FILE__))}/filesystem_completion_helper"
|
5
|
+
|
6
|
+
class TC_FILENAME_COMPLETION_PROC < Test::Unit::TestCase
|
7
|
+
include FilesystemCompletionHelper
|
8
|
+
|
9
|
+
def setup
|
10
|
+
FileUtils.mkdir_p("#{SUB_SUB_DIR}")
|
11
|
+
FileUtils.mkdir_p("#{SUB_DIR_WITH_SPACES}")
|
12
|
+
@comp_test_dir = Dir.new COMP_TEST_DIR
|
13
|
+
@sub_dir = Dir.new SUB_DIR
|
14
|
+
@sub_sub_dir = Dir.new SUB_SUB_DIR
|
15
|
+
@dir_with_spaces = Dir.new DIR_WITH_SPACES
|
16
|
+
@sub_dir_with_spaces = Dir.new SUB_DIR_WITH_SPACES
|
17
|
+
|
18
|
+
FileUtils.touch("#{@comp_test_dir.path}abc")
|
19
|
+
FileUtils.touch("#{@comp_test_dir.path}aaa")
|
20
|
+
FileUtils.touch("#{@sub_dir.path}abc")
|
21
|
+
FileUtils.touch("#{@sub_dir.path}aaa")
|
22
|
+
FileUtils.touch("#{@sub_sub_dir.path}aaa")
|
23
|
+
FileUtils.touch("#{@dir_with_spaces.path}filename with spaces")
|
24
|
+
FileUtils.touch("#{@sub_dir_with_spaces.path}another filename with spaces")
|
25
|
+
|
26
|
+
# The previous Dir.new calls seem to cache the dir entries on Windows.
|
27
|
+
@comp_test_dir = Dir.new COMP_TEST_DIR
|
28
|
+
@sub_dir = Dir.new SUB_DIR
|
29
|
+
@sub_sub_dir = Dir.new SUB_SUB_DIR
|
30
|
+
@dir_with_spaces = Dir.new DIR_WITH_SPACES
|
31
|
+
@sub_dir_with_spaces = Dir.new SUB_DIR_WITH_SPACES
|
32
|
+
setup_filesystem_for_completion
|
33
|
+
end
|
34
|
+
|
35
|
+
def teardown
|
36
|
+
teardown_filesystem_after_completion
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_listing_files_in_cwd
|
40
|
+
Dir.chdir(COMP_TEST_DIR) do
|
41
|
+
entries = Dir.entries(".").select { |e| e[0,1] == "a" }
|
42
|
+
assert_equal entries, Readline::FILENAME_COMPLETION_PROC.call("a")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_list_files_in_sub_directories
|
47
|
+
entries = @sub_dir.entries.select { |e| e[0,1] == "a" }
|
48
|
+
entries.map! { |e| "#{@sub_dir.path}#{e}" }
|
49
|
+
assert_equal entries, Readline::FILENAME_COMPLETION_PROC.call("#{@sub_dir.path}a")
|
50
|
+
|
51
|
+
entries = @sub_sub_dir.entries - %w( . .. )
|
52
|
+
entries.map! { |e| "#{@sub_sub_dir.path}#{e}" }
|
53
|
+
assert_equal entries, Readline::FILENAME_COMPLETION_PROC.call("#{@sub_sub_dir.path}")
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_list_files_and_directories_with_spaces
|
57
|
+
entries = @comp_test_dir.entries.select { |e| e[0,1] == "d" }
|
58
|
+
entries.map! { |e| @comp_test_dir.path + e }
|
59
|
+
assert_equal entries, Readline::FILENAME_COMPLETION_PROC.call("#{@comp_test_dir.path}d")
|
60
|
+
|
61
|
+
entries = @dir_with_spaces.entries - %w( . .. )
|
62
|
+
entries.map! { |e| @dir_with_spaces.path + e }
|
63
|
+
assert_equal entries, Readline::FILENAME_COMPLETION_PROC.call("#{@dir_with_spaces.path}")
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_list_files_in_current_directory
|
67
|
+
assert_equal((Dir.entries(".") - %w( . .. )).sort, Readline::FILENAME_COMPLETION_PROC.call("").sort)
|
68
|
+
end
|
69
|
+
end
|
data/test/test_readline.rb
CHANGED
@@ -124,6 +124,44 @@ class TC_Readline < Test::Unit::TestCase
|
|
124
124
|
assert_nothing_raised{ Readline.basic_quote_characters = "\"'" }
|
125
125
|
end
|
126
126
|
|
127
|
+
def test_attempted_comp_func_returns_nil_when_no_completion_proc_set
|
128
|
+
assert_equal nil, Readline.readline_attempted_completion_function("12", 0, 1)
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_attempted_comp_func_case_folding
|
132
|
+
Readline.completion_proc = Proc.new do |word|
|
133
|
+
%w( 123456 123abc abc123 ).grep(/^#{word}/i)
|
134
|
+
end
|
135
|
+
|
136
|
+
Readline.completion_case_fold = true
|
137
|
+
|
138
|
+
assert_equal [ "123", "123456", "123abc", nil ], Readline.readline_attempted_completion_function("123", 0, 3)
|
139
|
+
|
140
|
+
assert_equal [ "123abc", nil, nil ], Readline.readline_attempted_completion_function("123A", 0, 3)
|
141
|
+
|
142
|
+
ensure
|
143
|
+
Readline.module_eval do
|
144
|
+
@completion_proc = nil
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_attempted_comp_func_removes_replacement_from_possible_matches
|
149
|
+
Readline.completion_proc = Proc.new do |word|
|
150
|
+
%w( 123456 123abc abc123 ).grep(/^#{word}/)
|
151
|
+
end
|
152
|
+
|
153
|
+
assert_equal [ "123", "123456", "123abc", nil ], Readline.readline_attempted_completion_function("12", 0, 1)
|
154
|
+
|
155
|
+
assert_equal [ "123", "123456", "123abc", nil ], Readline.readline_attempted_completion_function("123", 0, 2)
|
156
|
+
|
157
|
+
assert_equal [ "123456", nil, nil ], Readline.readline_attempted_completion_function("1234", 0, 3)
|
158
|
+
|
159
|
+
ensure
|
160
|
+
Readline.module_eval do
|
161
|
+
@completion_proc = nil
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
127
165
|
def teardown
|
128
166
|
@proc = nil
|
129
167
|
end
|
metadata
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rb-readline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
4
|
+
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
7
|
- 4
|
9
|
-
-
|
10
|
-
version: 0.4.
|
8
|
+
- 1
|
9
|
+
version: 0.4.1
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Park Heesob
|
14
13
|
- Daniel Berger
|
15
14
|
- Luis Lavena
|
15
|
+
- Mark Somerville
|
16
16
|
autorequire:
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-
|
20
|
+
date: 2011-07-29 00:00:00 +01:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -28,7 +28,6 @@ dependencies:
|
|
28
28
|
requirements:
|
29
29
|
- - ">="
|
30
30
|
- !ruby/object:Gem::Version
|
31
|
-
hash: 3
|
32
31
|
segments:
|
33
32
|
- 0
|
34
33
|
version: "0"
|
@@ -39,6 +38,7 @@ email:
|
|
39
38
|
- phasis@gmail.com
|
40
39
|
- djberg96@gmail.com
|
41
40
|
- luislavena@gmail.com
|
41
|
+
- mark@scottishclimbs.com
|
42
42
|
executables: []
|
43
43
|
|
44
44
|
extensions: []
|
@@ -48,14 +48,21 @@ extra_rdoc_files:
|
|
48
48
|
- LICENSE
|
49
49
|
- CHANGES
|
50
50
|
files:
|
51
|
-
- examples/
|
51
|
+
- examples/shell2.rb
|
52
|
+
- examples/multi-line.rb
|
53
|
+
- examples/prompt.rb
|
52
54
|
- examples/example_readline_with_completion.rb
|
53
55
|
- examples/tinyirb.rb
|
56
|
+
- examples/example_readline.rb
|
57
|
+
- examples/term.rb
|
54
58
|
- lib/rb-readline.rb
|
55
59
|
- lib/rbreadline.rb
|
56
60
|
- lib/readline.rb
|
57
|
-
- test/
|
61
|
+
- test/test_completion.rb
|
58
62
|
- test/test_readline.rb
|
63
|
+
- test/filesystem_completion_helper.rb
|
64
|
+
- test/test_rbreadline.rb
|
65
|
+
- test/test_filename_completion_proc.rb
|
59
66
|
- README
|
60
67
|
- LICENSE
|
61
68
|
- CHANGES
|
@@ -78,7 +85,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
78
85
|
requirements:
|
79
86
|
- - ">="
|
80
87
|
- !ruby/object:Gem::Version
|
81
|
-
hash: 59
|
82
88
|
segments:
|
83
89
|
- 1
|
84
90
|
- 8
|
@@ -89,7 +95,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
95
|
requirements:
|
90
96
|
- - ">="
|
91
97
|
- !ruby/object:Gem::Version
|
92
|
-
hash: 17
|
93
98
|
segments:
|
94
99
|
- 1
|
95
100
|
- 3
|
@@ -98,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
103
|
requirements: []
|
99
104
|
|
100
105
|
rubyforge_project:
|
101
|
-
rubygems_version: 1.
|
106
|
+
rubygems_version: 1.3.7
|
102
107
|
signing_key:
|
103
108
|
specification_version: 3
|
104
109
|
summary: Pure-Ruby Readline Implementation
|