rb-scpt 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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'])