AXTyper 0.7.4 → 0.8.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.
- data/.yardopts_typer +1 -2
- data/README.typer.markdown +30 -8
- data/ext/accessibility/key_coder/key_coder.c +7 -0
- data/lib/accessibility/string.rb +22 -6
- data/lib/accessibility/version.rb +3 -1
- data/test/runner.rb +14 -0
- metadata +4 -6
- data/docs/KeyboardEvents.markdown +0 -122
data/.yardopts_typer
CHANGED
data/README.typer.markdown
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
# AXTyper
|
2
2
|
|
3
|
-
This gem is a component of
|
4
|
-
|
5
|
-
|
3
|
+
This gem is a component of
|
4
|
+
[AXElements](http://github.com/Marketcircle/AXElements). It provides
|
5
|
+
an interface for posting keyboard events to the system as well as a
|
6
|
+
mixin for parsing a string into a series of events.
|
6
7
|
|
7
|
-
|
8
|
+
|
9
|
+
## Quick Demo
|
8
10
|
|
9
11
|
The basics:
|
10
12
|
|
@@ -30,21 +32,41 @@ Something a bit more advanced:
|
|
30
32
|
end
|
31
33
|
```
|
32
34
|
|
33
|
-
|
35
|
+
A more detailed demonstration of what this library offers is offered in
|
36
|
+
[this blog post](http://ferrous26.com/blog/2012/04/03/axelements-part1/).
|
37
|
+
|
38
|
+
|
39
|
+
## Documentation
|
40
|
+
|
41
|
+
- [API documentation](http://rdoc.info/gems/AXTyper/frames)
|
42
|
+
- The AXElements [keyboarding tutorial](https://github.com/Marketcircle/AXElements/wiki/Keyboarding)
|
43
|
+
|
34
44
|
|
35
|
-
|
36
|
-
|
45
|
+
## Development
|
46
|
+
|
47
|
+
Development of this library happens as part of AXElements, but tests
|
48
|
+
and the API for this component should remain separate enough so that
|
49
|
+
it can be released as part of the AXTyper gem.
|
50
|
+
|
51
|
+
### Testing
|
52
|
+
|
53
|
+
Running tests for this subset of AXElements is best done by using the
|
54
|
+
`test:string` rake task, and also run `test:cruby` to make sure that
|
55
|
+
some MacRuby specific code didn't sneak into the keyboarding
|
56
|
+
component.
|
37
57
|
|
38
58
|
```shell
|
39
59
|
rake test:string
|
60
|
+
rake test:cruby
|
40
61
|
```
|
41
62
|
|
42
|
-
|
63
|
+
### TODO
|
43
64
|
|
44
65
|
The API for posting events is ad-hoc for the sake of demonstration;
|
45
66
|
AXElements exposes this functionality via `Kernel#type`. The standalone
|
46
67
|
API provided here could be improved.
|
47
68
|
|
69
|
+
|
48
70
|
## License
|
49
71
|
|
50
72
|
Copyright (c) 2012 Marketcircle Inc.
|
@@ -107,6 +107,13 @@ keycoder_post_event(VALUE self, VALUE event)
|
|
107
107
|
void
|
108
108
|
Init_key_coder()
|
109
109
|
{
|
110
|
+
/*
|
111
|
+
* Document-class: KeyCoder
|
112
|
+
*
|
113
|
+
* Class that encapsulates some low level work for finding key code mappings
|
114
|
+
* and posting keyboard events to the system.
|
115
|
+
*
|
116
|
+
*/
|
110
117
|
VALUE cKeyCoder = rb_define_class("KeyCoder", rb_cObject);
|
111
118
|
rb_define_singleton_method(cKeyCoder, "dynamic_mapping", keycoder_dynamic_mapping, 0);
|
112
119
|
rb_define_singleton_method(cKeyCoder, "post_event", keycoder_post_event, 1);
|
data/lib/accessibility/string.rb
CHANGED
@@ -5,10 +5,18 @@ require 'accessibility/key_coder'
|
|
5
5
|
|
6
6
|
##
|
7
7
|
# Parses strings of human readable text into a series of events meant to
|
8
|
-
# be processed by {Accessibility::Core#post
|
8
|
+
# be processed by {Accessibility::Core#post} or {KeyCoder.post_event}.
|
9
9
|
#
|
10
10
|
# Supports most, if not all, latin keyboard layouts, maybe some
|
11
|
-
# international layouts as well.
|
11
|
+
# international layouts as well. Japanese layouts can be made to work with
|
12
|
+
# use of `String#transform`.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
#
|
16
|
+
# app = AXUIElementCreateApplication(3456)
|
17
|
+
# include Accessibility::String
|
18
|
+
# app.post keyboard_events_for "Hello, world!\n"
|
19
|
+
#
|
12
20
|
module Accessibility::String
|
13
21
|
|
14
22
|
##
|
@@ -18,7 +26,7 @@ module Accessibility::String
|
|
18
26
|
# {Accessibility::String::EventGenerator::CUSTOM}.
|
19
27
|
#
|
20
28
|
# For more details on event generation, read the
|
21
|
-
#
|
29
|
+
# [Keyboarding documentation](http://github.com/Marketcircle/AXElements/wiki/Keyboarding).
|
22
30
|
#
|
23
31
|
# @param [String]
|
24
32
|
# @return [Array<Array(Fixnum,Boolean)>]
|
@@ -35,7 +43,7 @@ module Accessibility::String
|
|
35
43
|
# @example
|
36
44
|
#
|
37
45
|
# Lexer.new("Hai").lex # => ['H','a','i']
|
38
|
-
# Lexer.new("\\
|
46
|
+
# Lexer.new("\\CONTROL").lex # => [["\\CONTROL"]]
|
39
47
|
# Lexer.new("\\COMMAND+a").lex # => [["\\COMMAND", ['a']]]
|
40
48
|
# Lexer.new("One\nTwo").lex # => ['O','n','e',"\n",'T','w','o']
|
41
49
|
#
|
@@ -124,10 +132,13 @@ module Accessibility::String
|
|
124
132
|
end
|
125
133
|
|
126
134
|
# @private
|
135
|
+
# @return [String]
|
127
136
|
SPACE = " "
|
128
137
|
# @private
|
138
|
+
# @return [String]
|
129
139
|
PLUS = "+"
|
130
140
|
# @private
|
141
|
+
# @return [String]
|
131
142
|
CUSTOM_ESCAPE = "\\"
|
132
143
|
end
|
133
144
|
|
@@ -142,8 +153,8 @@ module Accessibility::String
|
|
142
153
|
# # Upper case 'A'
|
143
154
|
# EventGenerator.new(["A"]).generate # => [[56,true],[70,true],[70,false],[56,false]]
|
144
155
|
#
|
145
|
-
# # Press the
|
146
|
-
# EventGenerator.new([["\\
|
156
|
+
# # Press the volume up key
|
157
|
+
# EventGenerator.new([["\\F12"]]).generate # => [[0x6F,true],[0x6F,false]]
|
147
158
|
#
|
148
159
|
# # Hotkey, press and hold command key and then 'a', then release both
|
149
160
|
# EventGenerator.new([["\\CMD",["a"]]]).generate # => [[55,true],[70,true],[70,false],[55,false]]
|
@@ -462,14 +473,19 @@ module Accessibility::String
|
|
462
473
|
end
|
463
474
|
|
464
475
|
# @private
|
476
|
+
# @return [String]
|
465
477
|
EMPTY_STRING = ""
|
466
478
|
# @private
|
479
|
+
# @return [Array(Number,Boolean)]
|
467
480
|
OPTION_DOWN = [58, true]
|
468
481
|
# @private
|
482
|
+
# @return [Array(Number,Boolean)]
|
469
483
|
OPTION_UP = [58, false]
|
470
484
|
# @private
|
485
|
+
# @return [Array(Number,Boolean)]
|
471
486
|
SHIFT_DOWN = [56, true]
|
472
487
|
# @private
|
488
|
+
# @return [Array(Number,Boolean)]
|
473
489
|
SHIFT_UP = [56, false]
|
474
490
|
end
|
475
491
|
|
data/test/runner.rb
CHANGED
@@ -22,3 +22,17 @@ class MiniTest::Unit::TestCase
|
|
22
22
|
end
|
23
23
|
|
24
24
|
end
|
25
|
+
|
26
|
+
|
27
|
+
# Figure out if we are testing a compiled version of AXElements, since some
|
28
|
+
# tests will fail due to incomplete MacRuby features.
|
29
|
+
RUNNING_COMPILED =
|
30
|
+
$LOADED_FEATURES.find { |file| file.match /ax_elements.rbo/ }
|
31
|
+
|
32
|
+
def pid_for name # sneaky naming
|
33
|
+
NSWorkspace.sharedWorkspace.runningApplications.find do |app|
|
34
|
+
app.bundleIdentifier == name
|
35
|
+
end.processIdentifier
|
36
|
+
end
|
37
|
+
|
38
|
+
$LOAD_PATH << 'lib'
|
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: AXTyper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.8.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Mark Rada
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-24 00:00:00 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|
@@ -19,14 +19,14 @@ dependencies:
|
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: "2.
|
22
|
+
version: "2.12"
|
23
23
|
type: :development
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: "2.
|
29
|
+
version: "2.12"
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: yard
|
32
32
|
prerelease: false
|
@@ -71,7 +71,6 @@ extensions:
|
|
71
71
|
extra_rdoc_files:
|
72
72
|
- README.typer.markdown
|
73
73
|
- .yardopts_typer
|
74
|
-
- docs/KeyboardEvents.markdown
|
75
74
|
files:
|
76
75
|
- lib/accessibility/version.rb
|
77
76
|
- lib/accessibility/string.rb
|
@@ -81,7 +80,6 @@ files:
|
|
81
80
|
- test/runner.rb
|
82
81
|
- README.typer.markdown
|
83
82
|
- .yardopts_typer
|
84
|
-
- docs/KeyboardEvents.markdown
|
85
83
|
homepage: http://github.com/Marketcircle/AXElements
|
86
84
|
licenses:
|
87
85
|
- BSD 3-clause
|
@@ -1,122 +0,0 @@
|
|
1
|
-
# Keyboard Events
|
2
|
-
|
3
|
-
Keyboard events are a system provided by Apple that allows you to
|
4
|
-
simulate keyboard input. The API for this in the `ApplicationServices`
|
5
|
-
framework, but there is an analogue in the `Acessibility` APIs which
|
6
|
-
has the additional option of directing the input to a specific application.
|
7
|
-
|
8
|
-
Using accessibility actions and setting attributes you can already
|
9
|
-
perform most of the interactions that would be possible with the
|
10
|
-
keyboard simulation. However, there are some things that you will need
|
11
|
-
to, or it will just make more sense to, simulate keyboard input. For
|
12
|
-
example, to make use of hot keys you would have to add extra actions
|
13
|
-
or attributes to a control in the application; that would be more
|
14
|
-
work, possibly prone to error, than simply simulating the hot key from
|
15
|
-
outside the application. In other situations you may specifically want
|
16
|
-
to test out keyboard navigation and so actions would not be a good
|
17
|
-
substitute. It may be that the APIs that AXElements provides for
|
18
|
-
typing just make more sense when writing tests or scripts.
|
19
|
-
|
20
|
-
## Typing with the DSL
|
21
|
-
|
22
|
-
The {Accessibility::DSL} mix-in exposes keyboard events through the
|
23
|
-
`type` method. A simple example would look like this:
|
24
|
-
|
25
|
-
type "Hello, #{ENV['USER']}! How are you today?\n"
|
26
|
-
|
27
|
-
And watch your computer come to life! The `type` command takes an
|
28
|
-
additional optional parameter that we'll get to later. The first
|
29
|
-
parameter is just a string that you want AXElements to type out. How
|
30
|
-
to format the string should be obvious for the most part, but some
|
31
|
-
things like the command key and arrows might not be so obvious.
|
32
|
-
|
33
|
-
## Formatting Strings
|
34
|
-
|
35
|
-
Letters and numbers should be written just as you would for any other
|
36
|
-
string. Any of the standard symbols can also be plainly added to a
|
37
|
-
string that you want to have typed. Here are some examples:
|
38
|
-
|
39
|
-
type "UPPER CASE LETTERS"
|
40
|
-
type "lower case letters"
|
41
|
-
type "1337 message @/\/|) 57|_||=|="
|
42
|
-
type "A proper sentence can be typed out (all at once)."
|
43
|
-
|
44
|
-
### Regular Escape Sequences
|
45
|
-
|
46
|
-
Things like newlines and tabs should be formatted just like they would
|
47
|
-
in a regular string. That is, normal string escape sequences should
|
48
|
-
"just work" with AXElements. Here are some more examples:
|
49
|
-
|
50
|
-
type "Have a bad \b\b\b\b\b good day!"
|
51
|
-
type "First line.\nSecond line."
|
52
|
-
type "I \t like \t to \t use \t tabs \t a \t lot."
|
53
|
-
type "Explicit\sSpaces."
|
54
|
-
|
55
|
-
### Custom Escape Sequences
|
56
|
-
|
57
|
-
Unfortunately, there is no built in escape sequence for deleting to
|
58
|
-
the right or pressing command keys like `F1`. AXElements defines some
|
59
|
-
extra escape sequences in order to easily represent the remaining
|
60
|
-
keys.
|
61
|
-
|
62
|
-
These custom escape sequences __shoud start with two `\` characters__,
|
63
|
-
as in this example:
|
64
|
-
|
65
|
-
type "\\F1"
|
66
|
-
|
67
|
-
A custom escape sequence __should terminate with a space or the end of
|
68
|
-
the string__, as in this example:
|
69
|
-
|
70
|
-
type "\\PAGEDOWN notice the space afterwards\\PAGEUP but not before"
|
71
|
-
|
72
|
-
The full list of supported custom escape sequences is listed in
|
73
|
-
{Accessibility::StringParser::CUSTOM}. Some escapes have an alias,
|
74
|
-
such as the right arrow key which can be escaped as `"\\RIGHT"` or as
|
75
|
-
`"\\->"`.
|
76
|
-
|
77
|
-
### Hot Keys
|
78
|
-
|
79
|
-
To support pressing multiple keys at the same time (i.e. hot keys), you
|
80
|
-
must start with the custom escape sequence for the combination and
|
81
|
-
instead of ending with a space you should put a `+` character to chain
|
82
|
-
the next key. The entire sequence should be ended with a space or
|
83
|
-
nil. Some common examples are opening a file or quitting an
|
84
|
-
application:
|
85
|
-
|
86
|
-
type "\\COMMAND+o"
|
87
|
-
type "\\CONTROL+a Typing at the start of the line"
|
88
|
-
type "\\COMMAND+\\SHIFT+s"
|
89
|
-
|
90
|
-
You might also note that `CMD+SHIFT+s` could also be:
|
91
|
-
|
92
|
-
type "\\COMMAND+S"
|
93
|
-
|
94
|
-
Since a capital `S` will cause the shift key to be held down.
|
95
|
-
|
96
|
-
One caveat with hot keys is that you cannot use `"\\COMMAND+ "` to
|
97
|
-
represent command and space combination, you will need to use
|
98
|
-
`"\\COMMAND+\s"` instead.
|
99
|
-
|
100
|
-
## Protips
|
101
|
-
|
102
|
-
In order make sure that certain sequences of characters are properly
|
103
|
-
escaped, it is recommended to simply always use double quoted
|
104
|
-
strings.
|
105
|
-
|
106
|
-
### Posting To A Specific Application
|
107
|
-
|
108
|
-
The second argument to the `type` command can be an {AX::Application}
|
109
|
-
object. If you do not include the argument, the events will be posted
|
110
|
-
to the system, which usually means the application that currently is
|
111
|
-
active. Note that you cannot be more specific than the application
|
112
|
-
that you want to send the events to, within the application, the
|
113
|
-
control that has keyboard focus will receive the events.
|
114
|
-
|
115
|
-
### Changing Typing Speed
|
116
|
-
|
117
|
-
You can set the typing speed at load time by setting the environment
|
118
|
-
variable `KEY_RATE`. See {Accessibility::Core::KEY\_RATE} for details on
|
119
|
-
possible values. An example of using it would be:
|
120
|
-
|
121
|
-
KEY_RATE=SLOW irb -rubygems -rax_elements
|
122
|
-
KEY_RATE=0.25 rspec gui_spec.rb
|