fxri 0.3.3 → 0.3.4
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/bugs/fxri bug `concat' can't convert nil into Array (TypeError).eml +50 -0
- data/bugs/fxri with Ruby v1.8.5 via OneClickInstaller v1.8.5-21.eml +167 -0
- data/fxri +344 -319
- data/fxri-0.3.4.gem +0 -0
- data/fxri.gemspec +24 -24
- data/lib/Empty_Text_Field_Handler.rb +63 -63
- data/lib/FoxDisplayer.rb +148 -148
- data/lib/FoxTextFormatter.rb +274 -274
- data/lib/Globals.rb +50 -48
- data/lib/Icon_Loader.rb +35 -35
- data/lib/Packet_Item.rb +178 -178
- data/lib/Packet_List.rb +192 -192
- data/lib/Recursive_Open_Struct.rb +238 -233
- data/lib/RiManager.rb +159 -154
- data/lib/Search_Engine.rb +165 -165
- data/lib/fxirb-0.2.1/CHANGELOG +31 -0
- data/lib/fxirb-0.2.1/fxirb.rb +395 -0
- data/lib/fxirb.rb +400 -395
- metadata +24 -17
- data/fxri.kpf +0 -66
data/lib/RiManager.rb
CHANGED
@@ -1,155 +1,160 @@
|
|
1
|
-
require "yaml"
|
2
|
-
require 'rdoc/ri/ri_driver'
|
3
|
-
require 'pp'
|
4
|
-
|
5
|
-
class NameDescriptor
|
6
|
-
CLASS = 0
|
7
|
-
INSTANCE_METHOD = 1
|
8
|
-
CLASS_METHOD = 2
|
9
|
-
def type
|
10
|
-
@method_name ||= false
|
11
|
-
@is_class_method ||= false
|
12
|
-
if @method_name
|
13
|
-
if @is_class_method
|
14
|
-
CLASS_METHOD
|
15
|
-
else
|
16
|
-
INSTANCE_METHOD
|
17
|
-
end
|
18
|
-
else
|
19
|
-
CLASS
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_s
|
24
|
-
str = ""
|
25
|
-
str << @class_names.join("::")
|
26
|
-
if @method_name && str != ""
|
27
|
-
str << (@is_class_method ? "::" : "#")
|
28
|
-
end
|
29
|
-
str << @method_name if @method_name
|
30
|
-
str
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# This basically is a stripped down version of RiDriver.
|
35
|
-
# I cannot use RiDriver directly, because I need to set the driver.
|
36
|
-
class RiManager
|
37
|
-
def initialize(display, path = RI::Paths::PATH)
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
@
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
#
|
75
|
-
def
|
76
|
-
@
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
end
|
104
|
-
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
1
|
+
require "yaml"
|
2
|
+
require 'rdoc/ri/ri_driver'
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
class NameDescriptor
|
6
|
+
CLASS = 0
|
7
|
+
INSTANCE_METHOD = 1
|
8
|
+
CLASS_METHOD = 2
|
9
|
+
def type
|
10
|
+
@method_name ||= false
|
11
|
+
@is_class_method ||= false
|
12
|
+
if @method_name
|
13
|
+
if @is_class_method
|
14
|
+
CLASS_METHOD
|
15
|
+
else
|
16
|
+
INSTANCE_METHOD
|
17
|
+
end
|
18
|
+
else
|
19
|
+
CLASS
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
str = ""
|
25
|
+
str << @class_names.join("::")
|
26
|
+
if @method_name && str != ""
|
27
|
+
str << (@is_class_method ? "::" : "#")
|
28
|
+
end
|
29
|
+
str << @method_name if @method_name
|
30
|
+
str
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# This basically is a stripped down version of RiDriver.
|
35
|
+
# I cannot use RiDriver directly, because I need to set the driver.
|
36
|
+
class RiManager
|
37
|
+
def initialize(display, path = RI::Paths::PATH)
|
38
|
+
# See if search_paths exists, if so, append it to path
|
39
|
+
begin
|
40
|
+
path << $cfg.search_paths.split(';')
|
41
|
+
rescue
|
42
|
+
end
|
43
|
+
@reader = RI::RiReader.new(RI::RiCache.new(path))
|
44
|
+
@display = display
|
45
|
+
@display.reader = @reader
|
46
|
+
# prepare all names
|
47
|
+
@all_names = prepare_all_names
|
48
|
+
end
|
49
|
+
|
50
|
+
def prepare_all_names
|
51
|
+
names = Array.new
|
52
|
+
@reader.all_names.each do |name|
|
53
|
+
begin
|
54
|
+
names.push NameDescriptor.new(name)
|
55
|
+
rescue RiError => e
|
56
|
+
# silently ignore errors
|
57
|
+
end
|
58
|
+
end
|
59
|
+
names
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_names
|
63
|
+
@reader.all_names.each do |name|
|
64
|
+
begin
|
65
|
+
if (NameDescriptor.new(name).to_s != name)
|
66
|
+
p [name, NameDescriptor.new(name).to_s, NameDescriptor.new(name)]
|
67
|
+
end
|
68
|
+
rescue RiError => e
|
69
|
+
puts e
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns all fully names as name descriptors
|
75
|
+
def all_names
|
76
|
+
@all_names
|
77
|
+
end
|
78
|
+
|
79
|
+
# Searches for the description of a name and shows it using +display+.
|
80
|
+
def show(name_descriptor, width)
|
81
|
+
@display.width = width
|
82
|
+
# narrow down namespace
|
83
|
+
namespace = @reader.top_level_namespace
|
84
|
+
name_descriptor.class_names.each do |classname|
|
85
|
+
namespace = @reader.lookup_namespace_in(classname, namespace)
|
86
|
+
if namespace.empty?
|
87
|
+
raise RiError.new("Nothing known about #{name_descriptor}")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# At this point, if we have multiple possible namespaces, but one
|
92
|
+
# is an exact match for our requested class, prune down to just it
|
93
|
+
# PS: this comment is shamlessly stolen from ri_driver.rb
|
94
|
+
entries = namespace.find_all {|m| m.full_name == name_descriptor.full_class_name}
|
95
|
+
namespace = entries if entries.size == 1
|
96
|
+
|
97
|
+
if name_descriptor.method_name
|
98
|
+
methods = @reader.find_methods(name_descriptor.method_name, name_descriptor.is_class_method, namespace)
|
99
|
+
report_method_stuff(name_descriptor.method_name, methods)
|
100
|
+
else
|
101
|
+
report_class_stuff(namespace)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def report_class_stuff(namespace)
|
106
|
+
raise RiError.new("namespace") unless namespace.size==1
|
107
|
+
@display.display_class_info @reader.get_class(namespace[0])
|
108
|
+
end
|
109
|
+
|
110
|
+
def report_method_stuff(requested_method_name, methods)
|
111
|
+
if methods.size == 1
|
112
|
+
method = @reader.get_method(methods[0])
|
113
|
+
@display.display_method_info(method)
|
114
|
+
else
|
115
|
+
entries = methods.find_all {|m| m.name == requested_method_name}
|
116
|
+
if entries.size == 1
|
117
|
+
method = @reader.get_method(entries[0])
|
118
|
+
@display.display_method_info(method)
|
119
|
+
else
|
120
|
+
puts methods.map {|m| m.full_name}.join(", ")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
=begin
|
124
|
+
|
125
|
+
method = if (methods.size == 1)
|
126
|
+
@reader.get_method(methods[0])
|
127
|
+
else
|
128
|
+
entries = methods.find_all {|m| m.name == requested_method_name}
|
129
|
+
entries.size
|
130
|
+
# there really should be just *one* method that matches.
|
131
|
+
raise RiError.new("got a strange method") unless entries.size == 1
|
132
|
+
@reader.get_method(entries[0])
|
133
|
+
end
|
134
|
+
@display.display_method_info(method)
|
135
|
+
=end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
if __FILE__ == $0
|
140
|
+
display = Displayer.new
|
141
|
+
ri = RiManager.new(display)
|
142
|
+
ri.all_names.each do |name|
|
143
|
+
p [name.type, name.to_s] if name.type==0
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
=begin
|
149
|
+
# iterate through everything
|
150
|
+
reader.full_class_names.sort.each do |class_name|
|
151
|
+
classDesc = reader.find_class_by_name(class_name)
|
152
|
+
|
153
|
+
if class_name=="Integer"
|
154
|
+
pp classDesc.instance_methods
|
155
|
+
puts classDesc.to_yaml
|
156
|
+
#puts classDesc.methods
|
157
|
+
gets
|
158
|
+
end
|
159
|
+
end
|
155
160
|
=end
|
data/lib/Search_Engine.rb
CHANGED
@@ -1,165 +1,165 @@
|
|
1
|
-
# Copyright (c) 2005 Martin Ankerl
|
2
|
-
class Search_Engine
|
3
|
-
def initialize(gui, data)
|
4
|
-
@gui = gui
|
5
|
-
@data = data
|
6
|
-
@search_thread = nil
|
7
|
-
end
|
8
|
-
|
9
|
-
# Executed whenever a search criteria changes to update the packet list.
|
10
|
-
def on_search
|
11
|
-
# restart current search
|
12
|
-
@end_time = Time.now + $cfg.search_delay
|
13
|
-
@restart_search = true
|
14
|
-
@gui.search_label.enabled = false
|
15
|
-
return if @search_thread && @search_thread.status
|
16
|
-
|
17
|
-
@search_thread = Thread.new(@search_thread) do
|
18
|
-
begin
|
19
|
-
@gui.search_label.enabled = false
|
20
|
-
# wait untill deadline
|
21
|
-
while (t = (@end_time - Time.now)) > 0
|
22
|
-
sleep(t)
|
23
|
-
end
|
24
|
-
|
25
|
-
@data.gui_mutex.synchronize do
|
26
|
-
# the thread has to use the gui mutex inside
|
27
|
-
@restart_search = false
|
28
|
-
|
29
|
-
match_data = get_match_data
|
30
|
-
|
31
|
-
# remove all items
|
32
|
-
@gui.packet_list.dirty_clear
|
33
|
-
|
34
|
-
# add all items that match the search criteria
|
35
|
-
status_text_deadline = Time.now + $cfg.status_line_update_interval
|
36
|
-
@data.items.each do |item|
|
37
|
-
#item.parent = @gui.packet_list if match?(item, match_data)
|
38
|
-
if match?(item, match_data)
|
39
|
-
item.show
|
40
|
-
now = Time.now
|
41
|
-
if now > status_text_deadline
|
42
|
-
update_search_status_text
|
43
|
-
status_text_deadline = now + $cfg.status_line_update_interval
|
44
|
-
end
|
45
|
-
end
|
46
|
-
break if @restart_search
|
47
|
-
end
|
48
|
-
update_search_status_text
|
49
|
-
|
50
|
-
if (@gui.packet_list.numItems > 0)
|
51
|
-
@gui.packet_list.setCurrentItem(0)
|
52
|
-
@gui.packet_list.selectItem(0)
|
53
|
-
@gui.main.show_info(@gui.packet_list.getItem(0).packet_item.data)
|
54
|
-
end
|
55
|
-
@gui.search_label.enabled = true
|
56
|
-
|
57
|
-
end # synchronize
|
58
|
-
end while @restart_search# || match_data != @gui.search_field.text.downcase.split
|
59
|
-
end #thread.new
|
60
|
-
end
|
61
|
-
|
62
|
-
def get_match_data
|
63
|
-
str_to_match_data(@gui.search_field.text)
|
64
|
-
end
|
65
|
-
|
66
|
-
# Converts a string into a match_data representation.
|
67
|
-
def str_to_match_data(str, index=0)
|
68
|
-
words = [ ]
|
69
|
-
exclude = [ ]
|
70
|
-
is_exclude = false
|
71
|
-
|
72
|
-
while str[index]
|
73
|
-
case str[index]
|
74
|
-
when ?", ?'
|
75
|
-
word, index = get_word(str, index+1, str[index])
|
76
|
-
unless word.empty?
|
77
|
-
if is_exclude
|
78
|
-
exclude.push word
|
79
|
-
is_exclude = false
|
80
|
-
else
|
81
|
-
words.push word
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
when 32 # space
|
86
|
-
is_exclude = false
|
87
|
-
|
88
|
-
=begin
|
89
|
-
when ?>
|
90
|
-
min, index = get_word(str, index+1)
|
91
|
-
min = @gui.logic.size_to_nr(min)
|
92
|
-
|
93
|
-
when ?<
|
94
|
-
max, index = get_word(str, index+1)
|
95
|
-
max = @gui.logic.size_to_nr(max)
|
96
|
-
=end
|
97
|
-
when ?-
|
98
|
-
is_exclude = true
|
99
|
-
|
100
|
-
else
|
101
|
-
word, index = get_word(str, index)
|
102
|
-
if is_exclude
|
103
|
-
exclude.push word
|
104
|
-
is_exclude = false
|
105
|
-
else
|
106
|
-
words.push word
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
index += 1
|
111
|
-
end
|
112
|
-
|
113
|
-
# check if word has upcase letters
|
114
|
-
words.collect! do |w|
|
115
|
-
[w, /[A-Z]/.match(w)!=nil]
|
116
|
-
end
|
117
|
-
exclude.collect! do |w|
|
118
|
-
[w, /[A-Z]/.match(w)!=nil]
|
119
|
-
end
|
120
|
-
[words, exclude]
|
121
|
-
end
|
122
|
-
|
123
|
-
def get_word(str, index, delim=32) # 32==space
|
124
|
-
word = ""
|
125
|
-
c = str[index]
|
126
|
-
while (c && c != delim)
|
127
|
-
word += c.chr
|
128
|
-
index += 1
|
129
|
-
c = str[index]
|
130
|
-
end
|
131
|
-
[word, index]
|
132
|
-
end
|
133
|
-
|
134
|
-
# Update the text for the number of displayed packs.
|
135
|
-
def update_search_status_text
|
136
|
-
@gui.search_label.text = sprintf($cfg.text.search, @gui.packet_list.numItems, @data.items.size)
|
137
|
-
end
|
138
|
-
|
139
|
-
# Find out if item is matched by current search criteria.
|
140
|
-
def match?(item, match_data)
|
141
|
-
words, exclude, min, max = match_data
|
142
|
-
|
143
|
-
# check text that has to be there
|
144
|
-
searchable, sortable_downcase, sortable_normal = item.sortable(0)
|
145
|
-
words.each do |match_str, is_sensitive|
|
146
|
-
if is_sensitive
|
147
|
-
return false unless sortable_normal.include?(match_str)
|
148
|
-
else
|
149
|
-
return false unless sortable_downcase.include?(match_str)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
# check text not allowed to be there
|
154
|
-
exclude.each do |match_str, is_sensitive|
|
155
|
-
if is_sensitive
|
156
|
-
return false if sortable_normal.include?(match_str)
|
157
|
-
else
|
158
|
-
return false if sortable_downcase.include?(match_str)
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
# each check ok
|
163
|
-
true
|
164
|
-
end
|
165
|
-
end
|
1
|
+
# Copyright (c) 2005 Martin Ankerl
|
2
|
+
class Search_Engine
|
3
|
+
def initialize(gui, data)
|
4
|
+
@gui = gui
|
5
|
+
@data = data
|
6
|
+
@search_thread = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
# Executed whenever a search criteria changes to update the packet list.
|
10
|
+
def on_search
|
11
|
+
# restart current search
|
12
|
+
@end_time = Time.now + $cfg.search_delay
|
13
|
+
@restart_search = true
|
14
|
+
@gui.search_label.enabled = false
|
15
|
+
return if @search_thread && @search_thread.status
|
16
|
+
|
17
|
+
@search_thread = Thread.new(@search_thread) do
|
18
|
+
begin
|
19
|
+
@gui.search_label.enabled = false
|
20
|
+
# wait untill deadline
|
21
|
+
while (t = (@end_time - Time.now)) > 0
|
22
|
+
sleep(t)
|
23
|
+
end
|
24
|
+
|
25
|
+
@data.gui_mutex.synchronize do
|
26
|
+
# the thread has to use the gui mutex inside
|
27
|
+
@restart_search = false
|
28
|
+
|
29
|
+
match_data = get_match_data
|
30
|
+
|
31
|
+
# remove all items
|
32
|
+
@gui.packet_list.dirty_clear
|
33
|
+
|
34
|
+
# add all items that match the search criteria
|
35
|
+
status_text_deadline = Time.now + $cfg.status_line_update_interval
|
36
|
+
@data.items.each do |item|
|
37
|
+
#item.parent = @gui.packet_list if match?(item, match_data)
|
38
|
+
if match?(item, match_data)
|
39
|
+
item.show
|
40
|
+
now = Time.now
|
41
|
+
if now > status_text_deadline
|
42
|
+
update_search_status_text
|
43
|
+
status_text_deadline = now + $cfg.status_line_update_interval
|
44
|
+
end
|
45
|
+
end
|
46
|
+
break if @restart_search
|
47
|
+
end
|
48
|
+
update_search_status_text
|
49
|
+
|
50
|
+
if (@gui.packet_list.numItems > 0)
|
51
|
+
@gui.packet_list.setCurrentItem(0)
|
52
|
+
@gui.packet_list.selectItem(0)
|
53
|
+
@gui.main.show_info(@gui.packet_list.getItem(0).packet_item.data)
|
54
|
+
end
|
55
|
+
@gui.search_label.enabled = true
|
56
|
+
|
57
|
+
end # synchronize
|
58
|
+
end while @restart_search# || match_data != @gui.search_field.text.downcase.split
|
59
|
+
end #thread.new
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_match_data
|
63
|
+
str_to_match_data(@gui.search_field.text)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Converts a string into a match_data representation.
|
67
|
+
def str_to_match_data(str, index=0)
|
68
|
+
words = [ ]
|
69
|
+
exclude = [ ]
|
70
|
+
is_exclude = false
|
71
|
+
|
72
|
+
while str[index]
|
73
|
+
case str[index]
|
74
|
+
when ?", ?'
|
75
|
+
word, index = get_word(str, index+1, str[index])
|
76
|
+
unless word.empty?
|
77
|
+
if is_exclude
|
78
|
+
exclude.push word
|
79
|
+
is_exclude = false
|
80
|
+
else
|
81
|
+
words.push word
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
when 32 # space
|
86
|
+
is_exclude = false
|
87
|
+
|
88
|
+
=begin
|
89
|
+
when ?>
|
90
|
+
min, index = get_word(str, index+1)
|
91
|
+
min = @gui.logic.size_to_nr(min)
|
92
|
+
|
93
|
+
when ?<
|
94
|
+
max, index = get_word(str, index+1)
|
95
|
+
max = @gui.logic.size_to_nr(max)
|
96
|
+
=end
|
97
|
+
when ?-
|
98
|
+
is_exclude = true
|
99
|
+
|
100
|
+
else
|
101
|
+
word, index = get_word(str, index)
|
102
|
+
if is_exclude
|
103
|
+
exclude.push word
|
104
|
+
is_exclude = false
|
105
|
+
else
|
106
|
+
words.push word
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
index += 1
|
111
|
+
end
|
112
|
+
|
113
|
+
# check if word has upcase letters
|
114
|
+
words.collect! do |w|
|
115
|
+
[w, /[A-Z]/.match(w)!=nil]
|
116
|
+
end
|
117
|
+
exclude.collect! do |w|
|
118
|
+
[w, /[A-Z]/.match(w)!=nil]
|
119
|
+
end
|
120
|
+
[words, exclude]
|
121
|
+
end
|
122
|
+
|
123
|
+
def get_word(str, index, delim=32) # 32==space
|
124
|
+
word = ""
|
125
|
+
c = str[index]
|
126
|
+
while (c && c != delim)
|
127
|
+
word += c.chr
|
128
|
+
index += 1
|
129
|
+
c = str[index]
|
130
|
+
end
|
131
|
+
[word, index]
|
132
|
+
end
|
133
|
+
|
134
|
+
# Update the text for the number of displayed packs.
|
135
|
+
def update_search_status_text
|
136
|
+
@gui.search_label.text = sprintf($cfg.text.search, @gui.packet_list.numItems, @data.items.size)
|
137
|
+
end
|
138
|
+
|
139
|
+
# Find out if item is matched by current search criteria.
|
140
|
+
def match?(item, match_data)
|
141
|
+
words, exclude, min, max = match_data
|
142
|
+
|
143
|
+
# check text that has to be there
|
144
|
+
searchable, sortable_downcase, sortable_normal = item.sortable(0)
|
145
|
+
words.each do |match_str, is_sensitive|
|
146
|
+
if is_sensitive
|
147
|
+
return false unless sortable_normal.include?(match_str)
|
148
|
+
else
|
149
|
+
return false unless sortable_downcase.include?(match_str)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# check text not allowed to be there
|
154
|
+
exclude.each do |match_str, is_sensitive|
|
155
|
+
if is_sensitive
|
156
|
+
return false if sortable_normal.include?(match_str)
|
157
|
+
else
|
158
|
+
return false if sortable_downcase.include?(match_str)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# each check ok
|
163
|
+
true
|
164
|
+
end
|
165
|
+
end
|