AXElements 0.9.0 → 1.0.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +0 -4
- data/README.markdown +22 -17
- data/Rakefile +1 -1
- data/ext/accessibility/key_coder/extconf.rb +1 -1
- data/ext/accessibility/key_coder/key_coder.c +2 -4
- data/lib/accessibility.rb +3 -3
- data/lib/accessibility/core.rb +948 -0
- data/lib/accessibility/dsl.rb +30 -186
- data/lib/accessibility/enumerators.rb +1 -0
- data/lib/accessibility/factory.rb +78 -134
- data/lib/accessibility/graph.rb +5 -9
- data/lib/accessibility/highlighter.rb +86 -0
- data/lib/accessibility/{pretty_printer.rb → pp_inspector.rb} +4 -3
- data/lib/accessibility/qualifier.rb +3 -5
- data/lib/accessibility/screen_recorder.rb +217 -0
- data/lib/accessibility/statistics.rb +57 -0
- data/lib/accessibility/translator.rb +23 -32
- data/lib/accessibility/version.rb +2 -22
- data/lib/ax/application.rb +20 -159
- data/lib/ax/element.rb +42 -32
- data/lib/ax/scroll_area.rb +5 -6
- data/lib/ax/systemwide.rb +1 -33
- data/lib/ax_elements.rb +1 -9
- data/lib/ax_elements/core_graphics_workaround.rb +5 -0
- data/lib/ax_elements/nsarray_compat.rb +17 -97
- data/lib/ax_elements/vendor/inflection_data.rb +66 -0
- data/lib/ax_elements/vendor/inflections.rb +176 -0
- data/lib/ax_elements/vendor/inflector.rb +306 -0
- data/lib/minitest/ax_elements.rb +180 -0
- data/lib/mouse.rb +227 -0
- data/lib/rspec/expectations/ax_elements.rb +234 -0
- data/rakelib/gem.rake +3 -12
- data/rakelib/test.rake +15 -0
- data/test/helper.rb +20 -10
- data/test/integration/accessibility/test_core.rb +18 -0
- data/test/integration/accessibility/test_dsl.rb +40 -38
- data/test/integration/accessibility/test_enumerators.rb +1 -0
- data/test/integration/accessibility/test_graph.rb +0 -1
- data/test/integration/accessibility/test_qualifier.rb +2 -2
- data/test/integration/ax/test_application.rb +2 -9
- data/test/integration/ax/test_element.rb +0 -40
- data/test/integration/minitest/test_ax_elements.rb +89 -0
- data/test/integration/rspec/expectations/test_ax_elements.rb +102 -0
- data/test/sanity/accessibility/test_factory.rb +2 -2
- data/test/sanity/accessibility/test_highlighter.rb +56 -0
- data/test/sanity/accessibility/{test_pretty_printer.rb → test_pp_inspector.rb} +9 -9
- data/test/sanity/accessibility/test_statistics.rb +57 -0
- data/test/sanity/ax/test_application.rb +1 -16
- data/test/sanity/ax/test_element.rb +2 -2
- data/test/sanity/ax_elements/test_nsobject_inspect.rb +2 -4
- data/test/sanity/minitest/test_ax_elements.rb +17 -0
- data/test/sanity/rspec/expectations/test_ax_elements.rb +15 -0
- data/test/sanity/test_mouse.rb +22 -0
- data/test/test_core.rb +454 -0
- metadata +44 -69
- data/History.markdown +0 -41
- data/lib/accessibility/system_info.rb +0 -230
- data/lib/ax_elements/active_support_selections.rb +0 -10
- data/lib/ax_elements/mri.rb +0 -57
- data/test/sanity/accessibility/test_version.rb +0 -15
data/lib/ax/scroll_area.rb
CHANGED
@@ -22,13 +22,12 @@ class AX::ScrollArea < AX::Element
|
|
22
22
|
def scroll_to element
|
23
23
|
return if NSContainsRect(self.bounds, element.bounds)
|
24
24
|
Mouse.move_to self.to_point
|
25
|
-
|
26
|
-
# calculate direction and velocity for scrolling
|
25
|
+
# calculate direction to scroll
|
27
26
|
direction = element.position.y > self.position.y ? -5 : 5
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
until NSContainsRect(self.bounds, element.bounds)
|
28
|
+
Mouse.scroll direction
|
29
|
+
end
|
30
|
+
sleep 0.1
|
32
31
|
end
|
33
32
|
|
34
33
|
end
|
data/lib/ax/systemwide.rb
CHANGED
@@ -11,37 +11,10 @@ require 'accessibility/string'
|
|
11
11
|
class AX::SystemWide < AX::Element
|
12
12
|
include Accessibility::String
|
13
13
|
|
14
|
-
class << self
|
15
|
-
##
|
16
|
-
# Find and return the group that represents the desktop
|
17
|
-
#
|
18
|
-
# @return [AX::Group]
|
19
|
-
def desktop
|
20
|
-
AX::Application.finder.scroll_areas.first.groups.first
|
21
|
-
end
|
22
|
-
|
23
|
-
##
|
24
|
-
# @note This currently does not include spotlight or the
|
25
|
-
# notification center as they interact oddly with
|
26
|
-
# accessibility APIs and how AXElements handle errors
|
27
|
-
#
|
28
|
-
# Find and return menu bar items for the system
|
29
|
-
#
|
30
|
-
# That is, menu bar items that do not belong to the current
|
31
|
-
# app, but that belong to the system, such as the clock or
|
32
|
-
# wi-fi menu.
|
33
|
-
#
|
34
|
-
# @return [AX::MenuBarItem]
|
35
|
-
def status_items
|
36
|
-
AX::Application.new('SystemUIServer').menu_bar.children
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
|
41
14
|
##
|
42
15
|
# Overridden since there is only one way to get the element ref.
|
43
16
|
def initialize
|
44
|
-
super
|
17
|
+
super AXUIElementCreateSystemWide()
|
45
18
|
end
|
46
19
|
|
47
20
|
##
|
@@ -123,9 +96,4 @@ class AX::SystemWide < AX::Element
|
|
123
96
|
@ref.set_timeout_to seconds
|
124
97
|
end
|
125
98
|
|
126
|
-
# (see AX::Application.frontmost_application)
|
127
|
-
def focused_application
|
128
|
-
AX::Application.frontmost_app
|
129
|
-
end
|
130
|
-
|
131
99
|
end
|
data/lib/ax_elements.rb
CHANGED
@@ -1,20 +1,12 @@
|
|
1
|
-
require 'ax_elements/active_support_selections'
|
2
|
-
require 'accessibility/bridge'
|
3
|
-
require 'ax_elements/mri' unless on_macruby?
|
4
|
-
|
5
1
|
# Mix the language methods into the TopLevel
|
6
2
|
require 'accessibility/dsl'
|
7
3
|
include Accessibility::DSL
|
8
4
|
|
9
|
-
require 'accessibility/system_info'
|
10
|
-
|
11
5
|
##
|
12
|
-
# @deprecated Please use {AX::Application.dock} instead
|
13
|
-
#
|
14
6
|
# The Mac OS X dock application.
|
15
7
|
#
|
16
8
|
# @return [AX::Application]
|
17
|
-
AX::DOCK = AX::Application.dock
|
9
|
+
AX::DOCK = AX::Application.new('com.apple.dock')
|
18
10
|
|
19
11
|
# Load explicitly defined elements that are optional
|
20
12
|
require 'ax/button'
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'ax/element'
|
2
2
|
require 'accessibility/translator'
|
3
|
-
require 'active_support/core_ext/array/access'
|
4
3
|
|
5
4
|
##
|
6
5
|
# An old hack on arrays that allows you to map a single method across
|
@@ -12,6 +11,18 @@ require 'active_support/core_ext/array/access'
|
|
12
11
|
# on this and so I will just keep it around for backwards compatability.
|
13
12
|
module Accessibility::NSArrayCompat
|
14
13
|
|
14
|
+
##
|
15
|
+
# Equivalent to `#at(1)`
|
16
|
+
def second
|
17
|
+
at(1)
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Equivalent to `#at(2)`
|
22
|
+
def third
|
23
|
+
at(2)
|
24
|
+
end
|
25
|
+
|
15
26
|
##
|
16
27
|
# @note Debatably bad idea. Maintained for backwards compatibility.
|
17
28
|
#
|
@@ -29,11 +40,11 @@ module Accessibility::NSArrayCompat
|
|
29
40
|
# outline.rows.text_fields.values # all at once
|
30
41
|
#
|
31
42
|
def method_missing method, *args
|
32
|
-
smethod = TRANSLATOR.singularize(method.
|
43
|
+
smethod = TRANSLATOR.singularize(method.chomp('?'))
|
33
44
|
map do |x|
|
34
|
-
if !x.kind_of?
|
35
|
-
elsif x.respond_to? method
|
36
|
-
else
|
45
|
+
if !x.kind_of? AX::Element then super
|
46
|
+
elsif x.respond_to? method then x.send method, *args
|
47
|
+
else x.send smethod, *args
|
37
48
|
end
|
38
49
|
end
|
39
50
|
end
|
@@ -47,99 +58,8 @@ module Accessibility::NSArrayCompat
|
|
47
58
|
|
48
59
|
end
|
49
60
|
|
50
|
-
unless defined? NSArray
|
51
|
-
NSArray = Array
|
52
|
-
end
|
53
61
|
|
54
|
-
|
55
|
-
# AXElements extensions for `NSArray`
|
62
|
+
# AXElements extensions for `NSArray`.
|
56
63
|
class NSArray
|
57
64
|
include Accessibility::NSArrayCompat
|
58
|
-
|
59
|
-
if on_macruby?
|
60
|
-
|
61
|
-
##
|
62
|
-
# Returns the tail of the array from `position`
|
63
|
-
#
|
64
|
-
# @example
|
65
|
-
#
|
66
|
-
# [1, 2, 3, 4].from(0) # => [1, 2, 3, 4]
|
67
|
-
# [1, 2, 3, 4].from(2) # => [3, 4]
|
68
|
-
# [1, 2, 3, 4].from(10) # => []
|
69
|
-
# [].from(0) # => []
|
70
|
-
#
|
71
|
-
# @param position [Fixnum]
|
72
|
-
# @return [Array]
|
73
|
-
def from position
|
74
|
-
self[position, length] || []
|
75
|
-
end
|
76
|
-
|
77
|
-
##
|
78
|
-
# Returns the beginning of the array up to `position`
|
79
|
-
#
|
80
|
-
# [1, 2, 3, 4].to(0) # => [1]
|
81
|
-
# [1, 2, 3, 4].to(2) # => [1, 2, 3]
|
82
|
-
# [1, 2, 3, 4].to(10) # => [1, 2, 3, 4]
|
83
|
-
# [].to(0) # => []
|
84
|
-
#
|
85
|
-
# @param count [Fixnum]
|
86
|
-
# @return [Array]
|
87
|
-
def to count
|
88
|
-
take count + 1
|
89
|
-
end
|
90
|
-
|
91
|
-
##
|
92
|
-
# Equal to `self[1]`
|
93
|
-
def second
|
94
|
-
self[1]
|
95
|
-
end
|
96
|
-
|
97
|
-
##
|
98
|
-
# Equal to `self[2]`
|
99
|
-
def third
|
100
|
-
self[2]
|
101
|
-
end
|
102
|
-
|
103
|
-
##
|
104
|
-
# Equal to `self[3]`
|
105
|
-
def fourth
|
106
|
-
self[3]
|
107
|
-
end
|
108
|
-
|
109
|
-
##
|
110
|
-
# Equal to `self[4]`
|
111
|
-
def fifth
|
112
|
-
self[4]
|
113
|
-
end
|
114
|
-
|
115
|
-
##
|
116
|
-
# Equal to `self[41]`
|
117
|
-
#
|
118
|
-
# Also known as accessing "the reddit".
|
119
|
-
def forty_two
|
120
|
-
self[41]
|
121
|
-
end
|
122
|
-
|
123
|
-
else
|
124
|
-
|
125
|
-
##
|
126
|
-
# Create a new array with the same contents as the given array
|
127
|
-
#
|
128
|
-
# @param ary [Array]
|
129
|
-
def self.arrayWithArray ary
|
130
|
-
ary.dup
|
131
|
-
end
|
132
|
-
|
133
|
-
##
|
134
|
-
# Create and return a new empty array
|
135
|
-
#
|
136
|
-
# @return [Array]
|
137
|
-
def self.array
|
138
|
-
[]
|
139
|
-
end
|
140
|
-
|
141
|
-
end
|
142
|
-
|
143
|
-
alias_method :the_reddit, :forty_two
|
144
|
-
|
145
65
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Accessibility
|
2
|
+
Inflector.inflections do |inflect|
|
3
|
+
inflect.plural(/$/, 's')
|
4
|
+
inflect.plural(/s$/i, 's')
|
5
|
+
inflect.plural(/(ax|test)is$/i, '\1es')
|
6
|
+
inflect.plural(/(octop|vir)us$/i, '\1i')
|
7
|
+
inflect.plural(/(octop|vir)i$/i, '\1i')
|
8
|
+
inflect.plural(/(alias|status)$/i, '\1es')
|
9
|
+
inflect.plural(/(bu)s$/i, '\1ses')
|
10
|
+
inflect.plural(/(buffal|tomat)o$/i, '\1oes')
|
11
|
+
inflect.plural(/([ti])um$/i, '\1a')
|
12
|
+
inflect.plural(/([ti])a$/i, '\1a')
|
13
|
+
inflect.plural(/sis$/i, 'ses')
|
14
|
+
inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
|
15
|
+
inflect.plural(/(hive)$/i, '\1s')
|
16
|
+
inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
|
17
|
+
inflect.plural(/(x|ch|ss|sh)$/i, '\1es')
|
18
|
+
inflect.plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices')
|
19
|
+
inflect.plural(/(m|l)ouse$/i, '\1ice')
|
20
|
+
inflect.plural(/(m|l)ice$/i, '\1ice')
|
21
|
+
inflect.plural(/^(ox)$/i, '\1en')
|
22
|
+
inflect.plural(/^(oxen)$/i, '\1')
|
23
|
+
inflect.plural(/(quiz)$/i, '\1zes')
|
24
|
+
|
25
|
+
inflect.singular(/s$/i, '')
|
26
|
+
inflect.singular(/(n)ews$/i, '\1ews')
|
27
|
+
inflect.singular(/([ti])a$/i, '\1um')
|
28
|
+
inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis')
|
29
|
+
inflect.singular(/(^analy)ses$/i, '\1sis')
|
30
|
+
inflect.singular(/([^f])ves$/i, '\1fe')
|
31
|
+
inflect.singular(/(hive)s$/i, '\1')
|
32
|
+
inflect.singular(/(tive)s$/i, '\1')
|
33
|
+
inflect.singular(/([lr])ves$/i, '\1f')
|
34
|
+
inflect.singular(/([^aeiouy]|qu)ies$/i, '\1y')
|
35
|
+
inflect.singular(/(s)eries$/i, '\1eries')
|
36
|
+
inflect.singular(/(m)ovies$/i, '\1ovie')
|
37
|
+
inflect.singular(/(x|ch|ss|sh)es$/i, '\1')
|
38
|
+
inflect.singular(/(m|l)ice$/i, '\1ouse')
|
39
|
+
inflect.singular(/(bus)es$/i, '\1')
|
40
|
+
inflect.singular(/(o)es$/i, '\1')
|
41
|
+
inflect.singular(/(shoe)s$/i, '\1')
|
42
|
+
inflect.singular(/(cris|ax|test)es$/i, '\1is')
|
43
|
+
inflect.singular(/(octop|vir)i$/i, '\1us')
|
44
|
+
inflect.singular(/(alias|status)es$/i, '\1')
|
45
|
+
inflect.singular(/^(ox)en/i, '\1')
|
46
|
+
inflect.singular(/(vert|ind)ices$/i, '\1ex')
|
47
|
+
inflect.singular(/(matr)ices$/i, '\1ix')
|
48
|
+
inflect.singular(/(quiz)zes$/i, '\1')
|
49
|
+
inflect.singular(/(database)s$/i, '\1')
|
50
|
+
|
51
|
+
inflect.irregular('person', 'people')
|
52
|
+
inflect.irregular('man', 'men')
|
53
|
+
inflect.irregular('child', 'children')
|
54
|
+
inflect.irregular('sex', 'sexes')
|
55
|
+
inflect.irregular('move', 'moves')
|
56
|
+
inflect.irregular('cow', 'kine')
|
57
|
+
inflect.irregular('zombie', 'zombies')
|
58
|
+
|
59
|
+
inflect.uncountable(%w(equipment information rice money species series fish sheep jeans))
|
60
|
+
|
61
|
+
# Related to accessibility
|
62
|
+
inflect.acronym('UI')
|
63
|
+
inflect.acronym('RTF')
|
64
|
+
inflect.acronym('URL')
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
module Accessibility
|
2
|
+
module Inflector
|
3
|
+
# A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
|
4
|
+
# inflection rules. Examples:
|
5
|
+
#
|
6
|
+
# ActiveSupport::Inflector.inflections do |inflect|
|
7
|
+
# inflect.plural /^(ox)$/i, '\1\2en'
|
8
|
+
# inflect.singular /^(ox)en/i, '\1'
|
9
|
+
#
|
10
|
+
# inflect.irregular 'octopus', 'octopi'
|
11
|
+
#
|
12
|
+
# inflect.uncountable "equipment"
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
|
16
|
+
# pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
|
17
|
+
# already have been loaded.
|
18
|
+
class Inflections
|
19
|
+
##
|
20
|
+
# Singleton instance of the inflections database.
|
21
|
+
#
|
22
|
+
# @return [Accessibility::Inflector::Inflections]
|
23
|
+
def self.instance
|
24
|
+
@__instance__ ||= new
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms, :acronym_regex
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@plurals, @singulars, @uncountables, @humans, @acronyms, @acronym_regex = [], [], [], [], {}, /(?=a)b/
|
31
|
+
end
|
32
|
+
|
33
|
+
# Specifies a new acronym. An acronym must be specified as it will appear in a camelized string. An underscore
|
34
|
+
# string that contains the acronym will retain the acronym when passed to `camelize`, `humanize`, or `titleize`.
|
35
|
+
# A camelized string that contains the acronym will maintain the acronym when titleized or humanized, and will
|
36
|
+
# convert the acronym into a non-delimited single lowercase word when passed to +underscore+.
|
37
|
+
#
|
38
|
+
# Examples:
|
39
|
+
# acronym 'HTML'
|
40
|
+
# titleize 'html' #=> 'HTML'
|
41
|
+
# camelize 'html' #=> 'HTML'
|
42
|
+
# underscore 'MyHTML' #=> 'my_html'
|
43
|
+
#
|
44
|
+
# The acronym, however, must occur as a delimited unit and not be part of another word for conversions to recognize it:
|
45
|
+
#
|
46
|
+
# acronym 'HTTP'
|
47
|
+
# camelize 'my_http_delimited' #=> 'MyHTTPDelimited'
|
48
|
+
# camelize 'https' #=> 'Https', not 'HTTPs'
|
49
|
+
# underscore 'HTTPS' #=> 'http_s', not 'https'
|
50
|
+
#
|
51
|
+
# acronym 'HTTPS'
|
52
|
+
# camelize 'https' #=> 'HTTPS'
|
53
|
+
# underscore 'HTTPS' #=> 'https'
|
54
|
+
#
|
55
|
+
# Note: Acronyms that are passed to `pluralize` will no longer be recognized, since the acronym will not occur as
|
56
|
+
# a delimited unit in the pluralized result. To work around this, you must specify the pluralized form as an
|
57
|
+
# acronym as well:
|
58
|
+
#
|
59
|
+
# acronym 'API'
|
60
|
+
# camelize(pluralize('api')) #=> 'Apis'
|
61
|
+
#
|
62
|
+
# acronym 'APIs'
|
63
|
+
# camelize(pluralize('api')) #=> 'APIs'
|
64
|
+
#
|
65
|
+
# `acronym` may be used to specify any word that contains an acronym or otherwise needs to maintain a non-standard
|
66
|
+
# capitalization. The only restriction is that the word must begin with a capital letter.
|
67
|
+
#
|
68
|
+
# Examples:
|
69
|
+
# acronym 'RESTful'
|
70
|
+
# underscore 'RESTful' #=> 'restful'
|
71
|
+
# underscore 'RESTfulController' #=> 'restful_controller'
|
72
|
+
# titleize 'RESTfulController' #=> 'RESTful Controller'
|
73
|
+
# camelize 'restful' #=> 'RESTful'
|
74
|
+
# camelize 'restful_controller' #=> 'RESTfulController'
|
75
|
+
#
|
76
|
+
# acronym 'McDonald'
|
77
|
+
# underscore 'McDonald' #=> 'mcdonald'
|
78
|
+
# camelize 'mcdonald' #=> 'McDonald'
|
79
|
+
def acronym(word)
|
80
|
+
@acronyms[word.downcase] = word
|
81
|
+
@acronym_regex = /#{@acronyms.values.join("|")}/
|
82
|
+
end
|
83
|
+
|
84
|
+
# Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
|
85
|
+
# The replacement should always be a string that may include references to the matched data from the rule.
|
86
|
+
def plural(rule, replacement)
|
87
|
+
@uncountables.delete(rule) if rule.is_a?(String)
|
88
|
+
@uncountables.delete(replacement)
|
89
|
+
@plurals.insert(0, [rule, replacement])
|
90
|
+
end
|
91
|
+
|
92
|
+
# Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
|
93
|
+
# The replacement should always be a string that may include references to the matched data from the rule.
|
94
|
+
def singular(rule, replacement)
|
95
|
+
@uncountables.delete(rule) if rule.is_a?(String)
|
96
|
+
@uncountables.delete(replacement)
|
97
|
+
@singulars.insert(0, [rule, replacement])
|
98
|
+
end
|
99
|
+
|
100
|
+
# Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
|
101
|
+
# for strings, not regular expressions. You simply pass the irregular in singular and plural form.
|
102
|
+
#
|
103
|
+
# Examples:
|
104
|
+
# irregular 'octopus', 'octopi'
|
105
|
+
# irregular 'person', 'people'
|
106
|
+
def irregular(singular, plural)
|
107
|
+
@uncountables.delete(singular)
|
108
|
+
@uncountables.delete(plural)
|
109
|
+
if singular[0,1].upcase == plural[0,1].upcase
|
110
|
+
plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
|
111
|
+
plural(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + plural[1..-1])
|
112
|
+
singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
|
113
|
+
else
|
114
|
+
plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
|
115
|
+
plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
|
116
|
+
plural(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
|
117
|
+
plural(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
|
118
|
+
singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1])
|
119
|
+
singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1])
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Add uncountable words that shouldn't be attempted inflected.
|
124
|
+
#
|
125
|
+
# Examples:
|
126
|
+
# uncountable "money"
|
127
|
+
# uncountable "money", "information"
|
128
|
+
# uncountable %w( money information rice )
|
129
|
+
def uncountable(*words)
|
130
|
+
(@uncountables << words).flatten!
|
131
|
+
end
|
132
|
+
|
133
|
+
# Specifies a humanized form of a string by a regular expression rule or by a string mapping.
|
134
|
+
# When using a regular expression based replacement, the normal humanize formatting is called after the replacement.
|
135
|
+
# When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name')
|
136
|
+
#
|
137
|
+
# Examples:
|
138
|
+
# human /_cnt$/i, '\1_count'
|
139
|
+
# human "legacy_col_person_name", "Name"
|
140
|
+
def human(rule, replacement)
|
141
|
+
@humans.insert(0, [rule, replacement])
|
142
|
+
end
|
143
|
+
|
144
|
+
# Clears the loaded inflections within a given scope (default is <tt>:all</tt>).
|
145
|
+
# Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>,
|
146
|
+
# <tt>:singulars</tt>, <tt>:uncountables</tt>, <tt>:humans</tt>.
|
147
|
+
#
|
148
|
+
# Examples:
|
149
|
+
# clear :all
|
150
|
+
# clear :plurals
|
151
|
+
def clear(scope = :all)
|
152
|
+
case scope
|
153
|
+
when :all
|
154
|
+
@plurals, @singulars, @uncountables, @humans = [], [], [], []
|
155
|
+
else
|
156
|
+
instance_variable_set "@#{scope}", []
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Yields a singleton instance of Inflector::Inflections so you can specify additional
|
162
|
+
# inflector rules.
|
163
|
+
#
|
164
|
+
# Example:
|
165
|
+
# ActiveSupport::Inflector.inflections do |inflect|
|
166
|
+
# inflect.uncountable "rails"
|
167
|
+
# end
|
168
|
+
def inflections
|
169
|
+
if block_given?
|
170
|
+
yield Inflections.instance
|
171
|
+
else
|
172
|
+
Inflections.instance
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|