rb-readline 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|