rb-appscript 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/CHANGES +243 -0
  2. data/LICENSE +1 -0
  3. data/README +42 -0
  4. data/TODO +31 -0
  5. data/doc/aem-manual/01_introduction.html +48 -0
  6. data/doc/aem-manual/02_apioverview.html +89 -0
  7. data/doc/aem-manual/03_packingandunpackingdata.html +98 -0
  8. data/doc/aem-manual/04_references.html +401 -0
  9. data/doc/aem-manual/05_targettingapplications.html +133 -0
  10. data/doc/aem-manual/06_buildingandsendingevents.html +175 -0
  11. data/doc/aem-manual/07_findapp.html +54 -0
  12. data/doc/aem-manual/08_examples.html +85 -0
  13. data/doc/aem-manual/09_notes.html +41 -0
  14. data/doc/aem-manual/aemreferenceinheritance.gif +0 -0
  15. data/doc/aem-manual/full.css +21 -0
  16. data/doc/aem-manual/index.html +43 -0
  17. data/doc/appscript-manual/01_introduction.html +82 -0
  18. data/doc/appscript-manual/02_aboutappscripting.html +244 -0
  19. data/doc/appscript-manual/03_quicktutorial.html +154 -0
  20. data/doc/appscript-manual/04_gettinghelp.html +101 -0
  21. data/doc/appscript-manual/05_keywordconversion.html +91 -0
  22. data/doc/appscript-manual/06_classesandenums.html +174 -0
  23. data/doc/appscript-manual/07_applicationobjects.html +181 -0
  24. data/doc/appscript-manual/08_realvsgenericreferences.html +86 -0
  25. data/doc/appscript-manual/09_referenceforms.html +232 -0
  26. data/doc/appscript-manual/10_referenceexamples.html +142 -0
  27. data/doc/appscript-manual/11_applicationcommands.html +204 -0
  28. data/doc/appscript-manual/12_commandexamples.html +129 -0
  29. data/doc/appscript-manual/13_performanceissues.html +115 -0
  30. data/doc/appscript-manual/14_problemapps.html +193 -0
  31. data/doc/appscript-manual/15_notes.html +84 -0
  32. data/doc/appscript-manual/application_architecture.gif +0 -0
  33. data/doc/appscript-manual/application_architecture2.gif +0 -0
  34. data/doc/appscript-manual/finder_to_textedit_event.gif +0 -0
  35. data/doc/appscript-manual/full.css +21 -0
  36. data/doc/appscript-manual/index.html +49 -0
  37. data/doc/appscript-manual/relationships_example.gif +0 -0
  38. data/doc/appscript-manual/ruby_to_itunes_event.gif +0 -0
  39. data/doc/index.html +30 -0
  40. data/doc/mactypes-manual/index.html +216 -0
  41. data/doc/osax-manual/index.html +169 -0
  42. data/extconf.rb +54 -0
  43. data/misc/adobeunittypes.rb +14 -0
  44. data/misc/dump.rb +72 -0
  45. data/rb-appscript.gemspec +20 -0
  46. data/sample/AB_list_people_with_emails.rb +8 -0
  47. data/sample/Create_daily_iCal_todos.rb +72 -0
  48. data/sample/Hello_world.rb +9 -0
  49. data/sample/List_iTunes_playlist_names.rb +7 -0
  50. data/sample/Make_Mail_message.rb +29 -0
  51. data/sample/Open_file_in_TextEdit.rb +9 -0
  52. data/sample/Organize_Mail_messages.rb +57 -0
  53. data/sample/Print_folder_tree.rb +12 -0
  54. data/sample/Select_all_HTML_files.rb +8 -0
  55. data/sample/Set_iChat_status.rb +20 -0
  56. data/sample/Simple_Finder_GUI_Scripting.rb +14 -0
  57. data/sample/Stagger_Finder_windows.rb +21 -0
  58. data/sample/TextEdit_demo.rb +126 -0
  59. data/sample/iTunes_top40_to_html.rb +64 -0
  60. data/src/lib/_aem/aemreference.rb +1006 -0
  61. data/src/lib/_aem/codecs.rb +617 -0
  62. data/src/lib/_aem/connect.rb +100 -0
  63. data/src/lib/_aem/findapp.rb +83 -0
  64. data/src/lib/_aem/mactypes.rb +228 -0
  65. data/src/lib/_aem/send.rb +257 -0
  66. data/src/lib/_aem/typewrappers.rb +57 -0
  67. data/src/lib/_appscript/defaultterminology.rb +245 -0
  68. data/src/lib/_appscript/referencerenderer.rb +132 -0
  69. data/src/lib/_appscript/reservedkeywords.rb +107 -0
  70. data/src/lib/_appscript/terminology.rb +314 -0
  71. data/src/lib/aem.rb +216 -0
  72. data/src/lib/appscript.rb +830 -0
  73. data/src/lib/kae.rb +1484 -0
  74. data/src/lib/osax.rb +171 -0
  75. data/src/rbae.c +766 -0
  76. data/test/README +1 -0
  77. data/test/test_aemreference.rb +112 -0
  78. data/test/test_appscriptreference.rb +102 -0
  79. data/test/test_codecs.rb +159 -0
  80. data/test/test_findapp.rb +24 -0
  81. data/test/test_mactypes.rb +67 -0
  82. data/test/testall.sh +9 -0
  83. metadata +143 -0
@@ -0,0 +1,216 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
3
+ <head>
4
+
5
+ <title>mactypes</title>
6
+
7
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
8
+ <style type="text/css" media="all"><!--@import url(../appscript-manual/full.css);--></style>
9
+
10
+ </head>
11
+ <body>
12
+
13
+ <h1>mactypes</h1>
14
+
15
+ <!-- top navigation -->
16
+ <div class="navbar">
17
+ <a href="index.html">Up</a>
18
+
19
+ </div>
20
+
21
+ <!-- content -->
22
+ <div id="content">
23
+ <h2>What is mactypes?</h2>
24
+
25
+ <p>The mactypes module provides user-friendly wrappers for OS X Alias and File objects, commonly used by scriptable applications to identify filesystem objects and locations, and for unit type values used by some applications to represent lengths, etc. It is automatically imported when requiring appscript, aem or osax.</p>
26
+
27
+ <p class="hilitebox">Note that most scriptable applications do not use or understand POSIX paths, and while the Apple Event Manager does provide some built-in coercions for converting between path strings and alias/file objects, these work with HFS paths only. Therefore, when specifying files and folders to scriptable applications, use <code>MacTypes::Alias</code> and <code>MacTypes::FileURL</code> objects - not path strings - unless otherwise indicated.</p>
28
+
29
+
30
+ <h2><code>MacTypes::Alias</code></h2>
31
+
32
+ <p>The <code>Alias</code> class represents a persistent reference to a filesystem object. Aliases keep track of filesystem objects even if they're renamed or moved to another location on the same disk.</p>
33
+
34
+
35
+ <h3>Methods</h3>
36
+
37
+ <pre><code>Alias -- a persistent reference to a filesystem object
38
+ Constructors:
39
+
40
+ Alias.path(path) -- make Alias object from POSIX path
41
+
42
+ Alias.desc(desc) -- make Alias object from an AE::AEDesc
43
+ of TypeAlias
44
+
45
+ Methods:
46
+
47
+ path -- returns POSIX path string to the object's current location
48
+
49
+ desc -- returns AE::AEDesc of TypeAlias
50
+
51
+ to_s -- synonym for #path
52
+
53
+ inspect -- returns string representation of Alias object
54
+
55
+ to_alias -- returns self
56
+
57
+ to_file_url -- returns a MacTypes::FileURL object</code></pre>
58
+
59
+
60
+ <h3>Examples</h3>
61
+
62
+ <pre><code>require "appscript"
63
+
64
+ f = MacTypes::Alias.path('/Users/foo/some file')
65
+
66
+ puts f.to_s
67
+ # /Users/foo/some file
68
+
69
+ puts f.inspect
70
+ # MacTypes::Alias.path("/Users/foo/some file")
71
+
72
+ AS.app('TextEdit').open(f)
73
+ # opens document in TextEdit</code></pre>
74
+
75
+
76
+ <h3>Notes</h3>
77
+
78
+ <p>Note that comparing an <code>Alias</code> object against an <code>FileURL</code> object always returns false, even if both point to the same location.</p>
79
+
80
+
81
+
82
+ <h2><code>MacTypes::FileURL</code></h2>
83
+
84
+ <p>The <code>FileURL</code> class represents a fixed filesystem location. This may be deterministic (i.e. existing locations only) or non-deterministic depending on how the object is created.</p>
85
+
86
+ <h3>Methods</h3>
87
+
88
+ <pre><code>FileURL -- identifies a fixed filesystem location
89
+ Constructors:
90
+
91
+ FileURL.path(path) -- make FileURL object from POSIX path
92
+
93
+ FileURL.desc(desc) -- make FileURL object from an AE::AEDesc
94
+ of TypeFSS, TypeFSRef or TypeFileURL
95
+
96
+ Methods:
97
+
98
+ ==
99
+
100
+ hash
101
+
102
+ path -- returns POSIX path string
103
+
104
+ desc -- returns AE::AEDesc of TypeFSRef, TypeFSS or TypeFileURL
105
+
106
+ to_s -- synonym for #path
107
+
108
+ inspect -- returns string representation of FileURL object
109
+
110
+ to_alias -- returns a MacTypes::Alias object
111
+
112
+ to_file_url -- returns a new MacTypes::FileURL object</code></pre>
113
+
114
+
115
+ <h3>Examples</h3>
116
+
117
+ <pre><code>require "appscript"
118
+
119
+ f = MacTypes::FileURL.path('/Users/foo/new file')
120
+
121
+ puts f.to_s
122
+ # /Users/foo/new file
123
+
124
+ puts f.inspect
125
+ # MacTypes::FileURL.path("/Users/foo/new file")
126
+
127
+ AS.app('TextEdit').documents[1].save(:in => f)
128
+ # saves front TextEdit document at the given location</code></pre>
129
+
130
+
131
+ <h3>Notes</h3>
132
+
133
+ <p>Unlike the <code>Alias</code> class which wraps <code>TypeAlias</code> values only, the <code>FileURL</code> class provides a uniform wrapper for several file-related types that may be returned by applications: <code>TypeFSS</code>, <code>TypeFSRef</code> and <code>TypeFileURL</code>. When passing <code>FileURL</code> values to applications, you should not normally need to worry about which value type a <code>FileURL</code> object contains as well-designed applications will ask the Apple Event Manager to coerce the given value to the desired type as necessary.</p>
134
+
135
+ <p>When dealing with less well-behaved applications, however, you may need to pass an AEDesc of a specific type. In this case you should use the <code>desc</code> method to obtain an <code>AE::AEDesc</code> object, then call its <code>coerce</code> method to obtain an AEDesc of the desired type. For example, if an older Carbon application refuses to accept a FileURL identifying a non-existing file location, you may need to provide a FSSpec insteaf:</p>
136
+
137
+ <pre><code>require "appscript"
138
+
139
+ file_url = MacTypes::FileURL.path('/Users/foo/new file')
140
+
141
+ fs_spec = file_url.desc.coerce(KAE::TypeFSS)
142
+
143
+ AS.app('older app').documents[1].save(:in => fs_spec)</code></pre>
144
+
145
+ <p>When used in an application command, a <code>FileURL</code> object returned by appscript will always pack into the same <code>TypeFSRef</code>, <code>TypeFileURL</code> or <code>TypeFSS</code> AEDesc it was created from. A <code>FileURL</code> object returned by <code>FileURL.path</code>, <code>Alias#to_file_url</code> or <code>FileURL#to_file_url</code> will always pack into an AEDesc of <code>TypeFileURL</code>.</p>
146
+
147
+ <p>Note that comparing <code>FileURL</code> objects only tests for exact data equality; two objects that identify the same filesystem location by different means (e.g.comparing a <code>FileURL</code> object that was created from an existing AEDesc of <code>TypeFSRef</code> against one created from scratch), using paths of different case, etc. will test as false.</p>
148
+
149
+ <p>Note that AEDescs of <code>TypeFSRef</code> can represent existing filesystem locations only. AEDescs of <code>TypeFileURL</code> can represent both existing and non-existing locations. AEDescs of <code>TypeFSS</code> (FSSpecs) are deprecated on Mac OS X due to lack of proper Unicode and long filename support, and are retained for backwards compatibility with older applications only.</p>
150
+
151
+
152
+
153
+
154
+ <h2><code>MacTypes::FileNotFoundError</code></h2>
155
+
156
+ <p><code>FileNotFoundError</code> is a subclass of <code>RuntimeError</code>. It is raised by <code>Alias</code> and <code>FileURL</code> objects when an operation that only works for existing filesystem objects/locations fails. For example:</p>
157
+
158
+ <pre><code>require "appscript"
159
+
160
+ MacTypes::Alias.path('/some/non/existent/location')
161
+ # raises FileNotFoundError</code></pre>
162
+
163
+
164
+ <h2><code>MacTypes::Units</code></h2>
165
+
166
+ <p>The <code>Units</code> class represents a measurement of some sort, e.g. 3 inches, 98.5 degrees Fahrenheit.</p>
167
+
168
+ <pre><code>class Units
169
+
170
+ Constructor:
171
+
172
+ Units.new(value, type)
173
+ value : Fixnum | Bignum | Float -- the amount, e.g. 3.5
174
+ type : Symbol -- the unit of measurement, e.g. :centimeters
175
+
176
+ Methods:
177
+
178
+ ==
179
+
180
+ hash
181
+
182
+ inspect
183
+
184
+ value -- returns the amount
185
+
186
+ type -- returns the unit of measurement
187
+
188
+ to_i -- returns the amount as an integer
189
+
190
+ to_f -- returns the amount as a float
191
+
192
+ to_s -- returns the measurement as a string, e.g. "3.5 centimeters"</code></pre>
193
+
194
+ <p>For convenience, the <code>Units</code> class also implements an additional class method, <code>Units.method_missing</code>, to allow new values to be created using the unit of measurement as the constructor call, e.g.:</p>
195
+
196
+ <pre><code>MacTypes::Units.new(14, :inches)</code></pre>
197
+
198
+ <p>can also be written as:</p>
199
+
200
+ <pre><code>MacTypes::Units.inches(14)</code></pre>
201
+
202
+ <p>See the <a href="../appscript-manual/06_classesandenums.html">Classes and Enumerated Types</a> chapter of the appscript manual for a full list of unit types built into aem/appscript. Additional application-specific unit types can be added if needed.</p>
203
+
204
+
205
+ </div>
206
+
207
+ <!-- bottom navigation -->
208
+ <div class="navbar">
209
+ <a href="index.html">Up</a>
210
+
211
+ </div>
212
+
213
+ <!--footer-->
214
+ <p class="footer">&copy; 2006 HAS</p>
215
+ </body>
216
+ </html>
@@ -0,0 +1,169 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
3
+ <head>
4
+
5
+ <title>osax</title>
6
+
7
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
8
+ <style type="text/css" media="all"><!--@import url(../appscript-manual/full.css);--></style>
9
+
10
+ </head>
11
+ <body>
12
+
13
+ <h1>osax</h1>
14
+
15
+ <!-- top navigation -->
16
+ <div class="navbar">
17
+ <a href="index.html">Up</a>
18
+ </div>
19
+
20
+ <!-- content -->
21
+ <div id="content">
22
+ <h2>What is osax?</h2>
23
+
24
+ <p>The <code>OSAX</code> module provides an easy way to call scripting additions (a.k.a. OSAXen) from Ruby. It exports a single public class, <code>ScriptingAddition</code>, and two functions, <code>osax</code> and <code>scripting_additions</code>.</p>
25
+
26
+ <p>The <code>ScriptingAddition</code> class represents a single scripting addition. It is similar to an appscript application object, except that it defines commands for the specified scripting addition instead of the application's normal commands. </p>
27
+
28
+ <p>Once you've created a <code>ScriptingAddition</code> instance, you can invoke its commands in exactly the same way as you would call a scriptable application's commands in appscript.</p>
29
+
30
+ <p>For example:</p>
31
+
32
+ <pre><code>require "osax"
33
+
34
+ sa = OSAX::ScriptingAddition.new("StandardAdditions")
35
+
36
+ sa.say("Hello world", :using=&gt;"Victoria")</code></pre>
37
+
38
+ <p>The default application commands (<code>run</code>, <code>activate</code>, <code>quit</code>, etc.) are also available; see the appscript manual for details on those.</p>
39
+
40
+ <p>By default, <code>ScriptingAddition</code> objects are targetted at the current application. You can obtain a <code>ScriptingAddition</code> object targetted at another application by calling one of its <code>by...</code> methods.</p>
41
+
42
+
43
+
44
+ <h2><code>OSAX.scripting_additions</code></h2>
45
+
46
+ <p>The <code>scripting_additions</code> function returns the names of all installed scripting additions:</p>
47
+
48
+ <pre><code>require "osax"
49
+
50
+ p OSAX.scripting_additions
51
+ # Result: ["Digital Hub Scripting", "StandardAdditions", ...]</code></pre>
52
+
53
+
54
+
55
+ <h2><code>OSAX.osax</code></h2>
56
+
57
+ <p>The <code>osax</code> function provides a convenient shortcut for creating new <code>ScriptingAddition</code> instances:</p>
58
+
59
+ <pre><code>require "osax"
60
+
61
+ sa = OSAX.osax("StandardAdditions")
62
+
63
+ p sa
64
+ # Result: #&lt;OSAX::ScriptingAddition
65
+ # name="StandardAdditions"
66
+ # target=AEM::Application.current&gt;</code></pre>
67
+
68
+ <p>In addition, the <code>osax</code> function accepts an application name as an optional second argument, allowing you to specify the application you want to handle the scripting addition's commands, e.g.:</p>
69
+
70
+ <pre><code>OSAX.osax("StandardAdditions", "System Events")</code></pre>
71
+
72
+ <p>is shorthand for:</p>
73
+
74
+ <pre><code>OSAX::ScriptingAddition.new("StandardAdditions").by_name("System Events")</code></pre>
75
+
76
+ <p>To specify applications by other means (e.g. URL), create a <code>ScriptingAddition</code> object first, then call the appropriate <code>by...</code> method.</p>
77
+
78
+
79
+
80
+
81
+ <h2><code>OSAX::ScriptingAddition</code></h2>
82
+
83
+ <pre><code>ScriptingAddition -- represents a single scripting addition and its
84
+ target application
85
+
86
+ Constructors:
87
+
88
+ ScriptingAddition.new(name) -- make a ScriptingAddition object
89
+ for the specified scripting addition, targetted at the
90
+ current application
91
+
92
+ Methods:
93
+
94
+ # Introspection:
95
+
96
+ commands -- returns names of all available commands
97
+
98
+ parameters(commandName) -- returns a command's parameter names
99
+
100
+ # Specifying a different target application:
101
+
102
+ # Each of the following methods returns a new ScriptingAddition
103
+ # instance targetted at the specified application. The arguments
104
+ # are the same as for the by_name, by_creator, etc. methods in
105
+ # appscript.
106
+
107
+ by_name(name) -- name or full path of application, e.g. "Finder"
108
+
109
+ by_creator(creator) -- four-character creator code, e.g. "ttxt"
110
+
111
+ by_id(id) -- bundle id, e.g. "com.apple.ical"
112
+
113
+ by_pid(pid) -- Unix process ID, e.g. 4005
114
+
115
+ by_url(url) -- eppc URL, e.g. "eppc://jukebox-mac.local/iTunes"</code></pre>
116
+
117
+
118
+ <h2>Examples</h2>
119
+
120
+ <pre><code>require "osax"
121
+
122
+ # Create a new ScriptingAddition object:
123
+
124
+ sa = OSAX.osax("StandardAdditions")
125
+
126
+
127
+ # List all available commands:
128
+
129
+ p sa.commands
130
+ # Result: ["ASCII_character", "ASCII_number", "activate", ...]
131
+
132
+
133
+ # Call some commands:
134
+
135
+ sa.beep
136
+
137
+ p sa.path_to(:scripts_folder)
138
+ # Result: MacFile::Alias.at("/Users/foo/Library/Scripts/")
139
+
140
+ p sa.display_dialog("Ruby says hello!",
141
+ :buttons=&gt;["Hi!", "Howdy!", "Duuuude!"],
142
+ :default_button=&gt;3)
143
+ # Result: {:button_returned=&gt;"Howdy!"}</code></pre>
144
+
145
+
146
+ <h2>Notes</h2>
147
+
148
+ <p>When using scripting addition commands that require GUI access (e.g. <code>display_dialog</code>) targetted at the command-line Ruby interpreter, the osax module will automatically convert the non-GUI interpreter process into a full GUI process to allow these commands to operate correctly. If you want to avoid this, target these commands at a faceless GUI application such as System Events instead:</p>
149
+
150
+ <pre><code>sa = OSAX.osax("StandardAdditions", "System Events")
151
+ sa.activate # give focus to System Events
152
+ p sa.display_dialog("Ruby says hello!",
153
+ :buttons=&gt;["Hi!", "Howdy!", "Duuuude!"],
154
+ :default_button=&gt;3)
155
+ # Result: {:button_returned=&gt;"Duuuude!"}</code></pre>
156
+
157
+
158
+
159
+ </div>
160
+
161
+ <!-- bottom navigation -->
162
+ <div class="navbar">
163
+ <a href="index.html">Up</a>
164
+ </div>
165
+
166
+ <!--footer-->
167
+ <p class="footer">&copy; 2006 HAS</p>
168
+ </body>
169
+ </html>
data/extconf.rb ADDED
@@ -0,0 +1,54 @@
1
+ # appscript install script
2
+ # Based on RubyOSA extconf.rb
3
+ # Original copyright below:
4
+ #
5
+ # Copyright (c) 2006, Apple Computer, Inc. All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without
8
+ # modification, are permitted provided that the following conditions
9
+ # are met:
10
+ # 1. Redistributions of source code must retain the above copyright
11
+ # notice, this list of conditions and the following disclaimer.
12
+ # 2. Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ # 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16
+ # its contributors may be used to endorse or promote products derived
17
+ # from this software without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
20
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
23
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
+ # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
+ # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
28
+ # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+ # POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require 'mkmf'
32
+
33
+ $CFLAGS << ' -Wall'# -arch ppc -arch i386'
34
+ $LDFLAGS = '-framework Carbon'
35
+
36
+ # Avoid `ID' and `T_DATA' symbol collisions between Ruby and Carbon.
37
+ # (adapted code from RubyAEOSA - FUJIMOTO Hisakuni <hisa -at- fobj - com>)
38
+ ruby_h = "#{Config::CONFIG['archdir']}/ruby.h"
39
+ intern_h = "#{Config::CONFIG['archdir']}/intern.h"
40
+ new_filename_prefix = 'osx_'
41
+ [ ruby_h, intern_h ].each do |src_path|
42
+ dst_fname = File.join('./src', new_filename_prefix + File.basename(src_path))
43
+ $stderr.puts "create #{File.expand_path(dst_fname)} ..."
44
+ File.open(dst_fname, 'w') do |dstfile|
45
+ IO.foreach(src_path) do |line|
46
+ line = line.gsub(/\bID\b/, 'RB_ID')
47
+ line = line.gsub(/\bT_DATA\b/, 'RB_T_DATA')
48
+ line = line.gsub(/\bintern.h\b/, "#{new_filename_prefix}intern.h")
49
+ dstfile.puts line
50
+ end
51
+ end
52
+ end
53
+
54
+ create_makefile('ae', 'src')
@@ -0,0 +1,14 @@
1
+ #!/usr/local/bin/ruby
2
+ # Copyright (C) 2006 HAS.
3
+ # Released under MIT License.
4
+
5
+ AdobeUnitTypes = [
6
+ [:millimeters, "\x81MM\x8c"],
7
+ [:points, "\x81PS\x8c"],
8
+ [:picas, "\x81SP\x8c"],
9
+ [:traditional_points, "\x81PT\x8c"],
10
+ [:traditional_picas, "\x81PC\x8c"],
11
+ [:ciceros, "\x81CR\x8c"],
12
+ [:percent, "\x81PN\x8c"],
13
+ [:pixels, "\x81PX\x8c"],
14
+ ]
data/misc/dump.rb ADDED
@@ -0,0 +1,72 @@
1
+ #!/usr/local/bin/ruby
2
+ # Copyright (C) 2006 HAS.
3
+ # Released under MIT License.
4
+
5
+ require "ae"
6
+ require "aem"
7
+ require "findapp"
8
+ require "_appscript/terminology"
9
+
10
+ if ARGV.length != 3
11
+ puts "dump.rb
12
+
13
+ Outputs an application's terminology as a Ruby module file, suitable for use by AS::Application.
14
+
15
+ Usage:
16
+
17
+ ruby dump.rb application-name-or-path module-name module-path
18
+
19
+ Example:
20
+
21
+ ruby dump.rb Address\ Book AddressBook ~/addressbook_terms.rb"
22
+
23
+ exit
24
+ end
25
+
26
+ app_path = FindApp.by_name(ARGV[0])
27
+ module_name = ARGV[1]
28
+ out_path = ARGV[2]
29
+
30
+ if not /^[A-Z][A-Za-z0-9_]*$/ === module_name
31
+ raise RuntimeError, "Invalid module name."
32
+ end
33
+
34
+ File.open(out_path, "w") do |f|
35
+ # Get aete(s)
36
+ begin
37
+ aetes = AEM::Codecs.new.unpack(AE.get_app_terminology(app_path).coerce(KAE::TypeAEList))
38
+ rescue AE::MacOSError => e
39
+ if e.to_i == -192 # aete resource not found
40
+ raise RuntimeError, "No terminology found."
41
+ else
42
+ raise
43
+ end
44
+ end
45
+
46
+ # Parse aete(s) into intermediate tables, suitable for use by Terminology#tables_for_module
47
+ tables = TerminologyParser.build_tables_for_aetes(aetes)
48
+
49
+ # Write module code
50
+ f.puts "module #{module_name}"
51
+ f.puts "\tVersion = 1.1"
52
+ f.puts "\tPath = #{app_path.inspect}"
53
+ f.puts
54
+ (["Classes", "Enumerators", "Properties", "Elements"].zip(tables[0,4])).each do |name, table|
55
+ f.puts "\t#{name} = ["
56
+ table.sort.each do |item|
57
+ f.puts "\t\t#{item.inspect},"
58
+ end
59
+ f.puts "\t]"
60
+ f.puts
61
+ end
62
+ f.puts "\tCommands = ["
63
+ tables[4].sort.each do |name, code, params|
64
+ f.puts "\t\t[#{name.inspect}, #{code.inspect}, ["
65
+ params.each do |item|
66
+ f.puts "\t\t\t#{item.inspect},"
67
+ end
68
+ f.puts "\t\t]],"
69
+ end
70
+ f.puts "\t]"
71
+ f.puts "end"
72
+ end
@@ -0,0 +1,20 @@
1
+ require "rubygems"
2
+
3
+ spec = Gem::Specification.new do |s|
4
+ s.name = "rb-appscript"
5
+ s.version = "0.2.0"
6
+ s.author = "HAS"
7
+ s.homepage = "http://rb-appscript.rubyforge.org/"
8
+ s.rubyforge_project="rb-appscript"
9
+ s.summary="Ruby appscript (rb-appscript) is a high-level, user-friendly Apple event bridge that allows you to control scriptable Mac OS X applications using ordinary Ruby scripts."
10
+ s.files = Dir["**/*"].delete_if { |name| ["MakeFile", "ae.bundle", "mkmf.log", "rbae.o", "src/osx_ruby.h", "src/osx_intern.h"].include?(name) }
11
+ s.extensions = "extconf.rb"
12
+ s.test_files = Dir["test/test_*.rb"]
13
+ s.required_ruby_version = ">= 1.8"
14
+ end
15
+
16
+
17
+ if $0==__FILE__
18
+ Gem::manage_gems
19
+ Gem::Builder.new(spec).build
20
+ end
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Lists the name and email(s) of every person in Address Book with one or more email addresses.
4
+
5
+ require "appscript"
6
+
7
+ people_ref = AS.app('Address Book').people[AS.its.emails.ne([])]
8
+ p people_ref.name.get.zip(people_ref.emails.value.get)
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Creates daily recurring todo items in iCal.
4
+ #
5
+ # Ported from 'Create daily todos.scpt' by Alexander Kellett
6
+ # <http://web.mac.com/lypanov>
7
+ #
8
+ # While iCal makes it easy to create recurring events, it lacks a similar
9
+ # feature for To Do items. This script can be used to create a daily checklist
10
+ # of things to do.
11
+ #
12
+ # To begin, create a new calendar with the name "Shadow". Then, add a number
13
+ # of recurring events to this calendar. All Daily To Dos events must be
14
+ # recurring events as only recurring events are converted to To Dos. Start and
15
+ # end dates are ignored.
16
+ #
17
+ # Now, create a calendar called "Personal". When the script is run, all the
18
+ # To Do items will be added to this calendar. Finally, set up a cron job to
19
+ # run this script first thing every morning.
20
+ #
21
+ # See also:
22
+ # <http://web.mac.com/lypanov/iWeb/Web/Diary/1EDF1B30-C4AF-4A99-BC4D-
23
+ # 4A8AF14BFC96.html>
24
+ # <http://web.mac.com/lypanov/iWeb/Web/Diary/9950DF91-726E-42B2-A639-
25
+ # 1967D1DE7545.html>
26
+
27
+
28
+ require "appscript"
29
+
30
+ ICal = AS.app("iCal")
31
+
32
+ # The calendar in which recurring todo items should appear:
33
+ ToDoCalendarName = "Personal"
34
+
35
+ def create_to_do(summary_text)
36
+ # Adds To Dos to calendar "Personal"
37
+ now = Time.new
38
+ midnight = Time.local(now.year(), now.month(), now.day())
39
+ to_dos = ICal.calendars[ToDoCalendarName].todos
40
+ # don't create an item if it already exists for today!
41
+ if to_dos[AS.its.due_date.ge(midnight).and(
42
+ AS.its.summary.eq(summary_text))].count < 1
43
+ to_dos.end.make(:new=>:todo, :with_properties=>{
44
+ :due_date=>midnight, :summary=>summary_text})
45
+ end
46
+ end
47
+
48
+ def get_label(recurrence, label)
49
+ match = Regexp.new("(?:^|;)#{label}=(.*?)(?:$|;)").match(recurrence)
50
+ return match ? match[1] : nil
51
+ end
52
+
53
+ weekday_code = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"][Time.new.wday]
54
+ events = ICal.calendars["Shadow"].events
55
+
56
+ events.recurrence.get.zip(events.summary.get).each do |recurrence, summary|
57
+ recurs_on_this_weekday = false
58
+ frequency = get_label(recurrence, "FREQ")
59
+ case frequency
60
+ when "WEEKLY"
61
+ days = get_label(recurrence, "BYDAY")
62
+ if days and days.split(",").include?(weekday_code)
63
+ recurs_on_this_weekday = true
64
+ end
65
+ when "DAILY"
66
+ recurs_on_this_weekday = true
67
+ end
68
+ if recurs_on_this_weekday
69
+ puts summary
70
+ create_to_do(summary)
71
+ end
72
+ end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Hello world in TextEdit.
4
+
5
+ require "appscript"
6
+
7
+ te = AS.app('TextEdit')
8
+ te.activate
9
+ te.documents.end.make(:new => :document, :with_properties => {:text => "Hello World!\n"})
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # List names of playlists in iTunes.
4
+
5
+ require "appscript"
6
+
7
+ p AS.app('iTunes').sources[1].user_playlists.name.get
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Compose an outgoing message in Apple's Mail.app.
4
+
5
+ require "appscript"
6
+
7
+ def make_message(addresses, subject, content, show_window=false)
8
+ # Make an outgoing message in Mail.
9
+ # addresses : list of unicode -- a list of email addresses
10
+ # subject : unicode -- the message subject
11
+ # content : unicode -- the message content
12
+ # show_window : Boolean -- show message window in Mail
13
+ # Result : reference -- reference to the new outgoing message
14
+ mail = AS.app('Mail')
15
+ msg = mail.make(
16
+ :new => :outgoing_message,
17
+ :with_properties => {:visible => show_window})
18
+ addresses.each do |an_address|
19
+ msg.to_recipients.end.make(
20
+ :new => :recipient,
21
+ :with_properties => {:address => an_address})
22
+ end
23
+ msg.subject.set(subject)
24
+ msg.content.set(content)
25
+ return msg
26
+ end
27
+
28
+ # test
29
+ p make_message(['joe@foo.com', 'jane@bar.net'], 'Hello World', 'Some body text.', true)