AXElements 0.8.1 → 0.9.0

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.
Files changed (62) hide show
  1. data/.yardopts +4 -0
  2. data/History.markdown +41 -0
  3. data/README.markdown +59 -62
  4. data/Rakefile +1 -1
  5. data/ext/accessibility/key_coder/extconf.rb +1 -1
  6. data/ext/accessibility/key_coder/key_coder.c +8 -5
  7. data/lib/accessibility/dsl.rb +261 -87
  8. data/lib/accessibility/enumerators.rb +14 -11
  9. data/lib/accessibility/errors.rb +4 -3
  10. data/lib/accessibility/factory.rb +159 -108
  11. data/lib/accessibility/graph.rb +13 -9
  12. data/lib/accessibility/{pp_inspector.rb → pretty_printer.rb} +4 -5
  13. data/lib/accessibility/qualifier.rb +23 -13
  14. data/lib/accessibility/string.rb +4 -4
  15. data/lib/accessibility/system_info.rb +230 -0
  16. data/lib/accessibility/translator.rb +38 -28
  17. data/lib/accessibility/version.rb +24 -2
  18. data/lib/accessibility.rb +25 -8
  19. data/lib/ax/application.rb +207 -77
  20. data/lib/ax/element.rb +62 -65
  21. data/lib/ax/menu.rb +5 -1
  22. data/lib/ax/row.rb +1 -1
  23. data/lib/ax/scroll_area.rb +7 -6
  24. data/lib/ax/systemwide.rb +38 -5
  25. data/lib/ax_elements/active_support_selections.rb +10 -0
  26. data/lib/ax_elements/mri.rb +57 -0
  27. data/lib/ax_elements/nsarray_compat.rb +97 -17
  28. data/lib/ax_elements.rb +9 -1
  29. data/rakelib/gem.rake +11 -11
  30. data/rakelib/test.rake +0 -9
  31. data/test/helper.rb +10 -18
  32. data/test/integration/accessibility/test_dsl.rb +52 -42
  33. data/test/integration/accessibility/test_enumerators.rb +0 -1
  34. data/test/integration/accessibility/test_graph.rb +1 -0
  35. data/test/integration/accessibility/test_qualifier.rb +2 -2
  36. data/test/integration/ax/test_application.rb +9 -2
  37. data/test/integration/ax/test_element.rb +41 -1
  38. data/test/sanity/accessibility/test_factory.rb +23 -56
  39. data/test/sanity/accessibility/{test_pp_inspector.rb → test_pretty_printer.rb} +9 -9
  40. data/test/sanity/accessibility/test_translator.rb +2 -5
  41. data/test/sanity/accessibility/test_version.rb +15 -0
  42. data/test/sanity/ax/test_application.rb +17 -2
  43. data/test/sanity/ax/test_element.rb +2 -2
  44. data/test/sanity/ax_elements/test_nsobject_inspect.rb +4 -2
  45. data/test/sanity/test_ax_elements.rb +1 -0
  46. metadata +69 -39
  47. data/lib/accessibility/core.rb +0 -973
  48. data/lib/accessibility/highlighter.rb +0 -86
  49. data/lib/ax_elements/vendor/inflection_data.rb +0 -66
  50. data/lib/ax_elements/vendor/inflections.rb +0 -172
  51. data/lib/ax_elements/vendor/inflector.rb +0 -306
  52. data/lib/minitest/ax_elements.rb +0 -175
  53. data/lib/mouse.rb +0 -223
  54. data/lib/rspec/expectations/ax_elements.rb +0 -234
  55. data/test/integration/accessibility/test_core.rb +0 -18
  56. data/test/integration/minitest/test_ax_elements.rb +0 -89
  57. data/test/integration/rspec/expectations/test_ax_elements.rb +0 -102
  58. data/test/sanity/accessibility/test_core.rb +0 -561
  59. data/test/sanity/accessibility/test_highlighter.rb +0 -56
  60. data/test/sanity/minitest/test_ax_elements.rb +0 -17
  61. data/test/sanity/rspec/expectations/test_ax_elements.rb +0 -15
  62. data/test/sanity/test_mouse.rb +0 -19
@@ -8,7 +8,7 @@ module Accessibility::Enumerators
8
8
  class BreadthFirst
9
9
  include Enumerable
10
10
 
11
- # @param [#children]
11
+ # @param root [#children]
12
12
  def initialize root
13
13
  @root = root
14
14
  end
@@ -16,16 +16,14 @@ module Accessibility::Enumerators
16
16
  ##
17
17
  # Semi-lazily iterate through the tree.
18
18
  #
19
+ # @yield An element in the UI hierarchy
19
20
  # @yieldparam [AX::Element,AXUIElementRef]
20
21
  def each
21
- # @todo mutate the array less, perhaps use an index instead
22
- # of #shift, then the array only grows
23
22
  queue = [@root]
24
23
  until queue.empty?
25
- queue.shift.children.each do |x|
26
- queue << x
27
- yield x
28
- end
24
+ kids = queue.shift.children
25
+ kids.each do |x| yield x end
26
+ queue.concat kids
29
27
  end
30
28
  end
31
29
 
@@ -38,6 +36,9 @@ module Accessibility::Enumerators
38
36
  # being used...yet.
39
37
  #
40
38
  # Override `Enumerable#find` for performance reasons.
39
+ #
40
+ # @yield An element in the UI hierarchy
41
+ # @yieldparam [AX::Element,AXUIElementRef]
41
42
  def find
42
43
  each { |x| return x if yield x }
43
44
  end
@@ -50,11 +51,12 @@ module Accessibility::Enumerators
50
51
  class DepthFirst
51
52
  include Enumerable
52
53
 
53
- # @param [#children]
54
+ # @param root [#children]
54
55
  def initialize root
55
56
  @root = root
56
57
  end
57
58
 
59
+ # @yield An element in the UI hierarchy
58
60
  # @yieldparam [AX::Element,AXUIElementRef]
59
61
  def each
60
62
  stack = @root.children
@@ -70,6 +72,7 @@ module Accessibility::Enumerators
70
72
  # Walk the UI element tree and yield both the element and the
71
73
  # level that the element is at relative to the root.
72
74
  #
75
+ # @yield An element in the UI hierarchy
73
76
  # @yieldparam [AX::Element,AXUIElementRef]
74
77
  # @yieldparam [Number]
75
78
  def each_with_level &block
@@ -85,9 +88,9 @@ module Accessibility::Enumerators
85
88
  ##
86
89
  # Recursive implementation of a depth first iterator.
87
90
  #
88
- # @param [AX::Element]
89
- # @param [Number]
90
- # @param [#call]
91
+ # @param element [AX::Element]
92
+ # @param depth [Number]
93
+ # @param block [#call]
91
94
  def recursive_each_with_level element, depth, block
92
95
  block.call element, depth
93
96
  element.children.each do |x|
@@ -4,9 +4,10 @@ require 'accessibility/qualifier'
4
4
  # Error raised when an implicit search fails to return a result.
5
5
  class Accessibility::SearchFailure < NoMethodError
6
6
 
7
- # @param [AX::Element]
8
- # @param [#to_s]
9
- # @param [Hash{Symbol=>Object}]
7
+ # @param searcher [AX::Element]
8
+ # @param searchee [#to_s]
9
+ # @param filters [Hash{Symbol=>Object}]
10
+ # @yield Optional block that would have been used for a search filter
10
11
  def initialize searcher, searchee, filters, &block
11
12
  filters = {} unless filters.kind_of? Hash
12
13
  msg = "Could not find `#{pp_searchee searchee, filters, &block}` "
@@ -3,112 +3,27 @@ require 'accessibility/translator'
3
3
 
4
4
  ##
5
5
  # Namespace container for all the accessibility objects.
6
- module AX; end
6
+ module AX; class Element; end end
7
7
 
8
- ##
9
- # Mixin made for processing low level data from AXAPI methods.
10
- module Accessibility::Factory
11
-
12
- # @todo This should provide alternate #to_ruby functionality for
13
- # the __NSCFType class in order to avoid the overhead of
14
- # checking type information (or at least reducing it).
15
- # However, it will force the lower level to always wrap
16
- # element references; this should be ok most of the time
17
- # but makes testing a bit of a pain...hmmm
18
-
19
- ##
20
- # Processes any given data from an AXAPI function and wraps it if
21
- # needed. Meant for taking a return value from
22
- # {Accessibility::Core#attribute} and friends.
23
- #
24
- # Generally, used to process an `AXUIElementRef` into a some kind
25
- # of {AX::Element} subclass.
26
- def process value
27
- return nil if value.nil? # CFGetTypeID(nil) crashes runtime
28
- case CFGetTypeID(value)
29
- when ARRAY_TYPE then process_array value
30
- when REF_TYPE then process_element value
31
- else
32
- value
33
- end
34
- end
35
8
 
36
-
37
- private
9
+ class << AX
38
10
 
39
11
  ##
40
12
  # @private
41
13
  #
42
- # Reference to the singleton instance of the translator.
14
+ # Mutex to make sure we only create one class at a time.
43
15
  #
44
- # @return [Accessibility::Translator]
45
- TRANSLATOR = Accessibility::Translator.instance
16
+ # @return [Mutex]
17
+ MUTEX = Mutex.new
46
18
 
47
19
  ##
48
20
  # @private
49
21
  #
50
- # Type ID for `AXUIElementRef` objects.
22
+ # Find the class for a given role
51
23
  #
52
- # @return [Number]
53
- REF_TYPE = AXUIElementGetTypeID()
54
-
55
- ##
56
- # @private
57
- #
58
- # Type ID for `CFArrayRef` objects.
24
+ # If the class does not exist it will be created.
59
25
  #
60
- # @return [Number]
61
- ARRAY_TYPE = CFArrayGetTypeID()
62
-
63
- ##
64
- # @todo Should we handle cases where a subrole has a value of
65
- # 'Unknown'? What is the performance impact?
66
- #
67
- # Takes an `AXUIElementRef` and gives you some kind of wrapped
68
- # accessibility object.
69
- #
70
- # Some code paths have been unrolled for efficiency. Don't hate player,
71
- # hate the game.
72
- #
73
- # @param [AXUIElementRef]
74
- # @return [AX::Element]
75
- def process_element ref
76
- if role = ref.role
77
- role = TRANSLATOR.unprefix role
78
- attrs = ref.attributes
79
- if attrs.include? KAXSubroleAttribute
80
- subrole = ref.subrole
81
- # Some objects claim to have a subrole but return nil
82
- if subrole
83
- class_for2(TRANSLATOR.unprefix(subrole), role).new ref
84
- else
85
- class_for(role).new ref
86
- end
87
- else
88
- class_for(role).new ref
89
- end
90
- else # failsafe in case object dies before we even get the role
91
- AX::Element.new ref
92
- end
93
- end
94
-
95
- ##
96
- # We assume a homogeneous array and only wrap element arrays right now.
97
- #
98
- # @return [Array]
99
- def process_array vals
100
- return vals if vals.empty?
101
- return vals if CFGetTypeID(vals.first) != REF_TYPE
102
- return vals.map { |val| process_element val }
103
- end
104
-
105
- ##
106
- # @todo Consider using {AX.const_missing} instead.
107
- #
108
- # Find the class for a given role. If the class does not exist it will
109
- # be created on demand.
110
- #
111
- # @param [#to_s]
26
+ # @param role [#to_s]
112
27
  # @return [Class]
113
28
  def class_for role
114
29
  if AX.const_defined? role, false
@@ -119,14 +34,16 @@ module Accessibility::Factory
119
34
  end
120
35
 
121
36
  ##
122
- # Find the class for a given subrole and role. If the class does not
123
- # exist it will be created on demand.
37
+ # @private
124
38
  #
125
- # @param [#to_s]
126
- # @param [#to_s]
39
+ # Find the class for a given subrole and role
40
+ #
41
+ # If the class does not exist it will be created on demand.
42
+ #
43
+ # @param subrole [#to_s]
44
+ # @param role [#to_s]
127
45
  # @return [Class]
128
46
  def class_for2 subrole, role
129
- # @todo it would be nice if we didn't have to lookup twice
130
47
  if AX.const_defined? subrole, false
131
48
  AX.const_get subrole
132
49
  else
@@ -135,29 +52,163 @@ module Accessibility::Factory
135
52
  end
136
53
 
137
54
  ##
138
- # Create a new class in the {AX} namespace that has {AX::Element}
139
- # as the superclass.
55
+ # @private
56
+ #
57
+ # Create a class in the {AX} namespace that has {AX::Element} as the
58
+ # superclass
140
59
  #
141
- # @param [#to_s]
60
+ # @param name [#to_s]
142
61
  # @return [Class]
143
62
  def create_class name
144
- klass = Class.new AX::Element
145
- AX.const_set name, klass
63
+ MUTEX.synchronize do
64
+ # re-check now that we are in the critical section
65
+ @klass = if AX.const_defined? name, false
66
+ AX.const_get name
67
+ else
68
+ klass = Class.new AX::Element
69
+ AX.const_set name, klass
70
+ end
71
+ end
72
+ @klass
146
73
  end
147
74
 
148
75
  ##
76
+ # @private
77
+ #
149
78
  # Create a new class in the {AX} namesapce that has the given
150
- # `superklass` as the superclass..
79
+ # `superklass` as the superclass
151
80
  #
152
- # @param [#to_s] name
153
- # @param [#to_s] superklass
81
+ # @param name [#to_s]
82
+ # @param superklass [#to_s]
154
83
  # @return [Class]
155
84
  def create_class2 name, superklass
156
85
  unless AX.const_defined? superklass, false
157
86
  create_class superklass
158
87
  end
159
- klass = Class.new AX.const_get(superklass)
160
- AX.const_set name, klass
88
+ MUTEX.synchronize do
89
+ # re-check now that we are in the critical section
90
+ @klass = if AX.const_defined? name, false
91
+ AX.const_get name
92
+ else
93
+ klass = Class.new AX.const_get(superklass)
94
+ AX.const_set name, klass
95
+ end
96
+ end
97
+ @klass
98
+ end
99
+
100
+ end
101
+
102
+
103
+ if on_macruby?
104
+
105
+ ##
106
+ # Extensions to {Accessibility::Element} for the higher level abstractions
107
+ #
108
+ # These extensions only make sense in the context of the high level API
109
+ # but needs to be applied on the lower level class, so the code has been
110
+ # placed in its own file.
111
+ module Accessibility::Element
112
+
113
+ ##
114
+ # @todo Should we handle cases where a subrole has a value of
115
+ # 'Unknown'? What is the performance impact?
116
+ #
117
+ # Wrap the low level wrapper with the appropriate high level wrapper.
118
+ # This involves determining the proper class in the {AX} namespace,
119
+ # possibly creating it on demand, and then instantiating the class to
120
+ # wrap the low level object.
121
+ #
122
+ # Some code paths have been unrolled for efficiency. Don't hate player,
123
+ # hate the game.
124
+ #
125
+ # @return [AX::Element]
126
+ def to_ruby
127
+ type = AXValueGetType(self)
128
+ if type.zero?
129
+ to_element
130
+ else
131
+ to_box type
132
+ end
133
+ end
134
+
135
+
136
+ private
137
+
138
+ ##
139
+ # @private
140
+ #
141
+ # Reference to the singleton instance of the translator.
142
+ #
143
+ # @return [Accessibility::Translator]
144
+ TRANSLATOR = Accessibility::Translator.instance
145
+
146
+ def to_box type
147
+ ptr = Pointer.new ValueWrapper::BOX_TYPES[type]
148
+ AXValueGetValue(self, type, ptr)
149
+ ptr.value.to_ruby
150
+ end
151
+
152
+ def to_element
153
+ if roll = self.role
154
+ roll = TRANSLATOR.unprefix roll
155
+ if attributes.include? KAXSubroleAttribute
156
+ subroll = self.subrole
157
+ # Some objects claim to have a subrole but return nil
158
+ if subroll
159
+ AX.class_for2(TRANSLATOR.unprefix(subroll), roll).new self
160
+ else
161
+ AX.class_for(roll).new self
162
+ end
163
+ else
164
+ AX.class_for(roll).new self
165
+ end
166
+ else # failsafe in case object dies before we get the role
167
+ AX::Element.new self
168
+ end
169
+ end
170
+
171
+ end
172
+
173
+
174
+ else
175
+
176
+
177
+ ##
178
+ # `AXElements` extensions to the `Accessibility::Element` class
179
+ class Accessibility::Element
180
+
181
+ ##
182
+ # Override the default `#to_ruby` so that proper classes are
183
+ # chosen for each object.
184
+ #
185
+ # @return [AX::Element]
186
+ def to_ruby
187
+ if roll = self.role
188
+ roll = TRANSLATOR.unprefix roll
189
+ if attributes.include? KAXSubroleAttribute
190
+ subroll = self.subrole
191
+ # Some objects claim to have a subrole but return nil
192
+ if subroll
193
+ AX.class_for2(TRANSLATOR.unprefix(subroll), roll).new self
194
+ else
195
+ AX.class_for(roll).new self
196
+ end
197
+ else
198
+ AX.class_for(roll).new self
199
+ end
200
+ else # failsafe in case object dies before we get the role
201
+ AX::Element.new self
202
+ end
203
+ end
204
+
205
+ ##
206
+ # @private
207
+ #
208
+ # Reference to the singleton instance of the translator.
209
+ #
210
+ # @return [Accessibility::Translator]
211
+ TRANSLATOR = Accessibility::Translator.instance
161
212
  end
162
213
 
163
214
  end
@@ -31,7 +31,7 @@ class Accessibility::Graph
31
31
  # @return [AX::Element]
32
32
  attr_reader :element
33
33
 
34
- # @param [AX::Element]
34
+ # @param element [AX::Element]
35
35
  def initialize element
36
36
  @element = element
37
37
  @id = "element_#{element.object_id}"
@@ -47,7 +47,7 @@ class Accessibility::Graph
47
47
 
48
48
  def identifier
49
49
  klass = @element.class.to_s.split(NAMESPACE).last
50
- ident = @element.pp_identifier.dup
50
+ ident = @element.pp_identifier.to_s.dup
51
51
  if ident.length > 12
52
52
  ident = "#{ident[0...12]}..."
53
53
  end
@@ -58,9 +58,13 @@ class Accessibility::Graph
58
58
  end
59
59
 
60
60
  def shape
61
- (@element.attribute(:focused) && OCTAGON) ||
62
- (@element.actions.empty? && OVAL) ||
63
- BOX
61
+ if @element.attributes.include?(:focused) && @element.attribute(:focused)
62
+ OCTAGON
63
+ elsif @element.actions.empty?
64
+ OVAL
65
+ else
66
+ BOX
67
+ end
64
68
  end
65
69
 
66
70
  def style
@@ -69,7 +73,7 @@ class Accessibility::Graph
69
73
  return FILLED unless @element.attribute(:enabled)
70
74
  end
71
75
  # bold if focused and no children
72
- if @element.attribute(:focused)
76
+ if @element.attributes.include?(:focused) && @element.attribute(:focused)
73
77
  return BOLD if @element.size_of(:children).zero?
74
78
  end
75
79
  SOLID
@@ -128,8 +132,8 @@ class Accessibility::Graph
128
132
  # @return [String]
129
133
  attr_accessor :style
130
134
 
131
- # @param [Accessibility::Graph::Node]
132
- # @param [Accessibility::Graph::Node]
135
+ # @param head [Accessibility::Graph::Node]
136
+ # @param tail [Accessibility::Graph::Node]
133
137
  def initialize head, tail
134
138
  @head, @tail = head, tail
135
139
  end
@@ -155,7 +159,7 @@ class Accessibility::Graph
155
159
  # @return [Array<Accessibility::Graph::Edge>]
156
160
  attr_reader :edges
157
161
 
158
- # @param [AX::Element]
162
+ # @param root [AX::Element]
159
163
  def initialize root
160
164
  root_node = Node.new(root)
161
165
  @nodes = [root_node]
@@ -10,13 +10,13 @@
10
10
  # - `#attribute` returns the value of a given attribute
11
11
  # - `#size_of` returns the size for an attribute
12
12
  #
13
- module Accessibility::PPInspector
13
+ module Accessibility::PrettyPrinter
14
14
 
15
15
  ##
16
16
  # Create an identifier for the receiver by using various attributes
17
17
  # that should make it very easy to identify the element.
18
18
  #
19
- # @return [String]
19
+ # @return [String,#to_s]
20
20
  def pp_identifier
21
21
  # @note use, or lack of use, of #inspect is intentional for visual effect
22
22
 
@@ -49,8 +49,7 @@ module Accessibility::PPInspector
49
49
  return " id=#{attribute(:identifier)}"
50
50
  end
51
51
 
52
- # @todo should we have other fallbacks?
53
- return EMPTY_STRING
52
+ rescue NoMethodError
54
53
  end
55
54
 
56
55
  ##
@@ -88,7 +87,7 @@ module Accessibility::PPInspector
88
87
  # is the given attribute, and the check box value will be
89
88
  # determined by the value of the attribute.
90
89
  #
91
- # @param [Symbol]
90
+ # @param attr [Symbol]
92
91
  # @return [String]
93
92
  def pp_checkbox attr
94
93
  " #{attr}[#{attribute(attr) ? CHECKMARK : CROSS }]"
@@ -1,4 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
+
3
+ require 'active_support/core_ext/object/blank'
2
4
  require 'accessibility/translator'
3
5
 
4
6
  ##
@@ -22,21 +24,21 @@ class Accessibility::Qualifier
22
24
  # element.children.size > 5 && NSContainsRect(element.bounds, rect)
23
25
  # end
24
26
  #
25
- # @param [#to_s]
26
- # @param [Hash]
27
+ # @param klass [#to_s]
28
+ # @param criteria [Hash]
27
29
  # @yield Optional block that can qualify an element
28
30
  def initialize klass, criteria
29
31
  @klass = TRANSLATOR.classify(klass)
30
32
  @criteria = criteria
31
33
  @block = Proc.new if block_given?
32
- compile criteria
34
+ compile!
33
35
  end
34
36
 
35
37
  ##
36
38
  # Whether or not a candidate object matches the criteria given
37
39
  # at initialization.
38
40
  #
39
- # @param [AX::Element]
41
+ # @param element [AX::Element]
40
42
  def qualifies? element
41
43
  the_right_type?(element) && meets_criteria?(element)
42
44
  end
@@ -62,9 +64,9 @@ class Accessibility::Qualifier
62
64
  # array. This is done to avoid checking types for each call to
63
65
  # {#qualifies?}.
64
66
  #
65
- # @param [Hash]
66
- def compile criteria
67
- @filters = criteria.map do |key, value|
67
+ # @param criteria [Hash]
68
+ def compile!
69
+ @filters = @criteria.map do |key, value|
68
70
  if value.kind_of? Hash
69
71
  [:subsearch, key, value]
70
72
  elsif key.kind_of? Array
@@ -84,7 +86,7 @@ class Accessibility::Qualifier
84
86
  # Checks if a candidate object is of the correct class, respecting
85
87
  # that that the class being searched for may not be defined yet.
86
88
  #
87
- # @param [AX::Element]
89
+ # @param element [AX::Element]
88
90
  def the_right_type? element
89
91
  unless @const
90
92
  if AX.const_defined? @klass
@@ -100,7 +102,7 @@ class Accessibility::Qualifier
100
102
  # Determines if the element meets all the criteria of the filters,
101
103
  # spawning sub-searches if necessary.
102
104
  #
103
- # @param [AX::Element]
105
+ # @param element [AX::Element]
104
106
  def meets_criteria? element
105
107
  @filters.all? do |filter|
106
108
  self.send *filter, element
@@ -112,19 +114,27 @@ class Accessibility::Qualifier
112
114
  end
113
115
 
114
116
  def match attr, regexp, element
115
- element.attribute(attr).to_s.match regexp
117
+ if element.attributes.include? attr
118
+ element.attribute(attr).to_s.match regexp
119
+ end
116
120
  end
117
121
 
118
122
  def equality attr, value, element
119
- element.attribute(attr) == value
123
+ if element.attributes.include? attr
124
+ element.attribute(attr) == value
125
+ end
120
126
  end
121
127
 
122
128
  def parameterized_match attr, param, regexp, element
123
- element.parameterized_attribute(attr, param).to_s.match regexp
129
+ if element.parameterized_attributes.include? attr
130
+ element.parameterized_attribute(attr, param).to_s.match regexp
131
+ end
124
132
  end
125
133
 
126
134
  def parameterized_equality attr, param, value, element
127
- element.parameterized_attribute(attr, param) == value
135
+ if element.parameterized_attributes.include? attr
136
+ element.parameterized_attribute(attr, param) == value
137
+ end
128
138
  end
129
139
 
130
140
  def block_check element
@@ -26,9 +26,9 @@ module Accessibility::String
26
26
  # {Accessibility::String::EventGenerator::CUSTOM}.
27
27
  #
28
28
  # For more details on event generation, read the
29
- # [Keyboarding documentation](http://github.com/Marketcircle/AXElements/wiki/Keyboarding).
29
+ # [Keyboarding wiki](http://github.com/Marketcircle/AXElements/wiki/Keyboarding).
30
30
  #
31
- # @param [String]
31
+ # @param string [#to_s]
32
32
  # @return [Array<Array(Fixnum,Boolean)>]
33
33
  def keyboard_events_for string
34
34
  EventGenerator.new(Lexer.new(string).lex).generate
@@ -55,7 +55,7 @@ module Accessibility::String
55
55
  # @return [Array<String,Array<String,...>]
56
56
  attr_accessor :tokens
57
57
 
58
- # @param [#to_s]
58
+ # @param string [#to_s]
59
59
  def initialize string
60
60
  @chars = string.to_s
61
61
  @tokens = []
@@ -395,7 +395,7 @@ module Accessibility::String
395
395
  # @return [Array<Array(Fixnum,Boolean)>]
396
396
  attr_reader :events
397
397
 
398
- # @param [Array<String,Array<String,Array...>>]
398
+ # @param tokens [Array<String,Array<String,Array...>>]
399
399
  def initialize tokens
400
400
  @tokens = tokens
401
401
  # *3 since the output array will be at least *2 the