rb-scpt 1.0.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 (94) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +497 -0
  3. data/doc/aem-manual/01_introduction.html +60 -0
  4. data/doc/aem-manual/02_apioverview.html +107 -0
  5. data/doc/aem-manual/03_packingandunpackingdata.html +135 -0
  6. data/doc/aem-manual/04_references.html +409 -0
  7. data/doc/aem-manual/05_targetingapplications.html +164 -0
  8. data/doc/aem-manual/06_buildingandsendingevents.html +229 -0
  9. data/doc/aem-manual/07_findapp.html +63 -0
  10. data/doc/aem-manual/08_examples.html +94 -0
  11. data/doc/aem-manual/aemreferenceinheritance.gif +0 -0
  12. data/doc/aem-manual/index.html +56 -0
  13. data/doc/appscript-manual/01_introduction.html +94 -0
  14. data/doc/appscript-manual/02_aboutappscripting.html +247 -0
  15. data/doc/appscript-manual/03_quicktutorial.html +167 -0
  16. data/doc/appscript-manual/04_gettinghelp.html +188 -0
  17. data/doc/appscript-manual/05_keywordconversion.html +106 -0
  18. data/doc/appscript-manual/06_classesandenums.html +192 -0
  19. data/doc/appscript-manual/07_applicationobjects.html +211 -0
  20. data/doc/appscript-manual/08_realvsgenericreferences.html +96 -0
  21. data/doc/appscript-manual/09_referenceforms.html +241 -0
  22. data/doc/appscript-manual/10_referenceexamples.html +154 -0
  23. data/doc/appscript-manual/11_applicationcommands.html +245 -0
  24. data/doc/appscript-manual/12_commandexamples.html +138 -0
  25. data/doc/appscript-manual/13_performanceissues.html +142 -0
  26. data/doc/appscript-manual/14_notes.html +80 -0
  27. data/doc/appscript-manual/application_architecture.gif +0 -0
  28. data/doc/appscript-manual/application_architecture2.gif +0 -0
  29. data/doc/appscript-manual/finder_to_textedit_event.gif +0 -0
  30. data/doc/appscript-manual/index.html +62 -0
  31. data/doc/appscript-manual/relationships_example.gif +0 -0
  32. data/doc/appscript-manual/ruby_to_itunes_event.gif +0 -0
  33. data/doc/full.css +106 -0
  34. data/doc/index.html +45 -0
  35. data/doc/mactypes-manual/01_introduction.html +54 -0
  36. data/doc/mactypes-manual/02_aliasclass.html +124 -0
  37. data/doc/mactypes-manual/03_fileurlclass.html +126 -0
  38. data/doc/mactypes-manual/04_unitsclass.html +100 -0
  39. data/doc/mactypes-manual/index.html +53 -0
  40. data/doc/osax-manual/01_introduction.html +67 -0
  41. data/doc/osax-manual/02_interface.html +147 -0
  42. data/doc/osax-manual/03_examples.html +73 -0
  43. data/doc/osax-manual/04_notes.html +61 -0
  44. data/doc/osax-manual/index.html +53 -0
  45. data/doc/rb-appscript-logo.png +0 -0
  46. data/extconf.rb +65 -0
  47. data/rb-scpt.gemspec +14 -0
  48. data/sample/AB_export_vcard.rb +31 -0
  49. data/sample/AB_list_people_with_emails.rb +13 -0
  50. data/sample/Add_iCal_event.rb +21 -0
  51. data/sample/Create_daily_iCal_todos.rb +75 -0
  52. data/sample/Export_Address_Book_phone_numbers.rb +59 -0
  53. data/sample/Hello_world.rb +21 -0
  54. data/sample/List_iTunes_playlist_names.rb +11 -0
  55. data/sample/Make_Mail_message.rb +33 -0
  56. data/sample/Open_file_in_TextEdit.rb +13 -0
  57. data/sample/Organize_Mail_messages.rb +61 -0
  58. data/sample/Print_folder_tree.rb +16 -0
  59. data/sample/Select_all_HTML_files.rb +14 -0
  60. data/sample/Set_iChat_status.rb +24 -0
  61. data/sample/Simple_Finder_GUI_Scripting.rb +18 -0
  62. data/sample/Stagger_Finder_windows.rb +25 -0
  63. data/sample/TextEdit_demo.rb +130 -0
  64. data/sample/iTunes_top40_to_html.rb +71 -0
  65. data/src/SendThreadSafe.c +380 -0
  66. data/src/SendThreadSafe.h +139 -0
  67. data/src/lib/_aem/aemreference.rb +1022 -0
  68. data/src/lib/_aem/codecs.rb +662 -0
  69. data/src/lib/_aem/connect.rb +205 -0
  70. data/src/lib/_aem/encodingsupport.rb +77 -0
  71. data/src/lib/_aem/findapp.rb +85 -0
  72. data/src/lib/_aem/mactypes.rb +251 -0
  73. data/src/lib/_aem/send.rb +279 -0
  74. data/src/lib/_aem/typewrappers.rb +59 -0
  75. data/src/lib/_appscript/defaultterminology.rb +277 -0
  76. data/src/lib/_appscript/referencerenderer.rb +245 -0
  77. data/src/lib/_appscript/reservedkeywords.rb +116 -0
  78. data/src/lib/_appscript/safeobject.rb +249 -0
  79. data/src/lib/_appscript/terminology.rb +471 -0
  80. data/src/lib/aem.rb +253 -0
  81. data/src/lib/appscript.rb +1075 -0
  82. data/src/lib/kae.rb +1489 -0
  83. data/src/lib/osax.rb +659 -0
  84. data/src/rbae.c +979 -0
  85. data/test/README +3 -0
  86. data/test/test_aemreference.rb +118 -0
  87. data/test/test_appscriptcommands.rb +152 -0
  88. data/test/test_appscriptreference.rb +106 -0
  89. data/test/test_codecs.rb +186 -0
  90. data/test/test_findapp.rb +26 -0
  91. data/test/test_mactypes.rb +79 -0
  92. data/test/test_osax.rb +54 -0
  93. data/test/testall.sh +10 -0
  94. metadata +145 -0
Binary file
@@ -0,0 +1,65 @@
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
+ require 'rbconfig'
33
+
34
+ $CFLAGS << ' -Wall'
35
+ $LDFLAGS << ' -framework Carbon -framework ApplicationServices'
36
+
37
+ # Avoid `ID' and `T_DATA' symbol collisions between Ruby and Carbon.
38
+ # (adapted code from RubyAEOSA - FUJIMOTO Hisakuni <hisa -at- fobj - com>)
39
+
40
+ maj, min = RUBY_VERSION.split('.')
41
+ is_ruby_18 = (maj <= '1' and min.to_i < 9)
42
+ if is_ruby_18
43
+ header_path = RbConfig::CONFIG['archdir']
44
+ else
45
+ header_path = File.join(RbConfig::CONFIG['rubyhdrdir'], 'ruby')
46
+ end
47
+ ruby_h = File.join(header_path, 'ruby.h')
48
+ intern_h = File.join(header_path, 'intern.h')
49
+ new_filename_prefix = 'osx_'
50
+
51
+ [ ruby_h, intern_h ].each do |src_path|
52
+ dst_fname = File.join('./src', new_filename_prefix + File.basename(src_path))
53
+ $stderr.puts "create #{File.expand_path(dst_fname)} ..."
54
+ File.open(dst_fname, 'w') do |dstfile|
55
+ IO.foreach(src_path) do |line|
56
+ line = line.gsub(/\bID\b/, 'RB_ID')
57
+ line = line.gsub(/\bT_DATA\b/, 'RB_T_DATA')
58
+ line = line.gsub(/\b(?:ruby\/)?intern.h\b/, "#{new_filename_prefix}intern.h")
59
+ line = line.gsub('#include "defines.h"', '#include "ruby/defines.h"') if not is_ruby_18
60
+ dstfile.puts line
61
+ end
62
+ end
63
+ end
64
+
65
+ create_makefile('ae', 'src')
@@ -0,0 +1,14 @@
1
+ require "rubygems"
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "rb-scpt"
5
+ s.version = "1.0.0"
6
+ s.homepage = "https://github.com/BrendanThompson/rb-scpt"
7
+ s.summary="This is a fork of the original rb-appscript. Ruby AppleScript (rb-scpt) is a high-level, user-friendly Apple event bridge that allows you to control scriptable Mac OS X applications using ordinary Ruby scripts."
8
+ s.files = Dir["**/*"].delete_if { |name| ["MakeFile", "ae.bundle", "mkmf.log", "rbae.o", "SendThreadSafe.o", "src/osx_ruby.h", "src/osx_intern.h"].include?(name) }
9
+ s.extensions = "extconf.rb"
10
+ s.test_files = Dir["test/test_*.rb"]
11
+ s.authors = ["hhas","Brendan Thompson"]
12
+ s.email = 'brendan@btsystems.com.au'
13
+ s.required_ruby_version = ">= 1.8"
14
+ end
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Exports all Address Book entries as vcards to current working folder.
4
+ #
5
+ # Files are named as 'NAME.vcard' (note: existing files will be overwritten).
6
+ # If the name is missing, 'unknown' is used instead. If two or more people
7
+ # share the same name, files will be named 'NAME.vcard', 'NAME 1.vcard',
8
+ # 'NAME 2.vcard', etc.
9
+
10
+
11
+ # Note: if using the appscript gem, rubygems must be required first:
12
+ begin; require 'rubygems'; rescue LoadError; end
13
+
14
+ require 'appscript'
15
+ include Appscript
16
+
17
+ people = app('Address Book').people
18
+
19
+ found_names = []
20
+ people.name.get.zip(people.vcard.get).each do |name, vcard|
21
+ name = 'unknown' if name == ''
22
+ name = name.gsub('/', ':')
23
+ filename = "#{name}.vcard"
24
+ i = 1
25
+ while found_names.include?(filename.downcase)
26
+ filename = "#{name} #{i}.vcard"
27
+ i += 1
28
+ end
29
+ found_names.push(filename.downcase)
30
+ File.open(filename, 'w') { |f| f.puts vcard }
31
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Lists the name and email(s) of every person in Address Book with
4
+ # one or more email addresses.
5
+
6
+ # Note: if using the appscript gem, rubygems must be required first:
7
+ begin; require 'rubygems'; rescue LoadError; end
8
+
9
+ require "appscript"
10
+ include Appscript
11
+
12
+ people_ref = app('Address Book').people[its.emails.ne([])]
13
+ p people_ref.name.get.zip(people_ref.emails.value.get)
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Add an event to Home calendar that runs from 7am to 9 am tomorrow
4
+
5
+ # Note: if using the appscript gem, rubygems must be required first:
6
+ begin; require 'rubygems'; rescue LoadError; end
7
+
8
+ require 'appscript'
9
+ include Appscript
10
+
11
+ calendar_name = 'Home'
12
+ t = Time.now + 60 * 60 * 24
13
+ start = Time.local(t.year, t.month, t.day, 7)
14
+ end_ = start + 60 * 60 * 2
15
+ summary = 'First pants, then shoes.'
16
+
17
+ app('iCal').calendars[calendar_name].events.end.make(
18
+ :new => :event, :with_properties => {
19
+ :start_date => start,
20
+ :end_date => end_,
21
+ :summary => summary})
@@ -0,0 +1,75 @@
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
+ # Note: if using the appscript gem, rubygems must be required first:
28
+ begin; require 'rubygems'; rescue LoadError; end
29
+
30
+ require "appscript"
31
+ include Appscript
32
+
33
+ ICal = app("iCal")
34
+
35
+ # The calendar in which recurring todo items should appear:
36
+ ToDoCalendarName = "Personal"
37
+
38
+ def create_to_do(summary_text)
39
+ # Adds To Dos to calendar "Personal"
40
+ now = Time.new
41
+ midnight = Time.local(now.year(), now.month(), now.day())
42
+ to_dos = ICal.calendars[ToDoCalendarName].todos
43
+ # don't create an item if it already exists for today!
44
+ if to_dos[its.due_date.ge(midnight).and(
45
+ its.summary.eq(summary_text))].count < 1
46
+ to_dos.end.make(:new=>:todo, :with_properties=>{
47
+ :due_date=>midnight, :summary=>summary_text})
48
+ end
49
+ end
50
+
51
+ def get_label(recurrence, label)
52
+ match = Regexp.new("(?:^|;)#{label}=(.*?)(?:$|;)").match(recurrence)
53
+ return match ? match[1] : nil
54
+ end
55
+
56
+ weekday_code = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"][Time.new.wday]
57
+ events = ICal.calendars["Shadow"].events
58
+
59
+ events.recurrence.get.zip(events.summary.get).each do |recurrence, summary|
60
+ recurs_on_this_weekday = false
61
+ frequency = get_label(recurrence, "FREQ")
62
+ case frequency
63
+ when "WEEKLY"
64
+ days = get_label(recurrence, "BYDAY")
65
+ if days and days.split(",").include?(weekday_code)
66
+ recurs_on_this_weekday = true
67
+ end
68
+ when "DAILY"
69
+ recurs_on_this_weekday = true
70
+ end
71
+ if recurs_on_this_weekday
72
+ puts summary
73
+ create_to_do(summary)
74
+ end
75
+ end
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Exports phone numbers from Address Book.
4
+
5
+ # Note: if using the appscript gem, rubygems must be required first:
6
+ begin; require 'rubygems'; rescue LoadError; end
7
+
8
+ require "osax"
9
+ include Appscript, OSAX
10
+
11
+ # create Application object for Address Book
12
+ AB = app("Address Book")
13
+
14
+ # prompt user for name of Address Book group to export from
15
+ DefaultChoice = ["<All>"]
16
+
17
+ groups = DefaultChoice + AB.groups.name.get
18
+ choice = osax.choose_from_list(groups, :default_items => DefaultChoice)
19
+ if choice == false # user cancelled
20
+ exit
21
+ elsif choice == DefaultChoice
22
+ ref = AB
23
+ else
24
+ ref = AB.groups[choice[0]]
25
+ end
26
+
27
+ # build a reference identifying those people with one or more phone numbers
28
+ p = ref.people[its.phones.ne([])]
29
+
30
+ # get first and last names for those people, replacing any :missing_value
31
+ # entries with empty strings
32
+ last_names = p.last_name.get.collect { |val| val.is_a?(String) ? val : "" }
33
+ first_names = p.first_name.get.collect { |val| val.is_a?(String) ? val : "" }
34
+
35
+ # get lists of phone numbers and locations for those people
36
+ locations = p.phones.label.get
37
+ numbers = p.phones.value.get
38
+
39
+ # build an array containing each person's details:
40
+ # [[last name, first name, locations, numbers], ...]
41
+ people = last_names.zip(first_names, locations, numbers)
42
+
43
+ # sort array by last and first name
44
+ people.sort! do |a, b|
45
+ a[0,2].collect { |s| s.downcase } <=> b[0,2].collect { |s| s.downcase }
46
+ end
47
+
48
+ # print table
49
+ puts " #{'_' * 70} "
50
+ people.each do |last_name, first_name, locations, numbers|
51
+ name = [last_name, first_name].delete_if { |s| s == "" }.join(', ')
52
+ puts "|#{' ' * 70}|"
53
+ # print each phone number in turn
54
+ numbers.zip(locations).each do |number, location|
55
+ puts "| #{name.ljust(32)} #{number.ljust(20)} (#{(location + ')').ljust(13)} |"
56
+ name = ""
57
+ end
58
+ puts "|#{'_' * 70}|"
59
+ end
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Note: if using the appscript gem, rubygems must be required first:
4
+ begin; require 'rubygems'; rescue LoadError; end
5
+
6
+ # 1. "Hello world" in TextEdit:
7
+
8
+ require "appscript"
9
+ include Appscript
10
+
11
+ te = app('TextEdit')
12
+ te.activate
13
+ te.documents.end.make(:new => :document, :with_properties => {:text => "Hello World!\n"})
14
+
15
+
16
+ # 2. "Hello world" using StandardAdditions:
17
+
18
+ require "osax"
19
+ include OSAX
20
+
21
+ osax.display_dialog("Hello World")
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # List names of playlists in iTunes.
4
+
5
+ # Note: if using the appscript gem, rubygems must be required first:
6
+ begin; require 'rubygems'; rescue LoadError; end
7
+
8
+ require "appscript"
9
+ include Appscript
10
+
11
+ p app('iTunes').sources[1].user_playlists.name.get
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Compose an outgoing message in Apple's Mail.app.
4
+
5
+ # Note: if using the appscript gem, rubygems must be required first:
6
+ begin; require 'rubygems'; rescue LoadError; end
7
+
8
+ require "appscript"
9
+ include Appscript
10
+
11
+ def make_message(addresses, subject, content, show_window=false)
12
+ # Make an outgoing message in Mail.
13
+ # addresses : list of unicode -- a list of email addresses
14
+ # subject : unicode -- the message subject
15
+ # content : unicode -- the message content
16
+ # show_window : Boolean -- show message window in Mail
17
+ # Result : reference -- reference to the new outgoing message
18
+ mail = app('Mail')
19
+ msg = mail.make(
20
+ :new => :outgoing_message,
21
+ :with_properties => {:visible => show_window})
22
+ addresses.each do |an_address|
23
+ msg.to_recipients.end.make(
24
+ :new => :recipient,
25
+ :with_properties => {:address => an_address})
26
+ end
27
+ msg.subject.set(subject)
28
+ msg.content.set(content)
29
+ return msg
30
+ end
31
+
32
+ # test
33
+ p make_message(['joe@foo.com', 'jane@bar.net'], 'Hello World', 'Some body text.', true)
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Opens a file in TextEdit. (Demonstrates mactypes module usage.)
4
+
5
+ # Note: if using the appscript gem, rubygems must be required first:
6
+ begin; require 'rubygems'; rescue LoadError; end
7
+
8
+ require "appscript"
9
+ include Appscript
10
+
11
+ te = app('TextEdit')
12
+ te.activate
13
+ te.open(MacTypes::Alias.path('/Users/USERNAME/ReadMe.txt'))
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Set up a Mail mailbox folder for organising incoming emails from a
4
+ # particular sender.
5
+ #
6
+ # Based on an AppleScript by Michelle Steiner.
7
+ #
8
+ # To use: in Mail, select an incoming email message from the desired sender
9
+ # (e.g. a mailing list), then run this script. The script will first make a
10
+ # new mailbox folder for storing messages from this sender if one doesn't
11
+ # already exist. It will then create a new Mail rule that automatically moves
12
+ # incoming messages from this sender directly into this mailbox.
13
+
14
+ # Note: if using the appscript gem, rubygems must be required first:
15
+ begin; require 'rubygems'; rescue LoadError; end
16
+
17
+ require "appscript"
18
+ include Appscript
19
+
20
+ mail = app('Mail')
21
+
22
+ # get the current selection in Mail and make sure it's an email message
23
+ selection = mail.selection.get
24
+
25
+ if selection == [] or selection[0].class_.get != :message
26
+ puts "Please select a message and try again."
27
+ exit
28
+ end
29
+
30
+ # get a reference to the first selected message
31
+ msg = selection[0]
32
+
33
+ recipient = msg.to_recipients[1]
34
+ address = recipient.address.get
35
+
36
+ # determine the new mailbox's name based on the sender's name/address
37
+ if recipient.name.exists
38
+ folder_name = recipient.name.get
39
+ else
40
+ folder_name = /^[^@]*/.match(address)[0]
41
+ end
42
+
43
+ # make a new mailbox if one doesn't already exist
44
+ if not mail.mailboxes[folder_name].exists
45
+ mail.mailboxes.end.make(:new=>:mailbox, :with_properties=>{
46
+ :name=>folder_name})
47
+ end
48
+
49
+ # make a new mail rule to move list messages to the mailbox
50
+ if not mail.rules[folder_name].exists
51
+ new_rule = mail.rules[1].after.make(:new=>:rule, :with_properties=>{
52
+ :name=>folder_name,
53
+ :should_move_message=>true,
54
+ :move_message=>app.mailboxes[folder_name],
55
+ :stop_evaluating_rules=>true})
56
+ new_rule.make(:new=>:rule_condition, :with_properties=>{
57
+ :expression=>address,
58
+ :rule_type=>:to_header,
59
+ :qualifier=>:does_contain_value})
60
+ new_rule.enabled.set(true)
61
+ end
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Prints the sub-folder hierarchy of a given folder as a list of folder names indented according to depth.
4
+
5
+ # Note: if using the appscript gem, rubygems must be required first:
6
+ begin; require 'rubygems'; rescue LoadError; end
7
+
8
+ require "appscript"
9
+ include Appscript
10
+
11
+ def print_folder_tree(folder, indent='')
12
+ puts indent + folder.name.get
13
+ folder.folders.get.each { |folder| print_folder_tree(folder, indent + "\t") }
14
+ end
15
+
16
+ print_folder_tree(app('Finder').home.folders['Documents'])